feat(results): add video results skeleton and refresh detection summary UI

This commit is contained in:
2026-06-24 00:36:27 +05:30
parent c1c81687d8
commit 67237982c8
4 changed files with 165 additions and 33 deletions

View File

@@ -53,7 +53,7 @@ export default function AnnotatedVideoPlayer({
) : (
<>
<Loader2 className="h-7 w-7 animate-spin text-primary" />
<p className="text-xs font-medium uppercase tracking-widest">
<p className="text-xs">
{isLoading ? 'Loading annotated video...' : 'Preparing video...'}
</p>
</>

View File

@@ -1,7 +1,8 @@
'use client';
import { MapPin } from 'lucide-react';
import { CompletedVideoResult, DetectionResultLog } from '@/types';
import { Activity, AlertTriangle, MapPin, SignpostBig } from 'lucide-react';
import type { CompletedVideoResult, DetectionResultLog } from '@/types';
interface CurrentDetectionBarProps {
activeLog?: DetectionResultLog;
@@ -17,17 +18,23 @@ export default function CurrentDetectionBar({
{
label: 'Potholes',
value: currentCounts.unique_potholes || 0,
icon: AlertTriangle,
className: 'text-orange-500',
iconClassName: 'bg-orange-500/10 text-orange-500',
},
{
label: 'Signboards',
value: currentCounts.unique_signboards || 0,
icon: SignpostBig,
className: 'text-blue-500',
iconClassName: 'bg-blue-500/10 text-blue-500',
},
{
label: 'Total',
value: currentCounts.total_detections || 0,
icon: Activity,
className: 'text-green-500',
iconClassName: 'bg-green-500/10 text-green-500',
},
];
const latitude = activeLog?.latitude;
@@ -38,33 +45,56 @@ export default function CurrentDetectionBar({
: undefined;
return (
<div className="rounded-lg border bg-card px-4 py-3">
{coordinates && (
<div className="mb-3 flex justify-end">
<div className="flex max-w-full items-center gap-2 rounded-md border bg-muted/30 px-3 py-1.5">
<MapPin className="size-3.5 shrink-0 text-muted-foreground" />
<span className="truncate font-mono text-xs font-semibold text-foreground">
<section className="overflow-hidden rounded-lg border bg-card/80">
<div className="flex flex-col gap-3 border-b px-4 py-3 sm:flex-row sm:items-center sm:justify-between">
<div>
<p className="text-sm font-semibold text-foreground">
Current Detection Summary
</p>
<p className="text-xs text-muted-foreground">
Counts update as the playback timeline moves.
</p>
</div>
{coordinates ? (
<div className="flex max-w-full items-center gap-2 rounded-md bg-muted/40 px-3 py-1.5 text-xs text-muted-foreground">
<MapPin className="size-3.5 shrink-0" />
<span className="shrink-0 font-medium">Location</span>
<span className="truncate font-mono font-semibold text-foreground">
{coordinates}
</span>
</div>
</div>
)}
<div className="grid grid-cols-1 gap-3 sm:grid-cols-3">
{countItems.map((item) => (
<div
key={item.label}
className="flex items-center justify-between gap-3 rounded-lg border bg-muted/20 px-4 py-2"
>
<p className="text-xs font-bold uppercase tracking-wide text-muted-foreground">
{item.label}
</p>
<p className={`text-2xl font-bold leading-none ${item.className}`}>
{item.value}
</p>
</div>
))}
) : null}
</div>
</div>
<div className="grid grid-cols-1 gap-2 p-3 sm:grid-cols-3">
{countItems.map((item) => {
const Icon = item.icon;
return (
<div
key={item.label}
className="flex items-center justify-between gap-3 rounded-md bg-muted/25 px-3 py-2.5 ring-1 ring-border/60"
>
<div className="flex min-w-0 items-center gap-3">
<span
className={`flex size-8 shrink-0 items-center justify-center rounded-md ${item.iconClassName}`}
>
<Icon className="size-4" />
</span>
<p className="truncate text-xs font-semibold uppercase tracking-wide text-muted-foreground">
{item.label}
</p>
</div>
<p
className={`text-2xl font-bold leading-none ${item.className}`}
>
{item.value}
</p>
</div>
);
})}
</div>
</section>
);
}