-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
f412746
commit a8a649f
Showing
7 changed files
with
252 additions
and
0 deletions.
There are no files selected for viewing
25 changes: 25 additions & 0 deletions
25
src/app/(home)/search/_components/SearchFestivalList/SearchFestivalFallback.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
import { RegistorButton } from "@/components/core/Button"; | ||
import { ErrorIcon } from "@/components/icons"; | ||
|
||
const SearchFestivalFallback = () => { | ||
return ( | ||
<div className="flex flex-col items-center gap-[16px]"> | ||
<ErrorIcon width={56} height={56} className="text-gray-scale-300" /> | ||
<div className="flex w-full flex-col items-center gap-[6px]"> | ||
<h1 className="text-body1-medium text-gray-scale-900"> | ||
검색 결과가 없어요 | ||
</h1> | ||
<span className="text-caption1-regular text-gray-scale-600"> | ||
원하는 페스티벌이 없다면 피에스타에 등록해주세요. | ||
</span> | ||
<RegistorButton | ||
label="페스티벌 등록하기" | ||
href="/festival/new" | ||
className={"w-auto"} | ||
/> | ||
</div> | ||
</div> | ||
); | ||
}; | ||
|
||
export default SearchFestivalFallback; |
57 changes: 57 additions & 0 deletions
57
src/app/(home)/search/_components/SearchFestivalList/index.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,57 @@ | ||
"use client"; | ||
|
||
import isEmpty from "lodash/isEmpty"; | ||
import isString from "lodash/isString"; | ||
import { useQueryState } from "nuqs"; | ||
import { useEffect } from "react"; | ||
|
||
import FestivalSearchTile from "@/components/core/List/FestivalSearchTile/FestivalSearchTile"; | ||
import { ProgressCircle } from "@/components/core/Progress"; | ||
import { useGetSearchFestival } from "@/hooks/useGetSearchFestival"; | ||
import { useSearchHistory } from "@/hooks/useSearchHistory"; | ||
|
||
import SearchFestivalFallback from "./SearchFestivalFallback"; | ||
|
||
const SearchFestival = () => { | ||
const [query, setQuery] = useQueryState("query", { shallow: true }); | ||
const { data, isLoading } = useGetSearchFestival(query ?? "", 300); | ||
const { set } = useSearchHistory(); | ||
|
||
useEffect(() => { | ||
if (isString(query) && !isEmpty(query)) { | ||
set(query); | ||
} | ||
}, [data]); | ||
|
||
if (isLoading) { | ||
return ( | ||
<div className="flex h-[400px] w-full items-center justify-center"> | ||
<ProgressCircle className="size-[100px]" /> | ||
</div> | ||
); | ||
} | ||
|
||
if (query?.length === 0) { | ||
return null; | ||
} | ||
|
||
if (data?.length === 0) { | ||
return ( | ||
<div className="flex h-[400px] w-full items-center justify-center"> | ||
<SearchFestivalFallback /> | ||
</div> | ||
); | ||
} | ||
|
||
return ( | ||
<div className="flex w-full flex-col gap-[4px] rounded-[8px] p-[12px]"> | ||
{data?.map((festival) => { | ||
return ( | ||
<FestivalSearchTile key={festival.festivalId} festival={festival} /> | ||
); | ||
})} | ||
</div> | ||
); | ||
}; | ||
|
||
export default SearchFestival; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,49 @@ | ||
"use client"; | ||
|
||
import { useQueryState } from "nuqs"; | ||
|
||
import { SearchHistoryChip } from "@/components/core/Chip"; | ||
import { useSearchHistory } from "@/hooks/useSearchHistory"; | ||
import { useSwipingContainer } from "@/hooks/useSwipingContainer"; | ||
|
||
const SearchHistory = () => { | ||
const [query, setQuery] = useQueryState("query", { shallow: true }); | ||
const { containerRef, mouseDownHandler } = useSwipingContainer(); | ||
const { get, set, del, reset } = useSearchHistory(); | ||
|
||
if (query) { | ||
return null; | ||
} | ||
|
||
return ( | ||
<div className="flex h-auto w-full flex-col gap-[16px] py-[20px]"> | ||
<div className="flex w-full justify-between"> | ||
<span className="text-subtitle-semi text-gray-scale-900"> | ||
최근 검색한 페스티벌 | ||
</span> | ||
<button | ||
type="button" | ||
className="text-caption1-medium text-gray-scale-600" | ||
onClick={reset} | ||
> | ||
전체 삭제 | ||
</button> | ||
</div> | ||
<div | ||
ref={containerRef} | ||
onMouseDown={mouseDownHandler} | ||
className="flex min-h-[32px] w-full gap-[8px] overflow-hidden" | ||
> | ||
{get.map((history: string) => ( | ||
<SearchHistoryChip | ||
key={history} | ||
text={history} | ||
onClick={() => del(history)} | ||
/> | ||
))} | ||
</div> | ||
</div> | ||
); | ||
}; | ||
|
||
export default SearchHistory; |
23 changes: 23 additions & 0 deletions
23
src/app/(home)/search/_components/TrendingFestival/TrendingFestivalSkeleton.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
const TrendingFestivalSkeleton = () => { | ||
return ( | ||
<div role="status" className="animate-pulse"> | ||
<div className="flex h-full w-full flex-col gap-[16px]"> | ||
<div className="h-[19px] w-[150px] rounded-md bg-gray-scale-200" /> | ||
|
||
<ul className="flex w-full flex-col bg-gray-scale-50 p-[12px]"> | ||
{Array.from({ length: 5 }, (_, idx) => ( | ||
<li | ||
key={idx} | ||
className="flex h-auto w-full items-center gap-[12px] rounded-[8px] py-[16px]" | ||
> | ||
<div className="h-[17px] w-full rounded-md bg-gray-300"></div> | ||
</li> | ||
))} | ||
</ul> | ||
</div> | ||
<span className="sr-only">Loading...</span> | ||
</div> | ||
); | ||
}; | ||
|
||
export default TrendingFestivalSkeleton; |
60 changes: 60 additions & 0 deletions
60
src/app/(home)/search/_components/TrendingFestival/index.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,60 @@ | ||
"use client"; | ||
|
||
import { useSuspenseQuery } from "@tanstack/react-query"; | ||
import Link from "next/link"; | ||
import { useQueryState } from "nuqs"; | ||
|
||
import { getTrendingFestival } from "@/apis/festivals/trendingFestival/trendingFestival"; | ||
import { TrendingFestivalKeys } from "@/apis/festivals/trendingFestival/trendingFestivalKeys"; | ||
import { cn } from "@/utils"; | ||
|
||
const TrendingFestival = () => { | ||
const { data } = useSuspenseQuery({ | ||
queryKey: TrendingFestivalKeys.all, | ||
queryFn: getTrendingFestival, | ||
}); | ||
|
||
const [query, setQuery] = useQueryState("query", { shallow: true }); | ||
|
||
if (query) { | ||
return null; | ||
} | ||
|
||
return ( | ||
<div className="flex h-full w-full flex-col gap-[16px]"> | ||
<div className="flex w-full justify-start gap-[4px]"> | ||
<span className="text-subtitle-semi text-gray-scale-900"> | ||
실시간 급상승 페스티벌 | ||
</span> | ||
<span className="text-subtitle-semi text-primary-01">TOP 5</span> | ||
</div> | ||
|
||
<div className="flex w-full flex-col rounded-[8px] bg-gray-scale-50 p-[12px]"> | ||
{data.map((festival, idx, arr) => { | ||
return ( | ||
<Link | ||
href={`/festival/${festival.festivalId}`} | ||
key={festival.festivalId} | ||
className={cn( | ||
"w-full", | ||
idx + 1 !== arr.length && | ||
" border-b-[1px] border-gray-scale-200", | ||
)} | ||
> | ||
<div className="flex h-auto w-full items-center gap-[12px] rounded-[8px] py-[16px]"> | ||
<div className="text-subtitle-semi text-primary-01"> | ||
{idx + 1} | ||
</div> | ||
<div className="line-clamp-1 max-w-[90%] text-ellipsis whitespace-nowrap text-body2-medium text-gray-scale-600"> | ||
{festival.name} | ||
</div> | ||
</div> | ||
</Link> | ||
); | ||
})} | ||
</div> | ||
</div> | ||
); | ||
}; | ||
|
||
export default TrendingFestival; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
import { Suspense } from "react"; | ||
|
||
import { SearchHeader } from "@/layout/Mobile/MobileHeader"; | ||
|
||
import SearchView from "./view"; | ||
|
||
export default async function SearchPage() { | ||
return ( | ||
<Suspense> | ||
<div className="mb-[60px] mt-[44px]"> | ||
<SearchHeader /> | ||
<SearchView /> | ||
</div> | ||
</Suspense> | ||
); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
import { Suspense } from "react"; | ||
|
||
import SearchFestival from "./_components/SearchFestivalList"; | ||
import SearchHistory from "./_components/SearchHistory"; | ||
import TrendingFestival from "./_components/TrendingFestival"; | ||
import TrendingFestivalSkeleton from "./_components/TrendingFestival/TrendingFestivalSkeleton"; | ||
|
||
const SearchView = () => { | ||
return ( | ||
<main className="mt-[60px] flex h-full w-full flex-col gap-4 px-[16px]"> | ||
<SearchHistory /> | ||
|
||
<Suspense fallback={<TrendingFestivalSkeleton />}> | ||
<TrendingFestival /> | ||
</Suspense> | ||
|
||
<SearchFestival /> | ||
</main> | ||
); | ||
}; | ||
|
||
export default SearchView; |