import type { FC } from 'react'; import { useCallback, useEffect, useState } from 'react'; import { CalendarX, ShoppingCart } from 'lucide-react'; import { Card, Badge, EmptyState, Skeleton, toast } from '../ui'; import { ExportButton } from '../ui/ExportButton'; import { exportToExcel } from '../../lib/exporter'; import { odooApi, type CaducidadRow, type SugerenciaRow } from '../../services/odoo'; import type { BadgeVariant } from '../ui/Badge'; const fmtMoney = (n: number) => (n || 0).toLocaleString('es-MX', { style: 'currency', currency: 'MXN', maximumFractionDigits: 2 }); const caducidadBadge = (row: CaducidadRow): { variant: BadgeVariant; label: string } => { if (row.vencido) return { variant: 'danger', label: `Vencido hace ${Math.abs(row.dias_restantes)} días` }; if (row.dias_restantes <= 30) return { variant: 'warning', label: `${row.dias_restantes} días` }; return { variant: 'info', label: `${row.dias_restantes} días` }; }; const AlertasPanel: FC = () => { const [caducidades, setCaducidades] = useState([]); const [sugerencia, setSugerencia] = useState([]); const [totalSugerencia, setTotalSugerencia] = useState({ items: 0, costo_total: 0 }); const [loading, setLoading] = useState(true); const [exporting, setExporting] = useState(false); const load = useCallback(async () => { try { setLoading(true); const res = await odooApi.getInventarioAlertas(); if (res.status === 'success') { setCaducidades(res.caducidades); setSugerencia(res.sugerencia_compra); setTotalSugerencia(res.sugerencia_total); } } catch (err) { toast.error('Error al cargar alertas'); console.error(err); } finally { setLoading(false); } }, []); useEffect(() => { load(); }, [load]); const exportar = async () => { try { setExporting(true); await exportToExcel({ filename: `sugerencia-compra-${new Date().toISOString().split('T')[0]}`, sheetName: 'Sugerencia de compra', title: 'Sugerencia de compra — inventario SKEEN', subtitle: `${totalSugerencia.items} artículos bajo mínimo · costo estimado ${fmtMoney(totalSugerencia.costo_total)}`, columns: [ { header: 'Artículo', key: 'name' }, { header: 'Categoría', key: 'category' }, { header: 'Unidad', key: 'unit' }, { header: 'Existencia', key: 'qty', format: 'number' }, { header: 'Mínimo', key: 'qty_min', format: 'number' }, { header: 'Óptimo', key: 'qty_optimal', format: 'number' }, { header: 'Sugerido', key: 'sugerido', format: 'number' }, { header: 'Costo estimado', key: 'costo_estimado', format: 'currency' }, ], rows: sugerencia.map((s) => ({ ...s })), totals: { name: '', costo_estimado: totalSugerencia.costo_total }, }); toast.success('Excel descargado'); } catch (err) { toast.error('Error al exportar'); console.error(err); } finally { setExporting(false); } }; return (
{/* Caducidades */}

Caducidades

Artículos con fecha de caducidad registrada, ordenados por urgencia.

{loading ? ( ) : caducidades.length === 0 ? ( } /> ) : (
{caducidades.map((c) => { const b = caducidadBadge(c); return ( ); })}
Artículo Categoría Existencia Caduca Estado
{c.name} {c.category || '-'} {c.qty} {c.unit} {c.expiry_date} {b.label}
)}
{/* Sugerencia de compra */}

Sugerencia de compra

Artículos bajo su stock mínimo (o sin existencia). Sugerido = óptimo − existencia (o 2× mínimo).

{loading ? ( ) : sugerencia.length === 0 ? ( } /> ) : ( <>
{sugerencia.map((s) => ( ))}
Artículo Existencia Mínimo Óptimo Sugerido Costo est.
{s.name} {s.qty} {s.unit} {s.qty_min || '-'} {s.qty_optimal || '-'} +{s.sugerido} {s.unit} {fmtMoney(s.costo_estimado)}

Total estimado: {fmtMoney(totalSugerencia.costo_total)} {' '}({totalSugerencia.items} artículos)

)}
); }; export default AlertasPanel;