This commit adds a complete onboarding improvements system including progress
tracking, streamlined UI, and role-based family invitation system.
## Backend Changes
### Database Migrations
- Add onboarding tracking fields to users table (onboarding_completed, onboarding_step, onboarding_data)
- Add role-based invite codes to families table (parent/caregiver/viewer codes with expiration)
- Add indexes for fast invite code lookups
### User Preferences Module
- Add UserPreferencesController with onboarding endpoints
- Add UserPreferencesService with progress tracking methods
- Add UpdateOnboardingProgressDto for validation
- Endpoints: GET/PUT /api/v1/preferences/onboarding, POST /api/v1/preferences/onboarding/complete
### Families Module - Role-Based Invites
- Add generateRoleInviteCode() - Generate role-specific codes with expiration
- Add getRoleInviteCodes() - Retrieve all active codes for a family
- Add joinFamilyWithRoleCode() - Join family with automatic role assignment
- Add revokeRoleInviteCode() - Revoke specific role invite codes
- Add sendEmailInvite() - Generate code and send email invitation
- Endpoints: POST/GET/DELETE /api/v1/families/:id/invite-codes, POST /api/v1/families/join-with-role, POST /api/v1/families/:id/email-invite
### Email Service
- Add sendFamilyInviteEmail() - Send role-based invitation emails
- Beautiful HTML templates with role badges (👨👩👧 parent, 🤝 caregiver, 👁️ viewer)
- Role-specific permission descriptions
- Graceful fallback if email sending fails
### Auth Service
- Fix duplicate family creation bug in joinFamily()
- Ensure users only join family once during onboarding
## Frontend Changes
### Onboarding Page
- Reduce steps from 5 to 4 (combined language + measurements)
- Replace card-based selection with dropdown selectors
- Add automatic progress saving after each step
- Add progress restoration on page mount
- Extract FamilySetupStep into reusable component
### Family Page
- Add RoleInvitesSection component with accordion UI
- Generate/view/copy/regenerate/revoke controls for each role
- Send email invites directly from UI
- Display expiration dates (e.g., "Expires in 5 days")
- Info tooltips explaining role permissions
- Only visible to users with parent role
### API Client
- Add role-based invite methods to families API
- Add onboarding progress methods to users API
- TypeScript interfaces for all new data structures
## Features
✅ Streamlined 4-step onboarding with dropdown selectors
✅ Automatic progress save/restore across sessions
✅ Role-based family invites (parent/caregiver/viewer)
✅ Beautiful email invitations with role descriptions
✅ Automatic role assignment when joining with invite codes
✅ Granular permission control per role
✅ Email fallback if sending fails
✅ All changes tested and production-ready
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Fixed two critical issues in user settings:
1. Settings save 400 error - Removed invalid notifications boolean
that didn't match backend DTO structure
2. Push notifications toggle not working - Properly structured
notifications preferences as nested object with pushEnabled/emailEnabled
Changes:
- Updated state to use pushEnabled instead of simple notifications boolean
- Load pushEnabled from user.preferences.notifications.pushEnabled
- Send notifications as nested object to match UpdateProfileDto
- Both push and email notification toggles now work independently
Backend DTO expects:
{
preferences: {
notifications: {
pushEnabled: boolean,
emailEnabled: boolean
}
}
}
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Fixed critical permission bypass where viewers could:
- Remove family members (now only parents can)
- Invite new members (now only parents can)
- Generate share codes (now only parents can)
- Add children (now only parents can)
- Edit children (now only parents and caregivers can)
- Delete children (now only parents can)
Changes:
- Family page: Added isParent checks for all admin actions
- Children page: Added canAddChildren, canEditChildren, canDeleteChildren checks
- Both pages now use useSelectedFamily hook for consistent role access
Backend already had correct permission checks - this fixes the frontend to respect them.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Created useSelectedFamily hook for managing family selection across app
- Added family selector dropdown to family page when user has multiple families
- Family selection persists in localStorage
- Fixed bug where users could only see their first family
- Updated dev port from 3005 to 3030 in package.json
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Add validation in onSubmit to check for invite code when required
- Display user-friendly error message instead of API error
- Prevent form submission until invite code is provided
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Backend Changes:
- Added GET /api/v1/auth/registration/config public endpoint
- Returns registrationMode and requireInviteCode settings
- No authentication required - accessible before registration
- Injected ConfigService into AuthController
This allows the frontend to dynamically show/hide the invite code
field based on the current registration mode setting.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Frontend Changes:
- Added inviteCode field to registration schema (optional)
- Added invite code TextField to registration form UI
- Updated RegisterData interface in AuthContext to include inviteCode
- Pass inviteCode to backend during registration
- Added helpful placeholder text indicating field is optional
User Experience:
- Invite code field appears after email in registration form
- Helper text explains it's optional and can be left blank if registration is open
- Backend will validate the code if REGISTRATION_MODE=invite_only
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Created production-ready Dockerfiles with multi-stage builds
- Implemented complete CI/CD pipeline with GitHub Actions:
- Automated testing for backend and frontend
- Security scanning with Trivy
- Docker image building and pushing to GHCR
- Automated deployments to dev and production
- Zero-downtime deployment strategy with rollback
- Set up docker-compose for both development and production
- Configured Nginx reverse proxy with SSL support
- Domain configuration:
- Development: maternal.noru1.ro:3005, maternal-api.noru1.ro:3015
- Production: parentflowapp.com, api.parentflowapp.com
- Created comprehensive health check endpoints for monitoring
- Updated port configuration for development environment
- Added environment-specific configuration files
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Created EnhancedInsightsDashboard with multiple chart types:
- Area charts with gradients for activity trends
- Radar chart for weekly activity patterns
- 24-hour heatmap visualization
- Bubble/scatter chart for correlations
- Time of day distribution bar chart
- Added toggle between basic and enhanced chart views
- Implemented chart export functionality (PNG/PDF)
- Fixed API endpoint URLs (circadian-rhythm, query params)
- Fixed component library conflicts (shadcn/ui → MUI)
- Added comprehensive null safety for timestamp handling
- Added alert type translations in all 5 languages
- Installed html2canvas and jspdf for export features
- Applied consistent minimum width styling to all charts
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Add comprehensive API client methods for all advanced analytics endpoints
- Create CircadianRhythmCard component for sleep pattern visualization
- Create AnomalyAlertsPanel for anomaly detection and alerts
- Create GrowthPercentileChart with WHO/CDC percentiles
- Create CorrelationInsights for activity correlations
- Create TrendAnalysisChart with predictions
- Add advanced analytics page with all new components
- Add UI component library (shadcn/ui) setup
- Add navigation link to advanced analytics from insights page
All advanced analytics features are now accessible from the frontend UI.
- Remove mock authentication from authSlice to enable real user login
- Fix WebSocket connection errors by using real JWT tokens
- Consolidate duplicate filters on insights page into single shared filter
- Update InsightsDashboard to accept props instead of managing own state
- Add MUI Grid styling for 20% min-width and centering
- Improve UX with unified filter controls for both insights and predictions
Authentication & Token Management:
- Add deviceId to token refresh flow (backend requires both refreshToken and deviceId)
- Fix React Strict Mode token clearing race condition with retry logic
- Improve AuthContext to handle all token state combinations properly
- Store deviceId in localStorage alongside tokens
UI/UX Improvements:
- Remove deprecated legacyBehavior from Next.js Link components
- Update primary theme color to WCAG AA compliant #7c3aed
- Fix nested button error in TabBar voice navigation
- Fix invalid Tabs value error in DynamicChildDashboard
Multi-Child Dashboard:
- Load all children into Redux store properly
- Fetch metrics for all children, not just selected one
- Remove mock data to prevent unauthorized API calls
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
GraphQL endpoint was returning 400 errors due to authentication issues
with the GqlAuthGuard. Replaced GraphQL query with REST API calls to
match the working insights page pattern.
Changes:
- Removed useQuery(GET_DASHBOARD) GraphQL call
- Added REST API calls: childrenApi.getChildren(), trackingApi.getActivities()
- Calculate today's summary from activities client-side
- Load children and dashboard data separately
- Removed all GraphQL debug logging
Now home page uses same REST pattern as insights page:
1. Load children via childrenApi
2. Load activities via trackingApi
3. Calculate summary from filtered activities
This eliminates the GraphQL 400 errors and makes Today's Summary
display correctly with feeding count, sleep duration, diaper count.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Root cause: Trackers were using Redux state.auth.user (mock data) while
insights page was using useAuth() hook (real backend data from /me).
Since the user is logged in as andrei@cloudz.ro, AuthContext fetches
the real user with Alice child, but trackers were looking for mock
familyId 'fam_test123' which doesn't exist.
Fix: Changed all tracker pages and home page to use:
user?.families?.[0]?.familyId (from useAuth hook)
instead of:
state.auth.user?.familyId (from Redux mock)
This makes all pages consistent with the insights page approach.
Files updated:
- app/page.tsx (home)
- app/track/sleep/page.tsx
- app/track/feeding/page.tsx
- app/track/diaper/page.tsx
- app/track/activity/page.tsx
- app/track/growth/page.tsx
- app/track/medicine/page.tsx
Now all pages fetch children using the real logged-in user's familyId.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Updated all 6 tracking forms with ChildSelector component:
✅ Feeding form
✅ Sleep form
✅ Diaper form
✅ Activity form
✅ Growth form
✅ Medicine form
Changes applied to each form:
- Replace local child state with Redux state management
- Use ChildSelector component instead of custom select
- Sync selectedChildIds with Redux store
- Update API calls to use selectedChild.id
- Remove duplicate loadChildren functions
- Use Redux loading state
Build Results:
- ✅ All 38 pages compiled successfully
- ✅ No TypeScript errors
- ✅ No runtime warnings
- Bundle sizes optimized (all tracking forms 3-10 kB)
Phase 3 Activity Logging: 100% COMPLETE
- Replace local child state with Redux state management
- Use ChildSelector component instead of custom select
- Sync selectedChildIds with Redux store
- Update API calls to use selectedChild.id
- Remove loadChildren function
- Replace local child state with Redux state management
- Use ChildSelector component instead of custom select
- Sync selectedChildIds with Redux store
- Update API calls to use selectedChild.id
- Remove loadChildren function
- Replace local child state with Redux state management
- Use ChildSelector component instead of custom select
- Sync selectedChildIds with Redux store
- Update API calls to use selectedChild.id
- Remove duplicate child loading logic
- Build and test successfully
- Replace local child selector with shared ChildSelector component
- Use Redux for children state management
- Sync selected child with Redux store
- Remove duplicate child loading logic
- Maintain single child selection for feeding tracking
- Build and test successfully
**Theme-Aware Colors Across App:**
- Updated track page cards to use theme.palette colors
- Updated analytics page icons to use theme colors
- Updated login/register gradient backgrounds to use theme colors
- All colors now respond to Standard/High Contrast theme toggle
**Fixed Next Predicted Activity Section:**
- Connected to real analytics API predictions endpoint
- Fetches sleep and feeding predictions based on actual data
- Shows "Nap time in X minutes" when prediction available
- Displays formatted time using formatDistanceToNow
- Falls back to "Not enough data available for now. Keep tracking :)" when no predictions
**Multi-Language Support:**
- Added "notEnoughData" translation key to all 7 languages:
- English: "Not enough data available for now. Keep tracking :)"
- Spanish: "No hay suficientes datos disponibles por ahora. ¡Sigue rastreando! :)"
- French: "Pas assez de données disponibles pour le moment. Continuez à suivre :)"
- Portuguese: "Dados insuficientes disponíveis no momento. Continue rastreando :)"
- Chinese: "暂无足够数据。请继续记录 :)"
- German: "Derzeit nicht genügend Daten verfügbar. Weiter verfolgen :)"
- Italian: "Dati insufficienti al momento. Continua a monitorare :)"
**Color Mapping by Theme:**
*Purple Theme (Standard):*
- Feeding: Primary (#8b52ff)
- Sleep: Secondary (#ff7094)
- Diaper: Warning (amber)
- Medical: Error (red)
- Activity: Success (green)
- Growth: Primary Dark
*Peach Theme (High Contrast):*
- Feeding: Primary (#FFB6C1)
- Sleep: Secondary (#FFDAB9)
- Diaper: Warning (amber)
- Medical: Error (red)
- Activity: Success (green)
- Growth: Primary Dark
**Files Modified:**
- app/track/page.tsx - Dynamic theme colors
- app/analytics/page.tsx - Theme-aware icon colors
- app/(auth)/login/page.tsx - Gradient uses theme
- app/(auth)/register/page.tsx - Gradient uses theme
- app/page.tsx - Predictions integration
- locales/*/dashboard.json - All 7 languages
🎉 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Implemented comprehensive form accessibility improvements across all critical forms:
**Accessibility Attributes Added:**
- aria-required="true" on all required form fields
- aria-invalid on fields with validation errors
- aria-describedby linking error messages to inputs
- Unique id attributes on FormHelperText for error association
- role="alert" on error messages for screen reader announcements
- labelId on Select components for proper label association
- noValidate on forms to use custom validation
**Forms Updated:**
1. Login Form (app/(auth)/login/page.tsx)
- Email and password fields with full ARIA support
- Error message association with aria-describedby
2. Registration Form (app/(auth)/register/page.tsx)
- All text fields: name, email, password, DOB, parental email
- Checkbox fields: Terms, Privacy, COPPA consent
- Conditional required fields for minors
3. Child Dialog (components/children/ChildDialog.tsx)
- Name, birthdate, gender fields
- Dynamic aria-invalid based on validation state
4. Tracking Forms:
- Feeding form (app/track/feeding/page.tsx)
- Child selector, side selector, bottle type
- Food description with required validation
- Sleep form (app/track/sleep/page.tsx)
- Child selector, start/end time fields
- Quality and location selectors
**WCAG 2.1 Compliance:**
- ✅ 3.3.2 Labels or Instructions (AA)
- ✅ 4.1.3 Status Messages (AA)
- ✅ 1.3.1 Info and Relationships (A)
- ✅ 3.3.1 Error Identification (A)
**Documentation:**
- Updated REMAINING_FEATURES.md
- Marked Form Accessibility Enhancement as complete
- Status: 79 features completed (57%)
🎉 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
- **EULA Persistence Fix**: Fixed EULA dialog showing on every login
- Added eulaAcceptedAt/eulaVersion to AuthResponse interface
- Updated login/register/getUserById endpoints to return EULA fields
- Changed EULACheck to use refreshUser() instead of window.reload()
- **Touch Target Accessibility**: All interactive elements now meet 48x48px minimum
- Fixed 14 undersized IconButtons across 5 files
- Changed size="small" to size="medium" with minWidth/minHeight constraints
- Updated children page, AI chat, analytics cards, legal viewer
- **Alt Text for Images**: Complete image accessibility for screen readers
- Added photoAlt field to children table (Migration V009)
- PhotoUpload component now includes alt text input field
- All Avatar components have meaningful alt text
- Default alt text: "Photo of {childName}", "{userName}'s profile photo"
- **Medical Tracking Consolidation**: Unified medical page with tabs
- Medicine page now has 3 tabs: Medication, Temperature, Doctor Visit
- Backward compatibility for legacy 'medicine' activity type
- Created dedicated /track/growth page for physical measurements
- **Track Page Updates**:
- Simplified to 6 options: Feeding, Sleep, Diaper, Medical, Activity, Growth
- Fixed grid layout to 3 cards per row with minWidth: 200px
- Updated terminology from "Medicine" to "Medical"
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Changes:
- Created UnifiedInsightsDashboard component with 2 tabs
- Tab 1: Insights - Shows existing charts, stats, and recent activities
- Tab 2: Predictions - Shows AI-powered predictions for next activities
- Growth Spurt Alert appears at the top when detected
- Child selector for families with multiple children
- Clean tab navigation with Timeline and TrendingUp icons
Features Now Accessible from /insights:
✅ Growth Spurt Detection (appears as alert banner)
✅ Pattern Analysis (feeding, sleep, diaper trends)
✅ AI Predictions (next feeding time, sleep duration, etc.)
✅ Charts and visualizations
✅ Recent activities timeline
User Experience:
- Single page access from bottom navigation (Insights icon)
- No need for separate /analytics page
- All smart AI features visible in one place
- Tab switching for different views
Files Changed:
- app/insights/page.tsx - Updated to use UnifiedInsightsDashboard
- components/features/analytics/UnifiedInsightsDashboard.tsx (new)
* Manages state for both tabs
* Loads insights and predictions data
* Renders Growth Spurt Alert
* Tab navigation UI
🎯 Result: Users can now easily see all AI insights and predictions
from the Insights menu item in bottom navigation!
Co-Authored-By: Claude <noreply@anthropic.com>
- Created reusable PhotoUpload component with avatar preview
- Added photo upload to child create/edit dialog
- Added profile photo upload to settings page
- Show photo preview with fallback icon
- Display camera button for future file upload integration
- Support URL paste for immediate photo display
- Updated API types to support photoUrl field
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Convert Active Sessions and Trusted Devices to collapsible Accordion components
- Display count badge in collapsed state
- Show loading state in accordion header
- Implement 2-card grid layout on mobile (xs=6)
- Responsive card sizing and spacing
- Centered layout on mobile, horizontal on desktop
- Hide full birthdate on mobile, show age only
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Date/Time Formatting Polish:
- Added German and Italian locales to useLocalizedDate hook
- Applied localized date formatting to children birth dates (PPP format)
- InsightsDashboard already using localized date formatting
Number Formatting Polish:
- Applied Intl.NumberFormat to all statistics in InsightsDashboard
- Total feedings with locale-specific separators
- Average sleep hours with 1 decimal place
- Total diapers with locale-specific separators
- Supports different decimal formats per locale (1,000.50 vs 1.000,50)
Error Boundaries:
- Verified ErrorBoundary already implemented and integrated
- Global error boundary in app layout
- Isolated error boundaries in individual pages
- Error logging with severity levels
- Development mode error details display
Pre-Launch Readiness: 100% (all critical items complete)
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Updated track page cards to match home page styling with vibrant colors
- Applied consistent 140px height cards across track and insights pages
- Added mobile header bar with connection status and user menu
- Moved user menu from floating top-left to fixed header top-right
- Updated insights dashboard with home page color palette (#E91E63, #1976D2, etc.)
- Centered cards with minWidth constraints (200px for stats, 400px for charts)
- Fixed hydration mismatch by replacing JS media queries with CSS breakpoints
- Improved accessibility with viewport settings (removed zoom restrictions)
- Added UI improvements documentation
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Extract family data from registration response and add to user object
- Backend returns family separately in registration, but included in user for login
- Remove error messages for language/measurement preferences (they save correctly)
- Add detailed console logging for debugging family issues
- Improve error message when family is missing during child creation
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Added dateOfBirth, parentalEmail, and coppaConsentGiven to RegisterData interface
- Updated register function to include all required COPPA compliance fields in API payload
- Added debug logging to see registration payload
- Fixed 400 error during registration due to missing required dateOfBirth field
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Moved themeColor and viewport config from metadata to viewport export
- Fixes Next.js 15 warnings about unsupported metadata fields
- Registration error was actually due to user already existing (409)
- Backend validation passes correctly with deviceInfo included
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Repositioned Voice Command button to center of bottom navigation bar
- Added floating user menu icon in top-left corner on mobile
- User menu includes: Settings, Children, Family, and Logout options
- Updated bottom nav to show: Home, Track, Voice (center), Insights, History
- Hide original floating voice button on mobile to avoid duplication
- Improved mobile UX with easier thumb access to voice commands
- User avatar displays first letter of user's name
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Updated all Spanish (es) translation files with comprehensive translations for tracking, AI, family, insights, children, and settings pages
- Updated French (fr), Portuguese (pt), and Chinese (zh) translations to match English structure
- Added German (de) and Italian (it) language support with complete translation files
- Fixed medicine tracker route from /track/medication to /track/medicine
- Updated i18n config to support 7 languages: en, es, fr, pt, zh, de, it
- All tracking pages now fully localized: sleep, feeding, diaper, medicine, activity
- AI assistant interface fully translated with thinking messages and suggested questions
- Family management and insights pages now support all languages
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Changed quick action link from /track/medication to /track/medicine
to match the actual route defined in the app structure.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Updated getMedicineDetails() in medicine tracking page to:
- Convert ml dosages to oz when user has imperial preference
- Display non-liquid units (mg, tablets, drops) as-is
- Match the pattern used in feeding page for consistency
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Fixed measurement unit not persisting across page refreshes:
- Settings page now includes measurementUnit in the preferences object when saving
- MeasurementUnitSelector now accepts value/onChange props for controlled usage
- Settings state properly loads and saves measurementUnit from user preferences
- UnitInput component will now correctly read imperial/metric from user.preferences.measurementUnit
Previously, measurementUnit was only saved to localStorage but not synced to backend,
causing UnitInput to always default to metric since it reads from user.preferences.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Implemented automatic unit conversions for feeding and medicine tracking:
- Created UnitInput component for automatic ml↔oz conversions
- Updated Feeding page to use UnitInput for bottle amounts
- Updated Medicine page to use UnitInput for liquid medicine dosages
- All values stored in metric (ml) in database
- Display values automatically converted based on user's measurement preference
- Supports voice input with proper unit handling
Component features:
- Automatic conversion between metric and imperial
- User preference-based display
- Consistent metric storage
- Type safety with TypeScript
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>