refactor: remove unused files and fix naming convention
This commit is contained in:
@@ -1,116 +0,0 @@
|
||||
"use client"
|
||||
|
||||
import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card"
|
||||
|
||||
interface DetectionChartProps {
|
||||
potholes: number
|
||||
signboards: number
|
||||
isLoading?: boolean
|
||||
}
|
||||
|
||||
export function DetectionChart({ potholes, signboards, isLoading }: DetectionChartProps) {
|
||||
const total = potholes + signboards
|
||||
const potholePercent = total > 0 ? (potholes / total) * 100 : 50
|
||||
const signboardPercent = total > 0 ? (signboards / total) * 100 : 50
|
||||
|
||||
return (
|
||||
<Card className="overflow-hidden">
|
||||
<CardHeader className="pb-2">
|
||||
<CardTitle className="text-lg font-bold text-blue-600">Detection Distribution</CardTitle>
|
||||
</CardHeader>
|
||||
<CardContent className="pt-0">
|
||||
{isLoading ? (
|
||||
<div className="flex items-center justify-center h-48">
|
||||
<div className="w-32 h-32 rounded-full bg-primary/10" />
|
||||
</div>
|
||||
) : total === 0 ? (
|
||||
<div className="flex items-center justify-center h-48 text-muted-foreground">
|
||||
No detections yet
|
||||
</div>
|
||||
) : (
|
||||
<div className="flex items-center gap-6">
|
||||
{/* Donut Chart */}
|
||||
<div className="relative w-36 h-36 flex-shrink-0">
|
||||
<svg viewBox="0 0 100 100" className="w-full h-full transform -rotate-90">
|
||||
{/* Background circle */}
|
||||
<circle
|
||||
cx="50"
|
||||
cy="50"
|
||||
r="40"
|
||||
fill="none"
|
||||
stroke="hsl(var(--muted))"
|
||||
strokeWidth="16"
|
||||
opacity="0.2"
|
||||
/>
|
||||
{/* Potholes arc */}
|
||||
<circle
|
||||
cx="50"
|
||||
cy="50"
|
||||
r="40"
|
||||
fill="none"
|
||||
stroke="url(#potholeGradient)"
|
||||
strokeWidth="16"
|
||||
strokeDasharray={`${potholePercent * 2.51} 251`}
|
||||
strokeLinecap="round"
|
||||
className=""
|
||||
/>
|
||||
{/* Signboards arc */}
|
||||
<circle
|
||||
cx="50"
|
||||
cy="50"
|
||||
r="40"
|
||||
fill="none"
|
||||
stroke="url(#signboardGradient)"
|
||||
strokeWidth="16"
|
||||
strokeDashoffset={`-${potholePercent * 2.51}`}
|
||||
strokeLinecap="round"
|
||||
className=""
|
||||
/>
|
||||
<defs>
|
||||
<linearGradient id="potholeGradient" x1="0%" y1="0%" x2="100%" y2="0%">
|
||||
<stop offset="0%" stopColor="#f97316" />
|
||||
<stop offset="100%" stopColor="#ea580c" />
|
||||
</linearGradient>
|
||||
<linearGradient id="signboardGradient" x1="0%" y1="0%" x2="100%" y2="0%">
|
||||
<stop offset="0%" stopColor="#3b82f6" />
|
||||
<stop offset="100%" stopColor="#2563eb" />
|
||||
</linearGradient>
|
||||
</defs>
|
||||
</svg>
|
||||
<div className="absolute inset-0 flex items-center justify-center">
|
||||
<div className="text-center">
|
||||
<p className="text-2xl font-bold text-foreground">{total}</p>
|
||||
<p className="text-[10px] text-muted-foreground uppercase">Total</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Legend */}
|
||||
<div className="flex flex-col gap-3 flex-1">
|
||||
<div className="flex items-center justify-between p-3 rounded-lg bg-orange-500/10 border border-orange-500/20">
|
||||
<div className="flex items-center gap-2">
|
||||
<div className="w-3 h-3 rounded-full bg-gradient-to-r from-orange-500 to-orange-600" />
|
||||
<span className="text-sm font-medium">Potholes</span>
|
||||
</div>
|
||||
<div className="text-right">
|
||||
<p className="font-bold text-foreground">{potholes}</p>
|
||||
<p className="text-xs text-muted-foreground">{potholePercent.toFixed(0)}%</p>
|
||||
</div>
|
||||
</div>
|
||||
<div className="flex items-center justify-between p-3 rounded-lg bg-blue-500/10 border border-blue-500/20">
|
||||
<div className="flex items-center gap-2">
|
||||
<div className="w-3 h-3 rounded-full bg-gradient-to-r from-blue-500 to-blue-600" />
|
||||
<span className="text-sm font-medium">Signboards</span>
|
||||
</div>
|
||||
<div className="text-right">
|
||||
<p className="font-bold text-foreground">{signboards}</p>
|
||||
<p className="text-xs text-muted-foreground">{signboardPercent.toFixed(0)}%</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
</CardContent>
|
||||
</Card>
|
||||
)
|
||||
}
|
||||
@@ -1,130 +0,0 @@
|
||||
"use client"
|
||||
|
||||
import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card"
|
||||
import { Button } from "@/components/ui/button"
|
||||
import { Badge } from "@/components/ui/badge"
|
||||
import { Eye, AlertCircle } from "lucide-react"
|
||||
import { type Video } from "@/lib/api"
|
||||
import { Skeleton } from "@/components/ui/skeleton"
|
||||
|
||||
interface RecentAnalysesTableProps {
|
||||
videos: Video[]
|
||||
isLoading?: boolean
|
||||
onViewResults?: (videoId: string, detectionType: string) => void
|
||||
}
|
||||
|
||||
export function RecentAnalysesTable({ videos, isLoading, onViewResults }: RecentAnalysesTableProps) {
|
||||
const formatDate = (dateString: string) => {
|
||||
const date = new Date(dateString)
|
||||
return date.toLocaleDateString("en-IN", {
|
||||
day: "2-digit",
|
||||
month: "short",
|
||||
year: "numeric",
|
||||
hour: "2-digit",
|
||||
minute: "2-digit"
|
||||
})
|
||||
}
|
||||
|
||||
const getStatusBadge = (status: string) => {
|
||||
switch (status) {
|
||||
case "completed":
|
||||
return <Badge className="bg-emerald-500/20 text-emerald-600 border-emerald-500/30 hover:bg-emerald-500/30">Completed</Badge>
|
||||
case "processing":
|
||||
return <Badge className="bg-blue-500/20 text-blue-600 border-blue-500/30 hover:bg-blue-500/30">Processing</Badge>
|
||||
case "pending":
|
||||
return <Badge className="bg-yellow-500/20 text-yellow-600 border-yellow-500/30 hover:bg-yellow-500/30">Pending</Badge>
|
||||
case "failed":
|
||||
return <Badge className="bg-red-500/20 text-red-600 border-red-500/30 hover:bg-red-500/30">Failed</Badge>
|
||||
default:
|
||||
return <Badge variant="secondary">{status}</Badge>
|
||||
}
|
||||
}
|
||||
|
||||
const getDetectionTypeBadge = (type: string) => {
|
||||
if (type === "pothole-detection") {
|
||||
return <Badge className="bg-orange-500/20 text-orange-600 border-orange-500/30">Pothole</Badge>
|
||||
}
|
||||
if (type === "pot-sign-detection") {
|
||||
return <Badge className="bg-purple-500/20 text-purple-600 border-purple-500/30">Pothole & Sign</Badge>
|
||||
}
|
||||
return <Badge className="bg-blue-500/20 text-blue-600 border-blue-500/30">Signboard</Badge>
|
||||
}
|
||||
|
||||
return (
|
||||
<Card className="overflow-hidden">
|
||||
<CardHeader className="pb-3 border-b border-border/50">
|
||||
<CardTitle className="text-lg font-bold text-blue-600">Recent Analyses</CardTitle>
|
||||
</CardHeader>
|
||||
<CardContent className="p-0">
|
||||
{isLoading ? (
|
||||
<div className="p-6 space-y-4">
|
||||
{[1, 2, 3, 4, 5].map((i) => (
|
||||
<div key={i} className="flex items-center justify-between gap-4">
|
||||
<div className="flex-1 space-y-2">
|
||||
<Skeleton className="h-4 w-[60%]" />
|
||||
<Skeleton className="h-3 w-[40%]" />
|
||||
</div>
|
||||
<div className="flex gap-2">
|
||||
<Skeleton className="h-6 w-16 rounded-full" />
|
||||
<Skeleton className="h-6 w-16 rounded-full" />
|
||||
</div>
|
||||
<Skeleton className="h-8 w-16" />
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
) : videos.length === 0 ? (
|
||||
<div className="flex flex-col items-center justify-center py-12 text-muted-foreground">
|
||||
<AlertCircle className="h-10 w-10 mb-3 opacity-50" />
|
||||
<p className="text-sm">No analyses found</p>
|
||||
<p className="text-xs mt-1">Start a new analysis to see results here</p>
|
||||
</div>
|
||||
) : (
|
||||
<div className="divide-y divide-border/50">
|
||||
{videos.slice(0, 8).map((video) => (
|
||||
<div
|
||||
key={video.id}
|
||||
className="flex items-center justify-between p-4 hover:bg-primary/5"
|
||||
>
|
||||
<div className="flex items-center gap-4 flex-1 min-w-0">
|
||||
<div className="flex-1 min-w-0">
|
||||
<p className="text-sm font-medium truncate">
|
||||
{video.filename || `Video ${video.id.slice(0, 8)}...`}
|
||||
</p>
|
||||
<p className="text-xs text-muted-foreground">
|
||||
{formatDate(video.created_at)}
|
||||
</p>
|
||||
</div>
|
||||
<div className="flex items-center gap-2 shrink-0">
|
||||
{getDetectionTypeBadge(video.detection_type)}
|
||||
{getStatusBadge(video.status)}
|
||||
</div>
|
||||
<div className="text-right shrink-0 w-20">
|
||||
<p className="text-sm font-bold text-foreground">
|
||||
{video.detection_type === "pothole-detection"
|
||||
? video.unique_pothole ?? 0
|
||||
: video.detection_type === "pot-sign-detection"
|
||||
? (video.unique_pothole ?? 0) + (video.unique_defected_sign_board ?? 0) + (video.unique_good_sign_board ?? 0)
|
||||
: (video.unique_defected_sign_board ?? 0) + (video.unique_good_sign_board ?? 0)}
|
||||
</p>
|
||||
<p className="text-[10px] text-muted-foreground uppercase">Detections</p>
|
||||
</div>
|
||||
</div>
|
||||
{video.status === "completed" && onViewResults && (
|
||||
<Button
|
||||
variant="ghost"
|
||||
size="sm"
|
||||
onClick={() => onViewResults(video.id, video.detection_type)}
|
||||
className="ml-4 shrink-0"
|
||||
>
|
||||
<Eye className="h-4 w-4 mr-1" />
|
||||
View
|
||||
</Button>
|
||||
)}
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
)}
|
||||
</CardContent>
|
||||
</Card>
|
||||
)
|
||||
}
|
||||
@@ -1,38 +0,0 @@
|
||||
"use client"
|
||||
|
||||
import { Card, CardContent } from "@/components/ui/card"
|
||||
import { LucideIcon } from "lucide-react"
|
||||
|
||||
interface StatsCardProps {
|
||||
title: string
|
||||
value: string | number
|
||||
icon: LucideIcon
|
||||
gradient: string
|
||||
isLoading?: boolean
|
||||
}
|
||||
|
||||
export function StatsCard({ title, value, icon: Icon, gradient, isLoading }: StatsCardProps) {
|
||||
return (
|
||||
<Card className="glass-card card-glow border-0 overflow-hidden group">
|
||||
<CardContent className="p-5">
|
||||
<div className="flex items-center justify-between">
|
||||
<div className="space-y-1">
|
||||
<p className="text-xs font-medium text-muted-foreground uppercase tracking-wide">
|
||||
{title}
|
||||
</p>
|
||||
{isLoading ? (
|
||||
<div className="h-8 w-16 bg-primary/10 rounded" />
|
||||
) : (
|
||||
<p className="text-3xl font-bold text-foreground">
|
||||
{value}
|
||||
</p>
|
||||
)}
|
||||
</div>
|
||||
<div className={`p-3 rounded-xl ${gradient}`}>
|
||||
<Icon className="h-6 w-6 text-white" />
|
||||
</div>
|
||||
</div>
|
||||
</CardContent>
|
||||
</Card>
|
||||
)
|
||||
}
|
||||
Reference in New Issue
Block a user