diff --git a/frontend/components/analysis/analysis-view.tsx b/frontend/components/analysis/analysis-view.tsx index a502141..f0325f6 100644 --- a/frontend/components/analysis/analysis-view.tsx +++ b/frontend/components/analysis/analysis-view.tsx @@ -8,7 +8,6 @@ import { Area, AreaChart } from "@/components/charts/area-chart"; import { Bar } from "@/components/charts/bar"; import { BarChart } from "@/components/charts/bar-chart"; import { BarXAxis } from "@/components/charts/bar-x-axis"; -import { BarYAxis } from "@/components/charts/bar-y-axis"; import { Grid } from "@/components/charts/grid"; import { ChartTooltip } from "@/components/charts/tooltip"; import { XAxis } from "@/components/charts/x-axis"; @@ -196,7 +195,8 @@ export function AnalysisView() { - + {/* One tick per month so every point is labelled. */} + @@ -207,8 +207,9 @@ export function AnalysisView() { + {/* Vertical bars: weekdays live on the x-axis only. (A BarYAxis + here printed the categories down the left, overflowing the card.) */} - diff --git a/frontend/components/analysis/live-hospital-chart.tsx b/frontend/components/analysis/live-hospital-chart.tsx index fc6ca9d..804d99c 100644 --- a/frontend/components/analysis/live-hospital-chart.tsx +++ b/frontend/components/analysis/live-hospital-chart.tsx @@ -1,6 +1,8 @@ "use client"; +import { Pause, Play } from "lucide-react"; import { useEffect, useRef, useState } from "react"; +import { useTranslation } from "react-i18next"; import { LiveLineChart, @@ -9,24 +11,34 @@ import { import { LiveLine } from "@/components/charts/live-line"; import { LiveYAxis } from "@/components/charts/live-y-axis"; import { ChartTooltip } from "@/components/charts/tooltip"; +import { Button } from "@/components/ui/button"; // temetro has no real-time telemetry feed yet, so the "Live" panel simulates a // hospital signal (patients currently in the building) as a bounded random walk // that updates once a second. Swap `tick()` for a WebSocket/poll when a real // feed exists — the chart contract (append { time, value }) stays the same. +// +// The simulation (a 1s interval + an rAF animation loop) only runs while the +// clinician has explicitly toggled it on, so the Analysis page stays idle by +// default instead of animating in the background. const BASELINE = 48; const MIN = 24; const MAX = 90; const WINDOW_SECONDS = 30; export function LiveHospitalChart() { + const { t } = useTranslation(); + const [live, setLive] = useState(false); const [data, setData] = useState([]); const [value, setValue] = useState(BASELINE); const valueRef = useRef(BASELINE); useEffect(() => { - // Seed a short history so the line is drawn immediately on mount. + if (!live) return; + // Seed a short history so the line is drawn immediately on start. const now = Date.now() / 1000; + valueRef.current = BASELINE; + setValue(BASELINE); setData( Array.from({ length: WINDOW_SECONDS }, (_, i) => ({ time: now - (WINDOW_SECONDS - i), @@ -45,23 +57,60 @@ export function LiveHospitalChart() { ]); }, 1000); return () => clearInterval(id); - }, []); + }, [live]); return ( -
- - String(Math.round(v))} - momentumColors={{ - up: "var(--color-emerald-500)", - down: "var(--color-red-500)", - flat: "var(--chart-line-primary)", - }} - /> - String(Math.round(v))} position="left" /> - - +
+
+ +
+ + {live ? ( +
+ + String(Math.round(v))} + momentumColors={{ + up: "var(--color-emerald-500)", + down: "var(--color-red-500)", + flat: "var(--chart-line-primary)", + }} + /> + String(Math.round(v))} + position="left" + /> + + +
+ ) : ( +
+ {t("analysis.live.idle")} +
+ )}
); } diff --git a/frontend/lib/i18n/locales/en/translation.json b/frontend/lib/i18n/locales/en/translation.json index 9938031..e2b748d 100644 --- a/frontend/lib/i18n/locales/en/translation.json +++ b/frontend/lib/i18n/locales/en/translation.json @@ -556,7 +556,10 @@ "live": { "title": "Live", "subtitle": "Patients currently in the building, updating in real time.", - "label": "In the building now" + "label": "In the building now", + "start": "Go live", + "pause": "Pause", + "idle": "Live stream paused — press Go live to start." }, "patientVolume": { "title": "Patient volume",