diff --git a/client/src/protoFleet/features/fleetManagement/components/MinerList/MinerPowerUsage.tsx b/client/src/protoFleet/features/fleetManagement/components/MinerList/MinerPowerUsage.tsx index 5fa43ac62f..479e0effa0 100644 --- a/client/src/protoFleet/features/fleetManagement/components/MinerList/MinerPowerUsage.tsx +++ b/client/src/protoFleet/features/fleetManagement/components/MinerList/MinerPowerUsage.tsx @@ -2,6 +2,10 @@ import MinerMeasurement from "./MinerMeasurement"; import UnsupportedMetric from "./UnsupportedMetric"; import type { MinerStateSnapshot } from "@/protoFleet/api/generated/fleetmanagement/v1/fleetmanagement_pb"; import { getMinerMeasurement } from "@/protoFleet/features/fleetManagement/utils/getMinerMeasurement"; +import { getLatestMeasurementWithData } from "@/shared/utils/measurementUtils"; +import { formatPowerKW } from "@/shared/utils/stringUtils"; +import { INACTIVE_PLACEHOLDER } from "@/shared/constants"; +import SkeletonBar from "@/shared/components/SkeletonBar"; type MinerPowerUsageProps = { miner: MinerStateSnapshot; @@ -16,7 +20,15 @@ const MinerPowerUsage = ({ miner }: MinerPowerUsageProps) => { return ; } - return ; + if (powerUsage === undefined) return ; + if (powerUsage === null) return <>{INACTIVE_PLACEHOLDER}; + if (powerUsage.length === 0) return null; + + const latestValue = getLatestMeasurementWithData(powerUsage)?.value; + if (latestValue === undefined) return <>{INACTIVE_PLACEHOLDER}; + + const { value, unit } = formatPowerKW(latestValue); + return <>{value} {unit}; }; export default MinerPowerUsage; diff --git a/client/src/shared/utils/stringUtils.test.ts b/client/src/shared/utils/stringUtils.test.ts index 8c5147c240..62744cd727 100644 --- a/client/src/shared/utils/stringUtils.test.ts +++ b/client/src/shared/utils/stringUtils.test.ts @@ -4,6 +4,7 @@ import { addCommas, convertToSentenceCase, convertToTitleCase, + formatPowerKW, getDisplayValue, getMacAddressDisplay, padLeft, @@ -161,6 +162,24 @@ describe("convertToSentenceCase", () => { }); }); +describe("formatPowerKW", () => { + it("shows W for values below 1 kW", () => { + expect(formatPowerKW(0.0125)).toEqual({ value: "12.5", unit: "W" }); + expect(formatPowerKW(0)).toEqual({ value: "0.0", unit: "W" }); + expect(formatPowerKW(0.999)).toEqual({ value: "999.0", unit: "W" }); + }); + + it("shows kW for values at or above 1 kW", () => { + expect(formatPowerKW(1)).toEqual({ value: "1.0", unit: "kW" }); + expect(formatPowerKW(3.2)).toEqual({ value: "3.2", unit: "kW" }); + expect(formatPowerKW(12.5)).toEqual({ value: "12.5", unit: "kW" }); + }); + + it("applies comma separators for large kW values", () => { + expect(formatPowerKW(1200)).toEqual({ value: "1,200.0", unit: "kW" }); + }); +}); + describe("convertToTitleCase", () => { it("should capitalize the first letter of each word", () => { const input = "hello world"; diff --git a/client/src/shared/utils/stringUtils.ts b/client/src/shared/utils/stringUtils.ts index 9f2e04f71b..b7beaa6197 100644 --- a/client/src/shared/utils/stringUtils.ts +++ b/client/src/shared/utils/stringUtils.ts @@ -32,6 +32,18 @@ export const padLeft = (value: number, length: number) => { return value.toString().padStart(length, "0"); }; +/** + * Formats a power value in kW with adaptive units. + * Values >= 1 kW are shown in kW (1 decimal place). + * Values < 1 kW are converted to W (rounded to nearest integer). + */ +export const formatPowerKW = (kw: number): { value: string; unit: string } => { + if (kw >= 1) { + return { value: separateByCommas(kw.toFixed(1)), unit: "kW" }; + } + return { value: separateByCommas((kw * 1000).toFixed(1)), unit: "W" }; +}; + export const stripLeadingSlash = (str: string) => { return str.startsWith("/") ? str.substring(1) : str; };