import { useEffect, useRef, useState } from 'react'; import { BarChart, Bar, PieChart, Pie, Cell, XAxis, YAxis, Tooltip, ResponsiveContainer, CartesianGrid, } from 'recharts'; import { Apple, Award, Beef, Droplet, Flame, HeartPulse, Play, RefreshCw, Wheat, UploadCloud, } from 'lucide-react'; import { api } from '../api/client'; import { Spinner, EmptyState } from '../components/Atoms'; import { NavigationHeader } from '../components/NavigationHeader'; import { UploadExcelModal } from '../components/UploadExcelModal'; const PALETTE = ['#e2a33d', '#3f8556', '#8b2e3c', '#2c3e63', '#c2872a']; export function NutritionAnalyticsPage() { const [dashboard, setDashboard] = useState(null); const [loading, setLoading] = useState(true); const [job, setJob] = useState(null); const [isUploadOpen, setIsUploadOpen] = useState(false); const pollRef = useRef(null); const load = () => { setLoading(true); api.getNutritionAnalyticsDashboard(8).then(setDashboard).catch(() => setDashboard(null)).finally(() => setLoading(false)); }; useEffect(() => { load(); }, []); useEffect(() => { if (!job || job.status === 'done' || job.status === 'failed') { if (pollRef.current) clearInterval(pollRef.current); if (job?.status === 'done') load(); return; } pollRef.current = setInterval(() => { api.getNutritionIntelligenceJob(job.job_id).then(setJob).catch(() => {}); }, 2000); return () => clearInterval(pollRef.current); }, [job]); const runEnrich = () => api.enrichNutrition({}).then(setJob); const runTrain = () => api.trainNutritionModels().then(setJob); const distribution = dashboard?.distribution; const enrichmentCounts = distribution?.enrichment_status || {}; const totalTracked = Object.values(enrichmentCounts).reduce((a, b) => a + b, 0); const hasData = totalTracked > 0; const distributionData = distribution?.health_score_distribution ? Object.entries(distribution.health_score_distribution).map(([bucket, count]) => ({ bucket, count })) : []; return (

Nutrition data pipeline

{hasData ? `${enrichmentCounts.verified || 0} verified · ${enrichmentCounts.partial || 0} partial · ${enrichmentCounts.unavailable || 0} unavailable of ${totalTracked} tracked products` : 'No products enriched yet - run enrichment or upload Excel/CSV data.'}

{job && (

{job.kind === 'enrich' ? 'Enrichment' : 'Training'} {job.status} {job.total ? ` (${job.processed}/${job.total})` : ''} {job.detail ? ` - ${job.detail}` : ''}

)}
{loading ? ( ) : !hasData ? ( ) : ( <>
{distributionData.length > 0 && (
e.bucket}> {distributionData.map((_, i) => )}
)}
)}
setIsUploadOpen(false)} tabType="nutrition" tabTitle="Nutritional Intelligence Facts" onSuccess={() => load()} />
); } function ChartCard({ title, icon: Icon, children }) { return (

{title}

{children}
); } function Leaderboard({ title, icon: Icon, items = [], field, unit }) { return (

{title}

{items.length === 0 ? (

No data yet.

) : (
    {items.map((p, i) => (
  1. #{i + 1} {p.product_name || p.image_id} {p.brand} {p[field] != null ? `${Number(p[field]).toFixed(1)} ${unit}` : '–'}
  2. ))}
)}
); }