"use client"; import { useState, useEffect } from "react"; import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card"; import { Button } from "@/components/ui/button"; import { BarChart3, TrendingUp, TrendingDown, Calendar, DollarSign, Users, Clock, Download, Filter, } from "lucide-react"; interface ReportStats { totalRevenue: number; totalBookings: number; totalClients: number; avgOccupancy: number; revenueChange: number; bookingsChange: number; clientsChange: number; occupancyChange: number; } interface DailyRevenue { date: string; bookings: number; sales: number; total: number; } interface TopProduct { name: string; quantity: number; revenue: number; } interface CourtStats { name: string; site: string; bookings: number; revenue: number; occupancy: number; } export default function ReportsPage() { const [dateRange, setDateRange] = useState("month"); const [selectedSite, setSelectedSite] = useState("all"); const [loading, setLoading] = useState(true); const [stats, setStats] = useState({ totalRevenue: 0, totalBookings: 0, totalClients: 0, avgOccupancy: 0, revenueChange: 0, bookingsChange: 0, clientsChange: 0, occupancyChange: 0, }); const [dailyRevenue, setDailyRevenue] = useState([]); const [topProducts, setTopProducts] = useState([]); const [courtStats, setCourtStats] = useState([]); useEffect(() => { fetchReportData(); }, [dateRange, selectedSite]); const fetchReportData = async () => { setLoading(true); // Simulated data - in production, this would come from API await new Promise((resolve) => setTimeout(resolve, 500)); setStats({ totalRevenue: 125840, totalBookings: 342, totalClients: 156, avgOccupancy: 68, revenueChange: 12.5, bookingsChange: 8.3, clientsChange: 15.2, occupancyChange: -2.1, }); setDailyRevenue([ { date: "Lun", bookings: 4200, sales: 1800, total: 6000 }, { date: "Mar", bookings: 3800, sales: 1200, total: 5000 }, { date: "Mié", bookings: 4500, sales: 2100, total: 6600 }, { date: "Jue", bookings: 5200, sales: 1900, total: 7100 }, { date: "Vie", bookings: 6800, sales: 3200, total: 10000 }, { date: "Sáb", bookings: 8500, sales: 4100, total: 12600 }, { date: "Dom", bookings: 7200, sales: 3500, total: 10700 }, ]); setTopProducts([ { name: "Agua", quantity: 245, revenue: 4900 }, { name: "Gatorade", quantity: 180, revenue: 6300 }, { name: "Cerveza", quantity: 156, revenue: 7020 }, { name: "Pelotas HEAD", quantity: 42, revenue: 7560 }, { name: "Raqueta alquiler", quantity: 38, revenue: 3800 }, ]); setCourtStats([ { name: "Cancha 1", site: "Sede Norte", bookings: 68, revenue: 20400, occupancy: 72 }, { name: "Cancha 2", site: "Sede Norte", bookings: 54, revenue: 16200, occupancy: 58 }, { name: "Cancha 1", site: "Sede Centro", bookings: 72, revenue: 21600, occupancy: 76 }, { name: "Cancha 2", site: "Sede Centro", bookings: 61, revenue: 18300, occupancy: 65 }, { name: "Cancha 1", site: "Sede Sur", bookings: 48, revenue: 14400, occupancy: 51 }, { name: "Cancha 2", site: "Sede Sur", bookings: 39, revenue: 11700, occupancy: 42 }, ]); setLoading(false); }; const formatCurrency = (amount: number) => { return new Intl.NumberFormat("es-MX", { style: "currency", currency: "MXN", minimumFractionDigits: 0, }).format(amount); }; const maxRevenue = Math.max(...dailyRevenue.map((d) => d.total)); return (
{/* Header */}

Reportes

Análisis y estadísticas del negocio

{/* KPI Cards */}
{/* Charts Row */}
{/* Revenue Chart */} Ingresos por Día {loading ? (
) : (
{dailyRevenue.map((day) => (
{day.date}
{formatCurrency(day.total)}
))}
Reservas
Ventas
)} {/* Top Products */} Productos Más Vendidos {loading ? (
{[1, 2, 3, 4, 5].map((i) => (
))}
) : (
{topProducts.map((product, index) => (
{index + 1}

{product.name}

{product.quantity} unidades

{formatCurrency(product.revenue)}
))}
)}
{/* Courts Performance */} Rendimiento por Cancha {loading ? (
{[1, 2, 3].map((i) => (
))}
) : (
{courtStats.map((court, index) => ( ))}
Cancha Sede Reservas Ingresos Ocupación
{court.name} {court.site} {court.bookings} {formatCurrency(court.revenue)}
= 70 ? "bg-accent" : court.occupancy >= 50 ? "bg-amber-500" : "bg-red-400" }`} style={{ width: `${court.occupancy}%` }} />
{court.occupancy}%
)} {/* Summary Cards */}
Mejor Día

Sábado

{formatCurrency(12600)} en ingresos promedio

Hora Pico

18:00 - 20:00

85% de ocupación en este horario

Ticket Promedio

{formatCurrency(368)}

Por visita (reserva + consumo)

); } // Stat Card Component function StatCard({ title, value, change, icon: Icon, loading, }: { title: string; value: string; change: number; icon: React.ComponentType<{ className?: string }>; loading: boolean; }) { const isPositive = change >= 0; if (loading) { return (
); } return (
{title}

{value}

{isPositive ? ( ) : ( )} {isPositive ? "+" : ""} {change}% vs período anterior
); }