'use client';
import { useEffect, useRef } from 'react';
import { Activity, Film, ImageIcon, MapPin } from 'lucide-react';
import { ScrollArea } from '@/components/ui/scroll-area';
import { Skeleton } from '@/components/ui/skeleton';
import { useProtectedMediaObjectUrl } from '@/hooks/useProtectedMedia';
import { cn } from '@/lib/utils';
import type { DetectionResultLog } from '@/types';
interface DetectionLogsProps {
logs: DetectionResultLog[];
activeLogId?: string;
onSelect: (log: DetectionResultLog) => void;
}
const formatVideoTime = (seconds: number) => {
const safeSeconds = Number.isFinite(seconds) ? seconds : 0;
const minutes = Math.floor(safeSeconds / 60);
const secs = Math.floor(safeSeconds % 60);
return `${minutes}:${secs.toString().padStart(2, '0')}`;
};
function DetectionLogThumbnail({
url,
label,
}: {
url?: string | null;
label: string;
}) {
const { objectUrl, isLoading, isError } = useProtectedMediaObjectUrl(url);
if (!url) {
return (
);
}
if (isLoading) {
return ;
}
if (isError || !objectUrl) {
return (
N/A
);
}
return (
);
}
const DetectionLogs = ({ logs, activeLogId, onSelect }: DetectionLogsProps) => {
const activeLogRef = useRef(null);
useEffect(() => {
activeLogRef.current?.scrollIntoView({
block: 'nearest',
behavior: 'smooth',
});
}, [activeLogId]);
return (
{logs.length === 0 ? (
) : (
logs.map((log) => {
const timestampSeconds = log.frame.timestamp_seconds;
const { latitude, longitude } = log.location;
const isActive = activeLogId === log.id;
const label = log.detection.display_name;
return (
);
})
)}
);
};
export default DetectionLogs;