import React, { useState, useEffect, useMemo } from 'react'; import { BarChart3, TrendingUp, TrendingDown, DollarSign, Package, Clock, Star, AlertCircle, Building, Truck, CheckCircle, Calendar, Filter, Download, RefreshCw } from 'lucide-react'; import { useSuppliers, usePurchaseOrders, useDeliveries } from '../../api/hooks/useSuppliers'; import { useAuth } from '../../api/hooks/useAuth'; import Card from '../ui/Card'; import Button from '../ui/Button'; import LoadingSpinner from '../ui/LoadingSpinner'; interface AnalyticsFilters { period: 'last_7_days' | 'last_30_days' | 'last_90_days' | 'last_year'; supplier_id?: string; supplier_type?: string; } const SupplierAnalyticsDashboard: React.FC = () => { const { user } = useAuth(); const { statistics: supplierStats, activeSuppliers, topSuppliers, loadStatistics: loadSupplierStats, loadActiveSuppliers, loadTopSuppliers } = useSuppliers(); const { statistics: orderStats, loadStatistics: loadOrderStats } = usePurchaseOrders(); const { performanceStats: deliveryStats, loadPerformanceStats: loadDeliveryStats } = useDeliveries(); const [filters, setFilters] = useState({ period: 'last_30_days' }); const [isLoading, setIsLoading] = useState(true); // Load all analytics data useEffect(() => { if (user?.tenant_id) { loadAnalyticsData(); } }, [user?.tenant_id, filters]); const loadAnalyticsData = async () => { setIsLoading(true); try { await Promise.all([ loadSupplierStats(), loadActiveSuppliers(), loadTopSuppliers(10), loadOrderStats(), loadDeliveryStats(getPeriodDays(filters.period)) ]); } catch (error) { console.error('Error loading analytics data:', error); } finally { setIsLoading(false); } }; // Convert period to days const getPeriodDays = (period: string) => { switch (period) { case 'last_7_days': return 7; case 'last_30_days': return 30; case 'last_90_days': return 90; case 'last_year': return 365; default: return 30; } }; // Period options const periodOptions = [ { value: 'last_7_days', label: 'Últimos 7 días' }, { value: 'last_30_days', label: 'Últimos 30 días' }, { value: 'last_90_days', label: 'Últimos 90 días' }, { value: 'last_year', label: 'Último año' } ]; // Format currency const formatCurrency = (amount: number) => { return new Intl.NumberFormat('es-ES', { style: 'currency', currency: 'EUR', minimumFractionDigits: 0, maximumFractionDigits: 0 }).format(amount); }; // Format percentage const formatPercentage = (value: number) => { return `${value.toFixed(1)}%`; }; // Calculate performance metrics const performanceMetrics = useMemo(() => { if (!supplierStats || !orderStats || !deliveryStats) return null; return { supplierGrowth: supplierStats.active_suppliers > 0 ? ((supplierStats.total_suppliers - supplierStats.active_suppliers) / supplierStats.active_suppliers * 100) : 0, orderGrowth: orderStats.this_month_orders > 0 ? 15 : 0, // Mock growth calculation spendEfficiency: deliveryStats.quality_pass_rate, deliveryReliability: deliveryStats.on_time_percentage }; }, [supplierStats, orderStats, deliveryStats]); // Key performance indicators const kpis = useMemo(() => { if (!supplierStats || !orderStats || !deliveryStats) return []; return [ { title: 'Gasto Total', value: formatCurrency(supplierStats.total_spend), change: '+12.5%', changeType: 'positive' as const, icon: DollarSign, color: 'blue' }, { title: 'Pedidos Este Mes', value: orderStats.this_month_orders.toString(), change: '+8.3%', changeType: 'positive' as const, icon: Package, color: 'green' }, { title: 'Entregas a Tiempo', value: formatPercentage(deliveryStats.on_time_percentage), change: deliveryStats.on_time_percentage > 85 ? '+2.1%' : '-1.5%', changeType: deliveryStats.on_time_percentage > 85 ? 'positive' as const : 'negative' as const, icon: Clock, color: 'orange' }, { title: 'Calidad Promedio', value: formatPercentage(supplierStats.avg_quality_rating * 20), // Convert from 5-star to percentage change: '+3.2%', changeType: 'positive' as const, icon: Star, color: 'purple' } ]; }, [supplierStats, orderStats, deliveryStats]); if (isLoading) { return (
); } return (
{/* Header */}

Panel de Análisis de Proveedores

Insights y métricas de rendimiento de tus proveedores

{/* KPI Cards */}
{kpis.map((kpi, index) => (

{kpi.title}

{kpi.value}

{kpi.changeType === 'positive' ? ( ) : ( )} {kpi.change} vs período anterior
))}
{/* Performance Overview */} {performanceMetrics && (
{/* Supplier Performance */}

Rendimiento de Proveedores

Proveedores Activos
{supplierStats?.active_suppliers}/{supplierStats?.total_suppliers}
Calidad Promedio
{[...Array(5)].map((_, i) => ( ))}
{supplierStats?.avg_quality_rating.toFixed(1)}
Entregas Puntuales
{[...Array(5)].map((_, i) => ( ))}
{supplierStats?.avg_delivery_rating.toFixed(1)}
{/* Delivery Performance */}

Rendimiento de Entregas

{formatPercentage(deliveryStats?.on_time_percentage || 0)}
A tiempo
{deliveryStats?.on_time_deliveries || 0}
A Tiempo
{deliveryStats?.late_deliveries || 0}
Tardías
)} {/* Top Suppliers and Insights */}
{/* Top Suppliers */} {topSuppliers.length > 0 && (

Mejores Proveedores

{topSuppliers.slice(0, 5).map((supplier, index) => (
{index + 1}

{supplier.name}

{supplier.total_orders} pedidos

{formatCurrency(supplier.total_amount)}

{supplier.quality_rating?.toFixed(1) || 'N/A'}
))}
)} {/* Insights and Recommendations */}

Insights y Recomendaciones

{/* Performance insights */} {deliveryStats && deliveryStats.on_time_percentage > 90 && (

Excelente rendimiento de entregas

{formatPercentage(deliveryStats.on_time_percentage)} de entregas a tiempo. ¡Mantén la buena comunicación con tus proveedores!

)} {deliveryStats && deliveryStats.on_time_percentage < 80 && (

Oportunidad de mejora en entregas

Solo {formatPercentage(deliveryStats.on_time_percentage)} de entregas a tiempo. Considera revisar los acuerdos de servicio con tus proveedores.

)} {supplierStats && supplierStats.pending_suppliers > 0 && (

Proveedores pendientes de aprobación

Tienes {supplierStats.pending_suppliers} proveedores esperando aprobación. Revísalos para acelerar tu cadena de suministro.

)} {orderStats && orderStats.overdue_count > 0 && (

Pedidos vencidos

{orderStats.overdue_count} pedidos han superado su fecha de entrega. Contacta con tus proveedores para actualizar el estado.

)} {supplierStats && supplierStats.avg_quality_rating > 4 && (

Alta calidad de proveedores

Calidad promedio de {supplierStats.avg_quality_rating.toFixed(1)}/5. Considera destacar estos proveedores como preferidos.

)}
{/* Detailed Metrics */} {orderStats && (

Métricas Detalladas de Pedidos

{orderStats.total_orders}

Total Pedidos

{formatCurrency(orderStats.avg_order_value)} valor promedio
{orderStats.this_month_orders}

Este Mes

{formatCurrency(orderStats.this_month_spend)} gastado
{orderStats.pending_approval}

Pendientes Aprobación

Requieren revisión
{/* Order Status Breakdown */} {orderStats.status_counts && (

Distribución por Estado

{Object.entries(orderStats.status_counts).map(([status, count]) => (
{count as number}
{status.toLowerCase().replace('_', ' ')}
))}
)}
)}
); }; export default SupplierAnalyticsDashboard;