mirror of
https://github.com/blakeblackshear/frigate.git
synced 2026-02-15 07:35:27 +03:00
Add ability to filter by time range
This commit is contained in:
parent
8c540d7210
commit
52b562eed8
@ -13,6 +13,7 @@ import { Popover, PopoverContent, PopoverTrigger } from "../ui/popover";
|
||||
import { DateRangePicker } from "../ui/calendar-range";
|
||||
import { DateRange } from "react-day-picker";
|
||||
import { useState } from "react";
|
||||
import PlatformAwareDialog from "../overlay/dialog/PlatformAwareDialog";
|
||||
|
||||
type CalendarFilterButtonProps = {
|
||||
reviewSummary?: ReviewSummary;
|
||||
@ -24,6 +25,7 @@ export default function CalendarFilterButton({
|
||||
day,
|
||||
updateSelectedDay,
|
||||
}: CalendarFilterButtonProps) {
|
||||
const [open, setOpen] = useState(false);
|
||||
const selectedDate = useFormattedTimestamp(
|
||||
day == undefined ? 0 : day?.getTime() / 1000 + 1,
|
||||
"%b %-d",
|
||||
@ -65,20 +67,14 @@ export default function CalendarFilterButton({
|
||||
</>
|
||||
);
|
||||
|
||||
if (isMobile) {
|
||||
return (
|
||||
<Drawer>
|
||||
<DrawerTrigger asChild>{trigger}</DrawerTrigger>
|
||||
<DrawerContent>{content}</DrawerContent>
|
||||
</Drawer>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<Popover>
|
||||
<PopoverTrigger asChild>{trigger}</PopoverTrigger>
|
||||
<PopoverContent className="w-auto">{content}</PopoverContent>
|
||||
</Popover>
|
||||
<PlatformAwareDialog
|
||||
trigger={trigger}
|
||||
content={content}
|
||||
contentClassName="w-auto"
|
||||
open={open}
|
||||
onOpenChange={setOpen}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@ -19,6 +19,7 @@ import FilterSwitch from "./FilterSwitch";
|
||||
import { FilterList } from "@/types/filter";
|
||||
import CalendarFilterButton from "./CalendarFilterButton";
|
||||
import { CamerasFilterButton } from "./CamerasFilterButton";
|
||||
import PlatformAwareDialog from "../overlay/dialog/PlatformAwareDialog";
|
||||
|
||||
const REVIEW_FILTERS = [
|
||||
"cameras",
|
||||
@ -367,9 +368,10 @@ function GeneralFilterButton({
|
||||
/>
|
||||
);
|
||||
|
||||
if (isMobile) {
|
||||
return (
|
||||
<Drawer
|
||||
<PlatformAwareDialog
|
||||
trigger={trigger}
|
||||
content={content}
|
||||
open={open}
|
||||
onOpenChange={(open) => {
|
||||
if (!open) {
|
||||
@ -378,29 +380,7 @@ function GeneralFilterButton({
|
||||
|
||||
setOpen(open);
|
||||
}}
|
||||
>
|
||||
<DrawerTrigger asChild>{trigger}</DrawerTrigger>
|
||||
<DrawerContent className="max-h-[75dvh] overflow-hidden">
|
||||
{content}
|
||||
</DrawerContent>
|
||||
</Drawer>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<Popover
|
||||
open={open}
|
||||
onOpenChange={(open) => {
|
||||
if (!open) {
|
||||
setCurrentLabels(selectedLabels);
|
||||
}
|
||||
|
||||
setOpen(open);
|
||||
}}
|
||||
>
|
||||
<PopoverTrigger asChild>{trigger}</PopoverTrigger>
|
||||
<PopoverContent>{content}</PopoverContent>
|
||||
</Popover>
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@ -6,38 +6,26 @@ import { useCallback, useEffect, useMemo, useState } from "react";
|
||||
import { DropdownMenuSeparator } from "../ui/dropdown-menu";
|
||||
import { getEndOfDayTimestamp } from "@/utils/dateUtil";
|
||||
import { isDesktop, isMobile } from "react-device-detect";
|
||||
import { Drawer, DrawerContent, DrawerTrigger } from "../ui/drawer";
|
||||
import { Switch } from "../ui/switch";
|
||||
import { Label } from "../ui/label";
|
||||
import FilterSwitch from "./FilterSwitch";
|
||||
import { FilterList } from "@/types/filter";
|
||||
import { CalendarRangeFilterButton } from "./CalendarFilterButton";
|
||||
import { CamerasFilterButton } from "./CamerasFilterButton";
|
||||
import { SearchFilter, SearchSource } from "@/types/search";
|
||||
import {
|
||||
DEFAULT_SEARCH_FILTERS,
|
||||
SearchFilter,
|
||||
SearchFilters,
|
||||
SearchSource,
|
||||
} from "@/types/search";
|
||||
import { DateRange } from "react-day-picker";
|
||||
import { cn } from "@/lib/utils";
|
||||
import SubFilterIcon from "../icons/SubFilterIcon";
|
||||
import { FaLocationDot } from "react-icons/fa6";
|
||||
import { MdLabel } from "react-icons/md";
|
||||
import SearchSourceIcon from "../icons/SearchSourceIcon";
|
||||
|
||||
const SEARCH_FILTERS = [
|
||||
"cameras",
|
||||
"date",
|
||||
"general",
|
||||
"zone",
|
||||
"sub",
|
||||
"source",
|
||||
] as const;
|
||||
type SearchFilters = (typeof SEARCH_FILTERS)[number];
|
||||
const DEFAULT_REVIEW_FILTERS: SearchFilters[] = [
|
||||
"cameras",
|
||||
"date",
|
||||
"general",
|
||||
"zone",
|
||||
"sub",
|
||||
"source",
|
||||
];
|
||||
import PlatformAwareDialog from "../overlay/dialog/PlatformAwareDialog";
|
||||
import { FaArrowRight, FaClock } from "react-icons/fa";
|
||||
|
||||
type SearchFilterGroupProps = {
|
||||
className: string;
|
||||
@ -48,7 +36,7 @@ type SearchFilterGroupProps = {
|
||||
};
|
||||
export default function SearchFilterGroup({
|
||||
className,
|
||||
filters = DEFAULT_REVIEW_FILTERS,
|
||||
filters = DEFAULT_SEARCH_FILTERS,
|
||||
filter,
|
||||
filterList,
|
||||
onUpdateFilter,
|
||||
@ -182,6 +170,14 @@ export default function SearchFilterGroup({
|
||||
updateSelectedRange={onUpdateSelectedRange}
|
||||
/>
|
||||
)}
|
||||
{filters.includes("time") && (
|
||||
<TimeRangeFilterButton
|
||||
timeRange={filter?.timeRange}
|
||||
updateTimeRange={(timeRange) =>
|
||||
onUpdateFilter({ ...filter, timeRange })
|
||||
}
|
||||
/>
|
||||
)}
|
||||
{filters.includes("zone") && allZones.length > 0 && (
|
||||
<ZoneFilterButton
|
||||
allZones={filterValues.zones}
|
||||
@ -291,9 +287,11 @@ function GeneralFilterButton({
|
||||
/>
|
||||
);
|
||||
|
||||
if (isMobile) {
|
||||
return (
|
||||
<Drawer
|
||||
<PlatformAwareDialog
|
||||
trigger={trigger}
|
||||
content={content}
|
||||
contentClassName={isDesktop ? "" : "max-h-[75dvh] overflow-hidden p-4"}
|
||||
open={open}
|
||||
onOpenChange={(open) => {
|
||||
if (!open) {
|
||||
@ -302,29 +300,7 @@ function GeneralFilterButton({
|
||||
|
||||
setOpen(open);
|
||||
}}
|
||||
>
|
||||
<DrawerTrigger asChild>{trigger}</DrawerTrigger>
|
||||
<DrawerContent className="max-h-[75dvh] overflow-hidden p-4">
|
||||
{content}
|
||||
</DrawerContent>
|
||||
</Drawer>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<Popover
|
||||
open={open}
|
||||
onOpenChange={(open) => {
|
||||
if (!open) {
|
||||
setCurrentLabels(selectedLabels);
|
||||
}
|
||||
|
||||
setOpen(open);
|
||||
}}
|
||||
>
|
||||
<PopoverTrigger asChild>{trigger}</PopoverTrigger>
|
||||
<PopoverContent>{content}</PopoverContent>
|
||||
</Popover>
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
@ -418,6 +394,164 @@ export function GeneralFilterContent({
|
||||
);
|
||||
}
|
||||
|
||||
type TimeRangeFilterButtonProps = {
|
||||
timeRange?: string;
|
||||
updateTimeRange: (range: string | undefined) => void;
|
||||
};
|
||||
function TimeRangeFilterButton({
|
||||
timeRange,
|
||||
updateTimeRange,
|
||||
}: TimeRangeFilterButtonProps) {
|
||||
const [open, setOpen] = useState(false);
|
||||
const [startOpen, setStartOpen] = useState(false);
|
||||
const [endOpen, setEndOpen] = useState(false);
|
||||
|
||||
const [afterHour, beforeHour] = useMemo(() => {
|
||||
if (!timeRange || !timeRange.includes(",")) {
|
||||
return ["00:00", "24:00"];
|
||||
}
|
||||
|
||||
return timeRange.split(",");
|
||||
}, [timeRange]);
|
||||
|
||||
const [selectedAfterHour, setSelectedAfterHour] = useState(afterHour);
|
||||
const [selectedBeforeHour, setSelectedBeforeHour] = useState(beforeHour);
|
||||
|
||||
const trigger = (
|
||||
<Button
|
||||
size="sm"
|
||||
variant={timeRange ? "select" : "default"}
|
||||
className="flex items-center gap-2 capitalize"
|
||||
>
|
||||
<FaClock
|
||||
className={`${timeRange ? "text-selected-foreground" : "text-secondary-foreground"}`}
|
||||
/>
|
||||
<div
|
||||
className={`${timeRange ? "text-selected-foreground" : "text-primary"}`}
|
||||
>
|
||||
{timeRange ? `${afterHour} - ${beforeHour}` : "All Times"}
|
||||
</div>
|
||||
</Button>
|
||||
);
|
||||
const content = (
|
||||
<div className="scrollbar-container h-auto max-h-[80dvh] overflow-y-auto overflow-x-hidden">
|
||||
<div
|
||||
className={`mt-3 flex items-center rounded-lg bg-secondary text-secondary-foreground ${isDesktop ? "mx-8 gap-2 px-2" : "pl-2"}`}
|
||||
>
|
||||
<Popover
|
||||
open={startOpen}
|
||||
onOpenChange={(open) => {
|
||||
if (!open) {
|
||||
setStartOpen(false);
|
||||
}
|
||||
}}
|
||||
>
|
||||
<PopoverTrigger asChild>
|
||||
<Button
|
||||
className={`text-primary ${isDesktop ? "" : "text-xs"}`}
|
||||
variant={startOpen ? "select" : "default"}
|
||||
size="sm"
|
||||
onClick={() => {
|
||||
setStartOpen(true);
|
||||
setEndOpen(false);
|
||||
}}
|
||||
>
|
||||
{selectedAfterHour}
|
||||
</Button>
|
||||
</PopoverTrigger>
|
||||
<PopoverContent className="flex flex-col items-center">
|
||||
<input
|
||||
className="text-md mx-4 w-full border border-input bg-background p-1 text-secondary-foreground hover:bg-accent hover:text-accent-foreground dark:[color-scheme:dark]"
|
||||
id="startTime"
|
||||
type="time"
|
||||
value={selectedAfterHour}
|
||||
step="60"
|
||||
onChange={(e) => {
|
||||
const clock = e.target.value;
|
||||
const [hour, minute, _] = clock.split(":");
|
||||
setSelectedAfterHour(`${hour}:${minute}`);
|
||||
}}
|
||||
/>
|
||||
</PopoverContent>
|
||||
</Popover>
|
||||
<FaArrowRight className="size-4 text-primary" />
|
||||
<Popover
|
||||
open={endOpen}
|
||||
onOpenChange={(open) => {
|
||||
if (!open) {
|
||||
setEndOpen(false);
|
||||
}
|
||||
}}
|
||||
>
|
||||
<PopoverTrigger asChild>
|
||||
<Button
|
||||
className={`text-primary ${isDesktop ? "" : "text-xs"}`}
|
||||
variant={endOpen ? "select" : "default"}
|
||||
size="sm"
|
||||
onClick={() => {
|
||||
setEndOpen(true);
|
||||
setStartOpen(false);
|
||||
}}
|
||||
>
|
||||
{selectedBeforeHour}
|
||||
</Button>
|
||||
</PopoverTrigger>
|
||||
<PopoverContent className="flex flex-col items-center">
|
||||
<input
|
||||
className="text-md mx-4 w-full border border-input bg-background p-1 text-secondary-foreground hover:bg-accent hover:text-accent-foreground dark:[color-scheme:dark]"
|
||||
id="startTime"
|
||||
type="time"
|
||||
value={selectedBeforeHour}
|
||||
step="60"
|
||||
onChange={(e) => {
|
||||
const clock = e.target.value;
|
||||
const [hour, minute, _] = clock.split(":");
|
||||
setSelectedBeforeHour(`${hour}:${minute}`);
|
||||
}}
|
||||
/>
|
||||
</PopoverContent>
|
||||
</Popover>
|
||||
<DropdownMenuSeparator />
|
||||
</div>
|
||||
<div className="flex items-center justify-evenly p-2">
|
||||
<Button
|
||||
variant="select"
|
||||
onClick={() => {
|
||||
if (selectedAfterHour == "00:00" && selectedBeforeHour == "24:00") {
|
||||
updateTimeRange(undefined);
|
||||
} else {
|
||||
updateTimeRange(`${selectedAfterHour},${selectedBeforeHour}`);
|
||||
}
|
||||
|
||||
setOpen(false);
|
||||
}}
|
||||
>
|
||||
Apply
|
||||
</Button>
|
||||
<Button
|
||||
onClick={() => {
|
||||
setSelectedAfterHour("00:00");
|
||||
setSelectedBeforeHour("24:00");
|
||||
}}
|
||||
>
|
||||
Reset
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
||||
return (
|
||||
<PlatformAwareDialog
|
||||
trigger={trigger}
|
||||
content={content}
|
||||
open={open}
|
||||
onOpenChange={(open) => {
|
||||
setOpen(open);
|
||||
}}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
type ZoneFilterButtonProps = {
|
||||
allZones: string[];
|
||||
selectedZones?: string[];
|
||||
@ -485,9 +619,10 @@ function ZoneFilterButton({
|
||||
/>
|
||||
);
|
||||
|
||||
if (isMobile) {
|
||||
return (
|
||||
<Drawer
|
||||
<PlatformAwareDialog
|
||||
trigger={trigger}
|
||||
content={content}
|
||||
open={open}
|
||||
onOpenChange={(open) => {
|
||||
if (!open) {
|
||||
@ -496,29 +631,7 @@ function ZoneFilterButton({
|
||||
|
||||
setOpen(open);
|
||||
}}
|
||||
>
|
||||
<DrawerTrigger asChild>{trigger}</DrawerTrigger>
|
||||
<DrawerContent className="max-h-[75dvh] overflow-hidden p-4">
|
||||
{content}
|
||||
</DrawerContent>
|
||||
</Drawer>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<Popover
|
||||
open={open}
|
||||
onOpenChange={(open) => {
|
||||
if (!open) {
|
||||
setCurrentZones(selectedZones);
|
||||
}
|
||||
|
||||
setOpen(open);
|
||||
}}
|
||||
>
|
||||
<PopoverTrigger asChild>{trigger}</PopoverTrigger>
|
||||
<PopoverContent>{content}</PopoverContent>
|
||||
</Popover>
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
@ -679,9 +792,10 @@ function SubFilterButton({
|
||||
/>
|
||||
);
|
||||
|
||||
if (isMobile) {
|
||||
return (
|
||||
<Drawer
|
||||
<PlatformAwareDialog
|
||||
trigger={trigger}
|
||||
content={content}
|
||||
open={open}
|
||||
onOpenChange={(open) => {
|
||||
if (!open) {
|
||||
@ -690,29 +804,7 @@ function SubFilterButton({
|
||||
|
||||
setOpen(open);
|
||||
}}
|
||||
>
|
||||
<DrawerTrigger asChild>{trigger}</DrawerTrigger>
|
||||
<DrawerContent className="max-h-[75dvh] overflow-hidden p-4">
|
||||
{content}
|
||||
</DrawerContent>
|
||||
</Drawer>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<Popover
|
||||
open={open}
|
||||
onOpenChange={(open) => {
|
||||
if (!open) {
|
||||
setCurrentSubLabels(selectedSubLabels);
|
||||
}
|
||||
|
||||
setOpen(open);
|
||||
}}
|
||||
>
|
||||
<PopoverTrigger asChild>{trigger}</PopoverTrigger>
|
||||
<PopoverContent>{content}</PopoverContent>
|
||||
</Popover>
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
@ -863,32 +955,13 @@ function SearchTypeButton({
|
||||
/>
|
||||
);
|
||||
|
||||
if (isMobile) {
|
||||
return (
|
||||
<Drawer
|
||||
<PlatformAwareDialog
|
||||
trigger={trigger}
|
||||
content={content}
|
||||
open={open}
|
||||
onOpenChange={(open) => {
|
||||
setOpen(open);
|
||||
}}
|
||||
>
|
||||
<DrawerTrigger asChild>{trigger}</DrawerTrigger>
|
||||
<DrawerContent className="max-h-[75dvh] overflow-hidden p-4">
|
||||
{content}
|
||||
</DrawerContent>
|
||||
</Drawer>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<Popover
|
||||
open={open}
|
||||
onOpenChange={(open) => {
|
||||
setOpen(open);
|
||||
}}
|
||||
>
|
||||
<PopoverTrigger asChild>{trigger}</PopoverTrigger>
|
||||
<PopoverContent>{content}</PopoverContent>
|
||||
</Popover>
|
||||
onOpenChange={setOpen}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
45
web/src/components/overlay/dialog/PlatformAwareDialog.tsx
Normal file
45
web/src/components/overlay/dialog/PlatformAwareDialog.tsx
Normal file
@ -0,0 +1,45 @@
|
||||
import { Drawer, DrawerContent, DrawerTrigger } from "@/components/ui/drawer";
|
||||
import {
|
||||
Popover,
|
||||
PopoverContent,
|
||||
PopoverTrigger,
|
||||
} from "@/components/ui/popover";
|
||||
import { isMobile } from "react-device-detect";
|
||||
|
||||
type PlatformAwareDialogProps = {
|
||||
trigger: JSX.Element;
|
||||
content: JSX.Element;
|
||||
triggerClassName?: string;
|
||||
contentClassName?: string;
|
||||
open: boolean;
|
||||
onOpenChange: (open: boolean) => void;
|
||||
};
|
||||
export default function PlatformAwareDialog({
|
||||
trigger,
|
||||
content,
|
||||
triggerClassName = "",
|
||||
contentClassName = "",
|
||||
open,
|
||||
onOpenChange,
|
||||
}: PlatformAwareDialogProps) {
|
||||
if (isMobile) {
|
||||
return (
|
||||
<Drawer open={open} onOpenChange={onOpenChange}>
|
||||
<DrawerTrigger asChild>{trigger}</DrawerTrigger>
|
||||
<DrawerContent className="max-h-[75dvh] overflow-hidden p-4">
|
||||
{content}
|
||||
</DrawerContent> const [open, setOpen] = useState(false);
|
||||
|
||||
</Drawer>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<Popover open={open} onOpenChange={onOpenChange}>
|
||||
<PopoverTrigger asChild className={triggerClassName}>
|
||||
{trigger}
|
||||
</PopoverTrigger>
|
||||
<PopoverContent className={contentClassName}>{content}</PopoverContent>
|
||||
</Popover>
|
||||
);
|
||||
}
|
||||
@ -1,9 +1,12 @@
|
||||
import { useEventUpdate } from "@/api/ws";
|
||||
import { useApiFilterArgs } from "@/hooks/use-api-filter";
|
||||
import { useTimezone } from "@/hooks/use-date-utils";
|
||||
import { FrigateConfig } from "@/types/frigateConfig";
|
||||
import { SearchFilter, SearchQuery, SearchResult } from "@/types/search";
|
||||
import SearchView from "@/views/search/SearchView";
|
||||
import { useCallback, useEffect, useMemo, useState } from "react";
|
||||
import { TbExclamationCircle } from "react-icons/tb";
|
||||
import useSWR from "swr";
|
||||
import useSWRInfinite from "swr/infinite";
|
||||
|
||||
const API_LIMIT = 25;
|
||||
@ -11,6 +14,12 @@ const API_LIMIT = 25;
|
||||
export default function Explore() {
|
||||
// search field handler
|
||||
|
||||
const { data: config } = useSWR<FrigateConfig>("config", {
|
||||
revalidateOnFocus: false,
|
||||
});
|
||||
|
||||
const timezone = useTimezone(config);
|
||||
|
||||
const [search, setSearch] = useState("");
|
||||
|
||||
const [searchFilter, setSearchFilter, searchSearchParams] =
|
||||
@ -65,9 +74,11 @@ export default function Explore() {
|
||||
zones: searchSearchParams["zones"],
|
||||
before: searchSearchParams["before"],
|
||||
after: searchSearchParams["after"],
|
||||
time_range: searchSearchParams["timeRange"],
|
||||
search_type: searchSearchParams["search_type"],
|
||||
limit:
|
||||
Object.keys(searchSearchParams).length == 0 ? API_LIMIT : undefined,
|
||||
timezone,
|
||||
in_progress: 0,
|
||||
include_thumbnails: 0,
|
||||
},
|
||||
@ -94,7 +105,7 @@ export default function Explore() {
|
||||
include_thumbnails: 0,
|
||||
},
|
||||
];
|
||||
}, [searchTerm, searchSearchParams, similaritySearch]);
|
||||
}, [searchTerm, searchSearchParams, similaritySearch, timezone]);
|
||||
|
||||
// paging
|
||||
|
||||
|
||||
@ -1,3 +1,23 @@
|
||||
const SEARCH_FILTERS = [
|
||||
"cameras",
|
||||
"date",
|
||||
"time",
|
||||
"general",
|
||||
"zone",
|
||||
"sub",
|
||||
"source",
|
||||
] as const;
|
||||
export type SearchFilters = (typeof SEARCH_FILTERS)[number];
|
||||
export const DEFAULT_SEARCH_FILTERS: SearchFilters[] = [
|
||||
"cameras",
|
||||
"date",
|
||||
"time",
|
||||
"general",
|
||||
"zone",
|
||||
"sub",
|
||||
"source",
|
||||
];
|
||||
|
||||
export type SearchSource = "similarity" | "thumbnail" | "description";
|
||||
|
||||
export type SearchResult = {
|
||||
@ -36,6 +56,7 @@ export type SearchFilter = {
|
||||
zones?: string[];
|
||||
before?: number;
|
||||
after?: number;
|
||||
timeRange?: string;
|
||||
search_type?: SearchSource[];
|
||||
event_id?: string;
|
||||
};
|
||||
|
||||
@ -11,7 +11,13 @@ import {
|
||||
} from "@/components/ui/tooltip";
|
||||
import { cn } from "@/lib/utils";
|
||||
import { FrigateConfig } from "@/types/frigateConfig";
|
||||
import { SearchFilter, SearchResult, SearchSource } from "@/types/search";
|
||||
import {
|
||||
DEFAULT_SEARCH_FILTERS,
|
||||
SearchFilter,
|
||||
SearchFilters,
|
||||
SearchResult,
|
||||
SearchSource,
|
||||
} from "@/types/search";
|
||||
import { useCallback, useEffect, useMemo, useRef, useState } from "react";
|
||||
import { isMobileOnly } from "react-device-detect";
|
||||
import { LuImage, LuSearchX, LuText } from "react-icons/lu";
|
||||
@ -131,6 +137,20 @@ export default function SearchView({
|
||||
|
||||
const [searchDetail, setSearchDetail] = useState<SearchResult>();
|
||||
|
||||
const selectedFilters = useMemo<SearchFilters[]>(() => {
|
||||
const filters = [...DEFAULT_SEARCH_FILTERS];
|
||||
|
||||
if (
|
||||
searchFilter &&
|
||||
(searchFilter?.query?.length || searchFilter?.event_id?.length)
|
||||
) {
|
||||
const index = filters.indexOf("time");
|
||||
filters.splice(index, 1);
|
||||
}
|
||||
|
||||
return filters;
|
||||
}, [searchFilter]);
|
||||
|
||||
// search interaction
|
||||
|
||||
const [selectedIndex, setSelectedIndex] = useState<number | null>(null);
|
||||
@ -300,6 +320,7 @@ export default function SearchView({
|
||||
"w-full justify-between md:justify-start lg:justify-end",
|
||||
)}
|
||||
filter={searchFilter}
|
||||
filters={selectedFilters as SearchFilters[]}
|
||||
onUpdateFilter={onUpdateFilter}
|
||||
/>
|
||||
<ScrollBar orientation="horizontal" className="h-0" />
|
||||
|
||||
Loading…
Reference in New Issue
Block a user