"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 { Progress } from "@/components/ui/progress" import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/components/ui/select" import { Upload, Loader2, AlertCircle, ArrowLeft, MapPin, Package, FolderKanban } from "lucide-react" 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 || "http://127.0.0.1:8000/api/v1" const WS_URL = process.env.NEXT_PUBLIC_WS_URL || "ws://127.0.0.1:8000/api/v1" type DetectionType = "pothole-detection" | "sign-board-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") // 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("/") return } setSession(storedSession) setIsLoading(false) }, [router]) const connectWebSocket = (videoId: string) => { const ws = new WebSocket(`${WS_URL}/ws/${videoId}`) ws.onmessage = async (event) => { const data = JSON.parse(event.data) if (data.type === "progress" || data.progress !== undefined) { setProgress(data.progress || 0) let message = data.message || "Processing..." if (data.unique_potholes !== undefined) { message += ` | Unique: ${data.unique_potholes} | Total: ${data.total_detections || 0}` } else if (data.unique_signboards !== undefined) { message += ` | Unique: ${data.unique_signboards} | Total: ${data.total_detections || 0}` } setStatusMessage(message) } if (data.type === "complete" || data.status === "completed") { setStatusMessage("Processing completed! Saving video...") ws.close() // Store video file in IndexedDB for results page if (file) { try { await storeVideoFile(videoId, file) } catch (err) { console.error("Failed to store video file:", err) } } // Save video data and navigate to results saveVideoData({ videoId, detectionType }) setStatusMessage("Redirecting to results...") setTimeout(() => router.push("/results"), 500) } if (data.type === "error") { setError("Error: " + data.message) setStatusMessage("") setUploading(false) ws.close() } } ws.onerror = () => { setStatusMessage("Connection error. Retrying...") } } 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()) 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() setStatusMessage("Uploaded! Starting processing...") setProgress(10) connectWebSocket(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("/") } const getTitle = () => { return detectionType === "pothole-detection" ? "Pothole Detection System" : "Signboard Detection System" } if (isLoading) { return (
) } return (
{/* Header */}

{getTitle()}

Upload a video to detect and analyze with AI-powered processing

{/* Session Info Bar */} {session && (
Project: {session.projectName}
Package: {session.packageName}
Location: {session.locationName}
)} {/* Upload Card */} Upload Video Select a video file, detection type, and vehicle speed to start AI-powered analysis
{/* Video File Input */}
{ setFile(e.target.files?.[0] || null) setError(null) }} disabled={uploading} /> {file && (

Selected: {file.name} ({(file.size / 1024 / 1024).toFixed(2)} MB)

)}
{/* JSON File Input */}
{ setJsonFile(e.target.files?.[0] || null) setError(null) }} disabled={uploading} /> {jsonFile && (

Selected: {jsonFile.name} ({(jsonFile.size / 1024).toFixed(2)} KB)

)}
{/* Detection Type */}
{/* Speed Input */}
setSpeed(Number(e.target.value))} disabled={uploading} />
{/* Error Display */} {error && (

{error}

)} {/* Upload Button */} {/* Progress Section */} {uploading && (
{statusMessage} {progress}%
)}
) }