import { apiClient } from '@/lib/api-client'; import { useQuery } from '@tanstack/react-query'; import { Link, useLocation } from '@tanstack/react-router'; import { Building2, CalendarDays, ChevronDown, ChevronRight, Crosshair, Globe, Users, } from 'lucide-react'; import { Fragment, useState } from 'react'; import { AdminLayout } from './admin-layout'; function countryFlag(countryCode: string): string { if (countryCode === 'LOCAL' || countryCode === 'XX') return ''; const codePoints = countryCode .toUpperCase() .split('') .map((c) => 0x1f1e6 + c.charCodeAt(0) - 65); return String.fromCodePoint(...codePoints); } export function AdminPage() { const location = useLocation(); const [expandedCountry, setExpandedCountry] = useState(null); const complexesQuery = useQuery({ queryKey: ['admin-complexes'], queryFn: () => apiClient.admin.listComplexes(), }); const usersQuery = useQuery({ queryKey: ['admin-users'], queryFn: () => apiClient.admin.listUsers(), }); const geoQuery = useQuery({ queryKey: ['admin-geo-stats'], queryFn: () => apiClient.admin.getGeoStats(), }); const stats = { totalComplexes: complexesQuery.data?.length ?? 0, totalUsers: usersQuery.data?.length ?? 0, totalCourts: complexesQuery.data?.reduce((sum, c) => sum + c.courtCount, 0) ?? 0, totalBookings: complexesQuery.data?.reduce((sum, c) => sum + Math.round(c.avgBookingsPerDay * 30), 0) ?? 0, }; const cards = [ { label: 'Complejos', value: stats.totalComplexes, icon: Building2, color: 'text-blue-600', bg: 'bg-blue-100 dark:bg-blue-900/30', }, { label: 'Usuarios', value: stats.totalUsers, icon: Users, color: 'text-emerald-600', bg: 'bg-emerald-100 dark:bg-emerald-900/30', }, { label: 'Canchas', value: stats.totalCourts, icon: Crosshair, color: 'text-purple-600', bg: 'bg-purple-100 dark:bg-purple-900/30', }, { label: 'Reservas (30d)', value: stats.totalBookings.toLocaleString(), icon: CalendarDays, color: 'text-amber-600', bg: 'bg-amber-100 dark:bg-amber-900/30', }, ]; return (

Panel de Administración

Gestioná complejos, planes y usuarios de Playzer.

{cards.map((card) => { const Icon = card.icon; return (

{card.label}

{card.value}

); })}

Acceso rápido

Complejos

{stats.totalComplexes} complejos registrados

Planes

Administrar suscripciones

Usuarios

{stats.totalUsers} usuarios registrados

Usuarios por país / ciudad

{geoQuery.isLoading &&

Cargando...

} {geoQuery.data && geoQuery.data.countries.length === 0 && (

Aún no hay datos de geolocalización. Aparecerán a medida que los usuarios inicien sesión.

)} {geoQuery.data && geoQuery.data.countries.length > 0 && (
{geoQuery.data.countries.map((country) => { const isExpanded = expandedCountry === country.countryCode; const flag = countryFlag(country.countryCode); return ( setExpandedCountry(isExpanded ? null : country.countryCode)} onKeyDown={(e) => { if (e.key === 'Enter' || e.key === ' ') { e.preventDefault(); setExpandedCountry(isExpanded ? null : country.countryCode); } }} tabIndex={0} role="button" > {isExpanded && ( )} ); })}
País Usuarios
{country.cities.length > 1 || country.cities[0]?.city !== country.country ? ( ) : ( )} {flag} {country.country} {country.totalUsers}
{country.cities.map((city) => ( ))}
{city.city} {city.userCount}
{geoQuery.data.totalUniqueCountries}{' '} {geoQuery.data.totalUniqueCountries === 1 ? 'país' : 'países'} · solo sesiones activas con geolocalización resuelta
)}
); }