import { useQuery } from '@tanstack/react-query' import { BarChart, Bar, XAxis, YAxis, CartesianGrid, Tooltip, ResponsiveContainer, Cell } from 'recharts' import { TrendingUp, ReceiptText, Clock, Users, Trophy, XCircle, Package, Sunset, PiggyBank, ShoppingBag } from 'lucide-react' import client from '../../../api/client' import { FilterBar } from '../shared/FilterBar' import { Panel, DataTable, THead, TH, TR, TD, StatusBadge, WaiterAvatar, ChartTooltip } from '../shared/TablePrimitives' import StatCard from '../shared/StatCard' import EmptyState from '../shared/EmptyState' import SkeletonTable from '../shared/SkeletonTable' import ExportButton from '../shared/ExportButton' import { fmtEUR, fmtNum, fmtTime, fmtDateTime } from '../shared/reportDesignTokens' export default function Today() { const { data: bdData, isLoading: bdLoading } = useQuery({ queryKey: ['business-day-current'], queryFn: () => client.get('/api/reports/business-days/current').then(r => r.data), staleTime: 30 * 1000, refetchInterval: 30 * 1000, }) const bd = bdData?.business_day const { data: ordersData, isLoading: ordersLoading } = useQuery({ queryKey: ['today-orders', bd?.id], queryFn: () => client.get('/api/reports/orders/history', { params: { business_day_id: bd.id, page_size: 200 } }).then(r => r.data), enabled: !!bd?.id, staleTime: 30 * 1000, refetchInterval: 30 * 1000, }) const { data: trafficData } = useQuery({ queryKey: ['today-traffic', bd?.id], queryFn: () => client.get('/api/reports/traffic', { params: { business_day_id: bd.id } }).then(r => r.data), enabled: !!bd?.id, staleTime: 30 * 1000, }) if (bdLoading || ordersLoading) { return
} if (!bd) { return (
Live snapshot
) } const orders = Array.isArray(ordersData) ? ordersData : [] const hourlyMap = {} ;(trafficData?.by_hour || []).forEach(h => { hourlyMap[h.hour] = h }) const hours = Array.from({ length: 14 }, (_, i) => 10 + i) const hourlyChart = hours.map(h => ({ hour: `${String(h).padStart(2, '0')}:00`, revenue: hourlyMap[h]?.revenue || 0, })) const nowH = new Date().getHours() return (
Εργάσιμη μέρα ανοιχτή · άνοιξε {fmtTime(bd.opened_at)}
}> Ζωντανή Εικόνα
Έσοδα Μέχρι Τώρα
{fmtEUR(bd.revenue)}
{bd.orders_closed} κλειστές παραγγελίες · {fmtEUR(bd.orders_closed ? bd.revenue / bd.orders_closed : 0)} μέσος όρος
{bd.trackable_profit > 0 && (
Μεικτό Κέρδος
{fmtEUR(bd.trackable_profit)}
{bd.revenue > 0 && (
{((bd.trackable_profit / bd.revenue) * 100).toFixed(0)}% margin {bd.has_gap && ⚠ μερικό}
)}
)}
{bd.top_product && ( )} {bd.total_cost > 0 && ( )} {bd.trackable_profit > 0 && ( )}
Σήμερα}>
'€' + v} /> fmtEUR(v)} />} cursor={{ fill: '#f1f5f9' }} /> {hourlyChart.map((entry, i) => ( nowH ? '#e2e8f0' : '#60a5fa'} /> ))}
}> #ΤραπέζιΆνοιξεΈκλεισε ΕίδηΣύνολοΚέρδοςΚατάσταση {orders.slice(0, 30).map(o => { const activeItems = (o.items || []).filter(i => ['active', 'paid'].includes(i.status)) const total = activeItems.reduce((s, i) => s + i.unit_price * i.quantity, 0) const costedItems = activeItems.filter(i => i.unit_cost != null) const orderProfit = costedItems.length > 0 ? costedItems.reduce((s, i) => s + (i.unit_price - i.unit_cost) * i.quantity, 0) : null const isCancelled = o.status === 'cancelled' return ( #{o.id} {o.table_id} {fmtDateTime(o.opened_at)} {fmtDateTime(o.closed_at)} {(o.items || []).length} {fmtEUR(total)} {orderProfit != null ? = 0 ? 'text-green-700' : 'text-red-600'}>{fmtEUR(orderProfit)} : } ) })}
) }