diff --git a/src/app/(modules)/results/[videoId]/page.tsx b/src/app/(modules)/results/[videoId]/page.tsx index ab21747..9c73641 100644 --- a/src/app/(modules)/results/[videoId]/page.tsx +++ b/src/app/(modules)/results/[videoId]/page.tsx @@ -116,9 +116,6 @@ export default function VideoResultsPage() { {detectionData && ( )} diff --git a/src/components/video/detailedSummarySection.tsx b/src/components/video/detailedSummarySection.tsx deleted file mode 100644 index 477f864..0000000 --- a/src/components/video/detailedSummarySection.tsx +++ /dev/null @@ -1,321 +0,0 @@ -'use client'; - -import { useEffect, useState } from 'react'; -import dynamic from 'next/dynamic'; -import { Map as MapIcon, Activity } from 'lucide-react'; -import { - Card, - CardContent, - CardDescription, - CardHeader, - CardTitle, -} from '@/components/ui/card'; -import { ScrollArea } from '@/components/ui/scroll-area'; -import { Badge } from '@/components/ui/badge'; -import { Button } from '@/components/ui/button'; -import { ChainageSummaryData, DetectionResultLog } from '@/types'; -import { projectSummaryService } from '@/services/api'; -import { getDetectionModeConfig } from '@/constants/detectionModeConfig'; - -// Dynamically import MapModal with SSR disabled (Leaflet requires window object) -const MapModal = dynamic(() => import('@/components/map-modal'), { - ssr: false, -}); - -interface DetailedSummarySectionProps { - projectId: string; - videoId: string; - detectionType: string; - logs: DetectionResultLog[]; -} - -type DisplayDetection = { - id: string | number; - type: string; - class?: string; - confidence?: number; - latitude?: number | null; - longitude?: number | null; - frame_number: number; - timestamp_ms?: number; - chainageName?: string; - packageName?: string; -}; - -const DetailedSummarySection = ({ - projectId, - videoId, - detectionType, - logs, -}: DetailedSummarySectionProps) => { - const [summaryData, setSummaryData] = useState( - null, - ); - const [loading, setLoading] = useState(false); - const [showMap, setShowMap] = useState(false); - - useEffect(() => { - if (!videoId || !projectId) { - setSummaryData(null); - setLoading(false); - return; - } - - const fetchSummary = async () => { - setLoading(true); - try { - const data = - await projectSummaryService.getProjectSummaryByVideo( - projectId, - videoId, - ); - setSummaryData(data); - } catch (err) { - console.error('Failed to fetch summary:', err); - } finally { - setLoading(false); - } - }; - - fetchSummary(); - }, [videoId, projectId]); - - if (!videoId) return null; - - const modeConfig = getDetectionModeConfig(detectionType); - - // Flatten all detections for the scrollable list - const summaryDetections: DisplayDetection[] = []; - - Object.entries(summaryData?.packages || {}).forEach( - ([packageName, packageData]) => { - Object.entries(packageData?.chainages || {}).forEach( - ([chainageName, chainageData]) => { - chainageData?.detections?.forEach((detection) => { - summaryDetections.push({ - ...detection, - chainageName, - packageName, - }); - }); - }, - ); - }, - ); - const logDetections: DisplayDetection[] = logs.map((log) => ({ - id: log.id, - type: log.type, - class: log.label || log.type, - confidence: log.confidence, - latitude: log.latitude, - longitude: log.longitude, - frame_number: log.frame, - timestamp_ms: Math.round(log.timestamp_seconds * 1000), - })); - const allDetections = summaryDetections.length - ? summaryDetections - : logDetections; - const mapDetections = allDetections - .filter( - (detection) => - typeof detection.latitude === 'number' && - typeof detection.longitude === 'number', - ) - .map((detection, index) => ({ - id: - typeof detection.id === 'number' - ? detection.id - : Number.parseInt(detection.id.replace(/\D/g, ''), 10) || index + 1, - type: detection.type, - class: detection.class || detection.type, - confidence: detection.confidence || 0, - latitude: detection.latitude as number, - longitude: detection.longitude as number, - frame_number: detection.frame_number, - })); - - return ( -
- - -
-
-
- -
-
- Segments - - {modeConfig.label} detected - -
-
- -
-
- - -
- {loading ? ( -
- Loading segment summary... -
- ) : summaryData ? ( - <> - {/* Project Info */} -
-
- - Project - - - {summaryData.project.name} - -
- {summaryData.project.corridor_name && ( -
- - Corridor - - - {summaryData.project.corridor_name} - -
- )} -
- - {/* Packages and Chainages */} - {Object.entries(summaryData.packages).map( - ([packageName, packageData]) => ( -
-
- {packageName} -
-
- {Object.entries(packageData.chainages).map( - ([chainageName, chainageData]) => ( -
-
- {chainageName} -
-
- {chainageData.detection_count} -
-
- ), - )} -
-
- ), - )} - - ) : ( -
- Segment summary is not available for this result. -
- )} -
-
-
-
- - - -
-
- -
-
- - All Detections - - - Complete list with GPS coordinates - -
-
-
- - -
- {allDetections.length === 0 ? ( -
- No detailed detections available. -
- ) : ( - allDetections.map((detection, idx) => ( -
-
- - {(detection.class || detection.type || '').replace( - /_/g, - ' ', - )}{' '} - #{detection.id} - - - Frame {detection.frame_number} - -
-
- {detection.chainageName && ( -
- Segment:{' '} - - {detection.chainageName} - -
- )} - {typeof detection.confidence === 'number' && ( -
- Confidence:{' '} - - {(detection.confidence * 100).toFixed(1)}% - -
- )} - {typeof detection.latitude === 'number' && - typeof detection.longitude === 'number' ? ( -
- GPS: {detection.latitude}, {detection.longitude} -
- ) : ( -
- GPS: Not available -
- )} -
-
- )) - )} -
-
-
-
- - {/* Map Modal */} - setShowMap(false)} - detections={mapDetections} - detectionType={detectionType} - /> -
- ); -}; - -export default DetailedSummarySection; diff --git a/src/components/videoPlayerSection.tsx b/src/components/videoPlayerSection.tsx index 2848390..d3f44f0 100644 --- a/src/components/videoPlayerSection.tsx +++ b/src/components/videoPlayerSection.tsx @@ -14,22 +14,15 @@ import { useAnnotatedVideoQuery } from '@/app/(modules)/results/hooks/useVideoRe import AnnotatedVideoPlayer from './video/annotatedVideoPlayer'; import CurrentDetectionBar from './video/currentDetectionBar'; import DetectionLogs from './video/detectionLogs'; -import DetailedSummarySection from './video/detailedSummarySection'; import ResultStatsGrid from './video/resultStatsGrid'; import { useDetectionPlayback } from './video/useDetectionPlayback'; type VideoPlayerSectionProps = { data: CompletedVideoResult; - videoId: string; - detectionType: string; - projectId?: string; }; export default function VideoPlayerSection({ data, - videoId, - detectionType, - projectId, }: VideoPlayerSectionProps) { const videoRef = useRef(null); const { @@ -80,8 +73,6 @@ export default function VideoPlayerSection({ onSeeked={handleSeeked} /> - - + +
+ +
- ); }