import React, { useEffect, useState } from 'react'; import { createRoot } from 'react-dom/client'; import { PieChart, Pie, Cell, Tooltip, ResponsiveContainer } from 'recharts'; interface NutritionState { target: number; bmr: number; tdee: number; proteins: number; carbs: number; fats: number; protKcal: number; carbKcal: number; fatKcal: number; protPct: number; carbPct: number; fatPct: number; lang: 'fr' | 'en'; } declare global { interface Window { nutritionState?: NutritionState; __rechartsNutritionMounted?: boolean; } } const DEFAULT_STATE: NutritionState = { target: 2994, bmr: 1770, tdee: 2744, proteins: 164, carbs: 418, fats: 74, protKcal: 656, carbKcal: 1672, fatKcal: 666, protPct: 22, carbPct: 56, fatPct: 22, lang: 'fr', }; const RechartsNutritionPie: React.FC = () => { const [state, setState] = useState(() => window.nutritionState || DEFAULT_STATE); useEffect(() => { const handleUpdate = (e: Event) => { const customEvent = e as CustomEvent; if (customEvent.detail) { setState({ ...customEvent.detail }); } else if (window.nutritionState) { setState({ ...window.nutritionState }); } }; window.addEventListener('bodyidol:nutrition-update', handleUpdate); if (window.nutritionState) { setState({ ...window.nutritionState }); } return () => { window.removeEventListener('bodyidol:nutrition-update', handleUpdate); }; }, []); const isFr = state.lang === 'fr'; const data = [ { name: isFr ? 'Glucides (Énergie)' : 'Carbohydrates (Energy)', shortName: isFr ? 'Glucides' : 'Carbs', value: state.carbKcal, grams: state.carbs, pct: state.carbPct, color: '#10B981', // Emerald }, { name: isFr ? 'Protéines (Anabolisme)' : 'Proteins (Anabolism)', shortName: isFr ? 'Protéines' : 'Protein', value: state.protKcal, grams: state.proteins, pct: state.protPct, color: '#F4F4F5', // Platinum White }, { name: isFr ? 'Lipides (Hormones)' : 'Dietary Fats (Hormones)', shortName: isFr ? 'Lipides' : 'Fats', value: state.fatKcal, grams: state.fats, pct: state.fatPct, color: '#D4AF37', // Metallic Gold }, ]; return (
{/* Center Target Calories Overlay */}
{isFr ? 'CIBLE / JOUR' : 'DAILY TARGET'} {state.target.toLocaleString('fr-FR')} kcal
{data.map((entry, index) => ( ))} { if (!active || !payload || !payload.length) return null; const item = payload[0].payload; return (
{item.name}
{item.grams} g · {item.value} kcal ({item.pct}%)
); }} />
); }; function mountNutritionChart() { const container = document.getElementById('recharts-nutrition-pie-root'); if (container && !window.__rechartsNutritionMounted) { window.__rechartsNutritionMounted = true; const root = createRoot(container); root.render(); } } if (document.readyState === 'loading') { document.addEventListener('DOMContentLoaded', mountNutritionChart); } else { mountNutritionChart(); }