From 02c5425fcecdc67e5bb044da0ce52ea0fa8de88d Mon Sep 17 00:00:00 2001 From: "santasri.pachhal" Date: Thu, 19 Mar 2026 18:07:37 +0530 Subject: [PATCH] feat: modify map --- next-env.d.ts | 2 +- src/app/(modules)/dashboard/page.tsx | 121 ++++++++++++---- src/app/(modules)/upload/page.tsx | 1 + src/app/globals.css | 26 ++-- .../dashboard/chainage-bar-chart.tsx | 31 +++- .../dashboard/dashboard-map-content.tsx | 66 +++++---- src/components/dashboard/dashboard-map.tsx | 137 ++++++++++++------ .../dashboard/detection-donut-chart.tsx | 61 +++++--- src/components/map-modal.tsx | 38 +++-- src/constants/detectionModeConfig.ts | 16 +- 10 files changed, 341 insertions(+), 158 deletions(-) diff --git a/next-env.d.ts b/next-env.d.ts index 9edff1c..c4b7818 100644 --- a/next-env.d.ts +++ b/next-env.d.ts @@ -1,6 +1,6 @@ /// /// -import "./.next/types/routes.d.ts"; +import "./.next/dev/types/routes.d.ts"; // NOTE: This file should not be edited // see https://nextjs.org/docs/app/api-reference/config/typescript for more information. diff --git a/src/app/(modules)/dashboard/page.tsx b/src/app/(modules)/dashboard/page.tsx index 9b5362a..c32e4ff 100644 --- a/src/app/(modules)/dashboard/page.tsx +++ b/src/app/(modules)/dashboard/page.tsx @@ -20,6 +20,7 @@ import { PencilLine, CheckCircle2, Settings2, + Droplets, } from 'lucide-react'; import { StatsCard } from '@/components/dashboard/stats-card'; import { FilterSelector } from '@/components/dashboard/filter-selector'; @@ -74,6 +75,8 @@ interface DetectionStats { totalRoadCrack: number; totalDamagedRoadMarking: number; totalGoodSignboard: number; + totalDrainIssue: number; + totalDefectiveCulvert: number; totalRoadDamage: number; chainageData: Array<{ name: string; @@ -81,7 +84,9 @@ interface DetectionStats { pothole: number; road_crack: number; damaged_road_marking: number; - good_sign_board: number; + // good_sign_board: number; + drain_issue: number; + defective_culvert: number; total: number; }>; } @@ -94,6 +99,8 @@ function calculateStats(summary: ProjectSummary | null): DetectionStats { totalRoadCrack: 0, totalDamagedRoadMarking: 0, totalGoodSignboard: 0, + totalDrainIssue: 0, + totalDefectiveCulvert: 0, totalRoadDamage: 0, chainageData: [], }; @@ -104,21 +111,23 @@ function calculateStats(summary: ProjectSummary | null): DetectionStats { let total_road_crack = 0; let total_damaged_road_marking = 0; let total_good_sign_board = 0; + let total_drain_issue = 0; + let total_defective_culvert = 0; let total_road_damage = 0; const chainageData: DetectionStats['chainageData'] = []; for (const pkg of Object.values(summary.packages || {})) { for (const [chnName, chn] of Object.entries(pkg.chainages || {})) { - // Changed 'locName, loc' to 'chnName, chn' and 'pkg.locations' to 'pkg.chainages' - let chnDefectedSignboard = 0; // Changed 'locDefectedSignboard' to 'chnDefectedSignboard' - let chnPothole = 0; // Changed 'locPothole' to 'chnPothole' - let chnRoadCrack = 0; // Changed 'locRoadCrack' to 'chnRoadCrack' - let chnDamagedRoadMarking = 0; // Changed 'locDamagedRoadMarking' to 'chnDamagedRoadMarking' - let chnGoodSignboard = 0; // Changed 'locGoodSignboard' to 'chnGoodSignboard' + let chnDefectedSignboard = 0; + let chnPothole = 0; + let chnRoadCrack = 0; + let chnDamagedRoadMarking = 0; + let chnGoodSignboard = 0; + let chnDrainIssue = 0; + let chnDefectiveCulvert = 0; for (const detection of chn.detections || []) { - // Changed 'loc.detections' to 'chn.detections' - const type = detection.type.toLowerCase(); + const type = (detection.type || '').toLowerCase(); if (type === 'defected_sign_board') { chnDefectedSignboard++; total_defected_sign_board++; @@ -133,42 +142,55 @@ function calculateStats(summary: ProjectSummary | null): DetectionStats { total_damaged_road_marking++; } else if (type === 'good_sign_board') { chnGoodSignboard++; - total_good_sign_board++; + // total_good_sign_board++; + } else if (type === 'drain_issue') { + chnDrainIssue++; + total_drain_issue++; + } else if (type === 'defective_culvert') { + chnDefectiveCulvert++; + total_defective_culvert++; } } - const chnTotalDamage = // Changed 'locTotalDamage' to 'chnTotalDamage' - chnDefectedSignboard + chnPothole + chnRoadCrack + chnDamagedRoadMarking; - if ( chnDefectedSignboard > 0 || chnPothole > 0 || chnRoadCrack > 0 || chnDamagedRoadMarking > 0 || - chnGoodSignboard > 0 + chnGoodSignboard > 0 || + chnDrainIssue > 0 || + chnDefectiveCulvert > 0 ) { const shortName = chnName.length > 20 ? chnName.substring(0, 20) + '...' : chnName; chainageData.push({ - // Changed 'locationData.push' to 'chainageData.push' name: shortName, defected_sign_board: chnDefectedSignboard, pothole: chnPothole, road_crack: chnRoadCrack, damaged_road_marking: chnDamagedRoadMarking, - good_sign_board: chnGoodSignboard, + // good_sign_board: chnGoodSignboard, + drain_issue: chnDrainIssue, + defective_culvert: chnDefectiveCulvert, total: chnDefectedSignboard + chnPothole + chnRoadCrack + chnDamagedRoadMarking + - chnGoodSignboard, + // chnGoodSignboard + + chnDrainIssue + + chnDefectiveCulvert, }); } } } total_road_damage = - total_defected_sign_board + total_pothole + total_road_crack + total_damaged_road_marking; + total_defected_sign_board + + total_pothole + + total_road_crack + + total_damaged_road_marking + + total_drain_issue + + total_defective_culvert; return { totalDefectedSignboard: total_defected_sign_board, @@ -176,6 +198,8 @@ function calculateStats(summary: ProjectSummary | null): DetectionStats { totalRoadCrack: total_road_crack, totalDamagedRoadMarking: total_damaged_road_marking, totalGoodSignboard: total_good_sign_board, + totalDrainIssue: total_drain_issue, + totalDefectiveCulvert: total_defective_culvert, totalRoadDamage: total_road_damage, chainageData, }; @@ -192,6 +216,8 @@ export default function DashboardPage() { totalRoadCrack: 0, totalDamagedRoadMarking: 0, totalGoodSignboard: 0, + totalDrainIssue: 0, + totalDefectiveCulvert: 0, totalRoadDamage: 0, chainageData: [], }); @@ -291,6 +317,8 @@ export default function DashboardPage() { totalRoadCrack: 0, totalDamagedRoadMarking: 0, totalGoodSignboard: 0, + totalDrainIssue: 0, + totalDefectiveCulvert: 0, totalRoadDamage: 0, chainageData: [], // Changed 'locationData' to 'chainageData' }); @@ -302,6 +330,8 @@ export default function DashboardPage() { let totalRoadCrack = 0; let totalDamagedRoadMarking = 0; let totalGoodSignboard = 0; + let totalDrainIssue = 0; + let totalDefectiveCulvert = 0; const chainageData: DetectionStats['chainageData'] = []; const packagesToProcess = @@ -323,9 +353,11 @@ export default function DashboardPage() { let chnRoadCrack = 0; let chnDamagedRoadMarking = 0; let chnGoodSignboard = 0; + let chnDrainIssue = 0; + let chnDefectiveCulvert = 0; for (const detection of chn.detections || []) { - const type = detection.type.toLowerCase(); + const type = (detection.type || '').toLowerCase(); if (type === 'defected_sign_board') { chnDefectedSignboard++; totalDefectedSignboard++; @@ -339,8 +371,14 @@ export default function DashboardPage() { chnDamagedRoadMarking++; totalDamagedRoadMarking++; } else if (type === 'good_sign_board') { - chnGoodSignboard++; - totalGoodSignboard++; + // chnGoodSignboard++; + // totalGoodSignboard++; + } else if (type === 'drain_issue') { + chnDrainIssue++; + totalDrainIssue++; + } else if (type === 'defective_culvert') { + chnDefectiveCulvert++; + totalDefectiveCulvert++; } } @@ -349,7 +387,9 @@ export default function DashboardPage() { chnPothole > 0 || chnRoadCrack > 0 || chnDamagedRoadMarking > 0 || - chnGoodSignboard > 0 + chnGoodSignboard > 0 || + chnDrainIssue > 0 || + chnDefectiveCulvert > 0 ) { const shortName = chnName.length > 20 ? chnName.substring(0, 20) + '...' : chnName; chainageData.push({ @@ -358,13 +398,17 @@ export default function DashboardPage() { pothole: chnPothole, road_crack: chnRoadCrack, damaged_road_marking: chnDamagedRoadMarking, - good_sign_board: chnGoodSignboard, + // good_sign_board: chnGoodSignboard, + drain_issue: chnDrainIssue, + defective_culvert: chnDefectiveCulvert, total: chnDefectedSignboard + chnPothole + chnRoadCrack + chnDamagedRoadMarking + - chnGoodSignboard, + // chnGoodSignboard + + chnDrainIssue + + chnDefectiveCulvert, }); } } @@ -376,8 +420,15 @@ export default function DashboardPage() { totalRoadCrack, totalDamagedRoadMarking, totalGoodSignboard, + totalDrainIssue, + totalDefectiveCulvert, totalRoadDamage: - totalDefectedSignboard + totalPothole + totalRoadCrack + totalDamagedRoadMarking, + totalDefectedSignboard + + totalPothole + + totalRoadCrack + + totalDamagedRoadMarking + + totalDrainIssue + + totalDefectiveCulvert, chainageData, }); }, [projectSummary, selectedPackageId, selectedChainageId]); @@ -479,13 +530,21 @@ export default function DashboardPage() { /> + + + {/* - + */} {/* Charts Row - Side by Side */} @@ -502,12 +561,18 @@ export default function DashboardPage() { pothole={stats.totalPothole} roadCrack={stats.totalRoadCrack} damagedRoadMarking={stats.totalDamagedRoadMarking} - goodSignboard={stats.totalGoodSignboard} + // goodSignboard={stats.totalGoodSignboard} + drainIssue={stats.totalDrainIssue} + defectiveCulvert={stats.totalDefectiveCulvert} />
- Total detections: {stats.totalRoadDamage + stats.totalGoodSignboard} + Total detections:{' '} + {stats.totalRoadDamage + + // stats.totalGoodSignboard + + stats.totalDrainIssue + + stats.totalDefectiveCulvert}
diff --git a/src/app/(modules)/upload/page.tsx b/src/app/(modules)/upload/page.tsx index 1c75b9d..35a446c 100644 --- a/src/app/(modules)/upload/page.tsx +++ b/src/app/(modules)/upload/page.tsx @@ -30,6 +30,7 @@ const DETECTION_METHODS = [ { value: 'yoloe', label: 'YOLOE Open-Vocabulary Detection' }, { value: 'yoloe_trained_vl', label: 'YOLOE With Vision Language Model' }, { value: 'culvert_detection', label: 'Culvert Detection' }, + { value: 'combined', label: 'Combined Detection Model' }, ] as const; export default function UploadPage() { diff --git a/src/app/globals.css b/src/app/globals.css index 9915595..fd90460 100644 --- a/src/app/globals.css +++ b/src/app/globals.css @@ -23,11 +23,13 @@ --border: oklch(0.92 0.004 286.32); --input: oklch(0.92 0.004 286.32); --ring: oklch(0.702 0.183 293.541); - --chart-1: oklch(0.811 0.111 293.571); - --chart-2: oklch(0.606 0.25 292.717); - --chart-3: oklch(0.541 0.281 293.009); - --chart-4: oklch(0.491 0.27 292.581); - --chart-5: oklch(0.432 0.232 292.759); + --chart-1: oklch(0.65 0.18 25); /* Soft Red/Rose - High Priority */ + --chart-2: oklch(0.78 0.12 75); /* Warm Amber - Distinct */ + --chart-3: oklch(0.68 0.12 245); /* Azure Blue - Cool Professional */ + --chart-4: oklch(0.75 0.1 165); /* Mint Teal - Balanced */ + --chart-5: oklch(0.85 0.08 195); /* Soft Cyan - Subdued */ + --chart-6: oklch(0.62 0.22 295); /* Deep Violet - Theme Primary */ + --chart-8: oklch(0.58 0.2 335); /* Cool Magenta - Distant Accent */ --sidebar: oklch(0.985 0 0 / 0.6); --sidebar-foreground: oklch(0.141 0.005 285.823); --sidebar-primary: oklch(0.541 0.281 293.009); @@ -57,11 +59,13 @@ --border: oklch(1 0 0 / 10%); --input: oklch(1 0 0 / 15%); --ring: oklch(0.38 0.189 293.745); - --chart-1: oklch(0.811 0.111 293.571); - --chart-2: oklch(0.606 0.25 292.717); - --chart-3: oklch(0.541 0.281 293.009); - --chart-4: oklch(0.491 0.27 292.581); - --chart-5: oklch(0.432 0.232 292.759); + --chart-1: oklch(0.7 0.16 25); + --chart-2: oklch(0.82 0.14 75); + --chart-3: oklch(0.72 0.14 245); + --chart-4: oklch(0.78 0.12 165); + --chart-5: oklch(0.88 0.1 195); + --chart-6: oklch(0.65 0.24 295); + --chart-8: oklch(0.62 0.22 335); --sidebar: oklch(0.21 0.006 285.885 / 0.6); --sidebar-foreground: oklch(0.985 0 0); --sidebar-primary: oklch(0.606 0.25 292.717); @@ -100,6 +104,8 @@ --color-chart-3: var(--chart-3); --color-chart-4: var(--chart-4); --color-chart-5: var(--chart-5); + --color-chart-6: var(--chart-6); + --color-chart-8: var(--chart-8); --radius-sm: calc(var(--radius) - 4px); --radius-md: calc(var(--radius) - 2px); --radius-lg: var(--radius); diff --git a/src/components/dashboard/chainage-bar-chart.tsx b/src/components/dashboard/chainage-bar-chart.tsx index 9bea75c..8e14ea9 100644 --- a/src/components/dashboard/chainage-bar-chart.tsx +++ b/src/components/dashboard/chainage-bar-chart.tsx @@ -10,6 +10,7 @@ import { ChartTooltipContent, type ChartConfig, } from '@/components/ui/chart'; +import { DETECTION_TYPES } from '@/constants/detectionModeConfig'; interface ChainageData { name: string; @@ -17,6 +18,8 @@ interface ChainageData { pothole: number; road_crack: number; damaged_road_marking: number; + drain_issue: number; + defective_culvert: number; total: number; } @@ -27,20 +30,28 @@ interface ChainageBarChartProps { const chartConfig = { pothole: { - label: 'Potholes', - color: 'var(--chart-1)', + label: DETECTION_TYPES.pothole.label + 's', + color: DETECTION_TYPES.pothole.color, }, defected_sign_board: { - label: 'Defected Signboards', - color: 'var(--chart-2)', + label: DETECTION_TYPES.defected_sign_board.label + 's', + color: DETECTION_TYPES.defected_sign_board.color, }, road_crack: { - label: 'Road Cracks', - color: 'var(--chart-3)', + label: DETECTION_TYPES.road_crack.label + 's', + color: DETECTION_TYPES.road_crack.color, }, damaged_road_marking: { - label: 'Damaged Markings', - color: 'var(--chart-4)', + label: DETECTION_TYPES.damaged_road_marking.label + 's', + color: DETECTION_TYPES.damaged_road_marking.color, + }, + drain_issue: { + label: DETECTION_TYPES.drain_issue.label + 's', + color: DETECTION_TYPES.drain_issue.color, + }, + defective_culvert: { + label: DETECTION_TYPES.defective_culvert.label + 's', + color: DETECTION_TYPES.defective_culvert.color, }, } satisfies ChartConfig; @@ -69,6 +80,8 @@ export function ChainageBarChart({ data, isLoading = false }: ChainageBarChartPr defected_sign_board: item.defected_sign_board, road_crack: item.road_crack, damaged_road_marking: item.damaged_road_marking, + drain_issue: item.drain_issue, + defective_culvert: item.defective_culvert, })); return ( @@ -90,6 +103,8 @@ export function ChainageBarChart({ data, isLoading = false }: ChainageBarChartPr + + diff --git a/src/components/dashboard/dashboard-map-content.tsx b/src/components/dashboard/dashboard-map-content.tsx index cf75c03..1785bff 100644 --- a/src/components/dashboard/dashboard-map-content.tsx +++ b/src/components/dashboard/dashboard-map-content.tsx @@ -5,6 +5,7 @@ import { MapContainer, TileLayer, CircleMarker, Popup, useMap } from 'react-leaf import { LatLngBounds, LatLng } from 'leaflet'; import 'leaflet/dist/leaflet.css'; import { Detection } from '@/types'; +import { DETECTION_TYPES } from '@/constants/detectionModeConfig'; interface DashboardMapContentProps { detections: Detection[]; @@ -52,28 +53,21 @@ export default function DashboardMapContent({ detections }: DashboardMapContentP ]; // Get marker color based on detection type - const getMarkerColor = (type: string) => { - const t = type.toLowerCase(); - if (t === 'pothole') { - return { fill: '#ef4444', stroke: '#b91c1c' }; // Red - } else if (t === 'defected_sign_board') { - return { fill: '#3b82f6', stroke: '#1d4ed8' }; // Blue - } else if (t === 'road_crack') { - return { fill: '#f59e0b', stroke: '#b45309' }; // Orange - } else if (t === 'damaged_road_marking') { - return { fill: '#6366f1', stroke: '#4338ca' }; // Indigo - } else if (t === 'good_sign_board') { - return { fill: '#10b981', stroke: '#047857' }; // Emerald + const getMarkerColor = (typeId: string) => { + const config = DETECTION_TYPES[typeId.toLowerCase()]; + if (config) { + return { + fill: config.color, + stroke: '#ffffff' // White stroke for better visibility on the map + }; } return { fill: '#64748b', stroke: '#475569' }; // Default Slate }; // Get display name for detection type - const getTypeName = (type: string) => { - return type - .split('_') - .map((word) => word.charAt(0).toUpperCase() + word.slice(1)) - .join(' '); + const getTypeName = (typeId: string) => { + const config = DETECTION_TYPES[typeId.toLowerCase()]; + return config ? config.label : typeId.replace(/_/g, ' '); }; return ( @@ -106,23 +100,33 @@ export default function DashboardMapContent({ detections }: DashboardMapContentP fillOpacity={0.8} > -
-
{typeName}
-
-
- Class: - {detection.class.replace(/_/g, ' ')} +
+
+ {typeName} +
+ +
+
+ Class + {detection.class.replace(/_/g, ' ')}
-
- Confidence: - {(detection.confidence * 100).toFixed(1)}% +
+ Confidence + {(detection.confidence * 100).toFixed(1)}%
-
-
Coordinates
-
-
Lat: {detection.latitude!.toFixed(6)}
-
Lng: {detection.longitude!.toFixed(6)}
+ +
+
Location Details
+
+
+ Latitude + {detection.latitude!.toFixed(6)} +
+
+ Longitude + {detection.longitude!.toFixed(6)} +
diff --git a/src/components/dashboard/dashboard-map.tsx b/src/components/dashboard/dashboard-map.tsx index 3d377e2..5d589ee 100644 --- a/src/components/dashboard/dashboard-map.tsx +++ b/src/components/dashboard/dashboard-map.tsx @@ -3,7 +3,8 @@ import { useEffect, useState } from 'react'; import dynamic from 'next/dynamic'; import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card'; -import { Loader2, Milestone } from 'lucide-react'; +import { Loader2, Milestone, Maximize2, Minimize2 } from 'lucide-react'; +import { Button } from '@/components/ui/button'; import { Detection } from '@/types'; import { DETECTION_TYPES } from '@/constants/detectionModeConfig'; @@ -35,6 +36,8 @@ export function DashboardMap({ const [detections, setDetections] = useState([]); const [isLoading, setIsLoading] = useState(true); const [error, setError] = useState(null); + const [isMaximized, setIsMaximized] = useState(false); + const [selectedTypes, setSelectedTypes] = useState([]); useEffect(() => { if (!projectSummary) { @@ -62,8 +65,10 @@ export function DashboardMap({ for (const [chnName, chn] of Object.entries(chainagesToProcess)) { if (!chn) continue; - const chainageDetections = (chn as any).detections || []; - filteredDetections.push(...chainageDetections); + const chainageDetections = ((chn as any).detections || []).filter( + (d: any) => (d.type || d.class || '').toLowerCase() !== 'good_sign_board' + ); + filteredDetections.push(...chainageDetections); } } @@ -76,50 +81,93 @@ export function DashboardMap({ } }, [projectSummary, selectedPackageId, selectedChainageId]); - // Filter detections with valid GPS coordinates - const validDetections = detections.filter((d) => d.latitude && d.longitude); + // Handle detection type toggle + const toggleType = (typeId: string) => { + setSelectedTypes((prev) => { + if (prev.includes(typeId)) { + const next = prev.filter((id) => id !== typeId); + return next.length === 0 ? [] : next; + } else { + return [...prev, typeId]; + } + }); + }; + + // Filter detections with valid GPS coordinates and selected types + const validDetections = detections.filter((d) => { + const hasGps = d.latitude && d.longitude; + if (!hasGps) return false; + + if (selectedTypes.length === 0) return true; + const typeId = (d.type || d.class || '').toLowerCase(); + return selectedTypes.includes(typeId); + }); return ( - - -
-
-
- -
-
- Detection Map -

- {isLoading - ? 'Loading...' - : `${validDetections.length} detections with GPS coordinates`} -

-
-
- - {/* Dynamic Color Legend */} -
- {Object.values(DETECTION_TYPES).map((type) => { - const count = validDetections.filter( - (d) => (d.type || d.class || '').toLowerCase() === type.id.toLowerCase() - ).length; - - if (count === 0 && (type.id.includes('culvert') || type.id === 'drain_issue')) return null; - - return ( -
-
- - {type.label} ({count}) - -
- ); - })} + + + {/* Top Right Actions */} +
+
+
- - -
+ + {/* Bottom Left Legend */} +
+
+
+ {Object.values(DETECTION_TYPES).map((type) => { + const typeId = type.id.toLowerCase(); + const count = detections.filter( + (d) => (d.type || d.class || '').toLowerCase() === typeId && d.latitude && d.longitude + ).length; + + if ( + count === 0 && + (type.id.includes('culvert') || type.id === 'drain_issue') + ) + return null; + if (type.id === 'good_sign_board') return null; + + const isSelected = selectedTypes.length === 0 || selectedTypes.includes(typeId); + + return ( + + ); + })} +
+
+
+ +
{isLoading ? (
@@ -140,6 +188,9 @@ export function DashboardMap({ ) : ( )} + + {/* Bottom Left Label Overlay */} +
diff --git a/src/components/dashboard/detection-donut-chart.tsx b/src/components/dashboard/detection-donut-chart.tsx index 3e2a6ce..a5d42fa 100644 --- a/src/components/dashboard/detection-donut-chart.tsx +++ b/src/components/dashboard/detection-donut-chart.tsx @@ -10,36 +10,43 @@ import { ChartTooltipContent, type ChartConfig, } from '@/components/ui/chart'; +import { DETECTION_TYPES } from '@/constants/detectionModeConfig'; interface DetectionDonutChartProps { defectedSignboard: number; pothole: number; roadCrack: number; damagedRoadMarking: number; - goodSignboard: number; + // goodSignboard: number; + drainIssue: number; + defectiveCulvert: number; isLoading?: boolean; } const chartConfig = { pothole: { - label: 'Potholes', - color: 'var(--chart-1)', + label: DETECTION_TYPES.pothole.label + 's', + color: DETECTION_TYPES.pothole.color, }, defectedSignboard: { - label: 'Defected Signboards', - color: 'var(--chart-2)', + label: DETECTION_TYPES.defected_sign_board.label + 's', + color: DETECTION_TYPES.defected_sign_board.color, }, roadCrack: { - label: 'Road Cracks', - color: 'var(--chart-3)', + label: DETECTION_TYPES.road_crack.label + 's', + color: DETECTION_TYPES.road_crack.color, }, damagedRoadMarking: { - label: 'Damaged Markings', - color: 'var(--chart-4)', + label: DETECTION_TYPES.damaged_road_marking.label + 's', + color: DETECTION_TYPES.damaged_road_marking.color, }, - goodSignboard: { - label: 'Good Signboards', - color: 'var(--chart-5)', + drainIssue: { + label: DETECTION_TYPES.drain_issue.label + 's', + color: DETECTION_TYPES.drain_issue.color, + }, + defectiveCulvert: { + label: DETECTION_TYPES.defective_culvert.label + 's', + color: DETECTION_TYPES.defective_culvert.color, }, } satisfies ChartConfig; @@ -48,7 +55,9 @@ export function DetectionDonutChart({ pothole, roadCrack, damagedRoadMarking, - goodSignboard, + // goodSignboard, + drainIssue, + defectiveCulvert, isLoading = false, }: DetectionDonutChartProps) { const chartData = React.useMemo( @@ -66,13 +75,31 @@ export function DetectionDonutChart({ count: damagedRoadMarking, fill: 'var(--color-damagedRoadMarking)', }, + /* { + type: 'goodSignboard', + count: goodSignboard, + fill: 'var(--color-goodSignboard)', + }, */ { - type: 'goodSignboard', - count: goodSignboard, - fill: 'var(--color-goodSignboard)', + type: 'drainIssue', + count: drainIssue, + fill: 'var(--color-drainIssue)', + }, + { + type: 'defectiveCulvert', + count: defectiveCulvert, + fill: 'var(--color-defectiveCulvert)', }, ].filter((item) => item.count > 0), - [pothole, defectedSignboard, roadCrack, damagedRoadMarking, goodSignboard], + [ + pothole, + defectedSignboard, + roadCrack, + damagedRoadMarking, + // goodSignboard, + drainIssue, + defectiveCulvert, + ], ); const totalDetections = React.useMemo(() => { diff --git a/src/components/map-modal.tsx b/src/components/map-modal.tsx index 07e8536..5c08218 100644 --- a/src/components/map-modal.tsx +++ b/src/components/map-modal.tsx @@ -119,20 +119,34 @@ export default function MapModal({ open, onClose, detections, detectionType }: M fillOpacity={0.9} > -
-
- {(detection.type || '').replace(/_/g, ' ')} #{detection.id} +
+
+ {(detection.type || '').replace(/_/g, ' ')} #{detection.id}
-
- Frame: - {detection.frame_number} - Confidence: - - {(detection.confidence * 100).toFixed(0)}% - + +
+
+ Frame + {detection.frame_number} +
+
+ Confidence + {(detection.confidence * 100).toFixed(1)}% +
-
- {detection.latitude.toFixed(6)}, {detection.longitude.toFixed(6)} + +
+
Location Details
+
+
+ Latitude + {detection.latitude.toFixed(6)} +
+
+ Longitude + {detection.longitude.toFixed(6)} +
+
diff --git a/src/constants/detectionModeConfig.ts b/src/constants/detectionModeConfig.ts index 4b363e8..a08cf51 100644 --- a/src/constants/detectionModeConfig.ts +++ b/src/constants/detectionModeConfig.ts @@ -21,7 +21,7 @@ export const DETECTION_TYPES: Record = { pothole: { id: 'pothole', label: 'Pothole', - color: '#ef4444', + color: 'var(--chart-1)', countKey: 'unique_pothole', listKey: 'pothole_list', frameCountKey: 'pothole', @@ -29,7 +29,7 @@ export const DETECTION_TYPES: Record = { defected_sign_board: { id: 'defected_sign_board', label: 'Defect Sign Board', - color: '#3b82f6', + color: 'var(--chart-2)', countKey: 'unique_defected_sign_board', listKey: 'defected_sign_board_list', frameCountKey: 'defected_sign_board', @@ -37,7 +37,7 @@ export const DETECTION_TYPES: Record = { road_crack: { id: 'road_crack', label: 'Road Crack', - color: '#f59e0b', + color: 'var(--chart-3)', countKey: 'unique_road_crack', listKey: 'road_crack_list', frameCountKey: 'road_crack', @@ -45,7 +45,7 @@ export const DETECTION_TYPES: Record = { damaged_road_marking: { id: 'damaged_road_marking', label: 'Damage Road Mark', - color: '#6366f1', + color: 'var(--chart-4)', countKey: 'unique_damaged_road_marking', listKey: 'damaged_road_marking_list', frameCountKey: 'damaged_road_marking', @@ -53,7 +53,7 @@ export const DETECTION_TYPES: Record = { good_sign_board: { id: 'good_sign_board', label: 'Good Sign Board', - color: '#10b981', + color: 'var(--chart-5)', countKey: 'unique_good_sign_board', listKey: 'good_sign_board_list', frameCountKey: 'good_sign_board', @@ -61,7 +61,7 @@ export const DETECTION_TYPES: Record = { drain_issue: { id: 'drain_issue', label: 'Drain Issue', - color: '#a855f7', + color: 'var(--chart-6)', countKey: 'unique_drain_issue', listKey: 'drain_issue_list', frameCountKey: 'drain_issue', @@ -69,7 +69,7 @@ export const DETECTION_TYPES: Record = { good_culvert: { id: 'good_culvert', label: 'Good Culvert', - color: '#10b981', + color: 'var(--chart-5)', countKey: 'unique_good_culvert', listKey: 'good_culvert_list', frameCountKey: 'good_culvert', @@ -77,7 +77,7 @@ export const DETECTION_TYPES: Record = { defective_culvert: { id: 'defective_culvert', label: 'Defective Culvert', - color: '#ef4444', + color: 'var(--chart-8)', countKey: 'unique_defective_culvert', listKey: 'defective_culvert_list', frameCountKey: 'defective_culvert',