@@ -3,28 +3,44 @@ import { Button } from "@/shared/components/button";
33import { Input } from "@/shared/components/input" ;
44import { ThumbnailCard } from "@/shared/components/thumbnail-card" ;
55import { CardGridSkeleton } from "@/shared/components/skeletons" ;
6+ import {
7+ Select ,
8+ SelectContent ,
9+ SelectItem ,
10+ SelectTrigger ,
11+ SelectValue ,
12+ } from "@/shared/components/select" ;
613
714import BaseLayout from "@/shared/layouts/base-layout" ;
815import { Link } from "@tanstack/react-router" ;
9- import { Search , SearchX } from "lucide-react" ;
16+ import { ArrowDownUp , Search , SearchX } from "lucide-react" ;
1017import { useCardSets } from "@/domain/cardsets/hooks/use-card-sets" ;
1118import { CardSetFilterSection } from "@/domain/cardsets/components/card-set-filter-section" ;
1219import type { CardSetCategory } from "@/domain/cardsets/types" ;
20+ import type { CardSetSortBy , SortOrder } from "@/shared/apis/card-set" ;
1321import { EmptyState } from "@/shared/components/empty-state" ;
1422import { ErrorBoundary } from "@/shared/components/error-boundary" ;
1523
24+ const SORT_BY_OPTIONS : { value : CardSetSortBy ; label : string } [ ] = [
25+ { value : "id" , label : "최신순" } ,
26+ { value : "like" , label : "좋아요순" } ,
27+ { value : "book" , label : "북마크순" } ,
28+ ] ;
29+
1630interface CardSetGridProps {
1731 keyword ?: string ;
1832 category ?: CardSetCategory ;
33+ sortBy ?: CardSetSortBy ;
34+ order ?: SortOrder ;
1935}
2036
21- const CardSetGrid = ( { keyword, category } : CardSetGridProps ) => {
37+ const CardSetGrid = ( { keyword, category, sortBy , order } : CardSetGridProps ) => {
2238 const {
2339 data : cardsetsData ,
2440 fetchNextPage,
2541 hasNextPage,
2642 isFetchingNextPage,
27- } = useCardSets ( { keyword, category, size : 20 } ) ;
43+ } = useCardSets ( { keyword, category, size : 20 , sortBy , order } ) ;
2844
2945 return (
3046 < >
@@ -77,6 +93,8 @@ const CardSetList = () => {
7793 const [ selectedCategory , setSelectedCategory ] = useState <
7894 CardSetCategory | undefined
7995 > ( undefined ) ;
96+ const [ sortBy , setSortBy ] = useState < CardSetSortBy > ( "id" ) ;
97+ const [ order , setOrder ] = useState < SortOrder > ( "desc" ) ;
8098
8199 useEffect ( ( ) => {
82100 const timer = setTimeout ( ( ) => {
@@ -93,6 +111,10 @@ const CardSetList = () => {
93111 setSelectedCategory ( checked ? category : undefined ) ;
94112 } ;
95113
114+ const toggleOrder = ( ) => {
115+ setOrder ( ( prev ) => ( prev === "desc" ? "asc" : "desc" ) ) ;
116+ } ;
117+
96118 return (
97119 < BaseLayout >
98120 < div className = "space-y-6" >
@@ -115,21 +137,50 @@ const CardSetList = () => {
115137 </ div >
116138 </ div >
117139
118- { /* 필터 영역 */ }
140+ { /* 필터 및 정렬 영역 */ }
119141 < div className = "flex items-center justify-between gap-4" >
120142 < div className = "flex-1" >
121143 < CardSetFilterSection
122144 selectedCategories = { selectedCategory ? [ selectedCategory ] : [ ] }
123145 onCategoryChange = { handleCategoryChange }
124146 />
125147 </ div >
148+ < div className = "flex items-center gap-2 shrink-0" >
149+ < Select
150+ value = { sortBy }
151+ onValueChange = { ( v ) => setSortBy ( v as CardSetSortBy ) }
152+ >
153+ < SelectTrigger size = "sm" >
154+ < SelectValue />
155+ </ SelectTrigger >
156+ < SelectContent >
157+ { SORT_BY_OPTIONS . map ( ( opt ) => (
158+ < SelectItem key = { opt . value } value = { opt . value } >
159+ { opt . label }
160+ </ SelectItem >
161+ ) ) }
162+ </ SelectContent >
163+ </ Select >
164+ < Button
165+ variant = "outline"
166+ size = "sm"
167+ onClick = { toggleOrder }
168+ className = "flex items-center gap-1"
169+ >
170+ < ArrowDownUp className = "w-3.5 h-3.5" />
171+ { order === "desc" ? "내림차순" : "오름차순" }
172+ </ Button >
173+ </ div >
126174 </ div >
175+
127176 < ErrorBoundary >
128177 { /* 카드셋 리스트 - 로딩 중에는 그리드 영역만 스켈레톤으로 대체 */ }
129178 < Suspense fallback = { < CardGridSkeleton /> } >
130179 < CardSetGrid
131180 keyword = { searchKeyword || undefined }
132181 category = { selectedCategory }
182+ sortBy = { sortBy }
183+ order = { order }
133184 />
134185 </ Suspense >
135186 </ ErrorBoundary >
0 commit comments