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

367 lines
16 KiB
Markdown
Raw Permalink 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.

# DemoBMS — UI/UX Improvement Plan
> Generated from full page-by-page review (16 pages + shared layout).
> Work through phases in order — each phase builds on the previous.
---
## Phase 1 — Foundation Fixes
**Goal:** Fix broken/incomplete global chrome and shared infrastructure before touching individual pages.
**Effort:** ~12 days | **Risk:** Low
### 1.1 Topbar title map — complete it
- Add missing entries for: generator, leak, fire, network, energy, maintenance
- Replace pathname-based map with a route config object shared with sidebar
### 1.2 Topbar — replace placeholder avatar with Clerk UserButton
- Swap the blue circle for `<UserButton />` from `@clerk/nextjs`
- Removes the hardcoded placeholder and provides sign-out, profile link for free
### 1.3 Topbar — remove or disable the site selector
- The dropdown is hardcoded with 3 fake sites and does nothing
- Either wire it to real site context, or remove it entirely until it's real
- A non-functional control erodes trust
### 1.4 Topbar — consolidate the alarm badge
- Remove the alarm count badge from the sidebar nav item
- Keep it only on the topbar bell icon (single canonical location)
### 1.5 Sidebar — add section groupings with dividers
- Split 15 nav items into labelled groups:
- **OVERVIEW** — Dashboard, Floor Map
- **INFRASTRUCTURE** — Power, Generator, Cooling, Environmental
- **SAFETY** — Leak Detection, Fire & Safety, Network
- **OPERATIONS** — Assets, Alarms, Capacity
- **MANAGEMENT** — Reports, Energy & CO₂, Maintenance, Settings
- Render section headers as small ALL-CAPS muted labels with a horizontal rule above
- Collapsed sidebar: show only icons, hide section headers
### 1.6 Sidebar — move collapse toggle to bottom
- Currently the toggle is an absolutely-positioned button that's easy to miss
- Move it to the bottom of the sidebar as a regular icon button above Settings
- Add a tooltip: "Collapse menu" / "Expand menu"
### 1.7 Centralise threshold constants
- Create `/lib/thresholds.ts` exporting a single const object:
```ts
export const THRESHOLDS = {
temp: { warn: 26, critical: 28 },
humidity: { warn: 65, critical: 80 },
power: { warn: 0.75, critical: 0.85 }, // fraction of capacity
filter: { warn: 80, critical: 120 }, // Pa
compressor: { warn: 0.80, critical: 0.95 },
battery: { warn: 30, critical: 20 },
fuel: { warn: 30, critical: 15 },
}
```
- Replace all hardcoded threshold values across every page with imports from this file
### 1.8 Global spacing standardisation
- Audit and enforce: all page wrappers use `space-y-6`, all cards use `p-6`, all card headers use `pb-3`
- Create a `<PageShell title="">` wrapper component used by every page to ensure consistent top padding and title rendering
### 1.9 Empty state and error boundary
- Create a reusable `<ErrorCard message="">` component shown when a fetch fails
- Create a reusable `<EmptyCard message="">` for no-data states
- Wrap every data-dependent card in a try/catch that renders `<ErrorCard>` instead of crashing
- Add a top-level React error boundary in the dashboard layout
---
## Phase 2 — Alarms Page
**Goal:** Make the alarm page genuinely usable under operational pressure.
**Effort:** ~1 day | **Risk:** Low
### 2.1 Sticky filter bar
- Make the filter row (state tabs + severity dropdown) `sticky top-0 z-10` so it stays visible while scrolling through long alarm lists
### 2.2 Bulk action at top
- Move the "Bulk Resolve" button into the filter/action row at the top, not below the table
- Add a "Select All" checkbox in the table header
### 2.3 Swap Critical stat card for Avg Age
- Replace the "Critical" count card with "Avg Age" — the mean time alarms have been open
- Display as "Xh Ym" format
- Colour red if avg age > 1h, amber if > 15 min, green if < 15 min
### 2.4 Column priority on small screens
- On mobile/tablet, keep: Severity | Message | Escalation timer | Actions
- Drop: Sensor ID, State (already conveyed by row colour)
- Escalation timer must always be visible — it is the most operationally critical column
### 2.5 Pagination
- Add simple page controls: Previous / Page X of Y / Next
- Default page size: 25 rows
- Show total count above the table: "Showing 125 of 142 alarms"
### 2.6 Embed sparkline in stat cards
- Remove the standalone 24-hour sparkline chart
- Embed a micro line chart (24 data points, 40px tall) inside each stat card below the number
- Net result: less vertical space used, same information
---
## Phase 3 — Dashboard Page
**Goal:** Reduce clutter, improve at-a-glance legibility.
**Effort:** ~1 day | **Risk:** Low
### 3.1 Uniform KPI card grid
- Standardise all 6 KPI cards to the same height and same layout template
- Use a 3×2 grid (3 cols on lg, 2 on md, 1 on sm) consistently
### 3.2 Replace mini floor map
- The mini floor map widget is too small to be useful
- Replace with a "Room Quick Status" card:
- Two rows: Hall A / Hall B
- Each row: health badge (OK / Warning / Critical), avg temp, total power, CRAC state
- Link to /floor-map for full view
### 3.3 Data freshness pill in topbar
- Move the "last updated" indicator from the dashboard page into the topbar (right side, before the bell)
- Make it global — show the last successful API poll timestamp for any page
- Colour: green if < 60s, amber if 60120s, red if > 120s (stale)
### 3.4 Alarm feed / Room status layout
- Change the bottom row from 2-col + 1-col to 50/50
- Alarm Feed: left panel
- Room Quick Status: right panel (replaces mini floor map)
---
## Phase 4 — Power Page
**Goal:** Tame the long scroll, improve information hierarchy.
**Effort:** ~1.5 days | **Risk:** LowMedium
### 4.1 Page-internal anchor navigation
- Add a sticky sub-nav bar below the topbar with anchor links:
`Site Overview | UPS | Generator | Transfer Switch | Phase Analysis`
- Each section gets an `id=""` and smooth-scroll on click
### 4.2 Power path diagram
- Add a simple horizontal flow diagram at the top of the page:
`Grid → [ATS: feed A/B] → [UPS: battery/online] → Rack Distribution`
- Use coloured nodes (green = live, amber = degraded, red = fault)
- No library needed — a flex row of icon + connector line components
### 4.3 Always-visible Phase Summary card
- Show a collapsed "Phase Balance" summary card at all times (Phase A / B / C current kW in a 3-col grid)
- Expand to full Phase Imbalance Table on click or if violations exist
### 4.4 Per-rack bar chart — full width
- The per-rack chart needs more horizontal room to show 10 bars legibly
- Move it to full width above the history chart (stack them, not side by side)
---
## Phase 5 — Cooling Page
**Goal:** Reduce card density, surface critical maintenance items earlier.
**Effort:** ~1 day | **Risk:** Low
### 5.1 Standardise fleet summary bar
- Replace the horizontal KPI tile flex row with proper KPI cards matching dashboard style
### 5.2 Promote filter replacement alert
- If any CRAC unit is within 14 days of filter replacement threshold, show a dismissible alert banner at the top of the page
- Move the Predictive Filter Replacement card to the top of the page (above CRAC cards)
### 5.3 CRAC card — progressive disclosure
- The current CRAC card has 6 stacked sections
- Keep: thermal hero (supply/return/ΔT), capacity bar, fan speed
- Collapse into a "Details" accordion: compressor pressures + electrical readings
- The thermal hero section should be 30% larger — it is the most important readout
### 5.4 Thermal hero — increase visual weight
- Increase supply/return temp font to text-3xl
- ΔT value in a coloured pill (green/amber/red based on threshold)
- Add a small up/down arrow showing trend (last 5 min)
---
## Phase 6 — Environmental Page
**Goal:** Unify interactive state across sections, reduce redundancy.
**Effort:** ~1 day | **Risk:** Low
### 6.1 Shared room tab state
- All sections on the page (heatmap, dew point, trend chart) should react to a single room tab selector at the top of the page, not per-section tabs
- Add one prominent "Hall A / Hall B" tab switcher at the page level
### 6.2 Dual-axis chart — clarify axes
- Add unit labels on the Y-axis: left axis "Temperature (°C)", right axis "Humidity (%)"
- Change the humidity line to a dashed style (already done) but also add a subtle fill under it to visually distinguish it from the temperature line
- Add a brief legend note: "Shaded areas = ASHRAE A1 safe zone"
### 6.3 VESDA and Leak panels — link to dedicated pages
- Label both panels clearly as "Summary — see Leak Detection / Fire & Safety for detail"
- Add a "View full page →" link in each panel header
- This avoids duplicating full detail here
---
## Phase 7 — Floor Map Page
**Goal:** Improve overlay controls and map legibility.
**Effort:** ~1 day | **Risk:** LowMedium
### 7.1 Overlay controls — proper segmented control
- Replace the 4 overlay buttons with a shadcn `<Tabs>` style segmented control
- Active tab: filled background, not just a subtle border change
### 7.2 Hot/cold aisle labels — improve visibility
- Increase aisle divider label font size and weight
- Add icon: 🔴 Hot Aisle / 🔵 Cold Aisle (or Lucide Flame / Snowflake)
- Increase divider bar height slightly
### 7.3 Rack tile — secondary metric on hover only
- In Temperature overlay: show °C as main value; power bar appears on hover tooltip only
- In Power overlay: show % as main value; temp appears in tooltip
- Reduces visual clutter in the tile grid
### 7.4 CRAC strip — move above rack grid
- The CRAC strip is currently below the rack grid and easy to miss
- Move it above the grid with a stronger visual separator (border + label "Cooling Unit")
### 7.5 Leak sensor panel — add zone labels
- Add a brief location description to each sensor: "Hall A — under floor, near CRAC" etc.
- Use consistent zone label chips rather than free text
---
## Phase 8 — Assets Page
**Goal:** Make each tab genuinely useful and distinct from other pages.
**Effort:** ~1 day | **Risk:** Low
### 8.1 Rack Grid tab → Rack Summary Table
- Replace the visual rack grid (duplicates Floor Map) with a sortable table:
- Columns: Rack ID | Room | Temp (°C) | Power (kW) | Power % | Alarms | Status
- Sortable by any column
- Row click opens RackDetailSheet
### 8.2 Device List — sort headers
- Add click-to-sort on every column header with a sort direction indicator (chevron icon)
- Default sort: Type then Name
### 8.3 Device type legend
- Add a compact colour legend row above the device table explaining the dot colours
- One row of: ● Server ● Switch ● PDU ● Storage ● Firewall ● KVM
### 8.4 CRAC / UPS cards → inventory rows
- Replace the large card components with compact inventory table rows:
- ID | Type | Status | Room | Rack | Last Maintenance
- Link to full detail on click (CracDetailSheet / UpsCard modal)
---
## Phase 9 — Remaining Pages
**Goal:** Individual page improvements that don't interact with other phases.
**Effort:** ~1.5 days | **Risk:** Low
### 9.1 Generator page — add fuel runtime estimate
- Add "Est. runtime at current load: X hours" as the hero stat in each generator card
- Show a small fuel consumption trend chart (last 24h) if data is available
- Clearly differentiate this page from the generator section in Power page by adding: last start log, maintenance schedule table
### 9.2 Capacity page — radial gauge values
- Ensure a large centered text value (e.g. "74%") is always visible inside the gauge arc
- Add "Headroom: X kW" as a sub-label below the gauge
### 9.3 Capacity page — runway in months
- Display runway as "~2.3 months" alongside weeks
- Add a 90-day forecast line on the per-rack chart (dotted line extrapolating current growth)
### 9.4 Fire & Safety page — fire state improvements
- Fire-level cards: increase border to 4px, add a very faint red background overlay (`bg-red-950/30`)
- Replace small status dots with a proper status row: icon + label + state text (e.g. ✓ Detector 1 — Online)
- Show raw obscuration value (%/m) on the bar, not just the bar fill
### 9.5 Leak Detection page — add history
- Add "Last triggered: X days ago" to each sensor card
- Add a 30-day trigger count badge: "0 events" / "3 events"
- This keeps the page useful when all sensors are clear
### 9.6 Network page — improve port display
- Change port headline from "72%" to "36 / 48 ports active" — then show % as sub-label
- Group card metrics: top 3 bold (state, ports, bandwidth) + secondary row (CPU, memory, temp)
### 9.7 Reports page — promote export to top
- Move the 3 export buttons to a prominent action bar at the top of the page
- Add a page-level date range picker that controls all KPIs on the page simultaneously
- Always show numeric % labels on CRAC/UPS uptime bars
### 9.8 Maintenance page — modal for create form
- Move "Create window" form into a shadcn `<Dialog>` modal triggered by the header button
- In the target selector, group options: Site / Hall A racks / Hall B racks / Cooling / Power
- Add a 7-day horizontal timeline strip below the active windows list showing when each window falls
### 9.9 Settings page — skeleton structure
- Replace "Coming soon" with a tabbed layout: Profile | Notifications | Thresholds | Site Config
- Thresholds tab: shows the values from `lib/thresholds.ts` as editable fields (even if not persisted to backend yet)
- This makes the page look intentional rather than unfinished
---
## Phase 10 — Polish & Accessibility
**Goal:** Final consistency pass, mobile, keyboard navigation.
**Effort:** ~12 days | **Risk:** Low
### 10.1 Mobile audit
- Test every page at 375px and 768px width
- Fix broken chart widths (use `ResponsiveContainer` everywhere, check it's set)
- Ensure touch targets are ≥44px tall
- Test sidebar sheet on mobile
### 10.2 Focus rings and keyboard nav
- Add `focus-visible:ring-2 focus-visible:ring-primary` to all interactive elements that are missing it
- Verify logical tab order on every page (left-to-right, top-to-bottom)
- Add `aria-label` to icon-only buttons (alarm bell, collapse toggle, overlay buttons)
### 10.3 Chart skeleton height matching
- Measure actual rendered chart heights for each chart type
- Set skeleton `h-[]` to match exactly, preventing layout shift on load
### 10.4 Dark/light mode toggle
- Add a theme toggle button in the topbar (Moon / Sun icon)
- The ThemeProvider is already wired — just needs a toggle button and `localStorage` persistence
### 10.5 Loading state audit
- Every card that fetches data must show a `<Skeleton>` during initial load
- No card should show an empty white box or flash unstyled content
### 10.6 Toast notification consistency
- Audit all `toast.error()` / `toast.success()` calls across pages
- Ensure every user action (acknowledge alarm, bulk resolve, create maintenance window, export) has a corresponding success/error toast
---
## Summary Table
| Phase | Focus | Pages Touched | Est. Effort |
|-------|-------|---------------|-------------|
| 1 | Foundation fixes (nav, thresholds, errors) | All (shared) | 12 days |
| 2 | Alarms page | Alarms | 1 day |
| 3 | Dashboard page | Dashboard | 1 day |
| 4 | Power page | Power | 1.5 days |
| 5 | Cooling page | Cooling | 1 day |
| 6 | Environmental page | Environmental | 1 day |
| 7 | Floor Map page | Floor Map | 1 day |
| 8 | Assets page | Assets | 1 day |
| 9 | Remaining pages | Generator, Capacity, Fire, Leak, Network, Reports, Maintenance, Settings | 1.5 days |
| 10 | Polish & accessibility | All | 12 days |
| **Total** | | | **~1113 days** |
---
## Dependency Order
```
Phase 1 (foundation)
└─► Phase 2 (alarms)
└─► Phase 3 (dashboard)
└─► Phase 4 (power)
└─► Phase 5 (cooling)
└─► Phase 6 (environmental)
└─► Phase 7 (floor map)
└─► Phase 8 (assets)
└─► Phase 9 (remaining pages)
└─► Phase 10 (polish — last, after all pages stable)
```
Phases 29 are independent of each other and can be parallelised once Phase 1 is complete.