Final frontend added edit, delete
This commit is contained in:
@@ -73,6 +73,7 @@ export default function DashboardMapContent({ detections }: DashboardMapContentP
|
||||
zoom={13}
|
||||
className="h-full w-full"
|
||||
scrollWheelZoom={true}
|
||||
zoomAnimation={false}
|
||||
>
|
||||
<TileLayer
|
||||
attribution='© <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors'
|
||||
|
||||
@@ -13,7 +13,7 @@ const DashboardMapContent = dynamic(
|
||||
ssr: false,
|
||||
loading: () => (
|
||||
<div className="h-full w-full flex items-center justify-center">
|
||||
<Loader2 className="h-8 w-8 animate-spin text-primary" />
|
||||
<Loader2 className="h-8 w-8 text-primary" />
|
||||
</div>
|
||||
)
|
||||
}
|
||||
@@ -61,6 +61,7 @@ export function DashboardMap({
|
||||
: (pkg as any).locations || {}
|
||||
|
||||
for (const [locName, loc] of Object.entries(locationsToProcess)) {
|
||||
if (!loc) continue
|
||||
const locationDetections = (loc as any).detections || []
|
||||
filteredDetections.push(...locationDetections)
|
||||
}
|
||||
@@ -90,7 +91,7 @@ export function DashboardMap({
|
||||
<CardHeader className="pb-2">
|
||||
<div className="flex items-center justify-between">
|
||||
<div className="flex items-center gap-3">
|
||||
<div className="w-10 h-10 rounded-lg bg-white flex items-center justify-center shadow-lg border-2 border-[#1e40af] transition-transform duration-300 hover:scale-110">
|
||||
<div className="w-10 h-10 rounded-lg bg-white flex items-center justify-center shadow-lg border-2 border-[#1e40af]">
|
||||
<MapPin className="h-5 w-5 text-[#2563eb]" />
|
||||
</div>
|
||||
<div>
|
||||
@@ -120,7 +121,7 @@ export function DashboardMap({
|
||||
<div className="h-[400px] w-full relative">
|
||||
{isLoading ? (
|
||||
<div className="h-full w-full flex items-center justify-center bg-gray-50 dark:bg-gray-900/50">
|
||||
<Loader2 className="h-8 w-8 animate-spin text-indigo-500" />
|
||||
<Loader2 className="h-8 w-8 text-indigo-500" />
|
||||
</div>
|
||||
) : error ? (
|
||||
<div className="h-full w-full flex items-center justify-center bg-gray-50 dark:bg-gray-900/50">
|
||||
|
||||
@@ -21,7 +21,7 @@ export function DetectionChart({ potholes, signboards, isLoading }: DetectionCha
|
||||
<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 animate-pulse" />
|
||||
<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">
|
||||
@@ -52,7 +52,7 @@ export function DetectionChart({ potholes, signboards, isLoading }: DetectionCha
|
||||
strokeWidth="16"
|
||||
strokeDasharray={`${potholePercent * 2.51} 251`}
|
||||
strokeLinecap="round"
|
||||
className="transition-all duration-700"
|
||||
className=""
|
||||
/>
|
||||
{/* Signboards arc */}
|
||||
<circle
|
||||
@@ -62,10 +62,9 @@ export function DetectionChart({ potholes, signboards, isLoading }: DetectionCha
|
||||
fill="none"
|
||||
stroke="url(#signboardGradient)"
|
||||
strokeWidth="16"
|
||||
strokeDasharray={`${signboardPercent * 2.51} 251`}
|
||||
strokeDashoffset={`-${potholePercent * 2.51}`}
|
||||
strokeLinecap="round"
|
||||
className="transition-all duration-700"
|
||||
className=""
|
||||
/>
|
||||
<defs>
|
||||
<linearGradient id="potholeGradient" x1="0%" y1="0%" x2="100%" y2="0%">
|
||||
|
||||
@@ -18,7 +18,7 @@ export function DetectionDonutChart({ potholes, signboards, isLoading }: Detecti
|
||||
if (isLoading) {
|
||||
return (
|
||||
<div className="h-[250px] flex items-center justify-center">
|
||||
<Loader2 className="h-8 w-8 animate-spin text-primary/50" />
|
||||
<Loader2 className="h-8 w-8 text-primary/50" />
|
||||
</div>
|
||||
)
|
||||
}
|
||||
@@ -52,13 +52,14 @@ export function DetectionDonutChart({ potholes, signboards, isLoading }: Detecti
|
||||
paddingAngle={5}
|
||||
dataKey="value"
|
||||
strokeWidth={0}
|
||||
isAnimationActive={false}
|
||||
>
|
||||
{data.map((entry, index) => (
|
||||
<Cell
|
||||
key={`cell-${index}`}
|
||||
fill={entry.color}
|
||||
fillOpacity={0.8}
|
||||
className="transition-all duration-300 hover:fill-opacity-100"
|
||||
fillOpacity={1}
|
||||
className="hover:fill-opacity-80"
|
||||
/>
|
||||
))}
|
||||
</Pie>
|
||||
|
||||
@@ -58,7 +58,7 @@ export function GradientStatsCard({
|
||||
</h3>
|
||||
<div className="flex flex-col">
|
||||
{isLoading ? (
|
||||
<div className="h-14 w-24 bg-gray-100 dark:bg-gray-800 rounded-xl animate-pulse mt-2" />
|
||||
<div className="h-14 w-24 bg-gray-100 dark:bg-gray-800 rounded-xl mt-2" />
|
||||
) : (
|
||||
<>
|
||||
<p className="text-3xl md:text-4xl font-black tracking-tighter leading-tight text-[#1e3a8a]">
|
||||
|
||||
@@ -24,7 +24,7 @@ export function LocationBarChart({ data, isLoading }: LocationBarChartProps) {
|
||||
if (isLoading) {
|
||||
return (
|
||||
<div className="h-[300px] flex items-center justify-center">
|
||||
<Loader2 className="h-8 w-8 animate-spin text-primary/50" />
|
||||
<Loader2 className="h-8 w-8 text-primary/50" />
|
||||
</div>
|
||||
)
|
||||
}
|
||||
@@ -123,12 +123,14 @@ export function LocationBarChart({ data, isLoading }: LocationBarChartProps) {
|
||||
name="Potholes"
|
||||
fill="url(#barGradientPothole)"
|
||||
radius={[4, 4, 0, 0]}
|
||||
isAnimationActive={false}
|
||||
/>
|
||||
<Bar
|
||||
dataKey="signboards"
|
||||
name="Signboards"
|
||||
fill="url(#barGradientSignboard)"
|
||||
radius={[4, 4, 0, 0]}
|
||||
isAnimationActive={false}
|
||||
/>
|
||||
</BarChart>
|
||||
</ResponsiveContainer>
|
||||
|
||||
@@ -58,7 +58,7 @@ export function RecentAnalysesTable({ videos, isLoading, onViewResults }: Recent
|
||||
{isLoading ? (
|
||||
<div className="p-6 space-y-3">
|
||||
{[1, 2, 3, 4].map((i) => (
|
||||
<div key={i} className="h-14 bg-primary/5 rounded-lg animate-pulse" />
|
||||
<div key={i} className="h-14 bg-primary/5 rounded-lg" />
|
||||
))}
|
||||
</div>
|
||||
) : videos.length === 0 ? (
|
||||
@@ -72,7 +72,7 @@ export function RecentAnalysesTable({ videos, isLoading, onViewResults }: Recent
|
||||
{videos.slice(0, 8).map((video) => (
|
||||
<div
|
||||
key={video.id}
|
||||
className="flex items-center justify-between p-4 hover:bg-primary/5 transition-colors"
|
||||
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">
|
||||
|
||||
@@ -13,7 +13,7 @@ interface StatsCardProps {
|
||||
|
||||
export function StatsCard({ title, value, icon: Icon, gradient, isLoading }: StatsCardProps) {
|
||||
return (
|
||||
<Card className="glass-card card-glow border-0 overflow-hidden group hover:scale-[1.02] transition-transform duration-300">
|
||||
<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">
|
||||
@@ -21,14 +21,14 @@ export function StatsCard({ title, value, icon: Icon, gradient, isLoading }: Sta
|
||||
{title}
|
||||
</p>
|
||||
{isLoading ? (
|
||||
<div className="h-8 w-16 bg-primary/10 rounded animate-pulse" />
|
||||
<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} group-hover:scale-110 transition-transform duration-300`}>
|
||||
<div className={`p-3 rounded-xl ${gradient}`}>
|
||||
<Icon className="h-6 w-6 text-white" />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user