- 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>
BUG-1: Voice tracking not saving activities
- Fix activity data format to match backend CreateActivityDto
- Change 'timestamp' to 'startedAt' and 'data' to 'metadata'
- Remove duplicate voice button from mobile TabBar
BUG-2: Session persistence after revocation
- Add logout() call when revoking all sessions
- Add logout() call when removing all devices
- Ensures user is logged out after session/device revocation
- Clears tokens and redirects to login
BUG-3: Voice modal status not updating
- Set identifiedActivity before saving to show tracker name
- Display "Adding to [tracker] tracker..." during save
- Improves UX by showing which tracker is being updated
🤖 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>
Fixed React hydration warnings caused by invalid HTML nesting in the
DeviceTrustManagement component.
## Issues Fixed
- Error: "<p> cannot be a descendant of <p>"
- Error: "<div> cannot be a descendant of <p>"
- Error: "<p> cannot contain a nested <p>"
- Error: "<p> cannot contain a nested <div>"
## Root Cause
The ListItemText component renders its secondary prop as a <p> tag by default.
We were incorrectly nesting Box (<div>) and Typography (<p>) components inside
the secondary prop, causing invalid HTML structure.
## Solution
- Removed nested Box and Typography components from ListItemText props
- Used simple text content with <br /> for line breaks in secondary text
- Moved chips (Current, Trusted/Untrusted) outside of ListItemText
- Positioned chips as separate Box between ListItemText and ListItemSecondaryAction
- Maintained visual layout while fixing HTML structure
## Changes
- primary: Now just plain text (device.platform)
- secondary: Plain text with <br /> separator instead of nested Typography
- Chips: Moved to separate Box with flex layout
This ensures proper HTML semantics and eliminates hydration errors.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Improved the settings page by removing individual save buttons from each
preference component and adding unified save buttons per section:
## Changes Made
### Component Updates
- **TimeZoneSelector**: Converted to controlled component with value/onChange props
* Removed internal state management and save button
* Removed success/error alerts (now handled by parent)
* Added auto-detect as simple button without save
- **TimeFormatSelector**: Converted to controlled component with value/onChange props
* Removed internal state management and save button
* Removed success/error alerts (now handled by parent)
* Simplified to just radio buttons with preview
### Settings Page Improvements
- Added timezone and timeFormat to local state
- Created separate save handlers:
* `handleSaveProfile` - for name/email changes
* `handleSavePreferences` - for timezone and time format
- Three clear sections with dedicated save buttons:
1. **Profile Information** → "Save Profile" button
2. **Preferences** (Language, Units, Timezone, Time Format) → "Save Preferences" button
3. **Notifications** → "Save Notification Settings" button
### User Experience Benefits
- Clearer separation between different types of settings
- Single save action per logical section instead of multiple buttons
- Consistent save pattern across all settings cards
- Reduced visual clutter with fewer buttons on page
- Better organization: related settings grouped with one save action
Files changed: 3 files (TimeZoneSelector, TimeFormatSelector, settings page)
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
This commit implements comprehensive timezone and time format customization:
## Backend Changes
- Added timeFormat field ('12h' | '24h') to user preferences JSONB in user entity
- Timezone field already existed in user entity, now actively used
- Backend ready to accept timezone on registration
## Frontend Components (2 new)
- TimeZoneSelector: Dropdown with timezones grouped by region (Americas, Europe, Asia, Pacific, Africa)
* Auto-detect button to detect browser timezone
* Save functionality with success/error feedback
* Integrated into Settings > Preferences section
- TimeFormatSelector: Radio buttons to choose 12h vs 24h format
* Live preview showing current time in selected format
* Save functionality with user feedback
* Integrated into Settings > Preferences section
## Timezone Auto-Detection
- Register function now auto-detects user's timezone via Intl.DateTimeFormat()
- Detected timezone sent to backend during registration
- Timezone stored in user profile for persistent preference
## Enhanced useLocalizedDate Hook
- Added useAuth integration to access user timezone and timeFormat preferences
- Installed and integrated date-fns-tz for timezone conversion
- New format() function with timezone support via useTimezone option
- New formatTime() function respecting user's 12h/24h preference
- New formatDateTime() function combining date, time, and timezone
- All formatting now respects user's:
* Language (existing: en, es, fr, pt-BR, zh-CN)
* Timezone (user-selected or auto-detected)
* Time format (12h with AM/PM or 24h)
## Settings Page Updates
- Added TimeZoneSelector to Preferences card
- Added TimeFormatSelector to Preferences card
- Visual separators (Dividers) between preference sections
- Settings now show: Language | Units | Timezone | Time Format
## Translations
- Enhanced settings.json with timezone and time format keys:
* preferences.timezone, autoDetectTimezone, timezoneUpdated
* preferences.12hour, 24hour, timeFormatUpdated
## User Experience Flow
1. User registers → timezone auto-detected and saved
2. User can change timezone in Settings > Preferences > Time Zone
3. User can change time format in Settings > Preferences > Time Format
4. All dates/times throughout app respect these preferences
5. Changes persist across sessions
Files changed: 10 files
New dependencies: date-fns-tz
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Implemented comprehensive frontend localization infrastructure supporting
5 languages (English, Spanish, French, Portuguese, Chinese) with measurement
unit preferences (Metric/Imperial). This lays the foundation for international
user support.
**Core Infrastructure:**
- Installed i18next, react-i18next, i18next-browser-languagedetector
- Created I18nProvider component integrated into app layout
- Configured i18next with language detection and localStorage persistence
- Created 35 translation files (5 languages × 7 namespaces)
**Translation Namespaces:**
- common: App-wide UI elements, navigation, actions
- tracking: Activity tracking (feeding, sleep, diaper, milestones)
- ai: AI assistant chat interface
- auth: Authentication flows (login, signup, password reset)
- settings: Settings and preferences
- onboarding: Onboarding flow
- errors: Error messages and validation
**Custom Hooks:**
- useTranslation: Type-safe translation wrapper
- useLocale: Language and measurement system management
- useFormatting: Date, time, number, and unit formatting
**Measurement Unit Support:**
- Created unit conversion utilities (weight, height, temperature, volume)
- Metric: kg, cm, °C, ml
- Imperial: lb, in, °F, oz
- Bidirectional conversion functions
**UI Components:**
- LanguageSelector: Dropdown to change app language
- MeasurementUnitSelector: Toggle between Metric/Imperial
- Integrated both into Settings page Preferences section
**Next Steps (Remaining):**
- Add measurement preferences to backend user schema
- Create onboarding flow with language/measurement selection
- Apply translations to existing components (dashboard, tracking forms)
- Implement multi-language AI responses
- Add professional translations (currently using basic translations)
**File Highlights:**
- lib/i18n/config.ts: i18next configuration
- hooks/useFormatting.ts: Formatting utilities with locale support
- lib/utils/unitConversion.ts: Unit conversion logic
- components/settings/*Selector.tsx: Language and measurement selectors
- locales/*/: Translation files for 5 languages
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Frontend Compliance Features:
- Created compliance API client (data export, account deletion, deletion status)
- Added DataExport component with download functionality
- Added AccountDeletion component with 30-day grace period UI
- Updated Settings page with Privacy & Compliance sections
COPPA Age Verification:
- Added date of birth field to registration
- Age calculation with COPPA compliance (under 13 blocked)
- Parental email and consent for users 13-17
- Dynamic form validation based on age
Privacy & Terms:
- Separate checkboxes for Terms of Service and Privacy Policy
- Required acceptance for registration
- Links to policy pages
Completes GDPR Right to Data Portability and Right to Erasure.
Completes COPPA parental consent requirements.
- Create biometric API client with WebAuthn methods
- Add BiometricSettings component for credential management
- Support Face ID, Touch ID, Windows Hello enrollment
- Display list of enrolled credentials with metadata
- Add/remove/rename biometric credentials
- Check browser and platform authenticator support
- Integrate into settings page with animations
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Implements user interface for viewing and managing active sessions:
Session Management Features:
- SessionsManagement component with full session management UI
- List all active sessions with device information
- Platform-specific icons (Computer, Phone, Tablet)
- Current session indicator with green chip
- Session details: device fingerprint, platform, last used, created date
- Revoke individual sessions with confirmation dialog
- Revoke all sessions except current with bulk action
- Real-time session count display
User Experience:
- Visual device type indicators
- Human-readable time formatting (e.g., "2 hours ago")
- Current session clearly marked and protected from removal
- Warning dialogs before revoking sessions
- Success/error feedback with alerts
- Loading states for all operations
- Empty state handling
API Integration:
- Sessions API client in lib/api/sessions.ts
- Get all sessions
- Get session count
- Revoke specific session
- Revoke all sessions except current
- Proper error handling and user feedback
Settings Page Integration:
- Added Sessions Management section
- Placed after Security/MFA settings
- Animated transitions with staggered delays
- Maintains consistent settings page layout
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>