'use client'; import { useState, useEffect } from 'react'; import { Box, Stepper, Step, StepLabel, Button, Typography, Paper, TextField, Avatar, IconButton, Alert, CircularProgress, MenuItem, Card, CardActionArea, CardContent, Radio, RadioGroup, 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'; import { useRouter } from 'next/navigation'; import { useAuth } from '@/lib/auth/AuthContext'; import { childrenApi } from '@/lib/api/children'; 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'; import { FamilySetupStep, ChildData } from '@/components/onboarding/FamilySetupStep'; import { familiesApi } from '@/lib/api/families'; const steps = ['Welcome', 'Preferences', 'Family Setup', '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 ( {completed ? : icon} ); } export default function OnboardingPage() { const [activeStep, setActiveStep] = useState(0); const [selectedLanguage, setSelectedLanguage] = useState('en'); const [selectedMeasurement, setSelectedMeasurement] = useState('metric'); const [childName, setChildName] = useState(''); const [childBirthDate, setChildBirthDate] = useState(''); const [childGender, setChildGender] = useState<'male' | 'female' | 'other'>('other'); const [loading, setLoading] = useState(false); const [error, setError] = useState(''); const router = useRouter(); const { user, refreshUser } = useAuth(); const { setLanguage, setMeasurementSystem } = useLocale(); const { t } = useTranslation('onboarding'); const theme = useTheme(); // Restore onboarding progress on mount useEffect(() => { const restoreProgress = async () => { try { if (user?.id) { const status = await usersApi.getOnboardingStatus(); // If onboarding is completed, redirect to home if (status.completed) { router.push('/'); return; } // If user has saved progress, restore it if (status.step > 0) { setActiveStep(status.step); if (status.data?.selectedLanguage) { setSelectedLanguage(status.data.selectedLanguage); } if (status.data?.selectedMeasurement) { setSelectedMeasurement(status.data.selectedMeasurement); } } } } catch (err) { console.error('Failed to restore onboarding progress:', err); // Continue with default state if restore fails } }; restoreProgress(); }, [user?.id, router]); const handleNext = async () => { setError(''); // Step 1: Save preferences (language + measurement) if (activeStep === 1) { try { setLoading(true); await setLanguage(selectedLanguage); setMeasurementSystem(selectedMeasurement); // Save progress to backend if (user?.id) { await usersApi.updateOnboardingProgress({ step: activeStep + 1, data: { selectedLanguage, selectedMeasurement, }, }); await refreshUser(); } setActiveStep((prevActiveStep) => prevActiveStep + 1); } catch (err: any) { console.error('Failed to save preferences:', err); // Preferences were saved locally even if backend failed, so continue setActiveStep((prevActiveStep) => prevActiveStep + 1); } finally { setLoading(false); } return; } // Step 2: Family Setup - This is now handled by FamilySetupStep component if (activeStep === 2) { // The component handles the logic internally via onCreateFamily or onJoinFamily return; } if (activeStep === steps.length - 1) { // Complete onboarding try { setLoading(true); if (user?.id) { await usersApi.completeOnboarding(); } router.push('/'); } catch (err) { console.error('Failed to mark onboarding complete:', err); // Navigate anyway since onboarding flow is done router.push('/'); } finally { setLoading(false); } } else { setActiveStep((prevActiveStep) => prevActiveStep + 1); } }; const handleBack = () => { setActiveStep((prevActiveStep) => prevActiveStep - 1); }; const handleSkip = () => { router.push('/'); }; const handleCreateFamily = async (childData: ChildData) => { try { setLoading(true); setError(''); // Create a new family for the user const createdFamily = await familiesApi.createFamily({ name: `${user?.name || 'My'}'s Family`, }); await refreshUser(); // Refresh to get new family membership // Add the first child to the new family await childrenApi.createChild(createdFamily.id, { name: childData.name.trim(), birthDate: childData.birthDate, gender: childData.gender, }); setActiveStep((prev) => prev + 1); } catch (err: any) { console.error('Failed to create family:', err); setError(err.response?.data?.message || 'Failed to create family. Please try again.'); } finally { setLoading(false); } }; const handleJoinFamily = async (shareCode: string) => { try { setLoading(true); setError(''); await familiesApi.joinFamily({ shareCode }); await refreshUser(); // Refresh to get new family membership setActiveStep((prev) => prev + 1); } catch (err: any) { console.error('Failed to join family:', err); setError(err.response?.data?.message || 'Failed to join family. Please check the code and try again.'); } finally { setLoading(false); } }; return ( } sx={{ mb: 4 }} > {steps.map((label, index) => { let stepLabel = label; if (index === 0) stepLabel = t('welcome.title').split('!')[0]; else if (index === 1) stepLabel = t('language.title'); else if (index === 2) stepLabel = t('measurements.title'); else if (index === 3) stepLabel = 'Family Setup'; else if (index === 4) stepLabel = t('complete.title').split('!')[0]; // Only show label for active step on mobile const showLabel = activeStep === index; return ( {stepLabel} ); })} {/* Step 0: Welcome */} {activeStep === 0 && ( {t('welcome.title')} 🎉 {t('welcome.description')} 📊 {t('welcome.getStarted')} 🤖 AI Insights 👨‍👩‍👧 Family Sharing )} {/* Step 1: Preferences (Language + Measurements) */} {activeStep === 1 && ( {t('preferences.title') || 'Preferences'} {t('preferences.subtitle') || 'Set your language and measurement preferences'} {error && ( {error} )} {/* Language Dropdown */} setSelectedLanguage(e.target.value)} margin="normal" sx={{ mb: 2 }} > {supportedLanguages.map((lang) => ( {lang.nativeName} ({lang.name}) ))} {/* Measurement Dropdown */} setSelectedMeasurement(e.target.value as 'metric' | 'imperial')} margin="normal" > {t('measurements.metric.title') || 'Metric'} (kg, cm, °C) {t('measurements.imperial.title') || 'Imperial'} (lbs, inches, °F) {t('preferences.description') || 'You can change these settings later in your profile.'} )} {/* Step 2: Family Setup */} {activeStep === 2 && ( )} {/* Step 3: Complete */} {activeStep === 3 && ( {t('complete.title')} 🎉 {t('complete.description')} {t('complete.subtitle')} • Track your first feeding, sleep, or diaper change
• Chat with our AI assistant for parenting tips
• Explore insights and predictions based on your data
)}
{activeStep === 3 && ( )}
); }