diff --git a/web/src/components/filter/ReviewFilterGroup.tsx b/web/src/components/filter/ReviewFilterGroup.tsx index f2ad7bb46..489a997fb 100644 --- a/web/src/components/filter/ReviewFilterGroup.tsx +++ b/web/src/components/filter/ReviewFilterGroup.tsx @@ -16,8 +16,11 @@ import { ReviewFilter } from "@/types/review"; import { getEndOfDayTimestamp } from "@/utils/dateUtil"; import { useFormattedTimestamp } from "@/hooks/use-date-utils"; import { FaCalendarAlt, FaFilter, FaVideo } from "react-icons/fa"; -import { getIconTypeForGroup } from "@/utils/iconUtil"; import { IconType } from "react-icons"; +import { isMobile } from "react-device-detect"; +import { Drawer, DrawerContent, DrawerTrigger } from "../ui/drawer"; +import { Switch } from "../ui/switch"; +import { Label } from "../ui/label"; const ATTRIBUTES = ["amazon", "face", "fedex", "license_plate", "ups"]; @@ -137,6 +140,105 @@ function CamerasFilterButton({ selectedCameras, ); + const trigger = ( + + ); + const content = ( + <> + + Filter Cameras + + + { + if (isChecked) { + setCurrentCameras(undefined); + } + }} + /> + {groups.length > 0 && ( + <> + + {groups.map(([name, conf]) => { + return ( + { + setCurrentCameras([...conf.cameras]); + }} + /> + ); + })} + + )} + + {allCameras.map((item) => ( + { + if (isChecked) { + const updatedCameras = currentCameras ? [...currentCameras] : []; + + updatedCameras.push(item); + setCurrentCameras(updatedCameras); + } else { + const updatedCameras = currentCameras ? [...currentCameras] : []; + + // can not deselect the last item + if (updatedCameras.length > 1) { + updatedCameras.splice(updatedCameras.indexOf(item), 1); + setCurrentCameras(updatedCameras); + } + } + }} + /> + ))} + +
+ +
+ + ); + + if (isMobile) { + return ( + { + if (!open) { + setCurrentCameras(selectedCameras); + } + + setOpen(open); + }} + > + {trigger} + {content} + + ); + } + return ( - - - - - Filter Cameras - - { - if (isChecked) { - setCurrentCameras(undefined); - } - }} - /> - {groups.length > 0 && ( - <> - - {groups.map(([name, conf]) => { - return ( - { - setCurrentCameras([...conf.cameras]); - }} - /> - ); - })} - - )} - - {allCameras.map((item) => ( - { - if (isChecked) { - const updatedCameras = currentCameras - ? [...currentCameras] - : []; - - updatedCameras.push(item); - setCurrentCameras(updatedCameras); - } else { - const updatedCameras = currentCameras - ? [...currentCameras] - : []; - - // can not deselect the last item - if (updatedCameras.length > 1) { - updatedCameras.splice(updatedCameras.indexOf(item), 1); - setCurrentCameras(updatedCameras); - } - } - }} - /> - ))} - -
- -
-
+ {trigger} + {content}
); } @@ -255,6 +278,58 @@ function CalendarFilterButton({ "%b %-d", ); + const trigger = ( + + ); + const content = ( + <> + { + setSelectedDay(day); + }} + /> + +
+ +
+ + ); + + if (isMobile) { + return ( + { + if (!open) { + setSelectedDay(day); + } + + setOpen(open); + }} + > + {trigger} + {content} + + ); + } + return ( - - - - - { - setSelectedDay(day); - }} - /> - -
- -
-
+ {trigger} + {content}
); } @@ -320,6 +367,101 @@ function GeneralFilterButton({ selectedLabels, ); + const trigger = ( + + ); + const content = ( + <> +
+ setReviewed(reviewed == 0 ? 1 : 0)} + /> + +
+ + + Filter Labels + + + { + if (isChecked) { + setCurrentLabels(undefined); + } + }} + /> + + {allLabels.map((item) => ( + { + if (isChecked) { + const updatedLabels = currentLabels ? [...currentLabels] : []; + + updatedLabels.push(item); + setCurrentLabels(updatedLabels); + } else { + const updatedLabels = currentLabels ? [...currentLabels] : []; + + // can not deselect the last item + if (updatedLabels.length > 1) { + updatedLabels.splice(updatedLabels.indexOf(item), 1); + setCurrentLabels(updatedLabels); + } + } + }} + /> + ))} + +
+ +
+ + ); + + if (isMobile) { + return ( + { + if (!open) { + setReviewed(showReviewed ?? 0); + setCurrentLabels(selectedLabels); + } + + setOpen(open); + }} + > + {trigger} + {content} + + ); + } + return ( - - - - - <> - - - Filter Labels - - { - if (isChecked) { - setCurrentLabels(undefined); - } - }} - /> - - {allLabels.map((item) => ( - { - if (isChecked) { - const updatedLabels = currentLabels ? [...currentLabels] : []; - - updatedLabels.push(item); - setCurrentLabels(updatedLabels); - } else { - const updatedLabels = currentLabels ? [...currentLabels] : []; - - // can not deselect the last item - if (updatedLabels.length > 1) { - updatedLabels.splice(updatedLabels.indexOf(item), 1); - setCurrentLabels(updatedLabels); - } - } - }} - /> - ))} - -
- -
- -
+ {trigger} + {content}
); } diff --git a/web/src/components/ui/calendar.tsx b/web/src/components/ui/calendar.tsx index 039f62813..792df0890 100644 --- a/web/src/components/ui/calendar.tsx +++ b/web/src/components/ui/calendar.tsx @@ -25,19 +25,19 @@ function Calendar({ nav: "space-x-1 flex items-center", nav_button: cn( buttonVariants({ variant: "outline" }), - "h-7 w-7 bg-transparent p-0 opacity-50 hover:opacity-100" + "h-7 w-7 bg-transparent p-0 opacity-50 hover:opacity-100", ), nav_button_previous: "absolute left-1", nav_button_next: "absolute right-1", table: "w-full border-collapse space-y-1", - head_row: "flex", + head_row: "flex justify-center", head_cell: "text-muted-foreground rounded-md w-9 font-normal text-[0.8rem]", - row: "flex w-full mt-2", + row: "flex w-full mt-2 justify-center", cell: "h-9 w-9 text-center text-sm p-0 relative [&:has([aria-selected].day-range-end)]:rounded-r-md [&:has([aria-selected].day-outside)]:bg-accent/50 [&:has([aria-selected])]:bg-accent first:[&:has([aria-selected])]:rounded-l-md last:[&:has([aria-selected])]:rounded-r-md focus-within:relative focus-within:z-20", day: cn( buttonVariants({ variant: "ghost" }), - "h-9 w-9 p-0 font-normal aria-selected:opacity-100" + "h-9 w-9 p-0 font-normal aria-selected:opacity-100", ), day_range_end: "day-range-end", day_selected: diff --git a/web/src/components/ui/switch.tsx b/web/src/components/ui/switch.tsx index aa58baa29..343df17d0 100644 --- a/web/src/components/ui/switch.tsx +++ b/web/src/components/ui/switch.tsx @@ -9,7 +9,7 @@ const Switch = React.forwardRef< >(({ className, ...props }, ref) => (