refactor : restructure types

This commit is contained in:
2026-03-18 17:09:58 +05:30
parent f35389ab69
commit 7f8854ed78
31 changed files with 629 additions and 259 deletions

280
package-lock.json generated
View File

@@ -22,6 +22,7 @@
"@radix-ui/react-tooltip": "^1.2.8",
"@tanstack/react-table": "^8.21.3",
"@vercel/analytics": "1.3.1",
"axios": "^1.13.6",
"class-variance-authority": "^0.7.1",
"clsx": "^2.1.1",
"leaflet": "^1.9.4",
@@ -3032,6 +3033,12 @@
"node": ">=10"
}
},
"node_modules/asynckit": {
"version": "0.4.0",
"resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz",
"integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==",
"license": "MIT"
},
"node_modules/autoprefixer": {
"version": "10.4.27",
"resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-10.4.27.tgz",
@@ -3069,6 +3076,17 @@
"postcss": "^8.1.0"
}
},
"node_modules/axios": {
"version": "1.13.6",
"resolved": "https://registry.npmjs.org/axios/-/axios-1.13.6.tgz",
"integrity": "sha512-ChTCHMouEe2kn713WHbQGcuYrr6fXTBiu460OTwWrWob16g1bXn4vtz07Ope7ewMozJAnEquLk5lWQWtBig9DQ==",
"license": "MIT",
"dependencies": {
"follow-redirects": "^1.15.11",
"form-data": "^4.0.5",
"proxy-from-env": "^1.1.0"
}
},
"node_modules/baseline-browser-mapping": {
"version": "2.10.8",
"resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.10.8.tgz",
@@ -3116,6 +3134,19 @@
"node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7"
}
},
"node_modules/call-bind-apply-helpers": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz",
"integrity": "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==",
"license": "MIT",
"dependencies": {
"es-errors": "^1.3.0",
"function-bind": "^1.1.2"
},
"engines": {
"node": ">= 0.4"
}
},
"node_modules/caniuse-lite": {
"version": "1.0.30001780",
"resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001780.tgz",
@@ -3163,6 +3194,18 @@
"node": ">=6"
}
},
"node_modules/combined-stream": {
"version": "1.0.8",
"resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz",
"integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==",
"license": "MIT",
"dependencies": {
"delayed-stream": "~1.0.0"
},
"engines": {
"node": ">= 0.8"
}
},
"node_modules/csstype": {
"version": "3.2.3",
"resolved": "https://registry.npmjs.org/csstype/-/csstype-3.2.3.tgz",
@@ -3296,6 +3339,15 @@
"integrity": "sha512-qIMFpTMZmny+MMIitAB6D7iVPEorVw6YQRWkvarTkT4tBeSLLiHzcwj6q0MmYSFCiVpiqPJTJEYIrpcPzVEIvg==",
"license": "MIT"
},
"node_modules/delayed-stream": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz",
"integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==",
"license": "MIT",
"engines": {
"node": ">=0.4.0"
}
},
"node_modules/detect-libc": {
"version": "2.1.2",
"resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.1.2.tgz",
@@ -3322,6 +3374,20 @@
"csstype": "^3.0.2"
}
},
"node_modules/dunder-proto": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz",
"integrity": "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==",
"license": "MIT",
"dependencies": {
"call-bind-apply-helpers": "^1.0.1",
"es-errors": "^1.3.0",
"gopd": "^1.2.0"
},
"engines": {
"node": ">= 0.4"
}
},
"node_modules/electron-to-chromium": {
"version": "1.5.313",
"resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.313.tgz",
@@ -3343,6 +3409,51 @@
"node": ">=10.13.0"
}
},
"node_modules/es-define-property": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz",
"integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==",
"license": "MIT",
"engines": {
"node": ">= 0.4"
}
},
"node_modules/es-errors": {
"version": "1.3.0",
"resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz",
"integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==",
"license": "MIT",
"engines": {
"node": ">= 0.4"
}
},
"node_modules/es-object-atoms": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.1.tgz",
"integrity": "sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==",
"license": "MIT",
"dependencies": {
"es-errors": "^1.3.0"
},
"engines": {
"node": ">= 0.4"
}
},
"node_modules/es-set-tostringtag": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.1.0.tgz",
"integrity": "sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==",
"license": "MIT",
"dependencies": {
"es-errors": "^1.3.0",
"get-intrinsic": "^1.2.6",
"has-tostringtag": "^1.0.2",
"hasown": "^2.0.2"
},
"engines": {
"node": ">= 0.4"
}
},
"node_modules/escalade": {
"version": "3.2.0",
"resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz",
@@ -3368,6 +3479,42 @@
"node": ">=6.0.0"
}
},
"node_modules/follow-redirects": {
"version": "1.15.11",
"resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.11.tgz",
"integrity": "sha512-deG2P0JfjrTxl50XGCDyfI97ZGVCxIpfKYmfyrQ54n5FO/0gfIES8C/Psl6kWVDolizcaaxZJnTS0QSMxvnsBQ==",
"funding": [
{
"type": "individual",
"url": "https://github.com/sponsors/RubenVerborgh"
}
],
"license": "MIT",
"engines": {
"node": ">=4.0"
},
"peerDependenciesMeta": {
"debug": {
"optional": true
}
}
},
"node_modules/form-data": {
"version": "4.0.5",
"resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.5.tgz",
"integrity": "sha512-8RipRLol37bNs2bhoV67fiTEvdTrbMUYcFTiy3+wuuOnUog2QBHCZWXDRijWQfAkhBj2Uf5UnVaiWwA5vdd82w==",
"license": "MIT",
"dependencies": {
"asynckit": "^0.4.0",
"combined-stream": "^1.0.8",
"es-set-tostringtag": "^2.1.0",
"hasown": "^2.0.2",
"mime-types": "^2.1.12"
},
"engines": {
"node": ">= 6"
}
},
"node_modules/fraction.js": {
"version": "5.3.4",
"resolved": "https://registry.npmjs.org/fraction.js/-/fraction.js-5.3.4.tgz",
@@ -3409,6 +3556,39 @@
}
}
},
"node_modules/function-bind": {
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz",
"integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==",
"license": "MIT",
"funding": {
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/get-intrinsic": {
"version": "1.3.0",
"resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.3.0.tgz",
"integrity": "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==",
"license": "MIT",
"dependencies": {
"call-bind-apply-helpers": "^1.0.2",
"es-define-property": "^1.0.1",
"es-errors": "^1.3.0",
"es-object-atoms": "^1.1.1",
"function-bind": "^1.1.2",
"get-proto": "^1.0.1",
"gopd": "^1.2.0",
"has-symbols": "^1.1.0",
"hasown": "^2.0.2",
"math-intrinsics": "^1.1.0"
},
"engines": {
"node": ">= 0.4"
},
"funding": {
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/get-nonce": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/get-nonce/-/get-nonce-1.0.1.tgz",
@@ -3418,6 +3598,31 @@
"node": ">=6"
}
},
"node_modules/get-proto": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/get-proto/-/get-proto-1.0.1.tgz",
"integrity": "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==",
"license": "MIT",
"dependencies": {
"dunder-proto": "^1.0.1",
"es-object-atoms": "^1.0.0"
},
"engines": {
"node": ">= 0.4"
}
},
"node_modules/gopd": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz",
"integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==",
"license": "MIT",
"engines": {
"node": ">= 0.4"
},
"funding": {
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/graceful-fs": {
"version": "4.2.11",
"resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz",
@@ -3425,6 +3630,45 @@
"dev": true,
"license": "ISC"
},
"node_modules/has-symbols": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz",
"integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==",
"license": "MIT",
"engines": {
"node": ">= 0.4"
},
"funding": {
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/has-tostringtag": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.2.tgz",
"integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==",
"license": "MIT",
"dependencies": {
"has-symbols": "^1.0.3"
},
"engines": {
"node": ">= 0.4"
},
"funding": {
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/hasown": {
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz",
"integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==",
"license": "MIT",
"dependencies": {
"function-bind": "^1.1.2"
},
"engines": {
"node": ">= 0.4"
}
},
"node_modules/internmap": {
"version": "2.0.3",
"resolved": "https://registry.npmjs.org/internmap/-/internmap-2.0.3.tgz",
@@ -3754,6 +3998,36 @@
"@jridgewell/sourcemap-codec": "^1.5.5"
}
},
"node_modules/math-intrinsics": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz",
"integrity": "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==",
"license": "MIT",
"engines": {
"node": ">= 0.4"
}
},
"node_modules/mime-db": {
"version": "1.52.0",
"resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz",
"integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==",
"license": "MIT",
"engines": {
"node": ">= 0.6"
}
},
"node_modules/mime-types": {
"version": "2.1.35",
"resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz",
"integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==",
"license": "MIT",
"dependencies": {
"mime-db": "1.52.0"
},
"engines": {
"node": ">= 0.6"
}
},
"node_modules/motion": {
"version": "12.38.0",
"resolved": "https://registry.npmjs.org/motion/-/motion-12.38.0.tgz",
@@ -3994,6 +4268,12 @@
"integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==",
"license": "MIT"
},
"node_modules/proxy-from-env": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz",
"integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==",
"license": "MIT"
},
"node_modules/radix-ui": {
"version": "1.4.3",
"resolved": "https://registry.npmjs.org/radix-ui/-/radix-ui-1.4.3.tgz",

View File

@@ -23,6 +23,7 @@
"@radix-ui/react-tooltip": "^1.2.8",
"@tanstack/react-table": "^8.21.3",
"@vercel/analytics": "1.3.1",
"axios": "^1.13.6",
"class-variance-authority": "^0.7.1",
"clsx": "^2.1.1",
"leaflet": "^1.9.4",

View File

@@ -20,7 +20,8 @@ import { DetectionDonutChart } from "@/components/dashboard/detection-donut-char
import { LocationBarChart } from "@/components/dashboard/location-bar-chart";
import { DashboardMap } from "@/components/dashboard/dashboard-map";
import { PageHeader } from "@/components/page-header";
import { fetchProjects, type Project } from "@/lib/api";
import { fetchProjects } from "@/lib/api";
import { Project } from "@/types";
import {
Popover,
PopoverContent,

View File

@@ -18,13 +18,15 @@ import {
fetchAllPackages,
createLocation,
updateLocation,
deleteLocation,
type Project,
type Package as PackageType,
type Location,
type LocationCreate,
type LocationUpdate
deleteLocation
} from "@/lib/api"
import {
Project,
Package as PackageType,
Location,
LocationCreate,
LocationUpdate
} from "@/types"
import { ColumnDef } from "@tanstack/react-table"
import { toast } from "sonner"
import { Badge } from "@/components/ui/badge"

View File

@@ -2,7 +2,8 @@
import { useRouter } from "next/navigation"
import dynamic from "next/dynamic"
import { type SessionContext, saveSession } from "@/lib/api"
import { saveSession } from "@/lib/api"
import { SessionContext } from "@/types"
import { PowerCircle, TrendingUp } from "lucide-react"
import { PageHeader } from "@/components/page-header"
import { PoweredBy } from "@/components/powered-by"

View File

@@ -15,12 +15,14 @@ import {
fetchAllPackages,
createPackage,
updatePackage,
deletePackage,
type Project,
type Package as PackageType,
type PackageCreate,
type PackageUpdate
deletePackage
} from "@/lib/api"
import {
Project,
Package as PackageType,
PackageCreate,
PackageUpdate
} from "@/types"
import { ColumnDef } from "@tanstack/react-table"
import { toast } from "sonner"
import { Badge } from "@/components/ui/badge"

View File

@@ -9,7 +9,8 @@ import { Dialog, DialogContent, DialogDescription, DialogHeader, DialogTitle } f
import { Loader2, CheckCircle2, Layers, MapPin, Building2, Route, X } from "lucide-react"
import { DataTable } from "@/components/data-table"
import { PageHeader } from "@/components/page-header"
import { createProject, fetchProjects, updateProject, deleteProject, type ProjectCreate, type Project, type ProjectUpdate } from "@/lib/api"
import { createProject, fetchProjects, updateProject, deleteProject } from "@/lib/api"
import { ProjectCreate, Project, ProjectUpdate } from "@/types"
import { ColumnDef } from "@tanstack/react-table"
import { toast } from "sonner"
import { Badge } from "@/components/ui/badge"

View File

@@ -8,12 +8,11 @@ import VideoPlayerSection from "@/components/video-player-section"
import { PageHeader } from "@/components/page-header"
import { PoweredBy } from "@/components/powered-by"
import {
type SessionContext,
loadSession,
clearSession
} from "@/lib/api"
import { SessionContext, DetectionData, DetectionType } from "@/types"
import { getVideoFile, clearVideoFile } from "@/lib/video-storage"
import { DetectionData, DetectionType } from "@/lib/types"
import { ROUTES } from "@/utils/routes"
import { Card } from "@/components/ui/card"

View File

@@ -8,14 +8,13 @@ import VideoPlayerSection from "@/components/video-player-section"
import { PageHeader } from "@/components/page-header"
import { PoweredBy } from "@/components/powered-by"
import {
type SessionContext,
loadSession,
loadVideoData,
isSessionValid,
clearSession
} from "@/lib/api"
import { SessionContext, DetectionData, DetectionType } from "@/types"
import { clearVideoFile } from "@/lib/video-storage"
import { DetectionData, DetectionType } from "@/lib/types"
import { ROUTES } from "@/utils/routes"
import { Card } from "@/components/ui/card"

View File

@@ -7,9 +7,9 @@ import { Loader2, TrendingUp } from "lucide-react"
import { PageHeader } from "@/components/page-header"
import { PoweredBy } from "@/components/powered-by"
import {
type SessionContext,
loadSession,
} from "@/lib/api"
import { SessionContext } from "@/types"
import { ROUTES } from "@/utils/routes"
import { Button } from "@/components/ui/button"

View File

@@ -11,12 +11,12 @@ import { Loader2, TrendingUp } from "lucide-react"
import { PageHeader } from "@/components/page-header"
import { PoweredBy } from "@/components/powered-by"
import {
type SessionContext,
loadSession,
isSessionValid,
saveVideoData,
clearSession
} from "@/lib/api"
import { SessionContext } from "@/types"
import { ROUTES } from "@/utils/routes"
import { storeVideoFile } from "@/lib/video-storage"
import { cn } from "@/lib/utils"

View File

@@ -7,7 +7,7 @@ import {
SelectTrigger,
SelectValue,
} from "@/components/ui/select"
import { type Project } from "@/lib/api"
import { Project } from "@/types"
interface CompactProjectSelectorProps {
projects: Project[]

View File

@@ -4,7 +4,7 @@ import { useEffect } from "react"
import { MapContainer, TileLayer, CircleMarker, Popup, useMap } from "react-leaflet"
import { LatLngBounds, LatLng } from "leaflet"
import "leaflet/dist/leaflet.css"
import { type Detection } from "@/lib/api"
import { Detection } from "@/types"
interface DashboardMapContentProps {
detections: Detection[]

View File

@@ -4,7 +4,7 @@ import { useEffect, useState } from "react"
import dynamic from "next/dynamic"
import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card"
import { Loader2, MapPin } from "lucide-react"
import { type Detection } from "@/lib/api"
import { Detection } from "@/types"
// Dynamically import the map to avoid SSR issues with Leaflet
const DashboardMapContent = dynamic(

View File

@@ -8,7 +8,7 @@ import {
SelectValue,
} from "@/components/ui/select"
import { FolderOpen, Package, MapPin } from "lucide-react"
import { type Project } from "@/lib/api"
import { Project } from "@/types"
interface FilterSelectorProps {
projects: Project[]

View File

@@ -10,11 +10,13 @@ import {
fetchProjects,
fetchPackagesByProject,
fetchLocationsByPackage,
type Project,
type Package as PackageType,
type Location,
type SessionContext
} from "@/lib/api"
import {
Project,
Package as PackageType,
Location,
SessionContext
} from "@/types"
import { cn } from "@/lib/utils"
type ProjectSelectionSectionProps = {

View File

@@ -8,7 +8,7 @@ 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 } from "lucide-react"
import type { DetectionData, DetectionType } from "@/lib/types"
import type { DetectionData, DetectionType } from "@/types"
const API_URL = process.env.NEXT_PUBLIC_API_URL
const WS_URL = API_URL?.replace(/^https:\/\//, "wss://").replace(/^http:\/\//, "ws://")

View File

@@ -11,7 +11,7 @@ import { Target, AlertTriangle, Film, Activity, Gauge, Monitor, SignpostBig, Map
// Dynamically import MapModal with SSR disabled (Leaflet requires window object)
const MapModal = dynamic(() => import("@/components/map-modal"), { ssr: false })
import { DetectionData, DetectionType } from "@/lib/types"
import { DetectionData, DetectionType } from "@/types"
import { cn } from "@/lib/utils"
const API_URL = process.env.NEXT_PUBLIC_API_URL

View File

@@ -0,0 +1,3 @@
export const ENV_CONSTANT = {
BASE_API_URL: process.env.NEXT_PUBLIC_API_URL,
};

View File

@@ -6,52 +6,16 @@
const API_URL = process.env.NEXT_PUBLIC_API_URL
// Type definitions
export interface Project {
id: string
name: string
state: string | null
corridor_name: string | null
start_lat: number | null
start_lng: number | null
end_lat: number | null
end_lng: number | null
created_at: string
updated_at: string
}
import {
Project, ProjectCreate, ProjectUpdate,
Package, PackageCreate, PackageUpdate,
Location, LocationCreate, LocationUpdate,
PaginatedResponse, PaginationParams,
Video, VideoResultData,
Detection,
SessionContext, emptySessionContext
} from "@/types"
export interface Package {
id: string
project_id: string
name: string
region: string | null
created_at: string
updated_at: string
}
export interface Location {
id: string
package_id: string
segment_name: string
chainage_start_km: number | null
chainage_end_km: number | null
start_lat: number
start_lng: number
end_lat: number
end_lng: number
created_at: string
updated_at: string
}
export interface PaginatedResponse<T> {
items: T[]
totalItems: number
}
export interface PaginationParams {
skip?: number;
limit?: number;
}
// Helper function for GET API requests
async function apiRequest<T>(endpoint: string): Promise<T> {
@@ -88,60 +52,6 @@ async function apiPostRequest<T>(endpoint: string, body: unknown): Promise<T> {
return response.json()
}
// Create request body types
export interface ProjectCreate {
name: string
state?: string | null
corridor_name?: string | null
start_lat?: number | null
start_lng?: number | null
end_lat?: number | null
end_lng?: number | null
}
export interface PackageCreate {
project_id: string
name: string
region?: string | null
}
export interface LocationCreate {
package_id: string
segment_name: string
chainage_start_km?: number | null
chainage_end_km?: number | null
start_lat: number
start_lng: number
end_lat: number
end_lng: number
}
// Update request body types
export interface ProjectUpdate {
name?: string
state?: string | null
corridor_name?: string | null
start_lat?: number | null
start_lng?: number | null
end_lat?: number | null
end_lng?: number | null
}
export interface PackageUpdate {
name?: string
region?: string | null
}
export interface LocationUpdate {
segment_name?: string
chainage_start_km?: number | null
chainage_end_km?: number | null
start_lat?: number
start_lng?: number
end_lat?: number
end_lng?: number
}
// Helper function for PUT API requests
async function apiPutRequest<T>(endpoint: string, body: unknown): Promise<T> {
const response = await fetch(`${API_URL}${endpoint}`, {
@@ -293,23 +203,7 @@ export async function fetchAllLocations(params?: PaginationParams): Promise<Pagi
return apiRequest<PaginatedResponse<Location>>(`/locations/?skip=${skip}&limit=${limit}`)
}
// Video type for dashboard
export interface Video {
id: string
filename: string
detection_type: "pothole-detection" | "sign-board-detection" | "pot-sign-detection"
status: "pending" | "processing" | "completed" | "failed"
unique_defected_sign_board?: number
unique_pothole?: number
unique_road_crack?: number
unique_damaged_road_marking?: number
unique_good_sign_board?: number
total_road_damage?: number
total_detections?: number
created_at: string
updated_at: string
}
// Video functions
/**
* Fetch all videos (for dashboard)
*/
@@ -351,18 +245,7 @@ export async function fetchVideos(params?: PaginationParams): Promise<Video[]> {
}))
}
// Detection type for map display
export interface Detection {
id: number
video_id: string
type: string
class: string
confidence: number
latitude: number | null
longitude: number | null
frame_number: number
timestamp_ms: number
}
// Detection specific functions
/**
* Fetch all detections from completed videos (for dashboard map)
@@ -410,25 +293,8 @@ export async function fetchAllDetections(): Promise<Detection[]> {
}
/**
* Session context type for storing user selections
* Session storage utility functions
*/
export interface SessionContext {
projectId: string | null
projectName: string | null
packageId: string | null
packageName: string | null
locationId: string | null
locationName: string | null
}
export const emptySessionContext: SessionContext = {
projectId: null,
projectName: null,
packageId: null,
packageName: null,
locationId: null,
locationName: null
}
// Session Storage Keys
const SESSION_KEY = "visionroad_session"
@@ -468,14 +334,6 @@ export function clearSession(): void {
}
}
/**
* Video data for results page
*/
export interface VideoResultData {
videoId: string
detectionType: string
}
/**
* Save video result data
*/
@@ -485,6 +343,7 @@ export function saveVideoData(data: VideoResultData): void {
}
}
/**
* Load video result data
*/

View File

@@ -1,75 +0,0 @@
export type DetectionType = "pothole-detection" | "sign-board-detection" | "pot-sign-detection"
export interface DetectionListItem {
detection_id?: number
pothole_id?: number
signboard_id?: number
type: string
first_detected_frame: number
first_detected_time: number
confidence: number
bbox?: { x1: number; y1: number; x2: number; y2: number }
lat?: number
lng?: number
}
export type DetectionData = {
video_id: string
detection_type?: string
output_video_path?: string
video_info: {
fps: number
width: number
height: number
total_frames: number
}
summary: {
unique_defected_sign_board?: number
unique_pothole?: number
unique_road_crack?: number
unique_damaged_road_marking?: number
unique_good_sign_board?: number
total_road_damage?: number
total_detections: number
total_frames: number
detection_rate: number
}
pothole_list?: Array<DetectionListItem>
defected_sign_board_list?: Array<DetectionListItem>
road_crack_list?: Array<DetectionListItem>
damaged_road_marking_list?: Array<DetectionListItem>
good_sign_board_list?: Array<DetectionListItem>
signboard_list?: Array<DetectionListItem> // Keeping for backward compatibility
frames: Array<{
frame_id: number
// Legacy format: separate arrays
potholes?: Array<{
pothole_id: number
bbox: { x1: number; y1: number; x2: number; y2: number }
confidence: number
}>
signboards?: Array<{
signboard_id: number
type: string
bbox: { x1: number; y1: number; x2: number; y2: number }
confidence: number
}>
// Flat format (pot-sign-detection): unified detections array
detections?: Array<{
frame_id: number
detection_id: number
type: string
confidence: number
bbox: { x1: number; y1: number; x2: number; y2: number }
center?: { x: number; y: number }
area?: number
count?: {
defected_sign_board: number
pothole: number
road_crack: number
damaged_road_marking: number
good_sign_board: number
}
}>
}>
}

View File

@@ -0,0 +1,44 @@
import { ENV_CONSTANT } from "@/constants/secrect.constant";
import axios from "axios";
const BASE_URL = ENV_CONSTANT.BASE_API_URL;
const axiosClient = axios.create({
baseURL: BASE_URL,
headers: {
// "Content-Type": "application/json",
"ngrok-skip-browser-warning": "true"
},
});
// Add request interceptor to inject access token
axiosClient.interceptors.request.use(
(config) => {
if (typeof window !== "undefined") {
const token = localStorage.getItem("token");
if (token && config.headers) {
config.headers["Authorization"] = `Bearer ${token}`;
}
}
return config;
},
(error) => {
return Promise.reject(error);
}
);
// Basic response interceptor
axiosClient.interceptors.response.use(
(response) => response,
(error) => {
// Standard error handling can be added here later
return Promise.reject(error);
}
);
export const axiosAuth = axios.create({
baseURL: BASE_URL,
headers: { "Content-Type": "application/json" },
});
export default axiosClient;

65
src/types/analysis.ts Normal file
View File

@@ -0,0 +1,65 @@
import { DetectionListItem } from "./detection"
/**
* Analysis result types
*/
export type DetectionData = {
video_id: string
detection_type?: string
output_video_path?: string
video_info: {
fps: number
width: number
height: number
total_frames: number
}
summary: {
unique_defected_sign_board?: number
unique_pothole?: number
unique_road_crack?: number
unique_damaged_road_marking?: number
unique_good_sign_board?: number
total_road_damage?: number
total_detections: number
total_frames: number
detection_rate: number
}
pothole_list?: Array<DetectionListItem>
defected_sign_board_list?: Array<DetectionListItem>
road_crack_list?: Array<DetectionListItem>
damaged_road_marking_list?: Array<DetectionListItem>
good_sign_board_list?: Array<DetectionListItem>
signboard_list?: Array<DetectionListItem> // Keeping for backward compatibility
frames: Array<{
frame_id: number
// Legacy format: separate arrays
potholes?: Array<{
pothole_id: number
bbox: { x1: number; y1: number; x2: number; y2: number }
confidence: number
}>
signboards?: Array<{
signboard_id: number
type: string
bbox: { x1: number; y1: number; x2: number; y2: number }
confidence: number
}>
// Flat format (pot-sign-detection): unified detections array
detections?: Array<{
frame_id: number
detection_id: number
type: string
confidence: number
bbox: { x1: number; y1: number; x2: number; y2: number }
center?: { x: number; y: number }
area?: number
count?: {
defected_sign_board: number
pothole: number
road_crack: number
damaged_road_marking: number
good_sign_board: number
}
}>
}>
}

12
src/types/common.ts Normal file
View File

@@ -0,0 +1,12 @@
/**
* Common API pagination types
*/
export interface PaginatedResponse<T> {
items: T[]
totalItems: number
}
export interface PaginationParams {
skip?: number;
limit?: number;
}

29
src/types/detection.ts Normal file
View File

@@ -0,0 +1,29 @@
/**
* Detection types for map and display
*/
export interface Detection {
id: number
video_id: string
type: string
class: string
confidence: number
latitude: number | null
longitude: number | null
frame_number: number
timestamp_ms: number
}
export type DetectionType = "pothole-detection" | "sign-board-detection" | "pot-sign-detection"
export interface DetectionListItem {
detection_id?: number
pothole_id?: number
signboard_id?: number
type: string
first_detected_frame: number
first_detected_time: number
confidence: number
bbox?: { x1: number; y1: number; x2: number; y2: number }
lat?: number
lng?: number
}

8
src/types/index.ts Normal file
View File

@@ -0,0 +1,8 @@
export * from "./common"
export * from "./project"
export * from "./package"
export * from "./location"
export * from "./video"
export * from "./detection"
export * from "./analysis"
export * from "./session"

37
src/types/location.ts Normal file
View File

@@ -0,0 +1,37 @@
/**
* Location related types
*/
export interface Location {
id: string
package_id: string
segment_name: string
chainage_start_km: number | null
chainage_end_km: number | null
start_lat: number
start_lng: number
end_lat: number
end_lng: number
created_at: string
updated_at: string
}
export interface LocationCreate {
package_id: string
segment_name: string
chainage_start_km?: number | null
chainage_end_km?: number | null
start_lat: number
start_lng: number
end_lat: number
end_lng: number
}
export interface LocationUpdate {
segment_name?: string
chainage_start_km?: number | null
chainage_end_km?: number | null
start_lat?: number
start_lng?: number
end_lat?: number
end_lng?: number
}

22
src/types/package.ts Normal file
View File

@@ -0,0 +1,22 @@
/**
* Package related types
*/
export interface Package {
id: string
project_id: string
name: string
region: string | null
created_at: string
updated_at: string
}
export interface PackageCreate {
project_id: string
name: string
region?: string | null
}
export interface PackageUpdate {
name?: string
region?: string | null
}

35
src/types/project.ts Normal file
View File

@@ -0,0 +1,35 @@
/**
* Project related types
*/
export interface Project {
id: string
name: string
state: string | null
corridor_name: string | null
start_lat: number | null
start_lng: number | null
end_lat: number | null
end_lng: number | null
created_at: string
updated_at: string
}
export interface ProjectCreate {
name: string
state?: string | null
corridor_name?: string | null
start_lat?: number | null
start_lng?: number | null
end_lat?: number | null
end_lng?: number | null
}
export interface ProjectUpdate {
name?: string
state?: string | null
corridor_name?: string | null
start_lat?: number | null
start_lng?: number | null
end_lat?: number | null
end_lng?: number | null
}

20
src/types/session.ts Normal file
View File

@@ -0,0 +1,20 @@
/**
* Session related types for storing user selections
*/
export interface SessionContext {
projectId: string | null
projectName: string | null
packageId: string | null
packageName: string | null
locationId: string | null
locationName: string | null
}
export const emptySessionContext: SessionContext = {
projectId: null,
projectName: null,
packageId: null,
packageName: null,
locationId: null,
locationName: null
}

23
src/types/video.ts Normal file
View File

@@ -0,0 +1,23 @@
/**
* Video related types
*/
export interface Video {
id: string
filename: string
detection_type: "pothole-detection" | "sign-board-detection" | "pot-sign-detection"
status: "pending" | "processing" | "completed" | "failed"
unique_defected_sign_board?: number
unique_pothole?: number
unique_road_crack?: number
unique_damaged_road_marking?: number
unique_good_sign_board?: number
total_road_damage?: number
total_detections?: number
created_at: string
updated_at: string
}
export interface VideoResultData {
videoId: string
detectionType: string
}