blakeblackshear.frigate/web/src/components/card/ReviewCard.tsx
Nicolas Mowen 049f27d710
Ongoing review segments (#10924)
* Update review maintainer to save events when ongoing

* Handle previews for in progress review items

* Reset DB items in app

* Handle in progress review items

* Scroll back down to selected event item

* Handle undefined end time

* Formatting

* remove unused

* Make export handles have full resolution

* reduce preview thumbnail props

* fix missing return

Co-authored-by: Josh Hawkins <32435876+hawkeye217@users.noreply.github.com>

---------

Co-authored-by: Josh Hawkins <32435876+hawkeye217@users.noreply.github.com>
2024-04-11 07:42:16 -05:00

73 lines
2.3 KiB
TypeScript

import { baseUrl } from "@/api/baseUrl";
import { useFormattedTimestamp } from "@/hooks/use-date-utils";
import { FrigateConfig } from "@/types/frigateConfig";
import { ReviewSegment } from "@/types/review";
import { getIconForLabel } from "@/utils/iconUtil";
import { isSafari } from "react-device-detect";
import useSWR from "swr";
import TimeAgo from "../dynamic/TimeAgo";
import { useMemo } from "react";
import useImageLoaded from "@/hooks/use-image-loaded";
import ImageLoadingIndicator from "../indicators/ImageLoadingIndicator";
type ReviewCardProps = {
event: ReviewSegment;
currentTime: number;
onClick?: () => void;
};
export default function ReviewCard({
event,
currentTime,
onClick,
}: ReviewCardProps) {
const { data: config } = useSWR<FrigateConfig>("config");
const [imgRef, imgLoaded, onImgLoad] = useImageLoaded();
const formattedDate = useFormattedTimestamp(
event.start_time,
config?.ui.time_format == "24hour" ? "%H:%M" : "%I:%M %p",
);
const isSelected = useMemo(
() =>
event.start_time <= currentTime &&
(event.end_time ?? Date.now() / 1000) >= currentTime,
[event, currentTime],
);
return (
<div
className="w-full relative flex flex-col gap-1.5 cursor-pointer"
onClick={onClick}
>
<ImageLoadingIndicator
className="absolute inset-0"
imgLoaded={imgLoaded}
/>
<img
ref={imgRef}
className={`size-full rounded-lg ${isSelected ? "outline outline-[3px] outline-offset-1 outline-selected" : ""} ${imgLoaded ? "visible" : "invisible"}`}
src={`${baseUrl}${event.thumb_path.replace("/media/frigate/", "")}`}
loading={isSafari ? "eager" : "lazy"}
onLoad={() => {
onImgLoad();
}}
/>
<div className="flex justify-between items-center">
<div className="flex justify-evenly items-center gap-1">
{event.data.objects.map((object) => {
return getIconForLabel(object, "size-3 text-white");
})}
{event.data.audio.map((audio) => {
return getIconForLabel(audio, "size-3 text-white");
})}
<div className="font-extra-light text-xs">{formattedDate}</div>
</div>
<TimeAgo
className="text-xs text-muted-foreground"
time={event.start_time * 1000}
dense
/>
</div>
</div>
);
}