Skip to content

Commit e706546

Browse files
authored
feat: 학교 검색 페이지 /search 추가 (#194)
* remove: 레거시 파일 삭제 * feat: SearchPage 추가 * feat: 메인 홈 검색 기능 리다이렉트 변경 * feat: SearchContent 추가, 하위 컴포넌트 추가 SearchContent 분리의 이유: use client 사용을 위해 * design: UniversitySearchInput 디자인 수정 * fix: import 오류 수정 * feat: UniversityRegionTabs 구현, SearchContent 리팩토링 * feat: 학교 검색 버튼 변경 * feat: UniversityFfilterSection 다중 어학/국가 지원하게 변경 * feat: svg 추가 * feat: 어학/관심있는 나라 디자인 추가 * feat: search UniversityFilterSection의 어학성적 선택부분 수정 * feat: UniversityFilterSection 나라 디자인 추가 * feat: 이전 나라가 선택되어야 다음 나라를 선택할 수 있게 변경 * refactor: UniversitySearchInput ref 방식으로 전환하여 부모 컴포넌트 리렌더링 막기 * refactor: 어학/국가 전달을 핸들러 함수로 추상화 * refactor: 이름 통일 * refactor: changeRegion 추상화 * refactor: regions를 바깥으로 분리
1 parent f3c85e2 commit e706546

19 files changed

+316
-173
lines changed

public/svgs/search/down-arrow.svg

Lines changed: 3 additions & 0 deletions
Loading

public/svgs/search/hat-color.svg

Lines changed: 3 additions & 0 deletions
Loading

public/svgs/search/hat-gray.svg

Lines changed: 3 additions & 0 deletions
Loading

public/svgs/search/index.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
import IconDownArrow from "./down-arrow.svg";
2+
import IconHatColor from "./hat-color.svg";
3+
import IconHatGray from "./hat-gray.svg";
4+
import IconLocationColor from "./location-color.svg";
5+
import IconLocationGray from "./location-gray.svg";
6+
import IconSearch from "./search.svg";
7+
8+
export { IconSearch, IconHatColor, IconHatGray, IconLocationColor, IconLocationGray, IconDownArrow };
Lines changed: 3 additions & 0 deletions
Loading
Lines changed: 3 additions & 0 deletions
Loading

public/svgs/search/search.svg

Lines changed: 3 additions & 0 deletions
Loading

src/app/Home.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@ const Home = ({ newsList }: HomeProps) => {
6262

6363
<div className="flex flex-col gap-2.5 px-5 py-3.5">
6464
<div className="flex gap-[7px]">
65-
<Link className="flex h-[102px] flex-1 flex-col gap-2 rounded-lg bg-[#F0F5FF] p-2.5" href="/university">
65+
<Link className="flex h-[102px] flex-1 flex-col gap-2 rounded-lg bg-[#F0F5FF] p-2.5" href="/search">
6666
<div className="flex flex-col">
6767
<span className="text-sm font-bold text-secondary-900">학교 검색하기</span>
6868
<span className="text-[11px] font-medium leading-[14px] text-k-700">모든 학교 목록을 확인해보세요</span>

src/app/search/SearchContent.tsx

Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
"use client";
2+
3+
import { useRef, useState } from "react";
4+
5+
import BlockBtn from "@/components/button/BlockBtn";
6+
import UniversityFilterSection from "@/components/search/UniversityFilterSection";
7+
import UniversityRegionTabs from "@/components/search/UniversityRegionTabs";
8+
import UniversitySearchInput from "@/components/search/UniversitySearchInput";
9+
10+
import { LanguageTestEnum } from "@/types/score";
11+
import { RegionKo } from "@/types/university";
12+
13+
export interface RegionOption {
14+
label: string;
15+
value: RegionKo;
16+
}
17+
18+
const regions: RegionOption[] = [
19+
{ label: "유럽권", value: "유럽권" },
20+
{ label: "미주권", value: "미주권" },
21+
{ label: "아시아권", value: "아시아권" },
22+
];
23+
24+
const SearchContent = () => {
25+
// 권역 필터링
26+
const searchQueryRef = useRef<HTMLInputElement>(null);
27+
const [region, setRegion] = useState<RegionKo | null>(null);
28+
29+
const changeRegion = (value: string | null) => {
30+
if (value === null) {
31+
setRegion(null);
32+
return;
33+
}
34+
if (!["유럽권", "미주권", "아시아권"].includes(value)) {
35+
console.error("유효하지 않은 지역 선택");
36+
}
37+
setRegion(value as RegionKo);
38+
};
39+
40+
// 어학/국가 필터링
41+
const [language, setLanguage] = useState<string>("");
42+
const [countries, setCountries] = useState<string[]>(["", "", ""]);
43+
44+
const changeLanguage = (newLanguage: string) => {
45+
if (!Object.values(LanguageTestEnum).includes(newLanguage as LanguageTestEnum)) {
46+
console.error("유효하지 않은 어학 성적 선택");
47+
}
48+
setLanguage(newLanguage);
49+
};
50+
51+
const changeCountry = (index: number, newCountry: string) => {
52+
setCountries((prevCountries) => {
53+
// TODO: 이후 나라 체크 로직 추가하기
54+
const updatedCountries = [...prevCountries];
55+
updatedCountries[index] = newCountry;
56+
return updatedCountries;
57+
});
58+
};
59+
60+
const handleSearch = () => {
61+
const query = searchQueryRef.current?.value ?? "";
62+
console.log({ query, region, language, countries });
63+
};
64+
65+
return (
66+
<div className="flex flex-col gap-4 px-5 pb-8">
67+
<UniversitySearchInput ref={searchQueryRef} placeholder="해외 파견 학교를 검색하세요." />
68+
69+
<UniversityRegionTabs regions={regions} region={region} changeRegion={changeRegion} />
70+
71+
<UniversityFilterSection
72+
language={language}
73+
changeLanguage={changeLanguage}
74+
languageOptions={Object.values(LanguageTestEnum)}
75+
countries={countries}
76+
changeCountry={changeCountry}
77+
countryOptions={["오스트레일리아", "체코", "캐나다"]}
78+
/>
79+
80+
<BlockBtn onClick={handleSearch}>학교 검색</BlockBtn>
81+
</div>
82+
);
83+
};
84+
85+
export default SearchContent;

src/app/search/page.tsx

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
import { Metadata } from "next";
2+
3+
import TopDetailNavigation from "@/components/layout/TopDetailNavigation";
4+
5+
import SearchContent from "./SearchContent";
6+
7+
export const metadata: Metadata = {
8+
title: "파견학교 검색",
9+
};
10+
11+
const SearchPage = () => {
12+
return (
13+
<>
14+
<TopDetailNavigation title="파견학교 검색" />
15+
<div>
16+
<div className="px-5 py-6">
17+
<span className="text-[22px] font-bold leading-normal text-k-900">
18+
오직 나를 위한
19+
<br />
20+
맞춤 파견 학교 찾기
21+
</span>
22+
</div>
23+
<SearchContent />
24+
</div>
25+
</>
26+
);
27+
};
28+
29+
export default SearchPage;

0 commit comments

Comments
 (0)