import { useEffect, useMemo } from "react"; import { isIOS, isMobileOnly, isSafari } from "react-device-detect"; import useSWR from "swr"; import { useApiHost } from "@/api"; import { cn } from "@/lib/utils"; import { LuArrowRightCircle } from "react-icons/lu"; import { useNavigate } from "react-router-dom"; import { Tooltip, TooltipContent, TooltipTrigger, } from "@/components/ui/tooltip"; import { TooltipPortal } from "@radix-ui/react-tooltip"; import { SearchResult } from "@/types/search"; import ImageLoadingIndicator from "@/components/indicators/ImageLoadingIndicator"; import useImageLoaded from "@/hooks/use-image-loaded"; import ActivityIndicator from "@/components/indicators/activity-indicator"; type ExploreViewProps = { onSelectSearch: (searchResult: SearchResult) => void; }; export default function ExploreView({ onSelectSearch }: ExploreViewProps) { // title useEffect(() => { document.title = "Explore - Frigate"; }, []); // data const { data: events } = useSWR( [ "events/explore", { limit: isMobileOnly ? 5 : 10, }, ], { revalidateOnFocus: false, }, ); const eventsByLabel = useMemo(() => { if (!events) return {}; return events.reduce>((acc, event) => { const label = event.label || "Unknown"; if (!acc[label]) { acc[label] = []; } acc[label].push(event); return acc; }, {}); }, [events]); if (!events) { return ( ); } return (
{Object.entries(eventsByLabel).map(([label, filteredEvents]) => ( ))}
); } type ThumbnailRowType = { objectType: string; searchResults?: SearchResult[]; onSelectSearch: (searchResult: SearchResult) => void; }; function ThumbnailRow({ objectType, searchResults, onSelectSearch, }: ThumbnailRowType) { const navigate = useNavigate(); const handleSearch = (label: string) => { const similaritySearchParams = new URLSearchParams({ labels: label, }).toString(); navigate(`/explore?${similaritySearchParams}`); }; return (
{objectType.replaceAll("_", " ")} {searchResults && ( ( { // @ts-expect-error we know this is correct searchResults[0].event_count }{" "} tracked objects){" "} )}
{searchResults?.map((event) => (
))}
handleSearch(objectType)} >
); } type ExploreThumbnailImageProps = { event: SearchResult; onSelectSearch: (searchResult: SearchResult) => void; }; function ExploreThumbnailImage({ event, onSelectSearch, }: ExploreThumbnailImageProps) { const apiHost = useApiHost(); const [imgRef, imgLoaded, onImgLoad] = useImageLoaded(); return ( <> onSelectSearch(event)} onLoad={() => { onImgLoad(); }} /> ); } function ExploreMoreLink({ objectType }: { objectType: string }) { const formattedType = objectType.replaceAll("_", " "); const label = formattedType.endsWith("s") ? `${formattedType}es` : `${formattedType}s`; return
Explore More {label}
; }