- added modal for entry and exit sightings and plate patches
This commit is contained in:
@@ -152,7 +152,7 @@ const RegionSelector = ({
|
|||||||
|
|
||||||
colourMutation.mutate({ cameraFeedID, regions: regions });
|
colourMutation.mutate({ cameraFeedID, regions: regions });
|
||||||
|
|
||||||
// Convert Map to plain object for blackboard
|
// Convert map to plain object for blackboard
|
||||||
const serializableState = {
|
const serializableState = {
|
||||||
...state,
|
...state,
|
||||||
paintedCells: {
|
paintedCells: {
|
||||||
@@ -282,10 +282,16 @@ const RegionSelector = ({
|
|||||||
})}
|
})}
|
||||||
</>
|
</>
|
||||||
<div className="flex flex-col gap-4 mt-4">
|
<div className="flex flex-col gap-4 mt-4">
|
||||||
<button className="border border-blue-900 bg-blue-700 px-4 py-1 rounded-md" onClick={handleAddRegionClick}>
|
<button
|
||||||
|
className="border border-blue-900 bg-blue-700 px-4 py-1 rounded-md hover:bg-blue-800 hover:cursor-pointer"
|
||||||
|
onClick={handleAddRegionClick}
|
||||||
|
>
|
||||||
Add Bay
|
Add Bay
|
||||||
</button>
|
</button>
|
||||||
<button className="border border-red-900 bg-red-700 px-4 py-1 rounded-md" onClick={handleRemoveClick}>
|
<button
|
||||||
|
className="border border-red-900 bg-red-700 px-4 py-1 rounded-md hover:bg-red-800 hover:cursor-pointer"
|
||||||
|
onClick={handleRemoveClick}
|
||||||
|
>
|
||||||
Remove Bay
|
Remove Bay
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -1,73 +1,96 @@
|
|||||||
|
import { useState } from "react";
|
||||||
import { useCameraFeedContext } from "../../../../app/context/CameraFeedContext";
|
import { useCameraFeedContext } from "../../../../app/context/CameraFeedContext";
|
||||||
import type { DecodeReading } from "../../../../types/types";
|
import type { DecodeReading } from "../../../../types/types";
|
||||||
import { useSightingEntryAndExit } from "../../hooks/useSightingEntryAndExit";
|
import { useSightingEntryAndExit } from "../../hooks/useSightingEntryAndExit";
|
||||||
|
|
||||||
|
import PlatePatchModal from "./platePatchModal/PlatePatchModal";
|
||||||
|
|
||||||
const SightingEntryTable = () => {
|
const SightingEntryTable = () => {
|
||||||
const { state } = useCameraFeedContext();
|
const { state } = useCameraFeedContext();
|
||||||
|
const [isPlatePatchModalOpen, setIsPlatePatchModalOpen] = useState(false);
|
||||||
|
const [currentPatch, setCurrentPatch] = useState<DecodeReading | null>(null);
|
||||||
const cameraFeedID = state.cameraFeedID;
|
const cameraFeedID = state.cameraFeedID;
|
||||||
const { entryQuery } = useSightingEntryAndExit(cameraFeedID);
|
const { entryQuery } = useSightingEntryAndExit(cameraFeedID);
|
||||||
|
|
||||||
const isLoading = entryQuery?.isFetching;
|
const isLoading = entryQuery?.isFetching;
|
||||||
const readings = entryQuery?.data?.decodes;
|
const readings = entryQuery?.data?.decodes;
|
||||||
|
|
||||||
|
const handleRowClick = (reading: DecodeReading) => {
|
||||||
|
setCurrentPatch(reading);
|
||||||
|
setIsPlatePatchModalOpen(true);
|
||||||
|
};
|
||||||
|
|
||||||
if (isLoading) return <span className="text-slate-500">Loading Sighting data…</span>;
|
if (isLoading) return <span className="text-slate-500">Loading Sighting data…</span>;
|
||||||
return (
|
return (
|
||||||
<div className="border border-gray-600 rounded-lg m-2">
|
<>
|
||||||
{/* Desktop Table */}
|
<div className="border border-gray-600 rounded-lg m-2">
|
||||||
<div className="hidden md:block overflow-y-auto">
|
{/* Desktop Table */}
|
||||||
<table className="w-full text-left text-sm">
|
<div className="hidden md:block overflow-y-auto">
|
||||||
<thead className="bg-gray-700/50 text-gray-200 sticky top-0">
|
<table className="w-full text-left text-sm">
|
||||||
<tr>
|
<thead className="bg-gray-700/50 text-gray-200 sticky top-0">
|
||||||
<th className="px-4 py-3 font-semibold">VRM</th>
|
<tr>
|
||||||
<th className="px-4 py-3 font-semibold">Bay ID</th>
|
<th className="px-4 py-3 font-semibold">VRM</th>
|
||||||
<th className="px-4 py-3 font-semibold text-center">Seen Count</th>
|
<th className="px-4 py-3 font-semibold">Bay ID</th>
|
||||||
<th className="px-4 py-3 font-semibold">First Seen</th>
|
<th className="px-4 py-3 font-semibold text-center">Seen Count</th>
|
||||||
<th className="px-4 py-3 font-semibold">Last Seen</th>
|
<th className="px-4 py-3 font-semibold">First Seen</th>
|
||||||
</tr>
|
<th className="px-4 py-3 font-semibold">Last Seen</th>
|
||||||
</thead>
|
|
||||||
<tbody className="divide-y divide-gray-700">
|
|
||||||
{readings?.map((reading: DecodeReading) => (
|
|
||||||
<tr className="hover:bg-gray-800/30 transition-colors" key={reading?.id}>
|
|
||||||
<td className="px-4 py-3 font-mono font-semibold text-blue-400 text-lg">{reading?.vrm}</td>
|
|
||||||
<td className="px-4 py-3 text-gray-300">{reading?.laneID}</td>
|
|
||||||
<td className="px-4 py-3 text-center text-gray-300">{reading?.seenCount}</td>
|
|
||||||
<td className="px-4 py-3 text-gray-400 text-md">{reading?.firstSeenTimeHumane}</td>
|
|
||||||
<td className="px-4 py-3 text-gray-400 text-md">{reading?.lastSeenTimeHumane}</td>
|
|
||||||
</tr>
|
</tr>
|
||||||
))}
|
</thead>
|
||||||
</tbody>
|
<tbody className="divide-y divide-gray-700">
|
||||||
</table>
|
{readings?.map((reading: DecodeReading) => (
|
||||||
</div>
|
<tr
|
||||||
|
className="hover:bg-gray-800/30 transition-colors hover:cursor-pointer"
|
||||||
|
key={reading?.id}
|
||||||
|
onClick={() => handleRowClick(reading)}
|
||||||
|
>
|
||||||
|
<td className="px-4 py-3 font-mono font-semibold text-blue-400 text-lg">{reading?.vrm}</td>
|
||||||
|
<td className="px-4 py-3 text-gray-300">{reading?.laneID}</td>
|
||||||
|
<td className="px-4 py-3 text-center text-gray-300">{reading?.seenCount}</td>
|
||||||
|
<td className="px-4 py-3 text-gray-400 text-md">{reading?.firstSeenTimeHumane}</td>
|
||||||
|
<td className="px-4 py-3 text-gray-400 text-md">{reading?.lastSeenTimeHumane}</td>
|
||||||
|
</tr>
|
||||||
|
))}
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
|
||||||
{/* Mobile Cards */}
|
{/* Mobile */}
|
||||||
<div className="md:hidden overflow-y-auto space-y-3 p-3">
|
<div className="md:hidden overflow-y-auto space-y-3 p-3">
|
||||||
{readings?.map((reading: DecodeReading) => (
|
{readings?.map((reading: DecodeReading) => (
|
||||||
<div
|
<div
|
||||||
key={reading?.id}
|
key={reading?.id}
|
||||||
className="bg-gray-800/30 rounded-lg p-4 space-y-2 border border-gray-700 hover:border-gray-600 transition-colors"
|
className="bg-gray-800/30 rounded-lg p-4 space-y-2 border border-gray-700 hover:border-gray-600 transition-colors"
|
||||||
>
|
onClick={() => handleRowClick(reading)}
|
||||||
<div className="flex justify-between items-start">
|
>
|
||||||
<span className="font-mono font-semibold text-blue-400 text-xl">{reading?.vrm}</span>
|
<div className="flex justify-between items-start">
|
||||||
<span className="text-gray-400 text-sm">Bay {reading?.laneID}</span>
|
<span className="font-mono font-semibold text-blue-400 text-xl">{reading?.vrm}</span>
|
||||||
</div>
|
<span className="text-gray-400 text-sm">Bay {reading?.laneID}</span>
|
||||||
<div className="flex justify-between text-sm">
|
|
||||||
<span className="text-gray-400">Seen Count:</span>
|
|
||||||
<span className="text-gray-300 font-semibold">{reading?.seenCount}</span>
|
|
||||||
</div>
|
|
||||||
<div className="pt-2 border-t border-gray-700 space-y-1 text-xs">
|
|
||||||
<div className="flex justify-between">
|
|
||||||
<span className="text-gray-500">First Seen:</span>
|
|
||||||
<span className="text-gray-400">{reading?.firstSeenTimeHumane}</span>
|
|
||||||
</div>
|
</div>
|
||||||
<div className="flex justify-between">
|
<div className="flex justify-between text-sm">
|
||||||
<span className="text-gray-500">Last Seen:</span>
|
<span className="text-gray-400">Seen Count:</span>
|
||||||
<span className="text-gray-400">{reading?.lastSeenTimeHumane}</span>
|
<span className="text-gray-300 font-semibold">{reading?.seenCount}</span>
|
||||||
|
</div>
|
||||||
|
<div className="pt-2 border-t border-gray-700 space-y-1 text-xs">
|
||||||
|
<div className="flex justify-between">
|
||||||
|
<span className="text-gray-500">First Seen:</span>
|
||||||
|
<span className="text-gray-400">{reading?.firstSeenTimeHumane}</span>
|
||||||
|
</div>
|
||||||
|
<div className="flex justify-between">
|
||||||
|
<span className="text-gray-500">Last Seen:</span>
|
||||||
|
<span className="text-gray-400">{reading?.lastSeenTimeHumane}</span>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
))}
|
||||||
))}
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
<PlatePatchModal
|
||||||
|
isPlatePatchModalOpen={isPlatePatchModalOpen}
|
||||||
|
handleClose={() => setIsPlatePatchModalOpen(false)}
|
||||||
|
currentPatch={currentPatch}
|
||||||
|
direction={"entry"}
|
||||||
|
/>
|
||||||
|
</>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -1,8 +1,12 @@
|
|||||||
|
import { useState } from "react";
|
||||||
import { useCameraFeedContext } from "../../../../app/context/CameraFeedContext";
|
import { useCameraFeedContext } from "../../../../app/context/CameraFeedContext";
|
||||||
import type { DecodeReading } from "../../../../types/types";
|
import type { DecodeReading } from "../../../../types/types";
|
||||||
import { useSightingEntryAndExit } from "../../hooks/useSightingEntryAndExit";
|
import { useSightingEntryAndExit } from "../../hooks/useSightingEntryAndExit";
|
||||||
|
import PlatePatchModal from "./platePatchModal/PlatePatchModal";
|
||||||
|
|
||||||
const SightingExitTable = () => {
|
const SightingExitTable = () => {
|
||||||
|
const [isPlatePatchModalOpen, setIsPlatePatchModalOpen] = useState(false);
|
||||||
|
const [currentPatch, setCurrentPatch] = useState<DecodeReading | null>(null);
|
||||||
const { state } = useCameraFeedContext();
|
const { state } = useCameraFeedContext();
|
||||||
const cameraFeedID = state.cameraFeedID;
|
const cameraFeedID = state.cameraFeedID;
|
||||||
const { exitQuery } = useSightingEntryAndExit(cameraFeedID);
|
const { exitQuery } = useSightingEntryAndExit(cameraFeedID);
|
||||||
@@ -10,64 +14,82 @@ const SightingExitTable = () => {
|
|||||||
const isLoading = exitQuery?.isFetching;
|
const isLoading = exitQuery?.isFetching;
|
||||||
const readings = exitQuery?.data?.decodes;
|
const readings = exitQuery?.data?.decodes;
|
||||||
|
|
||||||
|
const handleRowClick = (reading: DecodeReading) => {
|
||||||
|
setCurrentPatch(reading);
|
||||||
|
setIsPlatePatchModalOpen(true);
|
||||||
|
};
|
||||||
|
|
||||||
if (isLoading) return <span className="text-slate-500">Loading Sighting data…</span>;
|
if (isLoading) return <span className="text-slate-500">Loading Sighting data…</span>;
|
||||||
return (
|
return (
|
||||||
<div className="border border-gray-600 rounded-lg m-2">
|
<>
|
||||||
{/* Desktop Table */}
|
<div className="border border-gray-600 rounded-lg m-2">
|
||||||
<div className="hidden md:block overflow-y-auto">
|
{/* Desktop Table */}
|
||||||
<table className="w-full text-left text-sm">
|
<div className="hidden md:block overflow-y-auto">
|
||||||
<thead className="bg-gray-700/50 text-gray-200 sticky top-0">
|
<table className="w-full text-left text-sm">
|
||||||
<tr>
|
<thead className="bg-gray-700/50 text-gray-200 sticky top-0">
|
||||||
<th className="px-4 py-3 font-semibold">VRM</th>
|
<tr>
|
||||||
<th className="px-4 py-3 font-semibold">Bay ID</th>
|
<th className="px-4 py-3 font-semibold">VRM</th>
|
||||||
<th className="px-4 py-3 font-semibold text-center">Seen Count</th>
|
<th className="px-4 py-3 font-semibold">Bay ID</th>
|
||||||
<th className="px-4 py-3 font-semibold">First Seen</th>
|
<th className="px-4 py-3 font-semibold text-center">Seen Count</th>
|
||||||
<th className="px-4 py-3 font-semibold">Last Seen</th>
|
<th className="px-4 py-3 font-semibold">First Seen</th>
|
||||||
</tr>
|
<th className="px-4 py-3 font-semibold">Last Seen</th>
|
||||||
</thead>
|
|
||||||
<tbody className="divide-y divide-gray-700">
|
|
||||||
{readings?.map((reading: DecodeReading) => (
|
|
||||||
<tr className="hover:bg-gray-800/30 transition-colors" key={reading?.id}>
|
|
||||||
<td className="px-4 py-3 font-mono font-semibold text-red-400 text-lg">{reading?.vrm}</td>
|
|
||||||
<td className="px-4 py-3 text-gray-300">{reading?.laneID}</td>
|
|
||||||
<td className="px-4 py-3 text-center text-gray-300">{reading?.seenCount}</td>
|
|
||||||
<td className="px-4 py-3 text-gray-400 text-md">{reading?.firstSeenTimeHumane}</td>
|
|
||||||
<td className="px-4 py-3 text-gray-400 text-md">{reading?.lastSeenTimeHumane}</td>
|
|
||||||
</tr>
|
</tr>
|
||||||
))}
|
</thead>
|
||||||
</tbody>
|
<tbody className="divide-y divide-gray-700">
|
||||||
</table>
|
{readings?.map((reading: DecodeReading) => (
|
||||||
</div>
|
<tr
|
||||||
|
className="hover:bg-gray-800/30 transition-colors hover:cursor-pointer"
|
||||||
|
key={reading?.id}
|
||||||
|
onClick={() => handleRowClick(reading)}
|
||||||
|
>
|
||||||
|
<td className="px-4 py-3 font-mono font-semibold text-red-400 text-lg">{reading?.vrm}</td>
|
||||||
|
<td className="px-4 py-3 text-gray-300">{reading?.laneID}</td>
|
||||||
|
<td className="px-4 py-3 text-center text-gray-300">{reading?.seenCount}</td>
|
||||||
|
<td className="px-4 py-3 text-gray-400 text-md">{reading?.firstSeenTimeHumane}</td>
|
||||||
|
<td className="px-4 py-3 text-gray-400 text-md">{reading?.lastSeenTimeHumane}</td>
|
||||||
|
</tr>
|
||||||
|
))}
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
|
||||||
{/* Mobile Cards */}
|
{/* Mobile Cards */}
|
||||||
<div className="md:hidden overflow-y-auto space-y-3 p-3">
|
<div className="md:hidden overflow-y-auto space-y-3 p-3">
|
||||||
{readings?.map((reading: DecodeReading) => (
|
{readings?.map((reading: DecodeReading) => (
|
||||||
<div
|
<div
|
||||||
key={reading?.id}
|
key={reading?.id}
|
||||||
className="bg-gray-800/30 rounded-lg p-4 space-y-2 border border-gray-700 hover:border-gray-600 transition-colors"
|
className="bg-gray-800/30 rounded-lg p-4 space-y-2 border border-gray-700 hover:border-gray-600 transition-colors"
|
||||||
>
|
onClick={() => handleRowClick(reading)}
|
||||||
<div className="flex justify-between items-start">
|
>
|
||||||
<span className="font-mono font-semibold text-red-400 text-xl">{reading?.vrm}</span>
|
<div className="flex justify-between items-start">
|
||||||
<span className="text-gray-400 text-sm">Bay {reading?.laneID}</span>
|
<span className="font-mono font-semibold text-red-400 text-xl">{reading?.vrm}</span>
|
||||||
</div>
|
<span className="text-gray-400 text-sm">Bay {reading?.laneID}</span>
|
||||||
<div className="flex justify-between text-sm">
|
|
||||||
<span className="text-gray-400">Seen Count:</span>
|
|
||||||
<span className="text-gray-300 font-semibold">{reading?.seenCount}</span>
|
|
||||||
</div>
|
|
||||||
<div className="pt-2 border-t border-gray-700 space-y-1 text-xs">
|
|
||||||
<div className="flex justify-between">
|
|
||||||
<span className="text-gray-500">First Seen:</span>
|
|
||||||
<span className="text-gray-400">{reading?.firstSeenTimeHumane}</span>
|
|
||||||
</div>
|
</div>
|
||||||
<div className="flex justify-between">
|
<div className="flex justify-between text-sm">
|
||||||
<span className="text-gray-500">Last Seen:</span>
|
<span className="text-gray-400">Seen Count:</span>
|
||||||
<span className="text-gray-400">{reading?.lastSeenTimeHumane}</span>
|
<span className="text-gray-300 font-semibold">{reading?.seenCount}</span>
|
||||||
|
</div>
|
||||||
|
<div className="pt-2 border-t border-gray-700 space-y-1 text-xs">
|
||||||
|
<div className="flex justify-between">
|
||||||
|
<span className="text-gray-500">First Seen:</span>
|
||||||
|
<span className="text-gray-400">{reading?.firstSeenTimeHumane}</span>
|
||||||
|
</div>
|
||||||
|
<div className="flex justify-between">
|
||||||
|
<span className="text-gray-500">Last Seen:</span>
|
||||||
|
<span className="text-gray-400">{reading?.lastSeenTimeHumane}</span>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
))}
|
||||||
))}
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
<PlatePatchModal
|
||||||
|
isPlatePatchModalOpen={isPlatePatchModalOpen}
|
||||||
|
handleClose={() => setIsPlatePatchModalOpen(false)}
|
||||||
|
currentPatch={currentPatch}
|
||||||
|
direction={"exit"}
|
||||||
|
/>
|
||||||
|
</>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,20 @@
|
|||||||
|
import type { DecodeReading } from "../../../../../types/types";
|
||||||
|
import ModalComponent from "../../../../../ui/ModalComponent";
|
||||||
|
import PlatePatchModalContent from "./PlatePatchModalContent";
|
||||||
|
|
||||||
|
type PlatePatchModalProps = {
|
||||||
|
isPlatePatchModalOpen: boolean;
|
||||||
|
handleClose: () => void;
|
||||||
|
currentPatch: DecodeReading | null;
|
||||||
|
direction?: "entry" | "exit";
|
||||||
|
};
|
||||||
|
|
||||||
|
const PlatePatchModal = ({ isPlatePatchModalOpen, handleClose, currentPatch, direction }: PlatePatchModalProps) => {
|
||||||
|
return (
|
||||||
|
<ModalComponent isModalOpen={isPlatePatchModalOpen} close={handleClose}>
|
||||||
|
<PlatePatchModalContent currentPatch={currentPatch} direction={direction} />
|
||||||
|
</ModalComponent>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default PlatePatchModal;
|
||||||
@@ -0,0 +1,64 @@
|
|||||||
|
import type { DecodeReading } from "../../../../../types/types";
|
||||||
|
|
||||||
|
type PlatePatchModalContentProps = {
|
||||||
|
currentPatch: DecodeReading | null;
|
||||||
|
direction?: "entry" | "exit";
|
||||||
|
};
|
||||||
|
|
||||||
|
const PlatePatchModalContent = ({ currentPatch, direction }: PlatePatchModalContentProps) => {
|
||||||
|
const imageSrc = `data:image/png;base64,${currentPatch?.plate || ""}`;
|
||||||
|
const imageUrl = currentPatch ? imageSrc : "";
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="space-y-4">
|
||||||
|
<div className="flex items-center justify-between border-b border-gray-600 pb-3">
|
||||||
|
<h2
|
||||||
|
className={`font-mono font-bold text-3xl tracking-wide
|
||||||
|
${direction === "entry" ? "text-blue-400" : "text-red-400"}`}
|
||||||
|
>
|
||||||
|
{currentPatch?.vrm}
|
||||||
|
</h2>
|
||||||
|
<span
|
||||||
|
className={`px-3 py-1 rounded-full text-xs font-semibold uppercase
|
||||||
|
${direction === "entry" ? "bg-blue-500/20 text-blue-400" : "bg-red-500/20 text-red-400"}`}
|
||||||
|
>
|
||||||
|
{direction === "entry" ? "Entry" : "Exit"}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="border border-gray-600 rounded-2xl">
|
||||||
|
<div className="flex bg-gray-800/50 rounded-lg p-4">
|
||||||
|
<img
|
||||||
|
src={imageUrl}
|
||||||
|
alt={`${direction === "entry" ? "Entry" : "Exit"} Image for ${currentPatch?.vrm || "N/A"}`}
|
||||||
|
className="rounded-lg border border-gray-600 max-w-full h-auto shadow-lg"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="grid grid-cols-2 gap-4 bg-gray-800/30 rounded-lg p-4">
|
||||||
|
<div className="space-y-1">
|
||||||
|
<p className="text-gray-400 text-xs uppercase tracking-wider">Bay ID</p>
|
||||||
|
<p className="text-gray-200 font-semibold text-lg">{currentPatch?.laneID || "N/A"}</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="space-y-1">
|
||||||
|
<p className="text-gray-400 text-xs uppercase tracking-wider">Seen Count</p>
|
||||||
|
<p className="text-gray-200 font-semibold text-lg">{currentPatch?.seenCount || "N/A"}</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="space-y-1 col-span-2">
|
||||||
|
<p className="text-gray-400 text-xs uppercase tracking-wider">First Seen</p>
|
||||||
|
<p className="text-gray-300 text-sm">{currentPatch?.firstSeenTimeHumane || "N/A"}</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="space-y-1 col-span-2">
|
||||||
|
<p className="text-gray-400 text-xs uppercase tracking-wider">Last Seen</p>
|
||||||
|
<p className="text-gray-300 text-sm">{currentPatch?.lastSeenTimeHumane || "N/A"}</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default PlatePatchModalContent;
|
||||||
@@ -35,12 +35,12 @@ const VideoFeedGridPainter = () => {
|
|||||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||||
const stageRef = useRef<any>(null);
|
const stageRef = useRef<any>(null);
|
||||||
|
|
||||||
const currentScale = stageSize.width / BACKEND_WIDTH;
|
|
||||||
const size = BACKEND_CELL_SIZE * currentScale;
|
|
||||||
|
|
||||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||||
const paintLayerRef = useRef<any>(null);
|
const paintLayerRef = useRef<any>(null);
|
||||||
|
|
||||||
|
const currentScale = stageSize.width / BACKEND_WIDTH;
|
||||||
|
const size = BACKEND_CELL_SIZE * currentScale;
|
||||||
|
|
||||||
const cameraASocket = useCameraFeedASocket();
|
const cameraASocket = useCameraFeedASocket();
|
||||||
const cameraBSocket = useCameraFeedBSocket();
|
const cameraBSocket = useCameraFeedBSocket();
|
||||||
const cameraCSocket = useCameraFeedCSocket();
|
const cameraCSocket = useCameraFeedCSocket();
|
||||||
|
|||||||
@@ -202,6 +202,7 @@ export type DecodeReading = {
|
|||||||
duplicate?: true;
|
duplicate?: true;
|
||||||
firstSeenTimeHumane: string;
|
firstSeenTimeHumane: string;
|
||||||
lastSeenTimeHumane: string;
|
lastSeenTimeHumane: string;
|
||||||
|
plate?: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
export type ColourData = {
|
export type ColourData = {
|
||||||
|
|||||||
@@ -26,7 +26,7 @@ const ModalComponent = ({ isModalOpen, children, close }: ModalComponentProps) =
|
|||||||
<div className="flex justify-end">
|
<div className="flex justify-end">
|
||||||
<button
|
<button
|
||||||
onClick={close}
|
onClick={close}
|
||||||
className="bg-gray-700 hover:bg-gray-600 text-white font-bold py-2 px-4 rounded-lg mb-4"
|
className="bg-gray-700 hover:bg-gray-600 text-white font-bold py-2 px-4 rounded-lg mb-4 hover:cursor-pointer"
|
||||||
>
|
>
|
||||||
Close
|
Close
|
||||||
</button>
|
</button>
|
||||||
|
|||||||
Reference in New Issue
Block a user