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

[6주차] Reddigg 미션 제출합니다. #16

Open
wants to merge 13 commits into
base: master
Choose a base branch
from
20 changes: 16 additions & 4 deletions src/app/search/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,7 @@ import tmdbApi, { requests } from "@/components/api";
import NavBar from "@/components/navbar";
import SearchBar from "./searchBar";
import { renderMovieLists } from "../utils/movieFunctions";
import { render } from "react-dom";

import { includesChosung } from "../utils/searchChosung";
type Props = {};
interface Movie {
id: number;
Expand All @@ -18,6 +17,16 @@ interface Movie {

function Search({}: Props) {
const [topRated, setTopRated] = useState<Movie[]>([]);
const [searchQuery, setSearchQuery] = useState("");

const handleSearchChange = (event: React.ChangeEvent<HTMLInputElement>) => {
setSearchQuery(event.target.value);
};

const filteredMovies = topRated.filter((movie) =>
includesChosung(movie.title, searchQuery),

Choose a reason for hiding this comment

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

함수 이름이 엣지넘치네요 ㅎㅎㅋㅋㅋㅋㅋㅋㅋㅋ 완전 직관적이에요

);

useEffect(() => {
const fetchMovies = async () => {
try {
Expand All @@ -34,14 +43,17 @@ function Search({}: Props) {

return (
<div className="flex flex-col items-center w-full h-screen">
<SearchBar />
<SearchBar
searchQuery={searchQuery}
onSearchChange={handleSearchChange}
/>

<h3 className="pl-[0.63rem] pt-[117px] text-start text-white text-preview font-bold mb-[1.3rem] w-[375px]">
Top Searches
</h3>

<div className="flex flex-col items-center justify-center w-full pb-[60px] overflow-y-auto">
{renderMovieLists(topRated)}
{renderMovieLists(filteredMovies)}
</div>
<NavBar />
</div>
Expand Down
10 changes: 8 additions & 2 deletions src/app/search/searchBar.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,11 @@
import { SearchIcon2, XIcon } from "../../../public/svgs";

const SearchBar = () => {
interface SearchBarProps {
searchQuery: string;
onSearchChange: (event: React.ChangeEvent<HTMLInputElement>) => void;
}

const SearchBar = ({ searchQuery, onSearchChange }: SearchBarProps) => {
return (
<div className="fixed top-[50px] left-1/2 transform -translate-x-1/2 flex items-center bg-[#424242] w-[375px] h-[50px]">
<div className="absolute inset-y-0 left-0 pl-5 flex items-center pointer-events-none">
Expand All @@ -9,10 +14,11 @@ const SearchBar = () => {

<input
type="text"
value={searchQuery}
onChange={onSearchChange}
className="w-full bg-[#424242] text-[#C4C4C4] pl-12 pr-12 focus:outline-none"
placeholder="Search for a show, movie, genre, e.t.c"
/>

<div className="absolute inset-y-0 right-0 pr-5 flex items-center pointer-events-none">
<XIcon className="h-5 w-5" />
</div>
Expand Down
58 changes: 58 additions & 0 deletions src/app/utils/searchChosung.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
const CHO_HANGUL: string[] = [
"ㄱ",
"ㄲ",
"ㄴ",
"ㄷ",
"ㄸ",
"ㄹ",
"ㅁ",
"ㅂ",
"ㅃ",
"ㅅ",
"ㅆ",
"ㅇ",
"ㅈ",
"ㅉ",
"ㅊ",
"ㅋ",
"ㅌ",
"ㅍ",
"ㅎ",
];

const HANGUL_START_CHARCODE: number = "가".charCodeAt(0);

const CHO_INTERVAL: number = Math.floor(
"까".charCodeAt(0) - "가".charCodeAt(0),
);
const JUNG_INTERVAL: number = Math.floor(
"개".charCodeAt(0) - "가".charCodeAt(0),
);

function combineHangul(cho: number, jung: number, jong: number): string {
return String.fromCharCode(
HANGUL_START_CHARCODE + cho * CHO_INTERVAL + jung * JUNG_INTERVAL + jong,
);
}

function createChosungRegex(search: string = ""): RegExp {
const regexPattern: string = CHO_HANGUL.reduce(
(acc: string, cho: string, index: number) =>
acc.replace(
new RegExp(cho, "g"),
`[${combineHangul(index, 0, 0)}-${combineHangul(index + 1, 0, -1)}]`,
),
search,
);

return new RegExp(`(${regexPattern})`, "g");
}

export function includesChosung(target: string, query: string): boolean {
if (!query) return true;
if (/[ㄱ-ㅎ|ㅏ-ㅣ|가-힣]/.test(query)) {
return createChosungRegex(query).test(target);
} else {
return target.toLowerCase().includes(query.toLowerCase());
}
}