import React, { useState, useEffect } from 'react'; import { db } from '../../firebase/config'; import { ref, onValue } from 'firebase/database'; import { Chart as ChartJS, CategoryScale, LinearScale, PointElement, LineElement, Title, Tooltip, Legend, BarElement } from 'chart.js'; import { Line, Bar } from 'react-chartjs-2'; import { TrendingUp, Package, Users as UsersIcon, Calendar, DollarSign, Plus, Trash2, Receipt } from 'lucide-react'; import { push, set, remove } from 'firebase/database'; ChartJS.register( CategoryScale, LinearScale, PointElement, LineElement, Title, Tooltip, Legend, BarElement ); export default function Reports() { const [salesData, setSalesData] = useState([0, 0, 0, 0, 0, 0, 0]); const [topProducts, setTopProducts] = useState({ labels: [], data: [] }); const [stats, setStats] = useState({ totalSales: 0, orderCount: 0, avgTicket: 0 }); const [todaySummary, setTodaySummary] = useState({ Efectivo: 0, Tarjeta: 0, QR: 0 }); const [expenses, setExpenses] = useState([]); const [newExpense, setNewExpense] = useState({ desc: '', amount: '', category: 'Insumos' }); useEffect(() => { onValue(ref(db, 'orders'), (snapshot) => { const data = snapshot.val(); if (data) { const orders = Object.values(data); const weeklySales = [0, 0, 0, 0, 0, 0, 0]; const productCounts = {}; const todayPayments = { Efectivo: 0, Tarjeta: 0, QR: 0 }; let total = 0; const todayStr = new Date().toLocaleDateString(); orders.forEach(order => { if (order.status === 'completed') { total += order.total; const orderDay = new Date(order.timestamp); const day = orderDay.getDay(); const index = (day + 6) % 7; weeklySales[index] += order.total; if (orderDay.toLocaleDateString() === todayStr) { todayPayments[order.paymentMethod || 'Efectivo'] += order.total; } order.items.forEach(item => { productCounts[item.name] = (productCounts[item.name] || 0) + item.qty; }); } }); setSalesData(weeklySales); setTodaySummary(todayPayments); // ... (rest of the stats logic continues) setStats({ totalSales: total, orderCount: orders.filter(o => o.status === 'completed').length, avgTicket: total / (orders.filter(o => o.status === 'completed').length || 1) }); const sortedProducts = Object.entries(productCounts) .sort((a,b) => b[1] - a[1]) .slice(0, 5); setTopProducts({ labels: sortedProducts.map(p => p[0]), data: sortedProducts.map(p => p[1]) }); } }); onValue(ref(db, 'expenses'), (snapshot) => { const data = snapshot.val(); setExpenses(data ? Object.keys(data).map(k => ({ id: k, ...data[k] })) : []); }); }, []); const handleAddExpense = async (e) => { e.preventDefault(); if (!newExpense.desc || !newExpense.amount) return; const expRef = push(ref(db, 'expenses')); await set(expRef, { ...newExpense, amount: parseFloat(newExpense.amount), timestamp: Date.now() }); setNewExpense({ desc: '', amount: '', category: 'Insumos' }); }; const lineData = { labels: ['Lun', 'Mar', 'Mié', 'Jue', 'Vie', 'Sáb', 'Dom'], datasets: [{ label: 'Ventas ($)', data: salesData, borderColor: '#FF5A5F', backgroundColor: 'rgba(255, 90, 95, 0.2)', fill: true, tension: 0.4 }] }; const barData = { labels: topProducts.labels, datasets: [{ label: 'Unidades Vendidas', data: topProducts.data, backgroundColor: 'rgba(0, 166, 153, 0.7)', borderRadius: 8 }] }; const options = { responsive: true, maintainAspectRatio: false, plugins: { legend: { labels: { color: '#9595a8' } } }, scales: { x: { ticks: { color: '#9595a8' }, grid: { color: 'rgba(255,255,255,0.05)' } }, y: { ticks: { color: '#9595a8' }, grid: { color: 'rgba(255,255,255,0.05)' } } } }; return (

Análisis de Negocio

Ventas Totales
${stats.totalSales.toFixed(2)}
Pedidos
{stats.orderCount}
Ticket Promedio
${stats.avgTicket.toFixed(2)}

Ventas por Día de la Semana

Productos Estrella

{/* Arqueo de Caja */}

Arqueo de Caja (Hoy)

{Object.entries(todaySummary).map(([method, amount]) => (
{method} ${amount.toFixed(2)}
))}
Corte Total Bruto: ${Object.values(todaySummary).reduce((a,b) => a + b, 0).toFixed(2)}
{/* Registro de Gastos */}

Registro de Egresos

setNewExpense({...newExpense, desc: e.target.value})} style={{...inputStyle, flex: 2}} /> setNewExpense({...newExpense, amount: e.target.value})} style={{...inputStyle, flex: 1}} />
{expenses.length === 0 ?

Sin gastos registrados

: expenses.map(exp => (
{exp.desc} -${exp.amount.toFixed(2)}
)) }
); } const inputStyle = { width: '100%', padding: '0.7rem', borderRadius: '8px', background: 'rgba(255,255,255,0.05)', border: '1px solid var(--border-subtle)', color: '#fff', outline: 'none', fontSize: '0.9rem' };