import { useTheme } from "@/context/theme-provider"; import { generateColors } from "@/utils/colorUtil"; import { useEffect, useMemo } from "react"; import Chart from "react-apexcharts"; import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow, } from "@/components/ui/table"; import { Popover, PopoverContent, PopoverTrigger, } from "@/components/ui/popover"; import { getUnitSize } from "@/utils/storageUtil"; import { LuAlertCircle } from "react-icons/lu"; type CameraStorage = { [key: string]: { bandwidth: number; usage: number; usage_percent: number; }; }; type TotalStorage = { used: number; total: number; }; type CombinedStorageGraphProps = { graphId: string; cameraStorage: CameraStorage; totalStorage: TotalStorage; }; export function CombinedStorageGraph({ graphId, cameraStorage, totalStorage, }: CombinedStorageGraphProps) { const { theme, systemTheme } = useTheme(); const entities = Object.keys(cameraStorage); const colors = generateColors(entities.length); const series = entities.map((entity, index) => ({ name: entity, data: [(cameraStorage[entity].usage / totalStorage.total) * 100], usage: cameraStorage[entity].usage, bandwidth: cameraStorage[entity].bandwidth, color: colors[index], // Assign the corresponding color })); // Add the unused percentage to the series series.push({ name: "Unused", data: [ ((totalStorage.total - totalStorage.used) / totalStorage.total) * 100, ], usage: totalStorage.total - totalStorage.used, bandwidth: 0, color: (systemTheme || theme) == "dark" ? "#404040" : "#E5E5E5", }); const options = useMemo(() => { return { chart: { id: graphId, background: (systemTheme || theme) == "dark" ? "#404040" : "#E5E5E5", selection: { enabled: false, }, toolbar: { show: false, }, zoom: { enabled: false, }, stacked: true, stackType: "100%", }, grid: { show: false, padding: { bottom: -45, top: -40, left: -20, right: -20, }, }, legend: { show: false, }, dataLabels: { enabled: false, }, plotOptions: { bar: { horizontal: true, }, }, states: { active: { filter: { type: "none", }, }, hover: { filter: { type: "none", }, }, }, tooltip: { enabled: false, x: { show: false, }, y: { formatter: function (val, { seriesIndex }) { if (series[seriesIndex]) { const usage = series[seriesIndex].usage; return `${getUnitSize(usage)} (${val.toFixed(2)}%)`; } }, }, theme: systemTheme || theme, }, xaxis: { axisBorder: { show: false, }, axisTicks: { show: false, }, labels: { formatter: function (val) { return val + "%"; }, }, min: 0, max: 100, }, yaxis: { show: false, min: 0, max: 100, }, } as ApexCharts.ApexOptions; }, [graphId, systemTheme, theme, series]); useEffect(() => { ApexCharts.exec(graphId, "updateOptions", options, true, true); }, [graphId, options]); return (
{getUnitSize(totalStorage.used)}
/
{getUnitSize(totalStorage.total)}
Camera Storage Used Percentage of Total Used Bandwidth {series.map((item) => ( {" "}
{item.name.replaceAll("_", " ")} {item.name === "Unused" && (
This value may not accurately represent the free space available to Frigate if you have other files stored on your drive beyond Frigate's recordings. Frigate does not track storage usage outside of its recordings.
)}
{getUnitSize(item.usage ?? 0)} {item.data[0].toFixed(2)}% {item.name === "Unused" ? "—" : `${getUnitSize(item.bandwidth)} / hour`}
))}
); }