288 lines
9.6 KiB
Markdown
288 lines
9.6 KiB
Markdown
---
|
|
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
|
|
---
|
|
|
|
<objective>
|
|
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.
|
|
</objective>
|
|
|
|
<execution_context>
|
|
@./.opencode/get-shit-done/workflows/execute-plan.md
|
|
@./.opencode/get-shit-done/templates/summary.md
|
|
</execution_context>
|
|
|
|
<context>
|
|
@.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
|
|
</context>
|
|
|
|
<tasks>
|
|
|
|
<task type="auto" tdd="true">
|
|
<name>task 1: Create RainfallCard component</name>
|
|
<files>src/app/components/RainfallCard.tsx, src/app/components/__tests__/RainfallCard.test.tsx</files>
|
|
<behavior>
|
|
- 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
|
|
</behavior>
|
|
<action>
|
|
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
|
|
</action>
|
|
<verify>
|
|
<automated>npm test -- --run RainfallCard 2>&1 | grep -E "(PASS|FAIL|✓|✗)"</automated>
|
|
</verify>
|
|
<done>RainfallCard component with 4 color variants created</done>
|
|
</task>
|
|
|
|
<task type="auto" tdd="true">
|
|
<name>task 2: Create ClockDisplay component</name>
|
|
<files>src/app/components/ClockDisplay.tsx, src/app/components/__tests__/ClockDisplay.test.tsx</files>
|
|
<behavior>
|
|
- Displays HH:MM:SS in 24-hour format
|
|
- Updates every second
|
|
- Shows date (YYYY-MM-DD) below or beside
|
|
- Cleans up interval on unmount
|
|
</behavior>
|
|
<action>
|
|
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)
|
|
</action>
|
|
<verify>
|
|
<automated>npm test -- --run ClockDisplay 2>&1 | grep -E "(PASS|FAIL|✓|✗)"</automated>
|
|
</verify>
|
|
<done>ClockDisplay with real-time updates created</done>
|
|
</task>
|
|
|
|
<task type="auto" tdd="true">
|
|
<name>task 3: Create CommStatus component</name>
|
|
<files>src/app/components/CommStatus.tsx, src/app/components/__tests__/CommStatus.test.tsx</files>
|
|
<behavior>
|
|
- Shows ASU (0-31), dBm, percentage
|
|
- Visual indicator for signal strength
|
|
- Updates from sensor store
|
|
- Compact for header placement
|
|
</behavior>
|
|
<action>
|
|
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
|
|
</action>
|
|
<verify>
|
|
<automated>npm test -- --run CommStatus 2>&1 | grep -E "(PASS|FAIL|✓|✗)"</automated>
|
|
</verify>
|
|
<done>CommStatus component with signal visualization</done>
|
|
</task>
|
|
|
|
<task type="auto" tdd="true">
|
|
<name>task 4: Create RainfallView dashboard</name>
|
|
<files>src/app/components/views/RainfallView.tsx, src/app/components/__tests__/RainfallView.test.tsx</files>
|
|
<behavior>
|
|
- Displays 4 RainfallCards in grid
|
|
- Shows optional ClockDisplay
|
|
- Shows CommStatus
|
|
- Uses sensor store data
|
|
- Responsive layout for both modes
|
|
</behavior>
|
|
<action>
|
|
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
|
|
</action>
|
|
<verify>
|
|
<automated>npm test -- --run RainfallView 2>&1 | grep -E "(PASS|FAIL|✓|✗)"</automated>
|
|
</verify>
|
|
<done>RainfallView dashboard with responsive grid created</done>
|
|
</task>
|
|
|
|
<task type="auto">
|
|
<name>task 5: Implement dual-mode responsive layout</name>
|
|
<files>src/app/components/views/RainfallView.tsx, src/styles/responsive.css</files>
|
|
<behavior>
|
|
- Port 8080: Compact layout for 1024x600
|
|
- Port 9090: Expanded layout for Full HD
|
|
- Cards resize appropriately
|
|
- Font sizes scale with mode
|
|
</behavior>
|
|
<action>
|
|
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
|
|
</action>
|
|
<verify>
|
|
<automated>grep -n "useDisplayMode\|kiosk\|remote" src/app/components/views/RainfallView.tsx 2>/dev/null | head -10</automated>
|
|
</verify>
|
|
<done>Dual-mode layout responds to port number</done>
|
|
</task>
|
|
|
|
</tasks>
|
|
|
|
<verification>
|
|
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`
|
|
</verification>
|
|
|
|
<success_criteria>
|
|
- 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
|
|
</success_criteria>
|
|
|
|
<output>
|
|
After completion, create `.planning/phases/01-foundation-dashboard/01-03-SUMMARY.md`
|
|
</output>
|