import { useState } from 'react' import React from 'react' import { motion, AnimatePresence } from 'framer-motion' import { useQuery } from '@tanstack/react-query' import { ComputerDesktopIcon as GamepadIcon, MagnifyingGlassIcon, AdjustmentsHorizontalIcon, TrophyIcon, PlayIcon, CheckCircleIcon, ChevronDownIcon, ListBulletIcon, Squares2X2Icon, PhotoIcon } from '@heroicons/react/24/outline' import GameCard, { GameItem } from '../components/GameCard' import { gamesApi } from '../services/api' type ViewMode = 'grid' | 'list' | 'covers' type SortOption = 'title_asc' | 'title_desc' | 'year_asc' | 'year_desc' | 'playtime_desc' | 'rating_desc' | 'last_played_desc' const sortOptions: { value: SortOption; label: string }[] = [ { value: 'title_asc', label: 'Title (A-Z)' }, { value: 'title_desc', label: 'Title (Z-A)' }, { value: 'year_asc', label: 'Release Year (Oldest First)' }, { value: 'year_desc', label: 'Release Year (Newest First)' }, { value: 'playtime_desc', label: 'Most Played' }, { value: 'rating_desc', label: 'Highest Rated' }, { value: 'last_played_desc', label: 'Last Played' } ] const categoryIcons = { BEATEN: TrophyIcon, PLAYING: PlayIcon, COMPLETED: CheckCircleIcon, UNPLAYED: GamepadIcon } const categoryColors = { BEATEN: 'from-yellow-500 to-amber-600', PLAYING: 'from-blue-500 to-blue-600', COMPLETED: 'from-green-500 to-green-600', UNPLAYED: 'from-gray-500 to-gray-600' } export default function GamesPage() { const [searchTerm, setSearchTerm] = useState('') const [selectedCategory, setSelectedCategory] = useState(null) const [viewMode, setViewMode] = useState('grid') const [sortBy, setSortBy] = useState('title_asc') const [showFilters, setShowFilters] = useState(false) const [expandedCategories, setExpandedCategories] = useState>(new Set(['BEATEN', 'PLAYING'])) const { data: gamesData, isLoading, error } = useQuery({ queryKey: ['games', searchTerm, sortBy], queryFn: () => gamesApi.getAll({ search: searchTerm, sort: sortBy }), enabled: !selectedCategory }) const { data: categoryData, isLoading: isLoadingCategory } = useQuery({ queryKey: ['games', 'category', selectedCategory, searchTerm, sortBy], queryFn: () => gamesApi.getByCategory(selectedCategory!, { search: searchTerm, sort: sortBy }), enabled: !!selectedCategory }) const toggleCategory = (category: string) => { setExpandedCategories(prev => { const newSet = new Set(prev) if (newSet.has(category)) { newSet.delete(category) } else { newSet.add(category) } return newSet }) } const handleSearch = (e: React.FormEvent) => { e.preventDefault() } const clearFilters = () => { setSearchTerm('') setSelectedCategory(null) setSortBy('title_asc') } const activeFiltersCount = [ searchTerm, selectedCategory, sortBy !== 'title_asc' ].filter(Boolean).length if (isLoading || isLoadingCategory) { return (
Loading games...
) } if (error) { return (

Error Loading Games

Failed to load your game library. Please try again later.

window.location.reload()} className="btn btn-primary" whileHover={{ scale: 1.05 }} whileTap={{ scale: 0.95 }} > Try Again
) } const categories = selectedCategory ? [{ name: selectedCategory, count: categoryData?.count || 0, games: categoryData?.games || [] }] : gamesData?.data || [] return (
{/* Header */}

Games Library

{/* Search and Filters */}
setSearchTerm(e.target.value)} className="w-full pl-10 pr-4 py-2 border border-gray-300 rounded-xl focus:ring-2 focus:ring-green-500 focus:border-transparent" />
setShowFilters(!showFilters)} className={`px-4 py-2 rounded-xl border transition-all duration-200 flex items-center gap-2 ${ activeFiltersCount > 0 ? 'border-green-500 bg-green-50 text-green-700' : 'border-gray-300 hover:border-gray-400' }`} whileHover={{ scale: 1.02 }} whileTap={{ scale: 0.98 }} > Filters {activeFiltersCount > 0 && ( {activeFiltersCount} )}
{/* Filters Panel */} {showFilters && (
{/* Sort */}
{/* View Mode */}
{[ { mode: 'grid' as ViewMode, icon: Squares2X2Icon, label: 'Grid' }, { mode: 'list' as ViewMode, icon: ListBulletIcon, label: 'List' }, { mode: 'covers' as ViewMode, icon: PhotoIcon, label: 'Covers' } ].map(({ mode, icon: Icon, label }) => ( setViewMode(mode)} className={`flex-1 px-3 py-2 rounded-lg border transition-all duration-200 flex items-center justify-center gap-1 ${ viewMode === mode ? 'border-green-500 bg-green-50 text-green-700' : 'border-gray-300 hover:border-gray-400' }`} whileHover={{ scale: 1.02 }} whileTap={{ scale: 0.98 }} > {label} ))}
{/* Clear Filters */}
Clear All Filters
)}
{/* Categories and Games */}
{/* Category Navigation */} {!selectedCategory && (
{categories.map((category: any) => { const Icon = categoryIcons[category.name as keyof typeof categoryIcons] return ( setSelectedCategory(category.name)} className="group relative px-6 py-3 bg-white rounded-xl shadow-sm border border-gray-200 hover:shadow-md transition-all duration-200" whileHover={{ scale: 1.02, y: -2 }} whileTap={{ scale: 0.98 }} >
{category.name}
{category.count} games
) })}
)} {/* Back to Categories */} {selectedCategory && ( setSelectedCategory(null)} className="flex items-center gap-2 px-4 py-2 bg-white rounded-lg border border-gray-300 hover:bg-gray-50 transition-all duration-200" whileHover={{ scale: 1.02 }} whileTap={{ scale: 0.98 }} > Back to Categories )} {/* Games List */}
{categories.map((category: any) => ( {/* Category Header */}
{React.createElement(categoryIcons[category.name as keyof typeof categoryIcons], { className: "w-5 h-5 text-white" })}

{category.name} ({category.count})

{!selectedCategory && ( toggleCategory(category.name)} className="flex items-center gap-2 px-3 py-1 text-sm text-gray-600 hover:text-gray-900 transition-colors" whileHover={{ scale: 1.02 }} whileTap={{ scale: 0.98 }} > {expandedCategories.has(category.name) ? 'Collapse' : 'Expand'} )}
{/* Games Grid/List */} {(expandedCategories.has(category.name) || selectedCategory) && ( {category.games.length === 0 ? (

No games found in this category

) : (
{category.games.map((game: GameItem, index: number) => ( ))}
)}
)}
))}
) }