refactor: redesign table module

This commit is contained in:
2026-03-18 01:03:58 +05:30
parent caf527f584
commit 344f37719e
24 changed files with 991 additions and 815 deletions

View File

@@ -1,7 +1,7 @@
"use client";
import { useState, useEffect } from "react";
import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card";
import { Card, CardContent, CardHeader, CardTitle, CardDescription, CardFooter } from "@/components/ui/card";
import {
AlertCircle,
Activity,
@@ -11,6 +11,7 @@ import {
Zap,
PencilLine,
CheckCircle2,
Settings2,
} from "lucide-react";
import { StatsCard } from "@/components/dashboard/stats-card";
import { CompactProjectSelector } from "@/components/dashboard/compact-project-selector";
@@ -26,9 +27,9 @@ import {
PopoverTrigger,
} from "@/components/ui/popover";
import { Button } from "@/components/ui/button";
import { Filter } from "lucide-react";
import { DashboardSkeleton } from "@/components/dashboard/dashboard-skeleton"
import { PoweredBy } from "@/components/powered-by";
import { toast } from "sonner";
const API_URL = process.env.NEXT_PUBLIC_API_URL;
@@ -207,14 +208,12 @@ export default function DashboardPage() {
totalRoadDamage: 0,
locationData: [],
});
const [error, setError] = useState<string | null>(null);
// Load projects on mount
useEffect(() => {
const loadProjects = async () => {
try {
setIsLoading(true);
setError(null);
const projectsData = await fetchProjects();
setProjects(projectsData);
@@ -223,9 +222,9 @@ export default function DashboardPage() {
}
} catch (err) {
console.error("Failed to load projects:", err);
setError(
"Failed to load projects. Please check if the backend is running.",
);
toast.error("Failed to load projects", {
description: "Please check if the backend is running."
});
} finally {
setTimeout(() => {
setIsLoading(false);
@@ -274,7 +273,6 @@ export default function DashboardPage() {
const loadProjectSummary = async () => {
try {
setIsLoading(true);
setError(null);
const response = await fetch(
`${API_URL}/summary/projects/${selectedProjectId}`,
@@ -294,7 +292,7 @@ export default function DashboardPage() {
setProjectSummary(summary);
} catch (err) {
console.error("Failed to load project summary:", err);
setError("Failed to load project summary.");
toast.error("Failed to load project summary");
setProjectSummary(null);
} finally {
setTimeout(() => {
@@ -422,10 +420,10 @@ export default function DashboardPage() {
}, [projectSummary, selectedPackageId, selectedLocationId]);
return (
<div className="min-h-screen text-gray-900 dark:text-gray-100">
<>
{/* Main Content */}
<main className="min-h-screen">
<div className="p-4 px-8 max-w-340 mx-auto">
<main>
<div>
{/* Header */}
<div className="mb-8 flex items-center justify-between">
<PageHeader
@@ -437,14 +435,14 @@ export default function DashboardPage() {
<Popover>
<PopoverTrigger asChild>
<Button variant="outline" className="gap-2 font-semibold">
<Filter className="h-4 w-4" />
<Settings2 className="h-4 w-4" />
<span>Filters</span>
</Button>
</PopoverTrigger>
<PopoverContent className="w-[320px] p-0 overflow-hidden" align="end">
<div className="p-4 border-b bg-muted/30">
<h3 className="font-bold text-sm flex items-center gap-2 text-foreground">
<Filter className="h-4 w-4 text-primary" />
<Settings2 className="h-4 w-4 text-primary" />
Filter Analysis
</h3>
<p className="text-xs mt-1 text-muted-foreground">Refine your view by project, package, or location</p>
@@ -467,14 +465,6 @@ export default function DashboardPage() {
</Popover>
</div>
{/* Error Display */}
{error && (
<div className="mb-4 flex items-center gap-2 p-3 rounded-xl bg-red-50 dark:bg-red-950/30 border border-red-200 dark:border-red-800 text-red-600 dark:text-red-400 text-sm">
<AlertCircle className="h-4 w-4 shrink-0" />
<p>{error}</p>
</div>
)}
{isLoading && !projectSummary ? (
<DashboardSkeleton />
) : (
@@ -522,18 +512,12 @@ export default function DashboardPage() {
{/* Charts Row - Side by Side */}
<div className="grid grid-cols-1 lg:grid-cols-2 gap-4 mb-4">
{/* Left Chart - Detection Distribution */}
<Card>
<CardHeader className="pb-2">
<CardTitle className="text-base font-bold flex items-center gap-2">
<div className="p-2 rounded-md bg-secondary text-secondary-foreground">
<BarChart3 className="h-5 w-5" />
</div>
<span className="text-xl">
Detection Distribution
</span>
</CardTitle>
<Card className="flex flex-col">
<CardHeader className="items-center pb-0">
<CardTitle>Detection Distribution</CardTitle>
<CardDescription>Breakdown of all detected road conditions</CardDescription>
</CardHeader>
<CardContent className="pt-4">
<CardContent className="flex-1 pb-0">
<DetectionDonutChart
defectedSignboard={stats.totalDefectedSignboard}
pothole={stats.totalPothole}
@@ -542,19 +526,20 @@ export default function DashboardPage() {
goodSignboard={stats.totalGoodSignboard}
/>
</CardContent>
<CardFooter className="flex-col gap-2 text-sm">
<div className="leading-none text-muted-foreground">
Total detections: {stats.totalRoadDamage + stats.totalGoodSignboard}
</div>
</CardFooter>
</Card>
{/* Right Chart - Location Bar Chart */}
<Card>
<CardHeader className="pb-2">
<CardTitle className="text-base font-bold flex items-center gap-2">
<div className="p-2 rounded-md bg-secondary text-secondary-foreground">
<MapPinIcon className="h-5 w-5" />
</div>
<span className="text-xl">Detections by Location</span>
</CardTitle>
{/* Right Chart - Detections by Location */}
<Card className="flex flex-col">
<CardHeader className="items-center pb-0">
<CardTitle>Detections by Location</CardTitle>
<CardDescription>Frequency of road issues across different map segments</CardDescription>
</CardHeader>
<CardContent className="pt-4">
<CardContent className="flex-1 pb-0">
<LocationBarChart
data={stats.locationData.map((loc) => ({
name: loc.name,
@@ -562,11 +547,15 @@ export default function DashboardPage() {
pothole: loc.pothole,
road_crack: loc.road_crack,
damaged_road_marking: loc.damaged_road_marking,
good_sign_board: loc.good_sign_board,
total: loc.total,
}))}
/>
</CardContent>
<CardFooter className="flex-col gap-2 text-sm">
<div className="leading-none text-muted-foreground">
Analysis based on latest processed sequence
</div>
</CardFooter>
</Card>
</div>
@@ -585,6 +574,6 @@ export default function DashboardPage() {
<PoweredBy />
</div>
</main>
</div>
</>
);
}