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 } from "./ExportDialog"; import { ExportMode } from "@/types/filter"; import ReviewActivityCalendar from "./ReviewActivityCalendar"; import { SelectSeparator } from "../ui/select"; import { 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 { isMobile } from "react-device-detect"; 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; reviewSummary?: ReviewSummary; allLabels: string[]; onUpdateFilter: (filter: ReviewFilter) => void; setRange: (range: TimeRange | undefined) => void; setMode: (mode: ExportMode) => void; }; export default function MobileReviewSettingsDrawer({ features = DEFAULT_DRAWER_FEATURES, camera, filter, currentSeverity, latestTime, currentTime, range, mode, reviewSummary, allLabels, onUpdateFilter, setRange, setMode, }: MobileReviewSettingsDrawerProps) { const [drawerMode, setDrawerMode] = useState("none"); // exports const [name, setName] = useState(""); const onStartExport = useCallback(() => { if (!range) { toast.error("No valid time range selected", { 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( "Successfully started export. View the file in the /exports folder.", { position: "top-center" }, ); setName(""); setRange(undefined); setMode("none"); } }) .catch((error) => { if (error.response?.data?.message) { toast.error( `Failed to start export: ${error.response.data.message}`, { position: "top-center" }, ); } else { toast.error(`Failed to start export: ${error.message}`, { position: "top-center", }); } }); }, [camera, name, range, setRange, setName, setMode]); // filters const [currentLabels, setCurrentLabels] = useState( filter?.labels, ); 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")} > Back
Calendar
{ onUpdateFilter({ ...filter, after: day == undefined ? undefined : day.getTime() / 1000, before: day == undefined ? undefined : getEndOfDayTimestamp(day), }); }} />
); } else if (drawerMode == "filter") { content = (
setDrawerMode("select")} > Back
Filter
{ onUpdateFilter({ ...filter, showAll }); }} setCurrentLabels={setCurrentLabels} updateLabelFilter={(newLabels) => onUpdateFilter({ ...filter, labels: newLabels }) } onClose={() => setDrawerMode("select")} />
); } return ( <> onStartExport()} onCancel={() => setMode("none")} /> { if (!open) { setDrawerMode("none"); } }} > {content} ); }