Files
road-monitoring-ui/src/components/video/annotatedDetectionImage.tsx

81 lines
2.4 KiB
TypeScript

'use client';
import { AlertTriangle, ImageIcon, Loader2 } from 'lucide-react';
import Image from 'next/image';
import { useProtectedMediaObjectUrl } from '@/hooks/useProtectedMedia';
import type { BoundingBoxOverlayItem, DetectionResultItem } from '@/types';
import BoundingBoxOverlay from '@/components/annotation/boundingBoxOverlay';
interface AnnotatedDetectionImageProps {
detection?: DetectionResultItem;
videoWidth: number;
videoHeight: number;
}
export default function AnnotatedDetectionImage({
detection,
videoWidth,
videoHeight,
}: AnnotatedDetectionImageProps) {
const { objectUrl, isLoading, isError } = useProtectedMediaObjectUrl(
detection?.detection.context_image_url,
);
const overlayDetections: BoundingBoxOverlayItem[] = detection
? [
{
id: detection.id,
class_name: detection.detection.class_name,
display_name: detection.detection.display_name,
confidence: detection.detection.confidence,
bounding_box: detection.detection.bounding_box,
},
]
: [];
const aspectRatio =
videoWidth > 0 && videoHeight > 0
? `${videoWidth} / ${videoHeight}`
: '16 / 9';
return (
<div
className="relative flex w-full items-center justify-center overflow-hidden rounded-lg border bg-black"
style={{ aspectRatio }}
>
{!detection ? (
<div className="flex flex-col items-center gap-2 text-muted-foreground">
<ImageIcon className="size-7" />
<p>Select a detection to view its image.</p>
</div>
) : isLoading ? (
<div className="flex flex-col items-center gap-2 text-muted-foreground">
<Loader2 className="size-7 animate-spin text-primary" />
<p>Loading detection image...</p>
</div>
) : isError || !objectUrl ? (
<div className="flex flex-col items-center gap-2 text-destructive">
<AlertTriangle className="size-7" />
<p>Failed to load the detection image.</p>
</div>
) : (
<>
<Image
src={objectUrl}
alt={`${detection.detection.display_name} detection`}
fill
unoptimized
className="object-contain"
/>
<BoundingBoxOverlay
detections={overlayDetections}
videoWidth={videoWidth}
videoHeight={videoHeight}
/>
</>
)}
</div>
);
}