# Phase 9: Console Application Frontend ## Objective Build the web-based frontend dashboard for the console application. The frontend provides device fleet management, real-time telemetry visualization, remote configuration, OTA firmware deployment, and alert management. It connects to the backend API (Phase 8) and uses SignalR for real-time updates. ## Prerequisites - Phase 8 complete (backend API running) - Node.js 18+ (for frontend build tooling) - Design system chosen ## Deliverables 1. React SPA with responsive dashboard 2. Device fleet overview with status indicators 3. Individual device detail page (telemetry, config, health) 4. Real-time telemetry charts 5. Remote configuration interface 6. Firmware management and deployment UI 7. Alert management dashboard 8. User authentication flow --- ## 9.1 Technology Stack | Component | Technology | Justification | |-----------|-----------|---------------| | Framework | React 18 | Component-based, large ecosystem | | Language | TypeScript | Type safety, better DX | | Build | Vite | Fast HMR, modern bundling | | Routing | React Router v6 | Standard React routing | | State | TanStack Query (React Query) | Server state caching, auto-refresh | | UI Library | Ant Design 5 | Complete component set, tables, forms, charts | | Charts | Apache ECharts (via echarts-for-react) | High-performance, rich chart types | | Real-time | @microsoft/signalr | SignalR client for live updates | | HTTP | Axios | HTTP client with interceptors | | Forms | Ant Design Form | Built-in validation | | Icons | Ant Design Icons | Consistent with UI library | ## 9.2 Project Structure ``` console/ ├── frontend/ │ ├── package.json │ ├── tsconfig.json │ ├── vite.config.ts │ ├── index.html │ ├── public/ │ │ └── favicon.ico │ └── src/ │ ├── main.tsx │ ├── App.tsx │ ├── api/ │ │ ├── client.ts # Axios instance with auth interceptor │ │ ├── devices.ts # Device API calls │ │ ├── telemetry.ts # Telemetry API calls │ │ ├── firmware.ts # Firmware API calls │ │ ├── alerts.ts # Alert API calls │ │ ├── auth.ts # Auth API calls │ │ └── commands.ts # Command API calls │ ├── hooks/ │ │ ├── useDevices.ts │ │ ├── useTelemetry.ts │ │ ├── useSignalR.ts │ │ └── useAuth.ts │ ├── pages/ │ │ ├── LoginPage.tsx │ │ ├── DashboardPage.tsx │ │ ├── DeviceListPage.tsx │ │ ├── DeviceDetailPage.tsx │ │ ├── FirmwarePage.tsx │ │ ├── AlertsPage.tsx │ │ ├── GroupsPage.tsx │ │ └── SettingsPage.tsx │ ├── components/ │ │ ├── layout/ │ │ │ ├── AppLayout.tsx │ │ │ ├── Sidebar.tsx │ │ │ └── Header.tsx │ │ ├── devices/ │ │ │ ├── DeviceTable.tsx │ │ │ ├── DeviceCard.tsx │ │ │ ├── DeviceStatusBadge.tsx │ │ │ ├── DeviceConfigForm.tsx │ │ │ ├── WifiScanModal.tsx │ │ │ └── CommandModal.tsx │ │ ├── telemetry/ │ │ │ ├── TelemetryChart.tsx │ │ │ ├── LiveReadings.tsx │ │ │ ├── PowerGauge.tsx │ │ │ └── EnergyCounter.tsx │ │ ├── firmware/ │ │ │ ├── FirmwareUpload.tsx │ │ │ ├── FirmwareTable.tsx │ │ │ └── DeployModal.tsx │ │ ├── alerts/ │ │ │ ├── AlertTable.tsx │ │ │ └── AlertBadge.tsx │ │ └── dashboard/ │ │ ├── FleetSummary.tsx │ │ ├── DeviceMap.tsx │ │ └── RecentAlerts.tsx │ ├── types/ │ │ ├── device.ts │ │ ├── telemetry.ts │ │ ├── firmware.ts │ │ └── alert.ts │ └── utils/ │ ├── formatters.ts │ └── constants.ts ``` ## 9.3 Page Layouts ### Dashboard (Home) Fleet-level overview — the first thing operators see. ``` ┌─────────────────────────────────────────────────────────────┐ │ ☰ Tau Acuvim Console admin ▼ [Logout] │ ├──────┬──────────────────────────────────────────────────────┤ │ │ │ │ Nav │ Fleet Overview │ │ │ ┌──────────┬──────────┬──────────┬──────────┐ │ │ 📊 │ │ Total │ Online │ Degraded │ Offline │ │ │Dash │ │ 24 │ 21 │ 1 │ 2 │ │ │ │ └──────────┴──────────┴──────────┴──────────┘ │ │ 📱 │ │ │Devs │ ┌────────────────────┬──────────────────────┐ │ │ │ │ Recent Alerts │ Fleet Power │ │ │ 📦 │ │ ⚠ Overvoltage │ ┌─────────────────┐ │ │ │FW │ │ ACV-001 2m ago │ │ Line chart │ │ │ │ │ │ ⚠ Modbus error │ │ (total kW over │ │ │ │ 🔔 │ │ ACV-015 5m ago │ │ last 24h) │ │ │ │Alert │ │ ● Device offline │ └─────────────────┘ │ │ │ │ │ ACV-008 1h ago │ │ │ │ ⚙ │ └────────────────────┴──────────────────────┘ │ │Sets │ │ │ │ Device Status Grid │ │ │ ┌──────┬──────┬──────┬──────┬──────┬──────┐ │ │ │ │●001 │●002 │●003 │●004 │●005 │●006 │ │ │ │ │230V │231V │229V │232V │ OFF │230V │ │ │ │ │10kW │12kW │9kW │11kW │ -- │8kW │ │ │ │ └──────┴──────┴──────┴──────┴──────┴──────┘ │ │ │ │ └──────┴──────────────────────────────────────────────────────┘ ``` ### Device List ``` ┌──────────────────────────────────────────────────────────────┐ │ Devices [+ Add Group] [⚡ Deploy] │ ├──────────────────────────────────────────────────────────────┤ │ Filter: [All ▼] [Online ▼] [Group ▼] Search: [________] │ ├──────────────────────────────────────────────────────────────┤ │ Status │ Device ID │ Name │ FW │ Conn │ P │ │────────┼─────────────────┼───────────────┼───────┼──────┼────│ │ ● │ ACV-AABBCCDDEEFF│ Building A │ 1.0.0 │ WiFi │10kW│ │ ● │ ACV-112233445566│ Building B │ 1.0.0 │ GSM │12kW│ │ ◐ │ ACV-FFEEDDCCBBAA│ Warehouse │ 0.9.0 │ WiFi │ 9kW│ │ ○ │ ACV-998877665544│ Solar Farm │ 1.0.0 │ -- │ -- │ ├──────────────────────────────────────────────────────────────┤ │ Showing 1-20 of 24 devices < 1 2 > │ └──────────────────────────────────────────────────────────────┘ Status indicators: ● Online ◐ Degraded ○ Offline ``` ### Device Detail ``` ┌──────────────────────────────────────────────────────────────┐ │ ← Devices / ACV-AABBCCDDEEFF - Building A │ ├──────────────────────────────────────────────────────────────┤ │ [Overview] [Telemetry] [Config] [Alerts] [Commands] [OTA] │ ├──────────────────────────────────────────────────────────────┤ │ │ │ ── Overview Tab ── │ │ │ │ Device Info │ Connection │ │ ID: ACV-AABBCCDDEEFF │ Type: WiFi │ │ Name: Building A │ SSID: MyNetwork │ │ Hardware: TTGO T-Call v1.4 │ RSSI: -45 dBm │ │ Firmware: v1.0.0 │ IP: 192.168.1.100 │ │ Uptime: 3d 2h 15m │ MQTT: Connected │ │ Boot count: 12 │ GSM: Available (standby) │ │ Last heartbeat: 30s ago │ SD: 4GB (0.1% used) │ │ │ │ │ ┌──────────────────────────────────────────────────────┐ │ │ │ Live Readings ● LIVE │ │ │ │ │ │ │ │ Phase Voltages Phase Currents │ │ │ │ Va: 230.1 V Ia: 15.2 A │ │ │ │ Vb: 231.4 V Ib: 14.8 A │ │ │ │ Vc: 229.8 V Ic: 15.5 A │ │ │ │ │ │ │ │ Power Energy │ │ │ │ Active: 10.5 kW Import: 12,345.6 kWh │ │ │ │ Reactive: 2.1 kVAR Export: 0.0 kWh │ │ │ │ Apparent: 10.7 kVA PF: 0.98 │ │ │ │ Freq: 50.01 Hz │ │ │ └──────────────────────────────────────────────────────┘ │ │ │ │ [Restart] [WiFi Scan] [Send Command] │ └──────────────────────────────────────────────────────────────┘ ``` ### Device Detail - Telemetry Tab ``` ┌──────────────────────────────────────────────────────────────┐ │ [Overview] [Telemetry] [Config] [Alerts] [Commands] [OTA] │ ├──────────────────────────────────────────────────────────────┤ │ │ │ Time Range: [Last 24h ▼] [Custom Range] [Export CSV] │ │ │ │ ┌──────────────────────────────────────────────────────────┐ │ │ │ Phase Voltages (V) │ │ │ │ 240 ┤ │ │ │ │ 235 ┤ ╭─╮ │ │ │ │ 230 ┤───╯ ╰──────────────────────────────────── │ │ │ │ 225 ┤ │ │ │ │ 220 ┤ │ │ │ │ └──┬────┬────┬────┬────┬────┬────┬────┬────┬── │ │ │ │ 00 03 06 09 12 15 18 21 24 │ │ │ │ ── Va ── Vb ── Vc │ │ │ └──────────────────────────────────────────────────────────┘ │ │ │ │ ┌──────────────────────────────────────────────────────────┐ │ │ │ Active Power (kW) │ │ │ │ 15 ┤ ╭───╮ │ │ │ │ 10 ┤────╮ ╯ ╰───────╮ │ │ │ │ 5 ┤ ╰──╯ ╰────── │ │ │ │ 0 ┤ │ │ │ │ └──┬────┬────┬────┬────┬────┬────┬────┬────┬── │ │ │ └──────────────────────────────────────────────────────────┘ │ │ │ │ ┌──────────────────────────────────────────────────────────┐ │ │ │ Power Factor & Frequency │ │ │ │ ... similar chart ... │ │ │ └──────────────────────────────────────────────────────────┘ │ └──────────────────────────────────────────────────────────────┘ ``` ### Device Detail - Config Tab ``` ┌──────────────────────────────────────────────────────────────┐ │ [Overview] [Telemetry] [Config] [Alerts] [Commands] [OTA] │ ├──────────────────────────────────────────────────────────────┤ │ │ │ WiFi Configuration │ MQTT Configuration │ │ SSID: [MyNetwork____] │ Broker: [broker.example.com] │ │ Password: [**********] │ Port: [1883] │ │ Enabled: [✓] │ Username: [device1] │ │ [Scan Networks] [Save] │ Password: [**********] │ │ │ Topic: [acuvim] │ │ GSM Configuration │ TLS: [ ] │ │ APN: [internet] │ [Test] [Save] │ │ Enabled: [✓] │ │ │ Priority: [WiFi first ▼] │ Sleep Configuration │ │ [Save] │ Enabled: [ ] │ │ │ Sleep: [15] min │ │ Modbus Configuration │ Wake: [300] sec │ │ Slave Address: [1] │ [Save] │ │ Baud Rate: [9600 ▼] │ │ │ Poll Interval: [5] sec │ Console URL │ │ [Save] │ [https://console.example.com] │ │ │ [Save] │ │ │ │ ⚠ Changes are pushed to the device immediately via MQTT. │ │ The device will apply settings and reconnect as needed. │ └──────────────────────────────────────────────────────────────┘ ``` ### Firmware Management Page ``` ┌──────────────────────────────────────────────────────────────┐ │ Firmware Management [Upload New] │ ├──────────────────────────────────────────────────────────────┤ │ │ │ Version │ Size │ Date │ Devices │ Status │ Action │ │─────────┼────────┼──────────────┼─────────┼────────┼─────────│ │ v1.2.0 │ 1.2 MB │ May 16, 2026 │ 0 / 24 │ Active │ [Deploy]│ │ v1.1.0 │ 1.1 MB │ May 10, 2026 │ 3 / 24 │ Active │ [Deploy]│ │ v1.0.0 │ 1.0 MB │ May 01, 2026 │ 21 / 24 │ Active │ [Deploy]│ │ v0.9.0 │ 0.9 MB │ Apr 15, 2026 │ 0 / 24 │ Archived│ │ ├──────────────────────────────────────────────────────────────┤ │ │ │ Deploy v1.2.0 to: │ │ ( ) All devices (24) │ │ ( ) Group: [Building A ▼] (8 devices) │ │ (●) Select devices: │ │ [✓] ACV-001 - Building A (v1.0.0) │ │ [✓] ACV-002 - Building B (v1.0.0) │ │ [ ] ACV-003 - Warehouse (v0.9.0) │ │ │ │ Release Notes: │ │ Added THD monitoring improvements │ │ │ │ [Deploy to 2 devices] │ └──────────────────────────────────────────────────────────────┘ ``` ### Alerts Page ``` ┌──────────────────────────────────────────────────────────────┐ │ Alerts Unresolved: 5 [Mark All Read] │ ├──────────────────────────────────────────────────────────────┤ │ Filter: [All ▼] [Warning ▼] [Active ▼] Search: [________] │ ├──────────────────────────────────────────────────────────────┤ │ Sev │ Device │ Alert │ Value │ Time │ Ack │ │─────┼───────────┼────────────────┼─────────┼─────────┼───────│ │ ⚠ │ ACV-001 │ Overvoltage │ 265.3V │ 2m ago │ [ ] │ │ ⚠ │ ACV-015 │ Modbus errors │ 12% │ 5m ago │ [ ] │ │ ● │ ACV-008 │ Device offline │ -- │ 1h ago │ [ ] │ │ ℹ │ ACV-003 │ Low PF │ 0.82 │ 2h ago │ [✓] │ │ ⚠ │ ACV-001 │ Undervoltage │ 198V │ 3h ago │ [✓] │ ├──────────────────────────────────────────────────────────────┤ │ Showing 1-20 of 45 alerts < 1 2 3 > │ └──────────────────────────────────────────────────────────────┘ Severity: ● Critical ⚠ Warning ℹ Info ``` ## 9.4 SignalR Integration ### Real-Time Hook ```typescript // useSignalR.ts function useSignalR() { const connection = new HubConnectionBuilder() .withUrl("/hubs/devices", { accessTokenFactory: () => getToken() }) .withAutomaticReconnect() .build(); useEffect(() => { connection.start(); connection.on("DeviceStatusChanged", (deviceId, status) => { queryClient.invalidateQueries(["devices"]); }); connection.on("TelemetryReceived", (deviceId, data) => { queryClient.setQueryData(["telemetry", deviceId, "latest"], data); }); connection.on("AlertCreated", (deviceId, alert) => { queryClient.invalidateQueries(["alerts"]); notification.warning({ message: alert.message }); }); return () => connection.stop(); }, []); } ``` ### Live Data Updates - Device status badges update in real-time (no page refresh) - Telemetry readings update live on device detail page - New alerts appear as toast notifications - Dashboard counters update automatically ## 9.5 Authentication Flow ### Login Page ``` ┌──────────────────────────────────────┐ │ │ │ Tau Acuvim Console │ │ │ │ Email: [________________] │ │ Password: [________________] │ │ │ │ [Login] │ │ │ │ Forgot password? │ │ │ └──────────────────────────────────────┘ ``` ### Auth Implementation ```typescript // Protected route wrapper function ProtectedRoute({ children }) { const { isAuthenticated } = useAuth(); if (!isAuthenticated) { return ; } return children; } ``` - JWT token stored in memory (not localStorage) for security - Refresh token in httpOnly cookie - Axios interceptor adds `Authorization` header automatically - On 401 response: redirect to login ## 9.6 Responsive Design - **Desktop (>1200px):** Full sidebar + content layout - **Tablet (768-1200px):** Collapsible sidebar, adjusted grid - **Mobile (<768px):** Bottom navigation, stacked cards, simplified tables Ant Design's grid system handles responsive breakpoints. Charts resize automatically using ECharts' responsive mode. ## 9.7 Build and Deploy ### Development ```bash cd console/frontend npm install npm run dev # Vite dev server with HMR (port 5173) ``` ### Production Build ```bash npm run build # Output to dist/ ``` ### Integration with Backend - In development: Vite proxy forwards `/api` and `/hubs` to the .NET backend - In production: the .NET backend serves the built frontend files from `wwwroot/` - `vite.config.ts` configures the proxy for development ```typescript // vite.config.ts export default defineConfig({ server: { proxy: { '/api': 'http://localhost:5000', '/hubs': { target: 'http://localhost:5000', ws: true } } } }); ``` ### Docker Integration Add to the Phase 8 Dockerfile: ```dockerfile # Build frontend FROM node:18 AS frontend WORKDIR /app/frontend COPY console/frontend/package*.json ./ RUN npm ci COPY console/frontend/ ./ RUN npm run build # Build backend FROM mcr.microsoft.com/dotnet/sdk:8.0 AS backend # ... build steps ... # Runtime FROM mcr.microsoft.com/dotnet/aspnet:8.0 # ... copy backend build ... COPY --from=frontend /app/frontend/dist ./wwwroot/ ``` ## 9.8 Testing & Validation | Test | Method | Pass Criteria | |------|--------|---------------| | Login | Enter valid credentials | Redirected to dashboard | | Dashboard loads | Navigate to / | Summary cards, alerts, grid visible | | Device list | Navigate to /devices | All devices listed with status | | Device detail | Click a device | Overview tab shows live data | | Telemetry charts | Select Telemetry tab | Charts render with historical data | | Time range | Change to Last 7 days | Charts update with correct range | | Config push | Edit WiFi settings, save | Config sent to device via MQTT | | WiFi scan | Click Scan Networks | Networks returned and displayed | | Firmware upload | Upload a .bin file | File uploaded, appears in list | | Firmware deploy | Deploy to selected devices | OTA commands sent | | Alert display | Trigger alert from device | Alert appears in list and as toast | | Alert acknowledge | Click acknowledge | Alert marked as acknowledged | | Real-time update | Watch dashboard while device publishes | Values update without refresh | | Responsive | Resize browser to mobile | Layout adapts correctly | | Auth protection | Access /devices without login | Redirected to /login | | CSV export | Export telemetry | Valid CSV downloaded | | Send command | Send restart command | Device restarts, response received | ## 9.9 Phase 9 Completion Criteria - [ ] React frontend builds and serves - [ ] Login/logout flow with JWT authentication - [ ] Dashboard shows fleet summary, alerts, device grid - [ ] Device list with filtering, search, pagination - [ ] Device detail with tabs: Overview, Telemetry, Config, Alerts, Commands, OTA - [ ] Live telemetry readings update via SignalR - [ ] Historical telemetry charts with time range selection - [ ] Remote configuration push (WiFi, MQTT, GSM, sleep, Modbus) - [ ] WiFi scan triggered from console and results displayed - [ ] Firmware upload and deployment UI - [ ] Alert management (list, filter, acknowledge) - [ ] Responsive design (desktop, tablet, mobile) - [ ] Integrated into .NET backend for production deployment --- **Previous Phase:** [Phase 8 — Console Application Backend](acuvim-spec-08.md) **Next Phase:** [Phase 10 — Integration Testing & Production Hardening](acuvim-spec-10.md)