Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[4주차-ts] Search BAR with TS #7

Open
wants to merge 16 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 26 additions & 0 deletions week4_ts/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
# Logs
logs
*.log
npm-debug.log*
yarn-debug.log*
yarn-error.log*
pnpm-debug.log*
lerna-debug.log*

node_modules
dist
dist-ssr
*.local

# Editor directories and files
.vscode/*
!.vscode/extensions.json
.idea
.DS_Store
*.suo
*.ntvs*
*.njsproj
*.sln
*.sw?

.env.local
13 changes: 13 additions & 0 deletions week4_ts/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<link rel="icon" type="image/svg+xml" href="/src/favicon.svg" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Vite App</title>
</head>
<body>
<div id="root"></div>
<script type="module" src="/src/index.tsx"></script>
</body>
</html>
27 changes: 27 additions & 0 deletions week4_ts/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
{
"name": "week4_ts",
"private": true,
"version": "0.0.0",
"scripts": {
"dev": "vite",
"build": "tsc && vite build",
"preview": "vite preview"
},
"dependencies": {
"@types/react-router-dom": "^5.3.3",
"@types/styled-components": "^5.1.25",
"axios": "^0.27.2",
"react": "^18.2.0",
"react-dom": "^18.0.0",
"react-router-dom": "^6.3.0",
"styled-components": "^5.3.5",
"styled-reset": "^4.4.1"
},
"devDependencies": {
"@types/react": "^18.0.14",
"@types/react-dom": "^18.0.0",
"@vitejs/plugin-react": "^1.3.0",
"typescript": "^4.6.3",
"vite": "^2.9.9"
}
}
129 changes: 129 additions & 0 deletions week4_ts/reset.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,129 @@
/* http://meyerweb.com/eric/tools/css/reset/
v2.0 | 20110126
License: none (public domain)
*/

html,
body,
div,
span,
applet,
object,
iframe,
h1,
h2,
h3,
h4,
h5,
h6,
p,
blockquote,
pre,
a,
abbr,
acronym,
address,
big,
cite,
code,
del,
dfn,
em,
img,
ins,
kbd,
q,
s,
samp,
small,
strike,
strong,
sub,
sup,
tt,
var,
b,
u,
i,
center,
dl,
dt,
dd,
ol,
ul,
li,
fieldset,
form,
label,
legend,
table,
caption,
tbody,
tfoot,
thead,
tr,
th,
td,
article,
aside,
canvas,
details,
embed,
figure,
figcaption,
footer,
header,
hgroup,
menu,
nav,
output,
ruby,
section,
summary,
time,
mark,
audio,
video {
margin: 0;
padding: 0;
border: 0;
font-size: 100%;
font: inherit;
vertical-align: baseline;
}
/* HTML5 display-role reset for older browsers */
article,
aside,
details,
figcaption,
figure,
footer,
header,
hgroup,
menu,
nav,
section {
display: block;
}
body {
line-height: 1;
}
ol,
ul {
list-style: none;
}
blockquote,
q {
quotes: none;
}
blockquote:before,
blockquote:after,
q:before,
q:after {
content: "";
content: none;
}
table {
border-collapse: collapse;
border-spacing: 0;
}
15 changes: 15 additions & 0 deletions week4_ts/src/App.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import Router from "./core/router";
import { ThemeProvider } from "styled-components";
import GlobalStyle from "./styles/globalStyle";
import theme from "./styles/theme";

export default function App() {
return (
<>
<ThemeProvider theme={theme}>
<GlobalStyle />
<Router />
</ThemeProvider>
</>
);
}
133 changes: 133 additions & 0 deletions week4_ts/src/components/Header.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,133 @@
import React, { useRef, useState } from "react";
import styled from "styled-components";
import { storeSearch } from "../libs/api";
import theme from "../styles/theme";
import { Params, Result } from "../type/result";

interface MainHeaderProps {
handleIsSearch: (newIsSearch: boolean) => void;
handleResults: (newResults: Result[]) => void;
}

interface Coordinates {
longitude: number;
latitude: number;
}

function Header(props: MainHeaderProps) {
const { handleIsSearch, handleResults } = props;
const [isLocation, setIsLocation] = useState<boolean>(false);
const [input, setInput] = useState<string>("");
//useRef의 타입을 어떻게 정의해여!?!!?
const searchRef = useRef<HTMLInputElement>(null);
const position = useRef<Coordinates>({ longitude: 0, latitude: 0 });
Comment on lines +21 to +23
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

잘한 것 같은데,!! 관련 아티클 첨부합니당
useRef 의 3가지 정의와 사용법(링크)

// 위치에 따른 가게 검색 handler
const storeSearchHttpHandler = async (params: Params) => {
const { data } = await storeSearch(params);
handleIsSearch(false);
handleResults(data.documents);
};
// 위치 handler
const handleMyLocation = () => {
// !position.current 가 무슨뜻일까?
// 그리고 내 위치를 켜면 내 위치가 아니라 이름에 바가 들어간게 나옴
if (!position.current) {
new Promise((resolve) => {
navigator.geolocation.getCurrentPosition((currentPosition) => {
position.current = currentPosition.coords;
const params = {
y: position.current.latitude,
x: position.current.longitude,
radius: 1000,
query: "바",
};
storeSearchHttpHandler(params);
});
});
} else {
const params = {
x: position.current.longitude,
y: position.current.latitude,
radius: 1000,
query: "바",
};
storeSearchHttpHandler(params);
}
};

// 클릭 시 검색 input 비활성화
const handleInputDisabled = () => {
if (searchRef.current !== null) {
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
if (searchRef.current !== null) {
if (searchRef.current)

로 해도 될것같은느낌~.~

searchRef.current.disabled = !searchRef.current.disabled;
setIsLocation((prev) => !prev);
}
};
// input 변화 감지
const handleInputChange = (e: React.ChangeEvent<HTMLInputElement>) => {
setInput(e.target.value);
};
// 검색 버튼
const handleSearchButton = (e: React.MouseEvent<HTMLButtonElement>) => {
handleIsSearch(true);
e.preventDefault();
if (searchRef.current) {
if (!searchRef.current.disabled) {
const params = {
query: input + " " + "바",
};
storeSearchHttpHandler(params);
} else {
handleMyLocation();
}
}
};

return (
<Styled.Root>
<Styled.Title>우리 동네 BAR 🥂</Styled.Title>
<Styled.SearchWrapper>
<MyLocationButton isChoice={isLocation} onClick={handleInputDisabled}>
현위치로 할래
</MyLocationButton>
<SearchLabel>찾고싶은 동네는</SearchLabel>
<SearchInput
ref={searchRef}
type="text"
onChange={handleInputChange}
value={input}
placeholder="지역을 입력해주세요"
/>
<SearchButton isChoice={handleIsSearch} type="submit" onClick={handleSearchButton}>
검색
</SearchButton>
</Styled.SearchWrapper>
</Styled.Root>
);
}

export default Header;

const Styled = {
Root: styled.header`
${({ theme }) => theme.flexColumnCenter};
`,
Title: styled.h1`
margin: 2rem 0;
`,
SearchWrapper: styled.div`
display: flex;
gap: 2rem;
`,
};

const MyLocationButton = styled.button<{ isChoice: boolean }>`
color: ${({ isChoice }) => (isChoice ? theme.colors.skyblue : theme.colors.lightgreen)};
`;

const SearchLabel = styled.label`
font-size: 2rem;
`;

const SearchInput = styled.input``;

const SearchButton = styled.button<{ isChoice: boolean }>``;
3 changes: 0 additions & 3 deletions week4_ts/src/components/Header/MyLocation.tsx

This file was deleted.

Loading