import { useTheme } from "@/context/theme-provider"; import { FrigateConfig } from "@/types/frigateConfig"; import { Threshold } from "@/types/graph"; import { useCallback, useEffect, useMemo } from "react"; import Chart from "react-apexcharts"; import useSWR from "swr"; type ThresholdBarGraphProps = { graphId: string; name: string; unit: string; threshold: Threshold; updateTimes: number[]; data: ApexAxisChartSeries; }; export function ThresholdBarGraph({ graphId, name, unit, threshold, updateTimes, data, }: ThresholdBarGraphProps) { const { data: config } = useSWR("config", { revalidateOnFocus: false, }); const lastValue = useMemo( // @ts-expect-error y is valid () => data[0].data[data[0].data.length - 1]?.y ?? 0, [data], ); const { theme, systemTheme } = useTheme(); const formatTime = useCallback( (val: unknown) => { const date = new Date(updateTimes[Math.round(val as number)] * 1000); return date.toLocaleTimeString([], { hour12: config?.ui.time_format != "24hour", hour: "2-digit", minute: "2-digit", }); }, [config, updateTimes], ); const options = useMemo(() => { return { chart: { id: graphId, selection: { enabled: false, }, toolbar: { show: false, }, zoom: { enabled: false, }, }, colors: [ ({ value }: { value: number }) => { if (value >= threshold.error) { return "#FA5252"; } else if (value >= threshold.warning) { return "#FF9966"; } else { return (systemTheme || theme) == "dark" ? "#404040" : "#E5E5E5"; } }, ], grid: { show: false, }, legend: { show: false, }, dataLabels: { enabled: false, }, plotOptions: { bar: { distributed: true, }, }, tooltip: { theme: systemTheme || theme, }, markers: { size: 0, }, xaxis: { tickAmount: 4, tickPlacement: "on", labels: { formatter: formatTime, }, axisBorder: { show: false, }, axisTicks: { show: false, }, }, yaxis: { show: false, min: 0, max: threshold.warning + 10, }, } as ApexCharts.ApexOptions; }, [graphId, threshold, systemTheme, theme, formatTime]); useEffect(() => { ApexCharts.exec(graphId, "updateOptions", options, true, true); }, [graphId, options]); return (
{name}
{lastValue} {unit}
); } const getUnitSize = (MB: number) => { if (isNaN(MB) || MB < 0) return "Invalid number"; if (MB < 1024) return `${MB} MiB`; if (MB < 1048576) return `${(MB / 1024).toFixed(2)} GiB`; return `${(MB / 1048576).toFixed(2)} TiB`; }; type StorageGraphProps = { graphId: string; used: number; total: number; }; export function StorageGraph({ graphId, used, total }: StorageGraphProps) { const { theme, systemTheme } = useTheme(); const options = useMemo(() => { return { chart: { id: graphId, background: (systemTheme || theme) == "dark" ? "#404040" : "#E5E5E5", selection: { enabled: false, }, toolbar: { show: false, }, zoom: { enabled: false, }, }, grid: { show: false, padding: { bottom: -40, top: -60, left: -20, right: 0, }, }, legend: { show: false, }, dataLabels: { enabled: false, }, plotOptions: { bar: { horizontal: true, }, }, tooltip: { theme: systemTheme || theme, }, xaxis: { axisBorder: { show: false, }, axisTicks: { show: false, }, labels: { show: false, }, }, yaxis: { show: false, min: 0, max: 100, }, }; }, [graphId, systemTheme, theme]); useEffect(() => { ApexCharts.exec(graphId, "updateOptions", options, true, true); }, [graphId, options]); return (
{getUnitSize(used)}
/
{getUnitSize(total)}
{Math.round((used / total) * 100)}%
); }