got to a good point with sighting modal, want to do cleanup
This commit is contained in:
32
src/components/SightingsWidget/InfoBar.tsx
Normal file
32
src/components/SightingsWidget/InfoBar.tsx
Normal file
@@ -0,0 +1,32 @@
|
||||
import type { SightingType, SightingWidgetType } from "../../types/types";
|
||||
import { capitalize, formatAge } from "../../utils/utils";
|
||||
|
||||
type InfoBarprops = {
|
||||
obj: SightingWidgetType | SightingType;
|
||||
};
|
||||
const InfoBar = ({ obj }: InfoBarprops) => {
|
||||
const isNPEDHit = obj?.metadata?.npedJSON?.status_code === 404;
|
||||
return (
|
||||
<div className="flex items-center gap-3 text-xs bg-neutral-900 px-2 py-1 rounded justify-between">
|
||||
<div className="flex items-center gap-3 text-xs">
|
||||
{" "}
|
||||
<div className="min-w-14">CH: {obj ? obj.charHeight : "—"}</div>
|
||||
<div className="min-w-14">Seen: {obj ? obj.seenCount : "—"}</div>
|
||||
<div className="min-w-20">{obj ? capitalize(obj.motion) : "—"}</div>
|
||||
<div className="min-w-14 opacity-80">
|
||||
{obj ? formatAge(obj.timeStampMillis) : "—"}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="min-w-14 opacity-80 ">
|
||||
{isNPEDHit ? (
|
||||
<span className="text-red-500 font-semibold">NPED HIT</span>
|
||||
) : (
|
||||
""
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default InfoBar;
|
||||
@@ -1,12 +1,14 @@
|
||||
import { useCallback, useEffect, useMemo, useState } from "react";
|
||||
import type { SightingType, SightingWidgetType } from "../../types/types";
|
||||
import { BLANK_IMG, capitalize, formatAge } from "../../utils/utils";
|
||||
import { BLANK_IMG } from "../../utils/utils";
|
||||
import NumberPlate from "../PlateStack/NumberPlate";
|
||||
import Card from "../UI/Card";
|
||||
import CardHeader from "../UI/CardHeader";
|
||||
import clsx from "clsx";
|
||||
import { useSightingFeedContext } from "../../context/SightingFeedContext";
|
||||
import SightingModal from "../SightingModal/SightingModal";
|
||||
import { useAlertHitContext } from "../../context/AlertHitContext";
|
||||
import InfoBar from "./InfoBar";
|
||||
|
||||
function useNow(tickMs = 1000) {
|
||||
const [, setNow] = useState(() => Date.now());
|
||||
@@ -42,6 +44,8 @@ export default function SightingHistoryWidget({
|
||||
selectedSighting,
|
||||
} = useSightingFeedContext();
|
||||
|
||||
const { disptach } = useAlertHitContext();
|
||||
|
||||
const onRowClick = useCallback(
|
||||
(sighting: SightingType | SightingWidgetType) => {
|
||||
if (!sighting) return;
|
||||
@@ -54,6 +58,20 @@ export default function SightingHistoryWidget({
|
||||
() => sightings?.filter(Boolean) as SightingWidgetType[],
|
||||
[sightings]
|
||||
);
|
||||
|
||||
useEffect(() => {
|
||||
rows?.forEach((obj) => {
|
||||
const isNPEDHit = obj?.metadata?.npedJSON?.status_code === 404;
|
||||
|
||||
if (isNPEDHit) {
|
||||
disptach({
|
||||
type: "ADD",
|
||||
payload: obj,
|
||||
});
|
||||
}
|
||||
});
|
||||
}, [rows, disptach]);
|
||||
|
||||
const handleClose = () => {
|
||||
setSightingModalOpen(false);
|
||||
};
|
||||
@@ -69,6 +87,7 @@ export default function SightingHistoryWidget({
|
||||
const motionAway = (obj?.motion ?? "").toUpperCase() === "AWAY";
|
||||
const primaryIsColour = obj?.srcCam === 1;
|
||||
const secondaryMissing = (obj?.vrmSecondary ?? "") === "";
|
||||
|
||||
return (
|
||||
<div
|
||||
key={idx}
|
||||
@@ -76,52 +95,29 @@ export default function SightingHistoryWidget({
|
||||
onClick={() => onRowClick(obj)}
|
||||
>
|
||||
{/* Info bar */}
|
||||
<div className="flex items-center gap-3 text-xs bg-neutral-900 px-2 py-1 rounded justify-between">
|
||||
<div className="flex items-center gap-3 text-xs">
|
||||
{" "}
|
||||
<div className="min-w-14">
|
||||
CH: {obj ? obj.charHeight : "—"}
|
||||
</div>
|
||||
<div className="min-w-14">
|
||||
Seen: {obj ? obj.seenCount : "—"}
|
||||
</div>
|
||||
<div className="min-w-20">
|
||||
{obj ? capitalize(obj.motion) : "—"}
|
||||
</div>
|
||||
<div className="min-w-14 opacity-80">
|
||||
{obj ? formatAge(obj.timeStampMillis) : "—"}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="min-w-14 opacity-80 ">
|
||||
{isNPEDHit ? (
|
||||
<span className="text-red-500 font-semibold">
|
||||
NPED HIT
|
||||
</span>
|
||||
) : (
|
||||
""
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
<InfoBar obj={obj} />
|
||||
|
||||
{/* Patch row */}
|
||||
<div
|
||||
className={`flex items-center gap-3 mt-2
|
||||
className={`flex items-center gap-3 mt-2 justify-between
|
||||
${isNPEDHit ? "border border-red-600" : ""}
|
||||
`}
|
||||
>
|
||||
<div
|
||||
className={`border p-1 ${
|
||||
primaryIsColour ? "" : "ring-2 ring-lime-400"
|
||||
} ${!obj ? "opacity-30" : ""}`}
|
||||
>
|
||||
<img
|
||||
src={obj?.plateUrlInfrared || BLANK_IMG}
|
||||
height={48}
|
||||
alt="infrared patch"
|
||||
className={!primaryIsColour ? "" : "opacity-60"}
|
||||
/>
|
||||
</div>
|
||||
{obj?.plateUrlInfrared && (
|
||||
<div
|
||||
className={`border p-1 ${
|
||||
primaryIsColour ? "" : "ring-2 ring-lime-400"
|
||||
} ${!obj ? "opacity-30" : ""}`}
|
||||
>
|
||||
<img
|
||||
src={obj?.plateUrlInfrared || BLANK_IMG}
|
||||
height={48}
|
||||
alt="infrared patch"
|
||||
className={!primaryIsColour ? "" : "opacity-60"}
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
|
||||
<div
|
||||
className={`border p-1 ${
|
||||
primaryIsColour ? "ring-2 ring-lime-400" : ""
|
||||
|
||||
Reference in New Issue
Block a user