# Dashboard Specification ## Job to Be Done When I open the app each morning, I want to immediately see whether I should train today, so that I can make informed decisions without manual data analysis. ## Components ### Decision Card (`decision-card.tsx`) Displays the daily training decision prominently. **Required Elements:** - Large status indicator (REST / GENTLE / LIGHT / REDUCED / TRAIN) - Color-coded background (red for REST, yellow for GENTLE/LIGHT/REDUCED, green for TRAIN) - Reason text explaining why this decision was made - Icon matching the decision status **Data Source:** - `/api/today` endpoint returns current decision ### Data Panel (`data-panel.tsx`) Shows the biometric data used to make the decision. **Required Elements:** - HRV Status (Balanced/Unbalanced/Unknown) - Body Battery Current (0-100) - Body Battery Yesterday Low (0-100) - Cycle Day (e.g., "Day 12") - Current Phase (MENSTRUAL, FOLLICULAR, OVULATION, EARLY_LUTEAL, LATE_LUTEAL) - Week Intensity Minutes (accumulated) - Phase Limit (weekly cap based on phase) - Remaining Minutes until limit **Visual Indicators:** - Color-code HRV status (green=Balanced, red=Unbalanced, gray=Unknown) - Progress bar for week intensity vs phase limit ### Nutrition Panel (`nutrition-panel.tsx`) Displays seed cycling and macro guidance. **Required Elements:** - Current seeds to consume (Flax+Pumpkin OR Sesame+Sunflower) - Carb range for the day (e.g., "20-100g") - Keto guidance (OPTIONAL / No / NEVER with reason) - Seed switch alert on day 15 **Data Source:** - `getNutritionGuidance(cycleDay)` from `src/lib/nutrition.ts` ### Override Toggles (`override-toggles.tsx`) Emergency modifications to the standard decision. **Override Types:** - `flare` - Hashimoto's flare (force REST) - `stress` - High stress day (force REST) - `sleep` - Poor sleep (<6 hours) (force GENTLE) - `pms` - PMS symptoms (force GENTLE) **Behavior:** - Toggle buttons for each override - Active overrides persist until manually cleared - Active overrides override the algorithmic decision - Store in `user.activeOverrides[]` ### Mini Calendar (`mini-calendar.tsx`) Visual cycle overview for the current month. **Required Elements:** - Monthly grid view - Today highlighted - Phase colors for each day - Period days marked distinctly - Quick navigation to previous/next month ## UI States ### Loading States Use skeleton loaders during data fetching: - Decision card: Shimmer placeholder for status and reason - Data panel: Skeleton rows for each metric - Mini calendar: Placeholder grid ### Error Handling Toast notifications for errors with actionable feedback: - Network errors: "Unable to fetch data. Retry?" - Garmin sync failed: "Garmin data unavailable. Using last known values." - Save errors: "Failed to save. Try again." Toast position: Bottom-right, auto-dismiss after 5 seconds (errors persist until dismissed). ## Dark Mode Auto-detect system preference via CSS `prefers-color-scheme`: - No manual toggle - Respect OS-level dark mode setting - Ensure all phase colors maintain contrast in both modes ## Onboarding First-time users see inline prompts/banners for missing setup: | Missing State | Banner Message | Action | |---------------|----------------|--------| | Garmin not connected | "Connect your Garmin to get started" | Link to /settings/garmin | | Last period not set | "Set your last period date for accurate tracking" | Opens date picker | | Notification time not set | "Set your preferred notification time" | Link to /settings | Banners appear at top of dashboard, dismissable once action completed. ## Responsive Design Mobile-responsive layout: - Single-column layout on mobile (<768px) - All critical metrics visible without scrolling - Touch-friendly toggle buttons (min 44x44px tap targets) - Collapsible sections for secondary content ## Accessibility Basic accessibility requirements: - Semantic HTML (proper heading hierarchy, landmarks) - Keyboard navigation for all interactive elements - Focus indicators visible - Color contrast minimum 4.5:1 for text - Phase colors supplemented with icons/text (not color-only) ## Success Criteria 1. User can determine training status within 3 seconds of opening app 2. All biometric data visible without scrolling on mobile 3. Override toggles accessible but not accidentally activated 4. Phase colors consistent across all components 5. Dashboard usable with keyboard only 6. Loading states display within 100ms of navigation ## Acceptance Tests - [ ] Dashboard loads decision from `/api/today` - [ ] Decision card shows correct status and color - [ ] Data panel displays all 8 required metrics - [ ] Nutrition panel shows correct seeds for cycle day - [ ] Override toggles update user record immediately - [ ] Mini calendar renders current month with phase colors - [ ] Skeleton loaders appear during data fetch - [ ] Toast notifications display on error - [ ] Dark mode activates based on system preference - [ ] Onboarding banner shows when Garmin not connected - [ ] Dashboard renders correctly on mobile viewport - [ ] All interactive elements keyboard-accessible