import { useTheme } from "@/context/theme-provider"; import { useDateLocale } from "@/hooks/use-date-locale"; import { FrigateConfig } from "@/types/frigateConfig"; import { formatUnixTimestampToDateTime } from "@/utils/dateUtil"; import { useCallback, useEffect, useMemo } from "react"; import Chart from "react-apexcharts"; import { isMobileOnly } from "react-device-detect"; import { useTranslation } from "react-i18next"; import { MdCircle } from "react-icons/md"; import useSWR from "swr"; const GRAPH_COLORS = ["#5C7CFA", "#ED5CFA", "#FAD75C"]; type CameraLineGraphProps = { graphId: string; unit: string; dataLabels: string[]; updateTimes: number[]; data: ApexAxisChartSeries; }; export function CameraLineGraph({ graphId, unit, dataLabels, updateTimes, data, }: CameraLineGraphProps) { const { t } = useTranslation(["views/system", "common"]); const { data: config } = useSWR("config", { revalidateOnFocus: false, }); const lastValues = useMemo(() => { if (!dataLabels || !data || data.length == 0) { return undefined; } return dataLabels.map( (_, labelIdx) => // @ts-expect-error y is valid data[labelIdx].data[data[labelIdx].data.length - 1]?.y ?? 0, ) as number[]; }, [data, dataLabels]); const { theme, systemTheme } = useTheme(); const locale = useDateLocale(); const timeFormat = config?.ui.time_format === "24hour" ? "24hour" : "12hour"; const format = useMemo(() => { return t(`time.formattedTimestampHourMinute.${timeFormat}`, { ns: "common", }); }, [t, timeFormat]); const formatTime = useCallback( (val: unknown) => { return formatUnixTimestampToDateTime( updateTimes[Math.round(val as number)], { timezone: config?.ui.timezone, date_format: format, locale, }, ); }, [config?.ui.timezone, format, locale, updateTimes], ); const options = useMemo(() => { return { chart: { id: graphId, selection: { enabled: false, }, toolbar: { show: false, }, zoom: { enabled: false, }, }, colors: GRAPH_COLORS, grid: { show: false, }, legend: { show: false, }, dataLabels: { enabled: false, }, stroke: { width: 1, }, tooltip: { theme: systemTheme || theme, }, markers: { size: 0, }, xaxis: { tickAmount: isMobileOnly ? 2 : 3, tickPlacement: "on", labels: { rotate: 0, formatter: formatTime, }, axisBorder: { show: false, }, axisTicks: { show: false, }, }, yaxis: { show: true, labels: { formatter: (val: number) => Math.ceil(val).toString(), }, min: 0, }, } as ApexCharts.ApexOptions; }, [graphId, systemTheme, theme, formatTime]); useEffect(() => { ApexCharts.exec(graphId, "updateOptions", options, true, true); }, [graphId, options]); return (
{lastValues && (
{dataLabels.map((label, labelIdx) => (
{t("cameras.label." + label)}
{lastValues[labelIdx]} {unit}
))}
)}
); } type EventsPerSecondLineGraphProps = { graphId: string; unit: string; name: string; updateTimes: number[]; data: ApexAxisChartSeries; }; export function EventsPerSecondsLineGraph({ graphId, unit, name, updateTimes, data, }: EventsPerSecondLineGraphProps) { const { data: config } = useSWR("config", { revalidateOnFocus: false, }); const { theme, systemTheme } = useTheme(); const lastValue = useMemo( // @ts-expect-error y is valid () => data[0].data[data[0].data.length - 1]?.y ?? 0, [data], ); const locale = useDateLocale(); const { t } = useTranslation(["common"]); const timeFormat = config?.ui.time_format === "24hour" ? "24hour" : "12hour"; const format = useMemo(() => { return t(`time.formattedTimestampHourMinute.${timeFormat}`, { ns: "common", }); }, [t, timeFormat]); const formatTime = useCallback( (val: unknown) => { return formatUnixTimestampToDateTime( updateTimes[Math.round(val as number) - 1], { timezone: config?.ui.timezone, date_format: format, locale, }, ); }, [config?.ui.timezone, format, locale, updateTimes], ); const options = useMemo(() => { return { chart: { id: graphId, selection: { enabled: false, }, toolbar: { show: false, }, zoom: { enabled: false, }, }, colors: GRAPH_COLORS, grid: { show: false, }, legend: { show: false, }, dataLabels: { enabled: false, }, stroke: { width: 1, }, tooltip: { theme: systemTheme || theme, }, markers: { size: 0, }, xaxis: { tickAmount: isMobileOnly ? 2 : 3, tickPlacement: "on", labels: { rotate: 0, formatter: formatTime, }, axisBorder: { show: false, }, axisTicks: { show: false, }, }, yaxis: { show: true, labels: { formatter: (val: number) => Math.ceil(val).toString(), }, min: 0, }, } as ApexCharts.ApexOptions; }, [graphId, systemTheme, theme, formatTime]); useEffect(() => { ApexCharts.exec(graphId, "updateOptions", options, true, true); }, [graphId, options]); return (
{name}
{lastValue} {unit}
); }