diff --git a/web/src/components/filter/HistoryFilterPopover.tsx b/web/src/components/filter/HistoryFilterPopover.tsx index cdbd6efe8..90c4e4d4e 100644 --- a/web/src/components/filter/HistoryFilterPopover.tsx +++ b/web/src/components/filter/HistoryFilterPopover.tsx @@ -1,26 +1,26 @@ -import { LuFilter } from "react-icons/lu"; +import { LuCheck, LuFilter, LuFocus } from "react-icons/lu"; import { Button } from "../ui/button"; import { Popover, PopoverContent, PopoverTrigger } from "../ui/popover"; import useSWR from "swr"; import { FrigateConfig } from "@/types/frigateConfig"; -import { useMemo } from "react"; +import { useMemo, useState } from "react"; import { DropdownMenu, - DropdownMenuCheckboxItem, DropdownMenuContent, DropdownMenuLabel, DropdownMenuSeparator, DropdownMenuTrigger, } from "../ui/dropdown-menu"; +import { Calendar } from "../ui/calendar"; type HistoryFilterPopoverProps = { - filter: HistoryFilter; - onUpdateFilter: (filter: HistoryFilter) => void; + filter: HistoryFilter | undefined; + onUpdateFilter: (filter: HistoryFilter) => void; }; export default function HistoryFilterPopover({ - filter, - onUpdateFilter + filter, + onUpdateFilter, }: HistoryFilterPopoverProps) { const { data: config } = useSWR("config"); const { data: allLabels } = useSWR(["labels"], { @@ -39,6 +39,10 @@ export default function HistoryFilterPopover({ }), [config, allLabels, allSubLabels] ); + const [selectedFilters, setSelectedFilters] = useState({ + cameras: filter == undefined ? [] : filter.cameras, + labels: filter == undefined ? [] : filter.labels, + }); return ( @@ -48,8 +52,8 @@ export default function HistoryFilterPopover({ Filter - -
+ +
+ +
); } + +type FilterCheckBoxProps = { + label: string; + isChecked: boolean; + onCheckedChange: (isChecked: boolean) => void; + onSingleSelect: () => void; +}; + +function FilterCheckBox({ + label, + isChecked, + onCheckedChange, + onSingleSelect, +}: FilterCheckBoxProps) { + return ( +
onCheckedChange(!isChecked)} + > + {isChecked ? ( + + ) : ( +
+ )} +
{label}
+ +
+ ); +} diff --git a/web/src/hooks/use-api-filter.ts b/web/src/hooks/use-api-filter.ts new file mode 100644 index 000000000..2d1ad4699 --- /dev/null +++ b/web/src/hooks/use-api-filter.ts @@ -0,0 +1,17 @@ +import { useState } from "react"; + +type useApiFilterReturn = [ + filter: F | undefined, + setFilter: (filter: F) => void, + searchParams: { + [key: string]: any; + }, +]; + +export default function useApiFilter< + F extends FilterType, +>(): useApiFilterReturn { + const [filter, setFilter] = useState(); + + return [filter, setFilter, {}]; +} diff --git a/web/src/pages/History.tsx b/web/src/pages/History.tsx index 5641ecdbe..16f17eeaa 100644 --- a/web/src/pages/History.tsx +++ b/web/src/pages/History.tsx @@ -20,6 +20,7 @@ import { AlertDialogTitle, } from "@/components/ui/alert-dialog"; import HistoryFilterPopover from "@/components/filter/HistoryFilterPopover"; +import useApiFilter from "@/hooks/use-api-filter"; const API_LIMIT = 200; @@ -31,10 +32,8 @@ function History() { [config] ); - const [searchFilter, setSearchFilter] = useState({ - cameras: [], - labels: [], - }); + const [historyFilter, setHistoryFilter, historySearchParams] = + useApiFilter(); const timelineFetcher = useCallback((key: any) => { const [path, params] = Array.isArray(key) ? key : [key, undefined]; @@ -147,8 +146,8 @@ function History() {
History setSearchFilter(filter)} + filter={historyFilter} + onUpdateFilter={(filter) => setHistoryFilter(filter)} />
diff --git a/web/src/types/filter.ts b/web/src/types/filter.ts new file mode 100644 index 000000000..e1c6c6cfc --- /dev/null +++ b/web/src/types/filter.ts @@ -0,0 +1 @@ +type FilterType = { [searchKey: string]: any }; diff --git a/web/src/types/history.ts b/web/src/types/history.ts index 76e4e367f..c5e75d0f2 100644 --- a/web/src/types/history.ts +++ b/web/src/types/history.ts @@ -39,7 +39,7 @@ type HourlyTimeline = { hours: { [key: string]: Timeline[] }; } -type HistoryFilter = { +interface HistoryFilter extends FilterType { cameras: string[], labels: string[], } \ No newline at end of file