---
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