import React, { useState, useMemo } from 'react'; import { Media, MediaCategory } from '@/types'; import { cn } from '@/lib/utils'; import { motion } from 'motion/react'; import { Star, Heart, Gamepad2, Film, Tv, Eye, Music, BookOpen, Monitor, ArrowUpDown, ArrowUp, ArrowDown } from 'lucide-react'; import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow, } from '@/components/ui/table'; interface MediaTableProps { mediaList: Media[]; onMediaClick: (media: Media) => void; onFavoriteToggle?: (media: Media) => void; favoriteIds?: Set; } type SortField = 'title' | 'category' | 'genre' | 'rating' | 'year' | 'plays'; type SortDirection = 'asc' | 'desc'; const categoryConfig: Record = { 'Anime': { label: 'ANIME', color: 'text-purple-400', bgColor: 'bg-purple-500/20', icon: null }, 'Movies': { label: 'MOVIE', color: 'text-blue-400', bgColor: 'bg-blue-500/20', icon: Film }, 'TV Series': { label: 'SERIES', color: 'text-green-400', bgColor: 'bg-green-500/20', icon: Tv }, 'Music': { label: 'MUSIC', color: 'text-pink-400', bgColor: 'bg-pink-500/20', icon: Music }, 'Books': { label: 'BOOK', color: 'text-yellow-400', bgColor: 'bg-yellow-500/20', icon: BookOpen }, 'Games': { label: 'GAME', color: 'text-indigo-400', bgColor: 'bg-indigo-500/20', icon: Gamepad2 }, 'Consoles': { label: 'CONSOLE', color: 'text-orange-400', bgColor: 'bg-orange-500/20', icon: Monitor }, 'Adult': { label: 'ADULT', color: 'text-rose-400', bgColor: 'bg-rose-500/20', icon: Eye }, }; export default function MediaTable({ mediaList, onMediaClick, onFavoriteToggle, favoriteIds = new Set() }: MediaTableProps) { const [sortField, setSortField] = useState('title'); const [sortDirection, setSortDirection] = useState('asc'); const handleSort = (field: SortField) => { if (sortField === field) { setSortDirection(prev => prev === 'asc' ? 'desc' : 'asc'); } else { setSortField(field); setSortDirection('asc'); } }; const sortedMedia = useMemo(() => { const sorted = [...mediaList]; sorted.sort((a, b) => { let comparison = 0; switch (sortField) { case 'title': comparison = a.title.localeCompare(b.title); break; case 'category': comparison = a.category.localeCompare(b.category); break; case 'genre': const genreA = a.genres?.[0] || ''; const genreB = b.genres?.[0] || ''; comparison = genreA.localeCompare(genreB); break; case 'rating': comparison = (b.rating || 0) - (a.rating || 0); break; case 'year': comparison = b.year.localeCompare(a.year); break; case 'plays': comparison = (b.playCount || 0) - (a.playCount || 0); break; } return sortDirection === 'asc' ? comparison : -comparison; }); return sorted; }, [mediaList, sortField, sortDirection]); const SortIcon = ({ field }: { field: SortField }) => { if (sortField !== field) { return ; } return sortDirection === 'asc' ? : ; }; const handleFavoriteClick = (e: React.MouseEvent, media: Media) => { e.stopPropagation(); onFavoriteToggle?.(media); }; return ( handleSort('title')} >
Title
handleSort('category')} >
Type
handleSort('genre')} >
Genre
handleSort('rating')} >
Rating
handleSort('year')} >
Year
handleSort('plays')} >
Plays
{sortedMedia.map((media) => { const categoryInfo = categoryConfig[media.category]; const CategoryIcon = categoryInfo?.icon; const isFavorite = favoriteIds.has(media.id); return ( onMediaClick(media)} > {/* Title Cell with Poster */}
{media.title}
{media.title}
{/* Type Badge */} {CategoryIcon && } {categoryInfo.label} {/* Genre */} {media.genres?.join(', ') || '-'} {/* Rating */}
{media.rating?.toFixed(1) || '-'}
{/* Year */} {media.year} {/* Plays */} {media.playCount || 0} {/* Favorite */}
); })}
); }