"use client" import { useState, useEffect } from "react" 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 { Dialog, DialogContent, DialogDescription, DialogHeader, DialogTitle } from "@/components/ui/dialog" import { Loader2, CheckCircle2, MapPin, Navigation, Milestone } from "lucide-react" import { SidebarNavigation } from "@/components/sidebar-navigation" import { DataTable } from "@/components/data-table" import { PageHeader } from "@/components/page-header" import { PoweredBy } from "@/components/powered-by" import { fetchProjects, fetchPackagesByProject, fetchAllLocations, fetchAllPackages, createLocation, updateLocation, deleteLocation, type Project, type Package as PackageType, type Location, type LocationCreate, type LocationUpdate } from "@/lib/api" import { toast } from "sonner" export default function CreateLocationPage() { const [locations, setLocations] = useState([]) const [projects, setProjects] = useState([]) const [packages, setPackages] = useState([]) const [allPackages, setAllPackages] = useState([]) const [isLoading, setIsLoading] = useState(true) const [isModalOpen, setIsModalOpen] = useState(false) const [isSubmitting, setIsSubmitting] = useState(false) const [error, setError] = useState(null) const [loadingProjects, setLoadingProjects] = useState(false) const [loadingPackages, setLoadingPackages] = useState(false) // Pagination state const [skip, setSkip] = useState(0) const [limit, setLimit] = useState(10) // Editing state const [isEditing, setIsEditing] = useState(false) const [currentLocation, setCurrentLocation] = useState(null) // Form fields const [selectedProjectId, setSelectedProjectId] = useState("") const [selectedPackageId, setSelectedPackageId] = useState("") const [segmentName, setSegmentName] = useState("") const [chainageStartKm, setChainageStartKm] = useState("") const [chainageEndKm, setChainageEndKm] = useState("") const [startLat, setStartLat] = useState("") const [startLng, setStartLng] = useState("") const [endLat, setEndLat] = useState("") const [endLng, setEndLng] = useState("") // Load locations and projects const loadLocations = async (currentSkip = skip, currentLimit = limit) => { try { setIsLoading(true) setError(null) const data = await fetchAllLocations({ skip: currentSkip, limit: currentLimit }) setLocations(data) } catch (err) { setError("Failed to load locations. Please check if the backend is running.") } finally { setIsLoading(false) } } const loadProjects = async () => { try { setLoadingProjects(true) const data = await fetchProjects({ skip: 0, limit: 1000 }) setProjects(data) } catch (err) { setError("Failed to load projects.") } finally { setLoadingProjects(false) } } const loadAllPackages = async () => { try { const data = await fetchAllPackages({ skip: 0, limit: 1000 }) setAllPackages(data) } catch (err) { console.error("Failed to load all packages") } } useEffect(() => { loadLocations(skip, limit) loadProjects() loadAllPackages() }, [skip, limit]) // Load packages when project changes useEffect(() => { if (!selectedProjectId) { setPackages([]) if (!isEditing) setSelectedPackageId("") return } const loadPackagesForProject = async () => { try { setLoadingPackages(true) if (!isEditing) setSelectedPackageId("") const data = await fetchPackagesByProject(selectedProjectId, { skip: 0, limit: 1000 }) setPackages(data) } catch (err) { setError("Failed to load packages for the selected project.") } finally { setLoadingPackages(false) } } loadPackagesForProject() }, [selectedProjectId, isEditing]) const resetForm = () => { setSelectedProjectId("") setSelectedPackageId("") setSegmentName("") setChainageStartKm("") setChainageEndKm("") setStartLat("") setStartLng("") setEndLat("") setEndLng("") setError(null) setIsEditing(false) setCurrentLocation(null) } const handleSubmit = async (e: React.FormEvent) => { e.preventDefault() if (!selectedPackageId && !isEditing) { setError("Please select a project and package first") return } if (!segmentName.trim()) { setError("Segment name is required") return } if (!startLat || !startLng || !endLat || !endLng) { setError("All GPS coordinates are required for locations") return } setIsSubmitting(true) setError(null) try { if (isEditing && currentLocation) { const data: LocationUpdate = { segment_name: segmentName.trim(), chainage_start_km: chainageStartKm ? parseFloat(chainageStartKm) : null, chainage_end_km: chainageEndKm ? parseFloat(chainageEndKm) : null, start_lat: parseFloat(startLat), start_lng: parseFloat(startLng), end_lat: parseFloat(endLat), end_lng: parseFloat(endLng), } await updateLocation(currentLocation.id, data) toast.success("Location updated successfully!") } else { const data: LocationCreate = { package_id: selectedPackageId, segment_name: segmentName.trim(), chainage_start_km: chainageStartKm ? parseFloat(chainageStartKm) : null, chainage_end_km: chainageEndKm ? parseFloat(chainageEndKm) : null, start_lat: parseFloat(startLat), start_lng: parseFloat(startLng), end_lat: parseFloat(endLat), end_lng: parseFloat(endLng), } await createLocation(data) toast.success("Location created successfully!") } // Refresh locations list await loadLocations() // Close modal and reset form immediately setIsModalOpen(false) resetForm() } catch (err) { setError(err instanceof Error ? err.message : `Failed to ${isEditing ? 'update' : 'create'} location`) } finally { setIsSubmitting(false) } } const handleEdit = (location: Location) => { setIsEditing(true) setCurrentLocation(location) // Find project for this package const pkg = allPackages.find(p => p.id === location.package_id) if (pkg) { setSelectedProjectId(pkg.project_id) setSelectedPackageId(location.package_id) } setSegmentName(location.segment_name || "") setChainageStartKm(location.chainage_start_km?.toString() || "") setChainageEndKm(location.chainage_end_km?.toString() || "") setStartLat(location.start_lat.toString()) setStartLng(location.start_lng.toString()) setEndLat(location.end_lat.toString()) setEndLng(location.end_lng.toString()) setIsModalOpen(true) } const handleDelete = async (location: Location) => { if (!confirm(`Are you sure you want to delete location "${location.segment_name}"?`)) return try { setIsLoading(true) await deleteLocation(location.id) toast.success("Location deleted successfully!") await loadLocations() } catch (err) { setError("Failed to delete location") } finally { setIsLoading(false) } } const getPackageName = (packageId: string) => { return allPackages.find(p => p.id === packageId)?.name || packageId } const isFormComplete = selectedPackageId && segmentName.trim() && startLat && startLng && endLat && endLng const columns = [ { key: "segment_name", header: "Segment Name", render: (location: Location) => (
{location.segment_name}
) }, { key: "package_id", header: "Package", render: (location: Location) => getPackageName(location.package_id) }, { key: "project", header: "Project", render: (location: Location) => { const pkg = allPackages.find(p => p.id === location.package_id) const project = projects.find(p => p.id === pkg?.project_id) return project?.name || "—" } }, { key: "chainage", header: "Chainage (km)", render: (location: Location) => { if (location.chainage_start_km !== null && location.chainage_end_km !== null) { return ( {location.chainage_start_km} - {location.chainage_end_km} ) } return "—" } }, { key: "start_gps", header: "Start GPS", render: (location: Location) => ( {location.start_lat.toFixed(4)}, {location.start_lng.toFixed(4)} ) }, { key: "end_gps", header: "End GPS", render: (location: Location) => ( {location.end_lat.toFixed(4)}, {location.end_lng.toFixed(4)} ) }, ] return (
{/* Refined Header */}
{/* Error Message */} {error && !isModalOpen && (
!

{error}

)} {/* Data Table */}
{ setIsEditing(false); setIsModalOpen(true); }} onEdit={handleEdit} onDelete={handleDelete} addButtonText="Add New Location" isLoading={isLoading} pagination={{ skip, limit, onPageChange: setSkip, onLimitChange: (newLimit) => { setLimit(newLimit); setSkip(0); // Reset skip when limit changes } }} />
{/* Modal Dialog */} { if (!open) { setIsModalOpen(false); resetForm(); } else { setIsModalOpen(true); } }}> e.preventDefault()} > {isEditing ? 'Edit Location' : 'Create New Location'} {isEditing ? 'Update disclosure details for your road infrastructure segment' : 'Select project & package, then fill in the location details'} {/* Error Message in Modal */} {error && (
!

{error}

)}
{/* Step 1: Select Project */} {!isEditing && (
1

Select Project

)} {/* Step 2: Select Package */} {!isEditing && (
2

Select Package

)} {/* Step 3: Location Details */}
{!isEditing && (
3

Location Information

)} {/* Segment Name & Chainage Row */}
setSegmentName(e.target.value)} placeholder="Location to Location" className="h-9 text-sm" required />
setChainageStartKm(e.target.value)} placeholder="0" className="h-9 text-sm" />
setChainageEndKm(e.target.value)} placeholder="0" className="h-9 text-sm" />
{/* GPS Coordinates Grid */}
{/* Start Point */}

Start Point

setStartLat(e.target.value)} placeholder="Lat" className="h-8 text-[11px]" required />
setStartLng(e.target.value)} placeholder="Lng" className="h-8 text-[11px]" required />
{/* End Point */}

End Point

setEndLat(e.target.value)} placeholder="Lat" className="h-8 text-[11px]" required />
setEndLng(e.target.value)} placeholder="Lng" className="h-8 text-[11px]" required />
{/* Submit Button */}
) }