@@ -27,6 +27,7 @@ import { ProgressStateEnum } from "@/api/models/Progress";
2727import MultiSelectFilterDialog , {
2828 FilterItem ,
2929} from "@/components/MultiSelectFilterDialog" ;
30+ import { Strong , TextLink } from "@/components/tailwind/text" ;
3031
3132const SORT_BY : { label : string ; value : string } [ ] = [
3233 { label : "Title" , value : "sort_title" } ,
@@ -79,8 +80,7 @@ export default function Library() {
7980 const { serverUrl, user } = useAuth ( ) ;
8081
8182 const CONTROL_HEIGHT_CLASS = "min-h-11 sm:min-h-9" ;
82- const INPUT_CONTROL_HEIGHT_CLASS =
83- "[&_input]:min-h-11 sm:[&_input]:min-h-9" ;
83+ const INPUT_CONTROL_HEIGHT_CLASS = "[&_input]:min-h-11 sm:[&_input]:min-h-9" ;
8484
8585 const urlInitializedRef = useRef ( false ) ;
8686 const [ search , setSearch ] = useState ( "" ) ;
@@ -183,12 +183,14 @@ export default function Library() {
183183 // Defer search to avoid spamming requests while user types quickly
184184 const deferredSearch = useDeferredValue ( search ) ;
185185
186- // Convert selected game type FilterItems to GamevaultGameTypeEnum values for API
186+ // Convert selected type FilterItems to GamevaultGameTypeEnum values for API
187187 const gameTypeValues = useMemo ( ( ) => {
188188 return selectedGameTypes
189189 . map ( ( item ) => String ( item . id ) )
190190 . filter ( ( v ) : v is GamevaultGameTypeEnum =>
191- Object . values ( GamevaultGameTypeEnum ) . includes ( v as GamevaultGameTypeEnum ) ,
191+ Object . values ( GamevaultGameTypeEnum ) . includes (
192+ v as GamevaultGameTypeEnum ,
193+ ) ,
192194 ) ;
193195 } , [ selectedGameTypes ] ) ;
194196
@@ -265,7 +267,9 @@ export default function Library() {
265267
266268 const isGameType = useCallback (
267269 ( value : string ) : value is GamevaultGameTypeEnum =>
268- Object . values ( GamevaultGameTypeEnum ) . includes ( value as GamevaultGameTypeEnum ) ,
270+ Object . values ( GamevaultGameTypeEnum ) . includes (
271+ value as GamevaultGameTypeEnum ,
272+ ) ,
269273 [ ] ,
270274 ) ;
271275
@@ -277,7 +281,10 @@ export default function Library() {
277281
278282 const isBookmark = useCallback (
279283 ( value : string ) : value is BookmarkFilter | "1" =>
280- value === "all" || value === "mine" || value === "others" || value === "1" ,
284+ value === "all" ||
285+ value === "mine" ||
286+ value === "others" ||
287+ value === "1" ,
281288 [ ] ,
282289 ) ;
283290
@@ -370,8 +377,16 @@ export default function Library() {
370377 . map ( ( i ) => String ( i . id ) )
371378 . filter ( ( v ) : v is GamevaultGameTypeEnum => isGameType ( v ) ) ,
372379 ) ;
373- setParamValues ( params , "tags" , selectedTags . map ( ( t ) => t . name ) ) ;
374- setParamValues ( params , "genres" , selectedGenres . map ( ( g ) => g . name ) ) ;
380+ setParamValues (
381+ params ,
382+ "tags" ,
383+ selectedTags . map ( ( t ) => t . name ) ,
384+ ) ;
385+ setParamValues (
386+ params ,
387+ "genres" ,
388+ selectedGenres . map ( ( g ) => g . name ) ,
389+ ) ;
375390 setParamValues (
376391 params ,
377392 "developers" ,
@@ -531,7 +546,7 @@ export default function Library() {
531546
532547 { /* Section 1: Multi-Select Filter Buttons */ }
533548 < div className = "grid grid-cols-2 sm:grid-cols-3 lg:grid-cols-5 gap-3" >
534- { /* Game Types */ }
549+ { /* Types */ }
535550 < div className = "col-span-1" >
536551 < label className = "block text-xs font-medium text-fg-muted mb-1" >
537552 Type
@@ -836,7 +851,7 @@ export default function Library() {
836851 </ div >
837852 </ div >
838853 ) }
839- < div className = "flex-1 overflow-y-scroll overflow-x-hidden" >
854+ < div className = "flex-1 overflow-y-scroll overflow-x-hidden text-center " >
840855 { ! serverUrl && (
841856 < div className = "p-8 text-sm text-fg-muted" >
842857 Connect to a server to load games.
@@ -851,7 +866,23 @@ export default function Library() {
851866 < div className = "p-8 text-sm text-fg-muted" > Loading games…</ div >
852867 ) }
853868 { serverUrl && ! loading && games . length === 0 && ! error && (
854- < div className = "p-8 text-sm text-fg-muted" > No games found.</ div >
869+ < div className = "p-8 text-sm text-fg-muted" >
870+ No games found.
871+ { ( search . trim ( ) || hasActiveFilters ) && (
872+ < div className = "mt-2" >
873+ < TextLink
874+ href = "#"
875+ onClick = { ( ) => {
876+ clearAllFilters ( ) ;
877+ setShowFilters ( false ) ;
878+ setSearch ( "" ) ;
879+ } }
880+ >
881+ < Strong > Try clearing all filters and search</ Strong >
882+ </ TextLink >
883+ </ div >
884+ ) }
885+ </ div >
855886 ) }
856887 < div className = "grid gap-4 grid-cols-[repeat(auto-fill,minmax(140px,1fr))] pb-8" >
857888 { games . map ( ( g ) => (
@@ -870,7 +901,7 @@ export default function Library() {
870901 < MultiSelectFilterDialog
871902 open = { gameTypesDialogOpen }
872903 onClose = { ( ) => setGameTypesDialogOpen ( false ) }
873- title = "Game Types"
904+ title = "Types"
874905 staticItems = { GAME_TYPE_FILTER_ITEMS }
875906 selectedItems = { selectedGameTypes }
876907 onSelectionChange = { setSelectedGameTypes }
0 commit comments