'use client'; import { useState, useEffect } from 'react'; import { Box, Typography, CircularProgress, Alert, ToggleButtonGroup, ToggleButton, FormControl, InputLabel, Select, MenuItem, } from '@mui/material'; import { LineChart, Line, XAxis, YAxis, CartesianGrid, Tooltip, Legend, ResponsiveContainer, ReferenceLine, } from 'recharts'; import { format } from 'date-fns'; import apiClient from '@/lib/api/client'; interface GrowthData { age: number; // months weight?: number; // kg height?: number; // cm headCircumference?: number; // cm date: string; } // WHO Growth Standards Percentiles (simplified for 0-24 months) // These are approximate values - in production, use exact WHO data const WHO_WEIGHT_PERCENTILES = { male: { p3: [3.3, 4.4, 5.1, 5.6, 6.0, 6.4, 6.7, 7.0, 7.2, 7.5, 7.7, 7.9, 8.1, 8.3, 8.5, 8.7, 8.9, 9.0, 9.2, 9.4, 9.5, 9.7, 9.9, 10.0, 10.2], p15: [3.6, 4.8, 5.5, 6.1, 6.5, 6.9, 7.2, 7.5, 7.8, 8.0, 8.3, 8.5, 8.7, 8.9, 9.1, 9.3, 9.5, 9.7, 9.9, 10.1, 10.3, 10.4, 10.6, 10.8, 11.0], p50: [4.0, 5.3, 6.1, 6.7, 7.2, 7.6, 8.0, 8.3, 8.6, 8.9, 9.2, 9.4, 9.7, 9.9, 10.1, 10.4, 10.6, 10.8, 11.0, 11.2, 11.5, 11.7, 11.9, 12.1, 12.3], p85: [4.4, 5.8, 6.7, 7.4, 7.9, 8.4, 8.8, 9.1, 9.5, 9.8, 10.1, 10.4, 10.6, 10.9, 11.2, 11.4, 11.7, 11.9, 12.2, 12.4, 12.7, 13.0, 13.2, 13.5, 13.7], p97: [4.8, 6.3, 7.3, 8.0, 8.6, 9.1, 9.5, 9.9, 10.3, 10.6, 11.0, 11.3, 11.6, 11.9, 12.2, 12.5, 12.8, 13.1, 13.4, 13.7, 14.0, 14.3, 14.6, 14.9, 15.2], }, female: { p3: [3.2, 4.2, 4.8, 5.3, 5.7, 6.0, 6.3, 6.6, 6.8, 7.0, 7.2, 7.4, 7.6, 7.8, 8.0, 8.2, 8.3, 8.5, 8.7, 8.8, 9.0, 9.2, 9.3, 9.5, 9.7], p15: [3.5, 4.6, 5.3, 5.8, 6.2, 6.5, 6.8, 7.1, 7.4, 7.6, 7.8, 8.1, 8.3, 8.5, 8.7, 8.9, 9.1, 9.3, 9.4, 9.6, 9.8, 10.0, 10.2, 10.4, 10.6], p50: [3.9, 5.1, 5.8, 6.4, 6.9, 7.3, 7.6, 7.9, 8.2, 8.5, 8.7, 9.0, 9.2, 9.5, 9.7, 10.0, 10.2, 10.4, 10.7, 10.9, 11.1, 11.4, 11.6, 11.8, 12.1], p85: [4.3, 5.6, 6.5, 7.1, 7.6, 8.0, 8.4, 8.7, 9.1, 9.4, 9.7, 10.0, 10.2, 10.5, 10.8, 11.0, 11.3, 11.6, 11.8, 12.1, 12.4, 12.6, 12.9, 13.2, 13.5], p97: [4.7, 6.1, 7.0, 7.7, 8.3, 8.7, 9.1, 9.5, 9.9, 10.2, 10.6, 10.9, 11.2, 11.5, 11.8, 12.1, 12.4, 12.7, 13.0, 13.3, 13.6, 13.9, 14.2, 14.5, 14.9], }, }; export default function GrowthCurve() { const [data, setData] = useState([]); const [isLoading, setIsLoading] = useState(true); const [error, setError] = useState(null); const [metric, setMetric] = useState<'weight' | 'height' | 'headCircumference'>('weight'); const [gender, setGender] = useState<'male' | 'female'>('male'); useEffect(() => { fetchGrowthData(); }, []); const fetchGrowthData = async () => { try { setIsLoading(true); // Fetch growth measurements from backend const response = await apiClient.get('/api/v1/activities/growth'); const growthActivities = response.data.data; // Process growth data const processedData: GrowthData[] = growthActivities.map((activity: any) => { const ageInMonths = calculateAgeInMonths(activity.childBirthDate, activity.measurementDate); return { age: ageInMonths, weight: activity.weight, height: activity.height, headCircumference: activity.headCircumference, date: format(new Date(activity.measurementDate), 'MMM dd, yyyy'), }; }); // Sort by age processedData.sort((a, b) => a.age - b.age); setData(processedData); // Fetch child profile to determine gender const profileResponse = await apiClient.get('/api/v1/children/profile'); if (profileResponse.data.data.gender) { setGender(profileResponse.data.data.gender.toLowerCase()); } } catch (err: any) { console.error('Failed to fetch growth data:', err); // If endpoint doesn't exist, create sample data for demonstration if (err.response?.status === 404) { setData(createSampleData()); } else { setError(err.response?.data?.message || 'Failed to load growth data'); } } finally { setIsLoading(false); } }; const calculateAgeInMonths = (birthDate: string, measurementDate: string): number => { const birth = new Date(birthDate); const measurement = new Date(measurementDate); const months = (measurement.getFullYear() - birth.getFullYear()) * 12 + (measurement.getMonth() - birth.getMonth()); return Math.max(0, months); }; const createSampleData = (): GrowthData[] => { // Sample data for demonstration (0-12 months) return [ { age: 0, weight: 3.5, height: 50, headCircumference: 35, date: 'Birth' }, { age: 1, weight: 4.5, height: 54, headCircumference: 37, date: '1 month' }, { age: 2, weight: 5.5, height: 58, headCircumference: 39, date: '2 months' }, { age: 3, weight: 6.3, height: 61, headCircumference: 40, date: '3 months' }, { age: 4, weight: 7.0, height: 64, headCircumference: 41, date: '4 months' }, { age: 6, weight: 7.8, height: 67, headCircumference: 43, date: '6 months' }, { age: 9, weight: 8.9, height: 72, headCircumference: 45, date: '9 months' }, { age: 12, weight: 9.8, height: 76, headCircumference: 46, date: '12 months' }, ]; }; const getPercentileData = () => { const percentiles = WHO_WEIGHT_PERCENTILES[gender]; const maxAge = Math.max(...data.map(d => d.age), 24); return Array.from({ length: maxAge + 1 }, (_, i) => ({ age: i, p3: percentiles.p3[i] || null, p15: percentiles.p15[i] || null, p50: percentiles.p50[i] || null, p85: percentiles.p85[i] || null, p97: percentiles.p97[i] || null, })); }; const handleMetricChange = (event: React.MouseEvent, newMetric: 'weight' | 'height' | 'headCircumference' | null) => { if (newMetric !== null) { setMetric(newMetric); } }; const handleGenderChange = (event: any) => { setGender(event.target.value); }; if (isLoading) { return ( ); } if (error) { return ( {error} ); } const percentileData = getPercentileData(); const combinedData = percentileData.map(p => { const userDataPoint = data.find(d => Math.round(d.age) === p.age); return { ...p, userValue: userDataPoint?.[metric] || null, }; }); return ( Growth Curve (WHO Standards) Track your child's growth against WHO percentiles Gender Weight Height Head {data.length === 0 ? ( No growth measurements recorded yet. Start tracking to see growth curves! ) : ( {/* WHO Percentile Lines */} {/* User's Actual Data */} )} * WHO (World Health Organization) growth standards are based on healthy breastfed children from diverse populations. Consult your pediatrician for personalized growth assessment. ); }