diff --git a/maternal-web/components/common/ChildSelector.tsx b/maternal-web/components/common/ChildSelector.tsx new file mode 100644 index 0000000..19a89f4 --- /dev/null +++ b/maternal-web/components/common/ChildSelector.tsx @@ -0,0 +1,267 @@ +'use client'; + +import React from 'react'; +import { + FormControl, + InputLabel, + Select, + MenuItem, + Checkbox, + ListItemText, + Avatar, + Box, + Chip, + SelectChangeEvent, +} from '@mui/material'; +import { Child } from '@/lib/api/children'; +import { GroupAdd, Person } from '@mui/icons-material'; + +export type ChildSelectorMode = 'single' | 'multiple' | 'all'; + +interface ChildSelectorProps { + children: Child[]; + selectedChildIds: string[]; + onChange: (childIds: string[]) => void; + mode?: ChildSelectorMode; + showAllOption?: boolean; + label?: string; + disabled?: boolean; + compact?: boolean; + required?: boolean; +} + +export default function ChildSelector({ + children, + selectedChildIds, + onChange, + mode = 'single', + showAllOption = false, + label = 'Select Child', + disabled = false, + compact = false, + required = false, +}: ChildSelectorProps) { + const handleChange = (event: SelectChangeEvent) => { + const value = event.target.value; + + if (mode === 'single') { + // Single selection + onChange(typeof value === 'string' ? [value] : value); + } else { + // Multiple selection + const selectedIds = typeof value === 'string' ? value.split(',') : value; + + // Handle "All" option + if (selectedIds.includes('all')) { + if (selectedChildIds.length === children.length) { + // Deselect all + onChange([]); + } else { + // Select all + onChange(children.map((c) => c.id)); + } + } else { + onChange(selectedIds); + } + } + }; + + const getDisplayValue = () => { + if (selectedChildIds.length === 0) { + return ''; + } + + if (mode === 'single') { + return selectedChildIds[0] || ''; + } + + // Multiple mode + if (showAllOption && selectedChildIds.length === children.length) { + return 'all'; + } + + return selectedChildIds; + }; + + const renderValue = (selected: string | string[]) => { + if (!selected || (Array.isArray(selected) && selected.length === 0)) { + return None selected; + } + + if (mode === 'single') { + const child = children.find((c) => c.id === selected); + if (!child) return None selected; + + return ( + + + {child.name[0]} + + {child.name} + + ); + } + + // Multiple mode + if (showAllOption && Array.isArray(selected) && selected.includes('all')) { + return ( + + } + label="All Children" + size="small" + sx={{ bgcolor: 'primary.light' }} + /> + + ); + } + + const selectedIds = Array.isArray(selected) ? selected : [selected]; + return ( + + {selectedIds.map((id) => { + const child = children.find((c) => c.id === id); + if (!child) return null; + + return ( + + {child.name[0]} + + } + label={child.nickname || child.name} + size="small" + sx={{ + bgcolor: `${child.displayColor}20`, + borderColor: child.displayColor, + borderWidth: 1, + borderStyle: 'solid', + }} + /> + ); + })} + + ); + }; + + if (children.length === 0) { + return ( + + No children available + + + ); + } + + // Single child - show simplified selector + if (children.length === 1 && mode === 'single') { + const child = children[0]; + return ( + + {label} + + + ); + } + + return ( + + {label} + + + ); +} diff --git a/maternal-web/lib/api/children.ts b/maternal-web/lib/api/children.ts index 48d4de0..1ee63e1 100644 --- a/maternal-web/lib/api/children.ts +++ b/maternal-web/lib/api/children.ts @@ -8,6 +8,9 @@ export interface Child { gender: 'male' | 'female' | 'other'; photoUrl?: string; photoAlt?: string; + displayColor: string; + sortOrder: number; + nickname?: string; medicalInfo?: any; createdAt: string; } @@ -18,9 +21,18 @@ export interface CreateChildData { gender: 'male' | 'female' | 'other'; photoUrl?: string; photoAlt?: string; + displayColor?: string; + nickname?: string; medicalInfo?: any; } +export interface FamilyStatistics { + totalChildren: number; + viewMode: 'tabs' | 'cards'; + ageRange: { youngest: number; oldest: number } | null; + genderDistribution: { male: number; female: number; other: number }; +} + export interface UpdateChildData extends Partial {} export const childrenApi = { @@ -59,4 +71,10 @@ export const childrenApi = { const response = await apiClient.get(`/api/v1/children/${id}/age`); return response.data.data; }, + + // Get family statistics for multi-child UI + getFamilyStatistics: async (familyId: string): Promise => { + const response = await apiClient.get(`/api/v1/children/family/${familyId}/statistics`); + return response.data.data; + }, };