BMS/ACTION_PLAN.md
2026-03-19 11:32:17 +00:00

149 lines
7.3 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# BMS Action Plan — Post-Audit Fixes
> Generated: 2026-03-10
> Based on cross-referencing live site (bmsdemo.rdx4.com) against IMPROVEMENTS.md and source audit.
> Excludes: Clerk auth (intentional public demo), scheduled PDF email (deferred).
---
## Phase 1 — Trivial Fixes (< 30 min, no backend, no context changes)
These are single-file, low-risk changes.
| # | File | Issue | Fix |
|---|------|-------|-----|
| 1.1 | `components/layout/sidebar.tsx` | Network is in the "Safety" group alongside Leak and Fire, which is semantically wrong | Move `/network` into the "Infrastructure" group, below Generator |
| 1.2 | `lib/api.ts` | Base path is `/api/backend` and all fetch paths start `/api/...`, resulting in `/api/backend/api/...` — looks like a double-prefix at first glance | Add a one-line comment above `const BASE` explaining the proxy path convention |
| 1.3 | `IMPROVEMENTS.md` | Settings page (`/settings`) is fully built but completely absent from the plan | Add a new entry to Phase 6 or a new Phase 7 "Untracked Additions" section to document it |
| 1.4 | `IMPROVEMENTS.md` | Item 6.11 "mini floor map thumbnail" is marked `[x]` but what was built is a `RoomStatusGrid` (tabular room stats), not a visual rack-grid thumbnail | Update the description to clarify what was actually delivered, or un-tick and add to backlog |
---
## Phase 2 — Settings Page: Wire Up Persistence
Currently all Settings save buttons have no `onClick` handler and threshold edits are never written anywhere. All pages read from the static `THRESHOLDS` constant in `lib/thresholds.ts`, making the entire Settings page cosmetic.
This phase makes Settings functional without a backend API — using `localStorage` and a React context so changes persist across refreshes and propagate to all pages at runtime.
### 2.1 — Create a `ThresholdContext`
**New file:** `lib/threshold-context.tsx`
- Wraps the static `THRESHOLDS` object as default values
- On mount, reads overrides from `localStorage` key `bms_thresholds` and merges
- Exposes `thresholds` (the merged values) and `setThresholds(patch)` (writes to localStorage and re-renders)
- Re-export a `useThresholds()` hook
### 2.2 — Add the provider to the dashboard layout
**File:** `app/(dashboard)/layout.tsx`
- Wrap children in `<ThresholdProvider>` so all dashboard pages share the same context
### 2.3 — Update pages to read from context
Pages that currently import and use `THRESHOLDS` directly need to call `useThresholds()` instead. A grep for `THRESHOLDS` in `app/(dashboard)/` will give the full list. Likely candidates:
- `environmental/page.tsx` (temp/humidity thresholds for heatmap + ASHRAE table)
- `cooling/page.tsx` (filter ΔP, COP, compressor thresholds)
- `power/page.tsx` (rack power warn/crit lines on bar chart)
- `capacity/page.tsx` (radial gauge colour bands)
- `floor-map/page.tsx` (rack tile colour scale)
`lib/thresholds.ts` stays as the canonical defaults — no change needed there.
### 2.4 — Wire the Save buttons in `settings/page.tsx`
**File:** `app/(dashboard)/settings/page.tsx`
- `ThresholdsTab`: call `setThresholds({ temp: { warn, critical }, humidity: { ... }, power: { ... } })` in the Save onClick
- `ProfileTab` / `NotificationsTab`: these are cosmetic for a demo — write to `localStorage` under `bms_profile` / `bms_notifications` keys so at least the values survive a refresh, even if they don't affect anything functional
### 2.5 — Add a visible "saved" confirmation
Currently there is no feedback when Save is clicked. Add a brief `sonner` toast (the project already uses it) on successful save. The `Toaster` is already mounted in the dashboard layout.
---
## Phase 3 — Dashboard: True Mini Floor Map Thumbnail
Item 6.11 was marked done but delivered a room status table rather than a visual map.
**File:** `app/(dashboard)/dashboard/page.tsx` + new component `components/dashboard/mini-floor-map.tsx`
- Replace (or sit alongside) `RoomStatusGrid` in the bottom row with a compact rack-grid tile
- Re-use the colour logic already written in `floor-map/page.tsx` (temp overlay colours by default)
- Each rack tile is a small coloured square (~12×16px), labelled with rack ID on hover tooltip
- CRAC units shown as labelled strips at room edge (same pattern as full floor map)
- Click navigates to `/floor-map`
- Room tabs (Hall A / Hall B) if both rooms are present
- Read from the same `/api/readings/rack-status` data already fetched on dashboard
This requires no backend changes — just a new presentational component that reuses existing API data.
---
## Phase 4 — Floor Map: Zoom/Pan + CRAC Coverage Shading
These are the two remaining open items from 6.12.
### 4.1 — Zoom / Pan
**File:** `app/(dashboard)/floor-map/page.tsx`
- Add `react-zoom-pan-pinch` (or equivalent) as a dependency: `pnpm add react-zoom-pan-pinch`
- Wrap the rack grid `div` in a `<TransformWrapper>` / `<TransformComponent>` block
- Add zoom controls (+ / / reset buttons) in the map header, above the legend
- Pinch-to-zoom should work on touch devices automatically via the library
### 4.2 — CRAC Coverage Shading
**File:** `app/(dashboard)/floor-map/page.tsx`
- Add a 5th overlay option to the overlay selector: **CRAC Coverage**
- When active, colour each rack tile according to which CRAC unit is its nearest thermal neighbour (assign by row proximity — CRACs at room ends serve the rows closest to them, split at the midpoint)
- Use a per-CRAC colour palette (46 distinct hues, low-opacity background fill)
- Show CRAC ID in the legend with its assigned colour
- No backend required — assignment is purely spatial, computed client-side from rack row index and CRAC position
---
## Phase 5 — Environmental: Particle Count (ISO 14644)
Item 6.10. This is the only remaining `[ ]` item that hasn't been deferred.
### 5.1 — Simulator
**File:** backend simulator (not in frontend repo — coordinate with backend)
- Add a `ParticleBot` (or extend an existing env bot) that emits:
- `particles_0_5um` — count/m³, particles ≥0.5 µm
- `particles_5um` — count/m³, particles ≥5 µm
- Derived ISO class (19) per room, changing slowly with occasional spikes
### 5.2 — Backend API
- New endpoint: `GET /api/environmental/particles?site_id=&room_id=`
- Returns current counts + derived ISO class per room
### 5.3 — Frontend
**File:** `app/(dashboard)/environmental/page.tsx` + `lib/api.ts`
- Add `fetchParticleStatus(siteId)` to `lib/api.ts`
- Add a new panel on the Environmental page: **"Air Quality — ISO 14644"**
- Per-room ISO class badge (ISO 19, colour-coded: green ≤7, amber 8, red 9)
- 0.5 µm and 5 µm count bars with threshold lines (ISO 8 limits: 3,520,000 and 29,300 /m³)
- A small note that DC target is ISO 8 (≤100,000 particles ≥0.5 µm/m³)
- Trend sparkline (last 24h)
---
## Execution Order Summary
| Phase | Scope | Backend needed? | Effort estimate |
|-------|-------|-----------------|-----------------|
| 1 — Trivial fixes | IMPROVEMENTS.md + sidebar + api.ts comment | No | ~20 min |
| 2 — Settings persistence | New context + localStorage + toast feedback | No | ~23 h |
| 3 — Mini floor map | New dashboard component | No | ~23 h |
| 4 — Floor map zoom/pan + CRAC shading | react-zoom-pan-pinch + overlay logic | No | ~34 h |
| 5 — Particle count | New simulator bot + API endpoint + env panel | Yes | ~34 h total |