From b43f0b29885951c538ca8a1c9708042ce66c65b1 Mon Sep 17 00:00:00 2001 From: Leejha <57664427+Leejha@users.noreply.github.com> Date: Sat, 16 Sep 2023 01:38:46 +0900 Subject: [PATCH] =?UTF-8?q?[JR-749]=20=EA=B2=80=EC=83=89=20=ED=8E=98?= =?UTF-8?q?=EC=9D=B4=EC=A7=80=20=EB=A6=AC=ED=8C=A9=ED=86=A0=EB=A7=81=20(#1?= =?UTF-8?q?42)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * refactor: 검색 페이지 각 상태에 따라 보기 쉽게 분리 * refactor: 컨테이너에서 로직을 관리하도록 변경 --- .../app/search/components/SearchContainer.tsx | 248 ++++++++++++++++++ apps/jurumarble/src/app/search/page.tsx | 199 +------------- 2 files changed, 250 insertions(+), 197 deletions(-) create mode 100644 apps/jurumarble/src/app/search/components/SearchContainer.tsx diff --git a/apps/jurumarble/src/app/search/components/SearchContainer.tsx b/apps/jurumarble/src/app/search/components/SearchContainer.tsx new file mode 100644 index 00000000..8241bc2f --- /dev/null +++ b/apps/jurumarble/src/app/search/components/SearchContainer.tsx @@ -0,0 +1,248 @@ +"use client"; + +import BottomBar from "components/BottomBar"; +import { Button } from "components/button"; +import SearchInput from "components/SearchInput"; +import useInput from "hooks/useInput"; +import SvgIcPrev from "src/assets/icons/components/IcPrev"; +import styled, { css, DefaultTheme } from "styled-components"; +import { useState } from "react"; +import { SORT_LIST } from "lib/constants"; +import DrinkList from "./DrinkList"; +import DrinkVoteList from "./DrinkVoteList"; +import SortSelect from "./SortSelect"; +import RegionSmallSelect from "./RegionSmallSelect"; + +const TAB_LIST = [ + { id: "total", name: "통합" }, + { id: "drinkInfo", name: "우리술 정보" }, + { id: "drinkVote", name: "우리술 투표" }, +] as const; + +type TabList = (typeof TAB_LIST)[number]["id"]; + +/** + * @Todo 아래와 같이 분리하기 + * + * + * + * + * + * @Todo 검색 상태를 관리하는 Context를 만들기 + * const {textInput} = useSearchContext() + */ + +function SearchContainer() { + const { value: searchText, onChange: onChangeSearchText } = useInput({ + initialValue: "", + useDebounce: true, + }); + + const [selectedTab, setSelectedTab] = useState("total"); + const onClickSelectedTab = (e: React.MouseEvent) => { + setSelectedTab(e.currentTarget.value as TabList); + }; + + const [sortOption, setSortOption] = useState(SORT_LIST[1].value); + const onChangeSortOption = (value: string) => { + setSortOption(value); + }; + + const [regionOption, setRegionOption] = useState(""); + const onChangeRegionOption = (value: string) => { + setRegionOption(value); + }; + + const isSelectedTab = (tabName: string) => { + return selectedTab === tabName; + }; + + const renderItem: Record< + TabList, + { topSectionItem: JSX.Element; bottomSectionItem: JSX.Element } + > = { + total: { + topSectionItem: ( + <> +

우리술 정보

+ + + 우리술 정보 더보기 + + + ), + bottomSectionItem: ( + <> +

우리술 투표

+ + + 우리술 투표 더보기 + + + ), + }, + drinkInfo: { + topSectionItem: ( + <> + + + + + + + ), + bottomSectionItem: <>, + }, + drinkVote: { + topSectionItem: <>, + bottomSectionItem: ( + <> + + + + + + + ), + }, + }; + const { topSectionItem, bottomSectionItem } = renderItem[selectedTab]; + + return ( + <> + + + + + + + {TAB_LIST.map(({ id, name }) => ( + + {name} + + ))} + + {topSectionItem} + + {isSelectedTab("total") && } + {bottomSectionItem} + + + ); +} + +const TopSection = styled.section` + padding: 0 20px; +`; + +const SearchBox = styled.div` + display: flex; + align-items: center; + gap: 14px; +`; + +const TabBox = styled.ul` + display: flex; + margin-top: 8px; +`; + +const DivideLine = styled.div` + ${({ theme }) => css` + background-color: ${theme.colors.bg_01}; + height: 8px; + margin-bottom: 8px; + `} +`; + +const SelectedButton = styled.button<{ theme: DefaultTheme; selected: boolean }>` + ${({ theme, selected }) => + css` + ${theme.typography.body02}; + color: ${theme.colors.black_03}; + padding: 16.5px 12px; + + ${selected + ? css` + ${theme.typography.body01}; + color: ${theme.colors.black_01}; + border-bottom: 3px solid ${theme.colors.black_01}; + ` + : css` + display: flex; + `} + `} +`; + +const SelectContainer = styled.div` + display: flex; + margin-top: 40px; + gap: 4px; +`; + +const H2 = styled.h2` + ${({ theme }) => css` + ${theme.typography.headline02}; + color: ${theme.colors.black_01}; + margin-top: 40px; + `} +`; + +const MoreButton = styled(Button)` + ${({ theme }) => css` + ${theme.typography.body01} + margin: 24px 0 40px 0; + `}; +`; + +const BottomSection = styled.section` + padding: 0 20px 96px; // 64(BottomBar height) + 32(margin) = 96 + overflow: auto; +`; + +export default SearchContainer; diff --git a/apps/jurumarble/src/app/search/page.tsx b/apps/jurumarble/src/app/search/page.tsx index 6c30ad1c..0c718957 100644 --- a/apps/jurumarble/src/app/search/page.tsx +++ b/apps/jurumarble/src/app/search/page.tsx @@ -1,204 +1,9 @@ "use client"; -import BottomBar from "components/BottomBar"; -import { Button } from "components/button"; -import SearchInput from "components/SearchInput"; -import useInput from "hooks/useInput"; -import SvgIcPrev from "src/assets/icons/components/IcPrev"; -import styled, { css, DefaultTheme } from "styled-components"; -import DrinkList from "./components/DrinkList"; -import DrinkVoteList from "./components/DrinkVoteList"; -import { useState } from "react"; -import { SORT_LIST } from "lib/constants"; -import SortSelect from "./components/SortSelect"; -import RegionSmallSelect from "./components/RegionSmallSelect"; - -const TAB_LIST = [ - { id: "total", name: "통합" }, - { id: "drinkInfo", name: "우리술 정보" }, - { id: "drinkVote", name: "우리술 투표" }, -]; +import SearchContainer from "./components/SearchContainer"; function Search() { - const { value: searchText, onChange: onChangeSearchText } = useInput({ - initialValue: "", - useDebounce: true, - }); - - const [selectedTab, setSelectedTab] = useState("total"); - const onClickSelectedTab = (e: React.MouseEvent) => { - setSelectedTab(e.currentTarget.value); - }; - - const [sortOption, setSortOption] = useState(SORT_LIST[1].value); - const onChangeSortOption = (value: string) => { - setSortOption(value); - }; - - const [regionOption, setRegionOption] = useState(""); - const onChangeRegionOption = (value: string) => { - setRegionOption(value); - }; - - const isSelectedTab = (tabName: string) => { - return selectedTab === tabName; - }; - - return ( - <> - - - - - - - {TAB_LIST.map(({ id, name }) => ( - - {name} - - ))} - - {!isSelectedTab("total") && ( - - - - - )} - {isSelectedTab("total") &&

우리술 정보

} - {isSelectedTab("drinkVote") ? ( - <> - ) : ( - <> - - {selectedTab === "total" && ( - - 우리술 정보 더보기 - - )} - - )} -
- {isSelectedTab("total") && } - - {selectedTab === "drinkInfo" ? ( - <> - ) : ( - <> - {isSelectedTab("total") &&

우리술 투표

} - - {isSelectedTab("total") && ( - - 우리술 투표 더보기 - - )} - - )} -
- - - - ); + return ; } -const TopSection = styled.section` - padding: 0 20px; -`; - -const SearchBox = styled.div` - display: flex; - align-items: center; - gap: 14px; -`; - -const TabBox = styled.ul` - display: flex; - margin-top: 8px; -`; - -const DivideLine = styled.div` - ${({ theme }) => css` - background-color: ${theme.colors.bg_01}; - height: 8px; - `} -`; - -const SelectedButton = styled.button<{ theme: DefaultTheme; selected: boolean }>` - ${({ theme, selected }) => - css` - ${theme.typography.body02}; - color: ${theme.colors.black_03}; - padding: 16.5px 12px; - - ${selected - ? css` - ${theme.typography.body01}; - color: ${theme.colors.black_01}; - border-bottom: 3px solid ${theme.colors.black_01}; - ` - : css` - display: flex; - `} - `} -`; - -const SelectContainer = styled.div` - display: flex; - margin-top: 40px; - gap: 4px; -`; - -const H2 = styled.h2` - ${({ theme }) => css` - ${theme.typography.headline02}; - color: ${theme.colors.black_01}; - margin-top: 40px; - `} -`; - -const MoreButton = styled(Button)` - ${({ theme }) => css` - ${theme.typography.body01} - margin: 24px 0 40px 0; - `}; -`; - -const BottomSection = styled.section` - padding: 0 20px 96px; - margin-top: 8px; // 64(BottomBar height) + 32(margin) = 96 - overflow: auto; -`; - export default Search;