diff --git a/frontend/src/components/dashboard/FuryDashboard.tsx b/frontend/src/components/dashboard/FuryDashboard.tsx index 30750c7..adbd4fa 100644 --- a/frontend/src/components/dashboard/FuryDashboard.tsx +++ b/frontend/src/components/dashboard/FuryDashboard.tsx @@ -23,6 +23,8 @@ import { type FuryMetricKey, fetchFuryDashboard, type FuryRange, + rangeToMultiplier, + DAY_IN_MS, } from "./furyDashboardApi" import SensorTrendChart from "./SensorTrendChart" @@ -316,6 +318,7 @@ function FuryDashboard() { readings={metric.readings} title={`${metric.label} Trend`} unit={metric.unit} + durationMs={rangeToMultiplier[range] * DAY_IN_MS} /> diff --git a/frontend/src/components/dashboard/SensorTrendChart.tsx b/frontend/src/components/dashboard/SensorTrendChart.tsx index 4897b55..23b625d 100644 --- a/frontend/src/components/dashboard/SensorTrendChart.tsx +++ b/frontend/src/components/dashboard/SensorTrendChart.tsx @@ -2,7 +2,6 @@ import { Box, Flex, Text } from "@chakra-ui/react" import type { FuryReading } from "./furyDashboardApi" -const DAY_IN_MS = 24 * 60 * 60 * 1000 const CHART_WIDTH = 640 const CHART_HEIGHT = 220 const CHART_PADDING_X = 18 @@ -14,6 +13,8 @@ interface SensorTrendChartProps { readings: FuryReading[] title: string unit: string + // duration in milliseconds to display (e.g. 24h, 7d) + durationMs?: number } const formatAxisValue = (value: number, unit: string) => { @@ -21,22 +22,21 @@ const formatAxisValue = (value: number, unit: string) => { return `${value.toFixed(digits)}${unit}` } -const formatTimeLabel = (isoDate: string) => { +const formatTimeLabel = (isoDate: string, showDate = false) => { return new Intl.DateTimeFormat(undefined, { + month: showDate ? "short" : undefined, + day: showDate ? "2-digit" : undefined, hour: "2-digit", minute: "2-digit", }).format(new Date(isoDate)) } -const getLastDayReadings = (readings: FuryReading[]) => { - const since = Date.now() - DAY_IN_MS +const getRecentReadings = (readings: FuryReading[], durationMs: number) => { + const since = Date.now() - durationMs return readings .filter((reading) => new Date(reading.updateTime).getTime() >= since) - .sort( - (left, right) => - new Date(left.updateTime).getTime() - new Date(right.updateTime).getTime(), - ) + .sort((left, right) => new Date(left.updateTime).getTime() - new Date(right.updateTime).getTime()) } const downsampleReadings = (readings: FuryReading[]) => { @@ -55,10 +55,10 @@ const downsampleReadings = (readings: FuryReading[]) => { return sampled } -function SensorTrendChart({ color, readings, title, unit }: SensorTrendChartProps) { - const dayReadings = downsampleReadings(getLastDayReadings(readings)) +function SensorTrendChart({ color, readings, title, unit, durationMs = 24 * 60 * 60 * 1000 }: SensorTrendChartProps) { + const recentReadings = downsampleReadings(getRecentReadings(readings, durationMs)) - if (dayReadings.length < 2) { + if (recentReadings.length < 2) { return ( {title} - Not enough samples yet to draw a 24-hour chart. + Not enough samples yet to draw a chart for the selected range. ) } - const values = dayReadings.map((reading) => reading.value) + const values = recentReadings.map((reading) => reading.value) const minValue = Math.min(...values) const maxValue = Math.max(...values) const valueRange = maxValue - minValue || 1 const innerWidth = CHART_WIDTH - CHART_PADDING_X * 2 const innerHeight = CHART_HEIGHT - CHART_PADDING_Y * 2 - const points = dayReadings.map((reading, index) => { + const points = recentReadings.map((reading, index) => { const x = CHART_PADDING_X + (index / Math.max(dayReadings.length - 1, 1)) * innerWidth @@ -113,7 +113,7 @@ function SensorTrendChart({ color, readings, title, unit }: SensorTrendChartProp {title} - Last 24 hours, sampled every few minutes + Last {Math.round(durationMs / (24 * 60 * 60 * 1000))} day(s), sampled @@ -203,9 +203,9 @@ function SensorTrendChart({ color, readings, title, unit }: SensorTrendChartProp - {formatTimeLabel(dayReadings[0].updateTime)} - {formatTimeLabel(dayReadings[midIndex].updateTime)} - {formatTimeLabel(dayReadings[dayReadings.length - 1].updateTime)} + {formatTimeLabel(recentReadings[0].updateTime, true)} + {formatTimeLabel(recentReadings[midIndex].updateTime)} + {formatTimeLabel(recentReadings[recentReadings.length - 1].updateTime, true)} diff --git a/frontend/src/components/dashboard/furyDashboardApi.ts b/frontend/src/components/dashboard/furyDashboardApi.ts index 9eaad98..b75a893 100644 --- a/frontend/src/components/dashboard/furyDashboardApi.ts +++ b/frontend/src/components/dashboard/furyDashboardApi.ts @@ -5,11 +5,11 @@ const furyApi = axios.create({ timeout: 15_000, }) -const DAY_IN_MS = 24 * 60 * 60 * 1000 +export const DAY_IN_MS = 24 * 60 * 60 * 1000 export type FuryRange = "24h" | "1w" | "1m" | "3m" | "1y" | "3y" -const rangeToMultiplier: Record = { +export const rangeToMultiplier: Record = { "24h": 1, "1w": 7, "1m": 30,