/* * Enterprise Dashboard Page * Main dashboard for enterprise parent tenants showing network-wide metrics */ import React, { useState, useEffect } from 'react'; import { useNavigate, useParams } from 'react-router-dom'; import { useQuery, useQueries } from '@tanstack/react-query'; import { useNetworkSummary, useChildrenPerformance, useDistributionOverview, useForecastSummary } from '../../api/hooks/enterprise'; import { Card, CardContent, CardHeader, CardTitle } from '../../components/ui/Card'; import { Badge } from '../../components/ui/Badge'; import { Button } from '../../components/ui/Button'; import { Users, ShoppingCart, TrendingUp, MapPin, Truck, Package, BarChart3, Network, Store, Activity, Calendar, Clock, CheckCircle, AlertTriangle, PackageCheck, Building2, DollarSign } from 'lucide-react'; import { useTranslation } from 'react-i18next'; import { LoadingSpinner } from '../../components/ui/LoadingSpinner'; import { ErrorBoundary } from 'react-error-boundary'; import { apiClient } from '../../api/client/apiClient'; // Components for enterprise dashboard const NetworkSummaryCards = React.lazy(() => import('../../components/dashboard/NetworkSummaryCards')); const DistributionMap = React.lazy(() => import('../../components/maps/DistributionMap')); const PerformanceChart = React.lazy(() => import('../../components/charts/PerformanceChart')); const EnterpriseDashboardPage = () => { const { tenantId } = useParams(); const navigate = useNavigate(); const { t } = useTranslation('dashboard'); const [selectedMetric, setSelectedMetric] = useState('sales'); const [selectedPeriod, setSelectedPeriod] = useState(30); const [selectedDate, setSelectedDate] = useState(new Date().toISOString().split('T')[0]); // Check if user has enterprise tier access useEffect(() => { const checkAccess = async () => { try { const response = await apiClient.get<{ tenant_type: string }>(`/tenants/${tenantId}`); if (response.tenant_type !== 'parent') { navigate('/unauthorized'); } } catch (error) { console.error('Access check failed:', error); navigate('/unauthorized'); } }; checkAccess(); }, [tenantId, navigate]); // Fetch network summary data const { data: networkSummary, isLoading: isNetworkSummaryLoading, error: networkSummaryError } = useNetworkSummary(tenantId!, { refetchInterval: 60000, // Refetch every minute }); // Fetch children performance data const { data: childrenPerformance, isLoading: isChildrenPerformanceLoading, error: childrenPerformanceError } = useChildrenPerformance(tenantId!, selectedMetric, selectedPeriod); // Fetch distribution overview data const { data: distributionOverview, isLoading: isDistributionLoading, error: distributionError } = useDistributionOverview(tenantId!, selectedDate, { refetchInterval: 60000, // Refetch every minute }); // Fetch enterprise forecast summary const { data: forecastSummary, isLoading: isForecastLoading, error: forecastError } = useForecastSummary(tenantId!); // Error boundary fallback const ErrorFallback = ({ error, resetErrorBoundary }: { error: Error; resetErrorBoundary: () => void }) => (

Something went wrong

{error.message}

); if (isNetworkSummaryLoading || isChildrenPerformanceLoading || isDistributionLoading || isForecastLoading) { return (
); } if (networkSummaryError || childrenPerformanceError || distributionError || forecastError) { return (

Error Loading Dashboard

{networkSummaryError?.message || childrenPerformanceError?.message || distributionError?.message || forecastError?.message}

); } return (
{/* Header */}

{t('enterprise.network_dashboard')}

{t('enterprise.network_summary_description')}

{/* Network Summary Cards */}
{/* Distribution Map and Performance Chart Row */}
{/* Distribution Map */}
{t('enterprise.distribution_map')}
setSelectedDate(e.target.value)} className="border rounded px-2 py-1 text-sm" />
{distributionOverview ? ( ) : (
{t('enterprise.no_distribution_data')}
)}
{/* Performance Chart */}
{t('enterprise.outlet_performance')}
{childrenPerformance ? ( ) : (
{t('enterprise.no_performance_data')}
)}
{/* Forecast Summary */}
{t('enterprise.network_forecast')} {forecastSummary && forecastSummary.aggregated_forecasts ? (

{t('enterprise.total_demand')}

{Object.values(forecastSummary.aggregated_forecasts).reduce((total: number, day: any) => total + Object.values(day).reduce((dayTotal: number, product: any) => dayTotal + (product.predicted_demand || 0), 0), 0 ).toLocaleString()}

{t('enterprise.days_forecast')}

{forecastSummary.days_forecast || 7}

{t('enterprise.avg_daily_demand')}

{forecastSummary.aggregated_forecasts ? Math.round(Object.values(forecastSummary.aggregated_forecasts).reduce((total: number, day: any) => total + Object.values(day).reduce((dayTotal: number, product: any) => dayTotal + (product.predicted_demand || 0), 0), 0) / Object.keys(forecastSummary.aggregated_forecasts).length ).toLocaleString() : 0}

{t('enterprise.last_updated')}

{forecastSummary.last_updated ? new Date(forecastSummary.last_updated).toLocaleTimeString() : 'N/A'}

) : (
{t('enterprise.no_forecast_data')}
)}
{/* Quick Actions */}

Agregar Punto de Venta

AƱadir un nuevo outlet a la red enterprise

Transferencias Internas

Gestionar pedidos entre obrador central y outlets

Rutas de Distribución

Optimizar rutas de entrega entre ubicaciones

); }; export default EnterpriseDashboardPage;