--- phase: 01-foundation-dashboard plan: 03 type: execute wave: 2 depends_on: - 01-01 - 01-02 files_modified: - src/app/components/views/RainfallView.tsx - src/app/components/RainfallCard.tsx - src/app/components/StationInfo.tsx - src/app/components/ClockDisplay.tsx - src/app/components/CommStatus.tsx - src/app/components/__tests__/RainfallView.test.tsx - src/app/components/__tests__/RainfallCard.test.tsx autonomous: true requirements: - DASH-01 - DASH-05 - DASH-06 - DASH-04 - UI-01 - UI-02 - UI-03 must_haves: truths: - Dashboard shows 4 rainfall cards (Today/Hourly/MAR/Yearly) - Cards update in real-time from sensor store - Clock displays HH:MM:SS with seconds - Comm status shows ASU/dBm/percentage - Layout adapts to kiosk (1024x600) and remote (Full HD) modes artifacts: - path: src/app/components/views/RainfallView.tsx provides: Main dashboard view exports: RainfallView min_lines: 60 - path: src/app/components/RainfallCard.tsx provides: Individual rainfall metric card exports: RainfallCard - path: src/app/components/ClockDisplay.tsx provides: Real-time clock component exports: ClockDisplay key_links: - from: RainfallView to: sensorStore via: useSensorStore hook - from: RainfallCard to: RainfallView via: Props passing rainfall data - from: ClockDisplay to: sensorStore via: Optional sync with store timestamp --- Create the main dashboard view with rainfall cards, clock display, communication status, and dual-mode responsive layout. Purpose: This is the primary user interface where operators view rainfall data and station status. Must work on both 7" touchscreen (1024x600) and Full HD remote displays. Output: RainfallView as main dashboard, RainfallCard components, ClockDisplay, and CommStatus with responsive layouts. @./.opencode/get-shit-done/workflows/execute-plan.md @./.opencode/get-shit-done/templates/summary.md @.planning/phases/01-foundation-dashboard/01-CONTEXT.md @.planning/phases/01-foundation-dashboard/01-01-SUMMARY.md @.planning/phases/01-foundation-dashboard/01-02-SUMMARY.md @sample_interface/src/app/components/views/RainfallView.tsx ## Key Implementation Details **Rainfall Metrics (4 cards):** - Today: Current day's rainfall in mm - Hourly: Current hour's rainfall in mm - MAR Acc: Monthly accumulation in mm - Yearly Acc: Yearly accumulation in mm **Card Design:** - Color-coded: Today (blue), Hourly (cyan), MAR (green), Yearly (purple) - Large value display: XX.X mm - Label below value - Compact for grid layout - Touch-friendly (44px+ tap area) **Grid Layout:** - Kiosk (1024x600): 2x2 grid, compact cards - Remote (Full HD): 4x1 or 2x2 with larger cards - Use CSS Grid with responsive breakpoints **Clock Display:** - Format: HH:MM:SS (24-hour) - Updates every second - Also shown in Header (this is secondary/alternative) **Comm Status:** - ASU: Signal strength (0-31) - dBm: Signal power - Percentage: Derived from ASU task 1: Create RainfallCard component src/app/components/RainfallCard.tsx, src/app/components/__tests__/RainfallCard.test.tsx - Displays rainfall value in mm (XX.X format) - Shows label (Today/Hourly/MAR Acc/Yearly Acc) - Color-coded border or background - Large readable text - Updates when value changes 1. Create src/app/components/RainfallCard.tsx: - Props: label (string), value (number), variant (today|hourly|monthly|yearly) - Format value to one decimal place - Color variants: today=blue, hourly=cyan, monthly=green, yearly=purple - Use shadcn/ui Card component as base - Min-height 100px for touch targets - Value text: text-3xl font-bold - Label text: text-sm text-muted-foreground - Add rain icon from Lucide (CloudRain) 2. Create tests: - Renders label and formatted value - Applies correct color variant - Updates on value change - Has minimum dimensions npm test -- --run RainfallCard 2>&1 | grep -E "(PASS|FAIL|✓|✗)" RainfallCard component with 4 color variants created task 2: Create ClockDisplay component src/app/components/ClockDisplay.tsx, src/app/components/__tests__/ClockDisplay.test.tsx - Displays HH:MM:SS in 24-hour format - Updates every second - Shows date (YYYY-MM-DD) below or beside - Cleans up interval on unmount 1. Create src/app/components/ClockDisplay.tsx: - Use useState for current time - Use useEffect with setInterval (1000ms) - Format with date-fns or native Intl - Display: Time large, date smaller - Optional: Sync with sensor store timestamp - Cleanup interval in useEffect return - Touch-friendly container 2. Create tests: - Renders time in correct format - Renders date in correct format - Cleanup works on unmount (no memory leaks) npm test -- --run ClockDisplay 2>&1 | grep -E "(PASS|FAIL|✓|✗)" ClockDisplay with real-time updates created task 3: Create CommStatus component src/app/components/CommStatus.tsx, src/app/components/__tests__/CommStatus.test.tsx - Shows ASU (0-31), dBm, percentage - Visual indicator for signal strength - Updates from sensor store - Compact for header placement 1. Create src/app/components/CommStatus.tsx: - Props: asu (number), dBm (number), percentage (number) - Calculate percentage from ASU if not provided: (asu/31)*100 - Visual indicator: signal bars or progress - Color: green (good), yellow (fair), red (poor) - Compact display: icon + brief text - Use Lucide Signal icon 2. Create tests: - Displays all three values - Calculates percentage correctly - Shows appropriate color indicator npm test -- --run CommStatus 2>&1 | grep -E "(PASS|FAIL|✓|✗)" CommStatus component with signal visualization task 4: Create RainfallView dashboard src/app/components/views/RainfallView.tsx, src/app/components/__tests__/RainfallView.test.tsx - Displays 4 RainfallCards in grid - Shows optional ClockDisplay - Shows CommStatus - Uses sensor store data - Responsive layout for both modes 1. Create/update src/app/components/views/RainfallView.tsx: - Import useSensorStore - Import RainfallCard, ClockDisplay, CommStatus - Get rainfall data from store - Grid layout: 2 cols on mobile/kiosk, 4 cols on desktop/remote - Use CSS Grid: grid-cols-2 lg:grid-cols-4 - Gap: gap-4 - Padding: p-4 - Add section title: "Rainfall Monitor" - Show last update timestamp - Responsive font sizes 2. Create tests: - Renders all 4 rainfall cards - Passes correct data to each card - Has responsive grid layout - Updates when store changes npm test -- --run RainfallView 2>&1 | grep -E "(PASS|FAIL|✓|✗)" RainfallView dashboard with responsive grid created task 5: Implement dual-mode responsive layout src/app/components/views/RainfallView.tsx, src/styles/responsive.css - Port 8080: Compact layout for 1024x600 - Port 9090: Expanded layout for Full HD - Cards resize appropriately - Font sizes scale with mode 1. Update RainfallView with mode-aware styling: - Import useDisplayMode from hooks - Apply conditional classes based on mode - Kiosk: More compact padding, smaller gaps - Remote: Larger spacing, bigger fonts 2. Create src/styles/responsive.css if needed: - Define mode-specific utilities - Or use Tailwind classes inline 3. Test responsive behavior: - Verify grid adapts to viewport - Cards maintain touch target size - No horizontal scroll at 1024px grep -n "useDisplayMode\|kiosk\|remote" src/app/components/views/RainfallView.tsx 2>/dev/null | head -10 Dual-mode layout responds to port number After completing all tasks: 1. Run `npm test` — all tests should pass 2. Verify dashboard exists: `ls src/app/components/views/RainfallView.tsx` 3. Check responsive classes: `grep -E "grid-cols-|lg:grid-cols" src/app/components/views/RainfallView.tsx` 4. Verify sensor store connection: `grep "useSensorStore" src/app/components/views/RainfallView.tsx` - RainfallCard component with 4 color variants exists - RainfallView displays 4 cards in responsive grid - ClockDisplay shows HH:MM:SS updating every second - CommStatus shows ASU/dBm with visual indicator - Layout adapts to kiosk (1024x600) and remote (Full HD) modes - All components tested and passing After completion, create `.planning/phases/01-foundation-dashboard/01-03-SUMMARY.md`