Skip to content

Commit 8228d92

Browse files
committed
feat(search): 모바일 검색 화면 추가 및 네비게이션 업데이트
- 모바일 전용 SearchScreen 컴포넌트 추가 - 하단 네비게이션에 chat 항목 추가 및 route 상수 사용하도록 수정 - mypage 탭의 active 상태 판별 로직 조정 - 헤더의 알림 버튼을 기능 복구 전까지 주석 처리 - 서브 헤더 노출 기준을 lg 브레이크포인트로 변경 - 로그아웃 시 불필요한 query 제거 로직 삭제
1 parent 7353a18 commit 8228d92

File tree

8 files changed

+85
-10
lines changed

8 files changed

+85
-10
lines changed

src/app/(public)/search/page.tsx

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
import { SearchScreen } from "@/screens/search";
2+
3+
export default function Page() {
4+
return <SearchScreen />;
5+
}

src/screens/search/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
export { SearchScreen } from "./ui/search-screen";
Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
"use client";
2+
3+
import { useEffect, useState } from "react";
4+
5+
import { useRouter } from "next/navigation";
6+
7+
import { ROUTES } from "@/shared/config/routes";
8+
import SearchInput from "@/shared/ui/input/search-input";
9+
import { SubHeader } from "@/widgets/sub-header/sub-header";
10+
11+
export function SearchScreen() {
12+
const router = useRouter();
13+
const [query, setQuery] = useState("");
14+
15+
useEffect(() => {
16+
const mediaQuery = window.matchMedia("(min-width: 1024px)");
17+
18+
const handleChange = () => {
19+
if (mediaQuery.matches) {
20+
router.replace(ROUTES.auctions);
21+
}
22+
};
23+
24+
handleChange();
25+
mediaQuery.addEventListener("change", handleChange);
26+
27+
return () => {
28+
mediaQuery.removeEventListener("change", handleChange);
29+
};
30+
}, [router]);
31+
32+
const handleSubmit = (event: React.FormEvent<HTMLFormElement>) => {
33+
event.preventDefault();
34+
const trimmed = query.trim();
35+
if (!trimmed) return;
36+
37+
const params = new URLSearchParams();
38+
params.set("query", trimmed);
39+
router.push(`${ROUTES.auctions}?${params.toString()}`);
40+
};
41+
42+
return (
43+
<div className="bg-background flex min-h-screen w-full flex-col lg:hidden">
44+
<SubHeader
45+
content={
46+
<form className="w-full" onSubmit={handleSubmit}>
47+
<SearchInput
48+
value={query}
49+
onChange={(event) => setQuery(event.target.value)}
50+
onDelete={() => setQuery("")}
51+
placeholder="검색어를 입력해주세요"
52+
/>
53+
</form>
54+
}
55+
/>
56+
57+
<main className="flex-1 px-4 pb-6">
58+
<section className="pt-4">
59+
<h2 className="text-sm font-semibold">최근 검색어</h2>
60+
<div className="mt-3 min-h-24" />
61+
</section>
62+
</main>
63+
</div>
64+
);
65+
}

src/widgets/bottom-nav/model/item.ts

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,15 @@
1-
import { House, Search, Plus, Bell, User } from "lucide-react";
1+
import { House, Search, Plus, MessageCircle, User } from "lucide-react";
2+
3+
import { ROUTES } from "@/shared/config/routes";
24

35
import type { LucideIcon } from "lucide-react";
46

57
export const BOTTOM_NAV_ITEMS = [
68
{ id: "home", label: "홈", href: "/", icon: House },
79
{ id: "search", label: "검색", href: "/search", icon: Search },
8-
{ id: "create", label: "등록", href: "/auctions/create", icon: Plus },
9-
{ id: "notification", label: "알림", href: "/notifications", icon: Bell },
10-
{ id: "profile", label: "내정보", href: "/users/me", icon: User },
10+
{ id: "create", label: "등록", href: ROUTES.auctionCreate, icon: Plus },
11+
{ id: "chat", label: "채팅", href: "/dm", icon: MessageCircle },
12+
{ id: "mypage", label: "내정보", href: ROUTES.myPage, icon: User },
1113
] as const;
1214

1315
export type BottomNavIdType = (typeof BOTTOM_NAV_ITEMS)[number]["id"];

src/widgets/bottom-nav/ui/bottom-nav.tsx

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,9 @@ export function BottomNav() {
2323
<BottomNavItem
2424
key={item.id}
2525
{...item}
26-
isActive={pathname === item.href}
26+
isActive={
27+
item.id === "mypage" ? pathname.startsWith("/users/me") : pathname === item.href
28+
}
2729
hasNotification={!!hasNotificationsById[item.id]}
2830
/>
2931
))}

src/widgets/header/ui/header-actions.tsx

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
import Link from "next/link";
44

5-
import { Bell, Plus } from "lucide-react";
5+
import { Plus } from "lucide-react";
66

77
import { ROUTES } from "@/shared/config/routes";
88
import { Button } from "@/shared/ui";
@@ -30,10 +30,11 @@ export default function HeaderActions({
3030
</Link>
3131
</Button>
3232

33-
<Button aria-label="알림" size="icon-lg" variant="ghost" className="relative">
33+
{/* TODO: 알림 기능 복구 시 다시 노출 */}
34+
{/* <Button aria-label="알림" size="icon-lg" variant="ghost" className="relative">
3435
<Bell className="size-5" />
3536
<span className="absolute top-1 right-1 h-2 w-2 rounded-full bg-red-500" />
36-
</Button>
37+
</Button> */}
3738

3839
<HeaderUserMenu avatarUrl={avatarUrl} avatarAlt={avatarAlt} />
3940
</div>

src/widgets/header/ui/header-user-menu.tsx

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,6 @@ export default function HeaderUserMenu({ avatarUrl, avatarAlt }: HeaderUserMenuP
4444
showToast.error("로그아웃에 실패했습니다. 잠시 후 다시 시도해주세요.");
4545
} finally {
4646
queryClient.setQueryData(userKeys.basic(), null);
47-
queryClient.removeQueries({ queryKey: userKeys.all, exact: false });
4847
router.refresh();
4948
router.push(ROUTES.login);
5049
}

src/widgets/sub-header/sub-header.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ export function SubHeader({ content = "", className, ...props }: SubHeaderProps)
1717
const router = useRouter();
1818

1919
return (
20-
<header className={cn("w-full md:hidden", className)} {...props}>
20+
<header className={cn("w-full lg:hidden", className)} {...props}>
2121
<div className="h-header flex items-center gap-3 px-2.5">
2222
<Button variant="ghost" size="icon-lg" aria-label="뒤로가기" onClick={() => router.back()}>
2323
<ChevronLeft />

0 commit comments

Comments
 (0)