import { useState } from 'react' import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query' import { toast } from 'sonner' import { roomsApi, type RoomDto } from '@/api/rooms' import type { AxiosError } from 'axios' import { Button } from '@/components/ui/button' import { Input } from '@/components/ui/input' import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '@/components/ui/card' import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow, } from '@/components/ui/table' import { AlertDialog, AlertDialogAction, AlertDialogCancel, AlertDialogContent, AlertDialogDescription, AlertDialogFooter, AlertDialogHeader, AlertDialogTitle, } from '@/components/ui/alert-dialog' import { Badge } from '@/components/ui/badge' import { Search, Plus, Trash2, ChevronLeft, ChevronRight, ExternalLink } from 'lucide-react' import { CreateAdminRoomDialog } from '@/components/CreateAdminRoomDialog' export default function RoomsPage() { const queryClient = useQueryClient() const [page, setPage] = useState(1) const [search, setSearch] = useState('') const [statusFilter, setStatusFilter] = useState<'WAITING' | 'PLAYING' | 'FINISHED' | ''>('') const [createDialogOpen, setCreateDialogOpen] = useState(false) const [isDeleteDialogOpen, setIsDeleteDialogOpen] = useState(false) const [roomToDelete, setRoomToDelete] = useState(null) const limit = 20 // Fetch rooms const { data, isLoading, error } = useQuery({ queryKey: ['admin', 'rooms', page, statusFilter], queryFn: () => roomsApi.getRooms({ page, limit, status: statusFilter || undefined, }), }) // Delete mutation const deleteMutation = useMutation({ mutationFn: (roomId: string) => roomsApi.deleteRoom(roomId), onSuccess: () => { queryClient.invalidateQueries({ queryKey: ['admin', 'rooms'] }) toast.success('Room deleted successfully') setIsDeleteDialogOpen(false) setRoomToDelete(null) }, onError: (error: unknown) => { const axiosError = error as AxiosError<{ message?: string }> toast.error(axiosError.response?.data?.message || 'Failed to delete room') }, }) const handleDelete = (room: RoomDto) => { setRoomToDelete(room) setIsDeleteDialogOpen(true) } const confirmDelete = () => { if (roomToDelete?.id) { deleteMutation.mutate(roomToDelete.id) } } const getStatusBadge = (status: string) => { switch (status) { case 'WAITING': return Waiting case 'PLAYING': return Playing case 'FINISHED': return Finished default: return {status} } } const filteredRooms = data?.rooms.filter(room => search === '' || room.code.toLowerCase().includes(search.toLowerCase()) || room.host.name?.toLowerCase().includes(search.toLowerCase()) || room.host.email?.toLowerCase().includes(search.toLowerCase()) ) || [] if (error) { return (

Rooms Management

Error loading rooms

Failed to load rooms. Please try again later.

) } return (

Rooms Management

View and manage game rooms

{/* Filters */}
setSearch(e.target.value)} className="max-w-sm" />
{/* Rooms Table */} All Rooms ({data?.total || 0}) Manage game rooms and their settings {isLoading ? (
Loading rooms...
) : ( <> Code Status Host Theme Pack Players Created Active Period Actions {filteredRooms.length === 0 ? ( No rooms found ) : ( filteredRooms.map((room) => ( {room.code} {room.isAdminRoom && ( Admin )} {getStatusBadge(room.status)}
{room.host.name || 'No name'}
{room.host.email && (
{room.host.email}
)}
{room.theme ? ( {room.theme.name} ) : ( Default )} {room.questionPack ? ( {room.questionPack.name} ) : ( - )} {room._count?.participants || 0} / {room.maxPlayers} {new Date(room.createdAt).toLocaleDateString()} {room.activeFrom && room.activeTo ? (
{new Date(room.activeFrom).toLocaleDateString()}
to {new Date(room.activeTo).toLocaleDateString()}
) : ( - )}
)) )}
{/* Pagination */} {data && data.totalPages > 1 && (
Showing {((page - 1) * limit) + 1} to {Math.min(page * limit, data.total)} of {data.total} rooms
Page {page} of {data.totalPages}
)} )}
{/* Create Room Dialog */} {createDialogOpen && ( setCreateDialogOpen(false)} onSuccess={() => { queryClient.invalidateQueries({ queryKey: ['admin', 'rooms'] }) setCreateDialogOpen(false) }} /> )} {/* Delete Confirmation Dialog */} Delete Room Are you sure you want to delete the room "{roomToDelete?.code}"? This action cannot be undone. Cancel {deleteMutation.isPending ? 'Deleting...' : 'Delete'}
) }