import { useCallback, useState } from "react"; import { Drawer, DrawerContent, DrawerTrigger } from "../ui/drawer"; import { Button } from "../ui/button"; import { FaArrowDown, FaCalendarAlt, FaCog, FaFilter } from "react-icons/fa"; import { TimeRange } from "@/types/timeline"; import { ExportContent, ExportPreviewDialog } from "./ExportDialog"; import { ExportMode, GeneralFilter } from "@/types/filter"; import ReviewActivityCalendar from "./ReviewActivityCalendar"; import { SelectSeparator } from "../ui/select"; import { RecordingsSummary, ReviewFilter, ReviewSeverity, ReviewSummary, } from "@/types/review"; import { getEndOfDayTimestamp } from "@/utils/dateUtil"; import { GeneralFilterContent } from "../filter/ReviewFilterGroup"; import { toast } from "sonner"; import axios from "axios"; import SaveExportOverlay from "./SaveExportOverlay"; import { isIOS, isMobile } from "react-device-detect"; import { useTranslation } from "react-i18next"; type DrawerMode = "none" | "select" | "export" | "calendar" | "filter"; const DRAWER_FEATURES = ["export", "calendar", "filter"] as const; export type DrawerFeatures = (typeof DRAWER_FEATURES)[number]; const DEFAULT_DRAWER_FEATURES: DrawerFeatures[] = [ "export", "calendar", "filter", ]; type MobileReviewSettingsDrawerProps = { features?: DrawerFeatures[]; camera: string; filter?: ReviewFilter; currentSeverity?: ReviewSeverity; latestTime: number; currentTime: number; range?: TimeRange; mode: ExportMode; showExportPreview: boolean; reviewSummary?: ReviewSummary; recordingsSummary?: RecordingsSummary; allLabels: string[]; allZones: string[]; onUpdateFilter: (filter: ReviewFilter) => void; setRange: (range: TimeRange | undefined) => void; setMode: (mode: ExportMode) => void; setShowExportPreview: (showPreview: boolean) => void; }; export default function MobileReviewSettingsDrawer({ features = DEFAULT_DRAWER_FEATURES, camera, filter, currentSeverity, latestTime, currentTime, range, mode, showExportPreview, reviewSummary, recordingsSummary, allLabels, allZones, onUpdateFilter, setRange, setMode, setShowExportPreview, }: MobileReviewSettingsDrawerProps) { const { t } = useTranslation(["views/recording", "components/dialog"]); const [drawerMode, setDrawerMode] = useState("none"); // exports const [name, setName] = useState(""); const onStartExport = useCallback(() => { if (!range) { toast.error(t("toast.error.noValidTimeSelected"), { position: "top-center", }); return; } if (range.before < range.after) { toast.error(t("toast.error.endTimeMustAfterStartTime"), { position: "top-center", }); return; } axios .post( `export/${camera}/start/${Math.round(range.after)}/end/${Math.round(range.before)}`, { playback: "realtime", name, }, ) .then((response) => { if (response.status == 200) { toast.success( t("export.toast.success", { ns: "components/dialog" }), { position: "top-center", }, ); setName(""); setRange(undefined); setMode("none"); } }) .catch((error) => { const errorMessage = error.response?.data?.message || error.response?.data?.detail || "Unknown error"; toast.error( t("export.toast.error.failed", { ns: "components/dialog", errorMessage, }), { position: "top-center", }, ); }); }, [camera, name, range, setRange, setName, setMode, t]); // filters const [currentFilter, setCurrentFilter] = useState({ labels: filter?.labels, zones: filter?.zones, showAll: filter?.showAll, ...filter, }); if (!isMobile) { return; } let content; if (drawerMode == "select") { content = (
{features.includes("export") && ( )} {features.includes("calendar") && ( )} {features.includes("filter") && ( )}
); } else if (drawerMode == "export") { content = ( { setMode(mode); if (mode == "timeline") { setDrawerMode("none"); } }} onCancel={() => { setMode("none"); setRange(undefined); setDrawerMode("select"); }} /> ); } else if (drawerMode == "calendar") { content = (
setDrawerMode("select")} > {t("button.back", { ns: "common" })}
{t("calendar")}
{ onUpdateFilter({ ...filter, after: day == undefined ? undefined : day.getTime() / 1000, before: day == undefined ? undefined : getEndOfDayTimestamp(day), }); }} />
); } else if (drawerMode == "filter") { content = (
setDrawerMode("select")} > {t("button.back", { ns: "common" })}
{t("filter")}
{ if (currentFilter !== filter) { onUpdateFilter(currentFilter); } }} onReset={() => { const resetFilter: GeneralFilter = {}; setCurrentFilter(resetFilter); onUpdateFilter(resetFilter); }} onClose={() => setDrawerMode("select")} />
); } return ( <> onStartExport()} onCancel={() => setMode("none")} onPreview={() => setShowExportPreview(true)} /> { if (!open) { setDrawerMode("none"); } }} > {content} ); }