"use client" import { useState, useEffect } from "react" import { useRouter } from "next/navigation" import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card" import { Button } from "@/components/ui/button" import { Input } from "@/components/ui/input" import { Label } from "@/components/ui/label" import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/components/ui/select" import { Loader2, TrendingUp } from "lucide-react" import { SidebarNavigation } from "@/components/sidebar-navigation" import { PageHeader } from "@/components/page-header" import { type SessionContext, loadSession, isSessionValid, saveVideoData, clearSession } from "@/lib/api" import { storeVideoFile } from "@/lib/video-storage" const API_URL = process.env.NEXT_PUBLIC_API_URL const WS_URL = API_URL?.replace(/^https:\/\//, "wss://").replace(/^http:\/\//, "ws://") type DetectionType = "pothole-detection" | "sign-board-detection" | "pot-sign-detection" export default function UploadPage() { const router = useRouter() const [session, setSession] = useState(null) const [isLoading, setIsLoading] = useState(true) // Form states const [file, setFile] = useState(null) const [jsonFile, setJsonFile] = useState(null) const [speed, setSpeed] = useState(30) const [detectionType, setDetectionType] = useState("pothole-detection") const [selectMethod, setSelectMethod] = useState("yolo_vl") // Upload states const [uploading, setUploading] = useState(false) const [progress, setProgress] = useState(0) const [statusMessage, setStatusMessage] = useState("") const [error, setError] = useState(null) // Load session on mount useEffect(() => { const storedSession = loadSession() if (!isSessionValid(storedSession)) { router.replace("/new-analysis") return } setSession(storedSession) setIsLoading(false) }, [router]) const handleUpload = async () => { if (!file) { setError("Please select a video file") return } const formData = new FormData() formData.append("file", file) formData.append("detection_type", detectionType) formData.append("speed_kmh", speed.toString()) formData.append("detection_mode", selectMethod) if (jsonFile) { formData.append("json_file", jsonFile) } setUploading(true) setProgress(0) setStatusMessage("Uploading...") setError(null) try { const response = await fetch(`${API_URL}/upload`, { method: "POST", headers: { "ngrok-skip-browser-warning": "true" }, body: formData }) if (!response.ok) { const errorText = await response.text() throw new Error(`Upload failed (${response.status}): ${errorText}`) } const result = await response.json() // Store file locally for potential recovery/results display if (file) { try { await storeVideoFile(result.video_id, file) } catch (err) { console.error("Failed to store video file:", err) } } saveVideoData({ videoId: result.video_id, detectionType }) // Redirect to the dynamic processing page router.push(`/upload/${result.video_id}`) } catch (err) { let errorMessage = "Upload failed" if (err instanceof TypeError && err.message === "Failed to fetch") { errorMessage = "Cannot connect to server. Please check if backend is running." } else if (err instanceof Error) { errorMessage = err.message } setError(errorMessage) setStatusMessage("") setUploading(false) setProgress(0) } } const handleBackToSelection = () => { clearSession() router.push("/new-analysis") } const getTitle = () => { if (detectionType === "pothole-detection") return "Pothole Detection" if (detectionType === "sign-board-detection") return "Signboard Detection" return "Pothole & Signboard Detection" } if (isLoading) { return (
) } return (
{/* Sidebar Navigation */} {/* Main Content */}
{/* Refined Header */}
{/* Compact Session Info Bar */} {session && (
Project {session.projectName}
Package {session.packageName}
Location {session.locationName}
)} {/* Upload Card */} Upload Video Select video file, detection type, vehicle speed, and method for analysis
{/* Video File Input */}
{ setFile(e.target.files?.[0] || null) setError(null) }} disabled={uploading} className="h-10 bg-gray-50 dark:bg-gray-800 file:mr-3 file:py-1.5 file:px-3 file:rounded-md file:border-0 file:bg-blue-100 dark:file:bg-blue-900/50 file:text-blue-600 dark:file:text-blue-400 file:font-medium file:text-xs hover:file:bg-blue-200" />
{/* JSON File Input */}
{ setJsonFile(e.target.files?.[0] || null) setError(null) }} disabled={uploading} className="h-10 bg-gray-50 dark:bg-gray-800 file:mr-3 file:py-1.5 file:px-3 file:rounded-md file:border-0 file:bg-blue-100 dark:file:bg-blue-900/50 file:text-blue-600 dark:file:text-blue-400 file:font-medium file:text-xs hover:file:bg-blue-200" />
{/* Detection, Speed, and Method Row */}
{/* Detection Type */}
{/* Speed Input */}
setSpeed(Number(e.target.value))} disabled={uploading} className="h-10 bg-gray-50 dark:bg-gray-800" />
{/* Select Method */}
{/* Error Display */} {error && (
!

{error}

)} {/* Upload Button */}
{/* Footer */}

Sentient Geeks Pvt. Ltd.

) }