docs: Add comprehensive multi-child implementation plan
Some checks failed
CI/CD Pipeline / Lint and Test (push) Has been cancelled
CI/CD Pipeline / E2E Tests (push) Has been cancelled
CI/CD Pipeline / Build Application (push) Has been cancelled

Added detailed implementation plan covering:
- Frontend: Dynamic UI, child selector, bulk activity logging, comparison analytics
- Backend: Bulk operations, multi-child queries, family statistics
- AI/Voice: Child name detection, context building, clarification flows
- Database: Schema enhancements, user preferences, bulk operation tracking
- State management, API enhancements, real-time sync updates
- Testing strategy: Unit, integration, and E2E tests
- Migration plan with feature flags for phased rollout
- Performance optimizations: Caching, indexes, code splitting

Also includes:
- Security fixes for multi-family data leakage in analytics pages
- ParentFlow branding updates
- Activity tracking navigation improvements
- Backend DTO and error handling fixes

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
2025-10-04 21:05:14 +00:00
parent f854fe6fcd
commit 95ef0e5e78
12 changed files with 2778 additions and 321 deletions

View File

@@ -23,6 +23,9 @@ import {
FormControlLabel,
FormControl,
Grid,
StepConnector,
stepConnectorClasses,
styled,
} from '@mui/material';
import { ArrowBack, ArrowForward, Check, Language, Straighten } from '@mui/icons-material';
import { motion, AnimatePresence } from 'framer-motion';
@@ -33,9 +36,60 @@ import { useLocale, MeasurementSystem } from '@/hooks/useLocale';
import { useTranslation } from '@/hooks/useTranslation';
import { supportedLanguages } from '@/lib/i18n/config';
import { usersApi } from '@/lib/api/users';
import { useTheme } from '@mui/material/styles';
import { StepIconProps } from '@mui/material/StepIcon';
const steps = ['Welcome', 'Language', 'Measurements', 'Add Child', 'Complete'];
// Custom connector for mobile-friendly stepper
const CustomConnector = styled(StepConnector)(({ theme }) => ({
[`&.${stepConnectorClasses.active}`]: {
[`& .${stepConnectorClasses.line}`]: {
borderColor: theme.palette.primary.main,
},
},
[`&.${stepConnectorClasses.completed}`]: {
[`& .${stepConnectorClasses.line}`]: {
borderColor: theme.palette.primary.main,
},
},
[`& .${stepConnectorClasses.line}`]: {
borderColor: theme.palette.divider,
borderTopWidth: 2,
borderRadius: 1,
},
}));
// Custom step icon showing numbers
const CustomStepIconRoot = styled('div')<{ ownerState: { active?: boolean; completed?: boolean } }>(
({ theme, ownerState }) => ({
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
width: 32,
height: 32,
borderRadius: '50%',
backgroundColor: ownerState.completed
? theme.palette.primary.main
: ownerState.active
? theme.palette.primary.main
: theme.palette.grey[300],
color: ownerState.active || ownerState.completed ? '#fff' : theme.palette.text.secondary,
fontWeight: 600,
fontSize: '0.875rem',
})
);
function CustomStepIcon(props: StepIconProps) {
const { active, completed, icon } = props;
return (
<CustomStepIconRoot ownerState={{ active, completed }}>
{completed ? <Check sx={{ fontSize: 18 }} /> : icon}
</CustomStepIconRoot>
);
}
export default function OnboardingPage() {
const [activeStep, setActiveStep] = useState(0);
const [selectedLanguage, setSelectedLanguage] = useState('en');
@@ -49,6 +103,7 @@ export default function OnboardingPage() {
const { user, refreshUser } = useAuth();
const { setLanguage, setMeasurementSystem } = useLocale();
const { t } = useTranslation('onboarding');
const theme = useTheme();
const handleNext = async () => {
setError('');
@@ -154,7 +209,7 @@ export default function OnboardingPage() {
flexDirection: 'column',
px: 3,
py: 4,
background: 'linear-gradient(135deg, #FFE4E1 0%, #FFDAB9 100%)',
background: `linear-gradient(135deg, ${theme.palette.primary.light} 0%, ${theme.palette.secondary.light} 100%)`,
}}
>
<Paper
@@ -163,13 +218,18 @@ export default function OnboardingPage() {
maxWidth: 600,
mx: 'auto',
width: '100%',
p: 4,
p: { xs: 3, sm: 4 },
borderRadius: 4,
background: 'rgba(255, 255, 255, 0.95)',
backdropFilter: 'blur(10px)',
}}
>
<Stepper activeStep={activeStep} sx={{ mb: 4 }}>
<Stepper
activeStep={activeStep}
alternativeLabel
connector={<CustomConnector />}
sx={{ mb: 4 }}
>
{steps.map((label, index) => {
let stepLabel = label;
if (index === 0) stepLabel = t('welcome.title').split('!')[0];
@@ -177,10 +237,24 @@ export default function OnboardingPage() {
else if (index === 2) stepLabel = t('measurements.title');
else if (index === 3) stepLabel = t('child.title');
else if (index === 4) stepLabel = t('complete.title').split('!')[0];
// Only show label for active step on mobile
const showLabel = activeStep === index;
return (
<Step key={label}>
<StepLabel>{stepLabel}</StepLabel>
<StepLabel
StepIconComponent={CustomStepIcon}
sx={{
'& .MuiStepLabel-label': {
display: { xs: showLabel ? 'block' : 'none', sm: 'block' },
mt: 1,
fontSize: { xs: '0.75rem', sm: '0.875rem' },
},
}}
>
{stepLabel}
</StepLabel>
</Step>
);
})}