'use client'; import { useState, useEffect } from 'react'; import { api } from '@/lib/api-client'; interface Stats { ordersToday: number; revenueTodayCents: number; revenueTodayFormatted: string; ordersByState: Record; outOfStockVariants: number; totalActiveProducts: number; newCustomersThisMonth: number; generatedAt: string; } function formatCents(cents: number): string { return `€${(cents / 100).toFixed(2)}`; } const STATE_LABELS: Record = { PENDING: 'Pendientes', AWAITING_PAYMENT: 'Esperando pago', PAID: 'Pagados', PROCESSING: 'Procesando', SHIPPED: 'Enviados', DELIVERED: 'Entregados', CANCELLED: 'Cancelados', REFUNDED: 'Reembolsados', PARTIALLY_REFUNDED: 'Reembolso parcial', }; const STATE_COLORS: Record = { PENDING: 'bg-amber-100 text-amber-700', AWAITING_PAYMENT: 'bg-orange-100 text-orange-700', PAID: 'bg-green-100 text-green-700', PROCESSING: 'bg-blue-100 text-blue-700', SHIPPED: 'bg-indigo-100 text-indigo-700', DELIVERED: 'bg-emerald-100 text-emerald-700', CANCELLED: 'bg-gray-100 text-gray-600', REFUNDED: 'bg-red-100 text-red-700', PARTIALLY_REFUNDED: 'bg-pink-100 text-pink-700', }; function KPICard({ label, value, sub, icon, trend, }: { label: string; value: string; sub?: string; icon: string; trend?: 'up' | 'down' | 'neutral'; }) { return (

{label}

{value}

{sub &&

{sub}

}
{icon}
); } function OrderStateBar({ state, count, total }: { state: string; count: number; total: number }) { const pct = total > 0 ? (count / total) * 100 : 0; const label = STATE_LABELS[state] ?? state; const color = STATE_COLORS[state] ?? 'bg-gray-100 text-gray-700'; return (
{label}
{count}
); } export default function DashboardPage() { const [stats, setStats] = useState(null); const [loading, setLoading] = useState(true); const [error, setError] = useState(''); useEffect(() => { api .get('/api/admin/stats') .then(setStats) .catch(() => setError('No se pudieron cargar las estadísticas')) .finally(() => setLoading(false)); }, []); if (loading) { return (
{[...Array(4)].map((_, i) => (
))}
{[...Array(5)].map((_, i) => (
))}
); } if (error || !stats) { return (
{error ?? 'Error desconocido'}
); } const totalOrders = Object.values(stats.ordersByState).reduce((a, b) => a + b, 0); const ordersByStateSorted = Object.entries(stats.ordersByState).sort( ([, a], [, b]) => b - a, ); return (
{/* KPI Cards */}
{/* Secondary KPIs */}
0 ? `${stats.outOfStockVariants} sin stock` : 'Sin alertas' } sub={stats.outOfStockVariants > 0 ? 'Revisar inventario' : 'Todo OK'} icon={stats.outOfStockVariants > 0 ? '🔴' : '✅'} />
{/* Orders by state */}

Pedidos por estado

{totalOrders} total
{totalOrders === 0 ? (

📋

No hay pedidos en el sistema

) : (
{ordersByStateSorted.map(([state, count]) => ( ))}
)}
{/* Quick actions */}

Acciones rápidas

{[ { href: '/products/new', label: '+ Nuevo producto', icon: '🌿' }, { href: '/orders', label: 'Ver pedidos', icon: '📦' }, { href: '/inventory', label: 'Revisar stock', icon: '📊' }, { href: '/customers', label: 'Clientes', icon: '👥' }, ].map(({ href, label, icon }) => ( {icon} {label} ))}
); }