updated ui and added NPED back

This commit is contained in:
2025-09-21 20:10:05 +01:00
parent 8f6fba1e63
commit 50cedaf2c4
11 changed files with 537 additions and 25 deletions

1
.env.production Normal file
View File

@@ -0,0 +1 @@
VITE_CAM_BASE=

View File

@@ -7,7 +7,7 @@
<title>MAV | In Car System</title> <title>MAV | In Car System</title>
</head> </head>
<body> <body>
<div id="root"></div> <div id="root" class="min-h-screen flex flex-col"></div>
<script type="module" src="/src/main.tsx"></script> <script type="module" src="/src/main.tsx"></script>
</body> </body>
</html> </html>

497
public/NPED.svg Normal file

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 252 KiB

View File

@@ -130,7 +130,7 @@ const CameraSettingFields = ({
<button <button
type="submit" type="submit"
className="bg-blue-800 text-white rounded-lg p-2 mx-auto" className="bg-blue-800 text-white rounded-lg p-2 mx-auto h-[100%] w-full"
> >
Save settings Save settings
</button> </button>

View File

@@ -13,21 +13,19 @@ const CameraSettings = ({ title, side }: { title: string; side: string }) => {
updateCameraConfigError, updateCameraConfigError,
} = useFetchCameraConfig(side); } = useFetchCameraConfig(side);
console.log(updateCameraConfigError); console.log(updateCameraConfigError);
console.log(isPending);
return ( return (
<Card> <Card>
{isError && <>Cannot Fetch camera config</>} {isPending && <>Loading camera config</>}
{isError && <>Error fetching camera config</>}
{isPending ? ( <div className="relative flex flex-col space-y-3 h-full">
<>Loading</> <CardHeader title={title} icon={faWrench} />
) : ( <CameraSettingFields
<div className="relative flex flex-col space-y-3 h-full"> initialData={data}
<CardHeader title={title} icon={faWrench} /> updateCameraConfig={updateCameraConfig}
<CameraSettingFields />
initialData={data} </div>
updateCameraConfig={updateCameraConfig}
/>
</div>
)}
</Card> </Card>
); );
}; };

View File

@@ -12,7 +12,7 @@ type AlertItemProps = {
const AlertItem = ({ item }: AlertItemProps) => { const AlertItem = ({ item }: AlertItemProps) => {
const [isModalOpen, setIsModalOpen] = useState(false); const [isModalOpen, setIsModalOpen] = useState(false);
const motionAway = (item?.motion ?? "").toUpperCase() === "AWAY"; const motionAway = (item?.motion ?? "").toUpperCase() === "AWAY";
// const isNPEDHit = item?.metadata?.npedJSON?.status_code === 404; const isNPEDHit = item?.metadata?.npedJSON?.status_code === 404;
const isHotListHit = item?.metadata?.hotlistMatches?.Hotlist0 === true; const isHotListHit = item?.metadata?.hotlistMatches?.Hotlist0 === true;
const handleClick = () => { const handleClick = () => {
@@ -36,6 +36,13 @@ const AlertItem = ({ item }: AlertItemProps) => {
className="h-20 object-contain rounded-md" className="h-20 object-contain rounded-md"
/> />
)} )}
{isNPEDHit && (
<img
src={HotListImg}
alt="hotlistHit"
className="h-20 object-contain rounded-md"
/>
)}
<div className="flex flex-col"> <div className="flex flex-col">
<small>MAKE: {item.make}</small> <small>MAKE: {item.make}</small>
<small>MODEL: {item.model}</small> <small>MODEL: {item.model}</small>

View File

@@ -1,11 +1,12 @@
import Card from "../../UI/Card"; import Card from "../../UI/Card";
import CardHeader from "../../UI/CardHeader"; import CardHeader from "../../UI/CardHeader";
import NPEDFields from "./NPEDFields"; import NPEDFields from "./NPEDFields";
import NPEDIcon from "/NPED.svg";
const NPEDCard = () => { const NPEDCard = () => {
return ( return (
<Card> <Card>
<CardHeader title={"NPED Config"} img={"/NPED.jpg"} /> <CardHeader title={"NPED Config"} img={NPEDIcon} />
<NPEDFields /> <NPEDFields />
</Card> </Card>
); );

View File

@@ -26,6 +26,7 @@ const SightingDataFields = () => {
<Field <Field
as="select" as="select"
className="p-2 border border-gray-400 rounded-lg text-white bg-[#253445]" className="p-2 border border-gray-400 rounded-lg text-white bg-[#253445]"
name="overviewImageScaleFactor"
> >
<option value="HIGH">Full</option> <option value="HIGH">Full</option>
<option value="MEDIUM">3/4</option> <option value="MEDIUM">3/4</option>
@@ -38,6 +39,7 @@ const SightingDataFields = () => {
<Field <Field
as="select" as="select"
className="p-2 border border-gray-400 rounded-lg text-white bg-[#253445]" className="p-2 border border-gray-400 rounded-lg text-white bg-[#253445]"
name="overviewType"
> >
<option value="PlainOverview">Plain Overview</option> <option value="PlainOverview">Plain Overview</option>
<option value="IncludePlatePatches">Include Plate Patches</option> <option value="IncludePlatePatches">Include Plate Patches</option>
@@ -60,6 +62,7 @@ const SightingDataFields = () => {
<Field <Field
as="select" as="select"
className="p-2 border border-gray-400 rounded-lg text-white bg-[#253445]" className="p-2 border border-gray-400 rounded-lg text-white bg-[#253445]"
name="vrmToTransit"
> >
<option value="PlainOverview">plain VRM ASCII (default)</option> <option value="PlainOverview">plain VRM ASCII (default)</option>
<option value="IncludePlatePatches">plain VRM ASCII (default)</option> <option value="IncludePlatePatches">plain VRM ASCII (default)</option>
@@ -70,6 +73,7 @@ const SightingDataFields = () => {
<Field <Field
as="select" as="select"
className="p-2 border border-gray-400 rounded-lg text-white bg-[#253445]" className="p-2 border border-gray-400 rounded-lg text-white bg-[#253445]"
name="staticReadAction"
> >
<option value="UseLaneDirection">Use Lane Direction</option> <option value="UseLaneDirection">Use Lane Direction</option>
<option value="IncludePlatePatches">plain VRM ASCII (default)</option> <option value="IncludePlatePatches">plain VRM ASCII (default)</option>
@@ -80,6 +84,7 @@ const SightingDataFields = () => {
<Field <Field
as="select" as="select"
className="p-2 border border-gray-400 rounded-lg text-white bg-[#253445]" className="p-2 border border-gray-400 rounded-lg text-white bg-[#253445]"
name="noRegionAction"
> >
<option value="UseLaneDirection">Send</option> <option value="UseLaneDirection">Send</option>
<option value="IncludePlatePatches">plain VRM ASCII (default)</option> <option value="IncludePlatePatches">plain VRM ASCII (default)</option>
@@ -90,6 +95,7 @@ const SightingDataFields = () => {
<Field <Field
as="select" as="select"
className="p-2 border border-gray-400 rounded-lg text-white bg-[#253445]" className="p-2 border border-gray-400 rounded-lg text-white bg-[#253445]"
name="countryCodeType"
> >
<option value="IBAN 2 Character code (default)"> <option value="IBAN 2 Character code (default)">
IBAN 2 Character code (default) IBAN 2 Character code (default)

View File

@@ -4,9 +4,11 @@ import { Outlet } from "react-router";
const Container = () => { const Container = () => {
return ( return (
<div> <div className="min-h-screen">
<Header /> <Header />
<Outlet /> <div className="min-h-screen">
<Outlet />
</div>
<Footer /> <Footer />
</div> </div>
); );

View File

@@ -90,16 +90,14 @@ export default function Header() {
const utcStr = formatFromMs(serverNowMs, "utc"); const utcStr = formatFromMs(serverNowMs, "utc");
return ( return (
<div className="relative bg-[#253445] border-b border-gray-500 items-center mx-auto px-2 sm:px-6 lg:px-8 p-4 flex flex-row justify-between"> <div className="relative bg-[#253445] border-b border-gray-500 items-center mx-auto px-2 sm:px-6 lg:px-8 p-4 flex flex-col md:flex-row justify-between">
{/* Left: Logo */}
<div className="w-30"> <div className="w-30">
<Link to={"/"}> <Link to={"/"}>
<img src={Logo} alt="Logo" width={150} height={150} /> <img src={Logo} alt="Logo" width={150} height={150} />
</Link> </Link>
</div> </div>
{/* Right: Texts stacked + icons */} <div className="flex flex-col md:flex-row items-center space-x-24 justify-items-center">
<div className="flex items-center space-x-24 "> <div className="flex flex-col leading-tight text-white tabular-nums text-xl text-right mx-auto md:mx-10">
<div className="flex flex-col leading-tight text-white tabular-nums text-xl text-right">
<h2>Local: {localStr}</h2> <h2>Local: {localStr}</h2>
<h2>UTC: {utcStr}</h2> <h2>UTC: {utcStr}</h2>
</div> </div>

View File

@@ -1,9 +1,11 @@
import { useRef, useCallback, useEffect } from "react"; import { useRef, useCallback, useEffect } from "react";
import { useQuery } from "@tanstack/react-query"; import { useQuery } from "@tanstack/react-query";
import { CAM_BASE } from "../utils/config";
const apiUrl = import.meta.env.VITE_LOCAL_BASE; const apiUrl = CAM_BASE;
async function fetchSnapshot(cameraSide: string) { async function fetchSnapshot(cameraSide: string) {
console.log(`${apiUrl}/${cameraSide}-preview`);
const response = await fetch(`${apiUrl}/${cameraSide}-preview`); const response = await fetch(`${apiUrl}/${cameraSide}-preview`);
if (!response.ok) { if (!response.ok) {
throw new Error("Cannot reach endpoint"); throw new Error("Cannot reach endpoint");