initial commit

This commit is contained in:
2025-08-13 14:23:48 +01:00
commit 92e3617335
44 changed files with 2936 additions and 0 deletions

View File

@@ -0,0 +1,22 @@
import { useEffect, useState } from "react";
export const useGetConfigs = () => {
const [configs, setConfigs] = useState(null);
const apiUrl = import.meta.env.VITE_BASEURL;
useEffect(() => {
async function getConfigs() {
try {
const response = await fetch(`${apiUrl}/api/config-ids`);
if (!response.ok) {
console.log("failed fetching");
}
const data = await response.json();
setConfigs(data);
} catch (error) {
console.log(error);
}
}
getConfigs();
}, [apiUrl]);
return { configs };
};

View File

@@ -0,0 +1,83 @@
import { useRef, useCallback, useEffect } from "react";
import { useQuery } from "@tanstack/react-query";
const apiUrl = import.meta.env.VITE_BASEURL;
async function fetchSnapshot(cameraSide: string) {
const response = await fetch(
`http://100.116.253.81/Colour-preview`
//`${apiUrl}/${cameraSide}-preview`
);
if (!response.ok) {
throw new Error("Cannot reach endpoint");
}
return await response.blob();
}
export function useGetOverviewSnapshot(cameraSide: string) {
const latestUrlRef = useRef<string | null>(null);
const canvasRef = useRef<HTMLCanvasElement | null>(null);
const imageRef = useRef<HTMLImageElement | null>(null);
const drawImage = useCallback(() => {
const canvas = canvasRef.current;
const ctx = canvas?.getContext("2d");
const img = imageRef.current;
if (!canvas || !ctx || !img) return;
canvas.width = canvas.clientWidth;
canvas.height = canvas.clientHeight;
ctx.drawImage(img, 0, 0, canvas.width, canvas.height);
}, []);
const {
data: snapshotBlob,
isError,
error,
} = useQuery({
queryKey: ["overviewSnapshot", cameraSide],
queryFn: () => fetchSnapshot(cameraSide),
refetchOnWindowFocus: false,
refetchInterval: 1000,
});
useEffect(() => {
if (!snapshotBlob) return;
const imgUrl = URL.createObjectURL(snapshotBlob);
const img = new Image();
imageRef.current = img;
img.onload = () => {
drawImage();
};
img.src = imgUrl;
if (latestUrlRef.current) {
URL.revokeObjectURL(latestUrlRef.current);
}
latestUrlRef.current = imgUrl;
return () => {
if (latestUrlRef.current) {
URL.revokeObjectURL(latestUrlRef.current);
latestUrlRef.current = null;
}
};
}, [snapshotBlob, drawImage]);
useEffect(() => {
window.addEventListener("resize", drawImage);
return () => {
window.removeEventListener("resize", drawImage);
};
}, [drawImage]);
if (isError) {
console.error("Snapshot error:", error);
}
return { canvasRef };
}

View File

@@ -0,0 +1,59 @@
import { useQuery } from "@tanstack/react-query";
import { useCallback, useEffect, useRef } from "react";
async function fetchSighting() {
const response = await fetch(
`http://100.116.253.81/mergedHistory/sightingSummary?mostRecentRef=-1`
);
if (!response.ok) throw new Error("Failed to fetch sighting");
return response.json();
}
export function useLatestSighting() {
const latestUrlRef = useRef<string | null>(null);
const canvasRef = useRef<HTMLCanvasElement | null>(null);
const sightingImageRef = useRef<HTMLImageElement | null>(null);
const drawImage = useCallback(() => {
const canvas = canvasRef.current;
const ctx = canvas?.getContext("2d");
const img2 = sightingImageRef.current;
if (!img2 || !canvas) return;
canvas.width = canvas.clientWidth;
canvas.height = canvas.clientHeight;
ctx?.drawImage(img2, 0, 0, 200, 50);
}, [sightingImageRef]);
const { data } = useQuery({
queryKey: ["latestSighting"],
queryFn: fetchSighting,
refetchInterval: 500,
});
useEffect(() => {
const img = new Image();
sightingImageRef.current = img;
img.onload = () => {
drawImage();
};
img.src = data?.plateUrlColour;
if (latestUrlRef.current) {
URL.revokeObjectURL(latestUrlRef.current);
}
latestUrlRef.current = img.src;
return () => {
if (latestUrlRef.current) {
URL.revokeObjectURL(latestUrlRef.current);
latestUrlRef.current = null;
}
};
}, [data?.plateUrlColour, drawImage]);
return { data, sightingImageRef, canvasRef };
}

View File

@@ -0,0 +1,33 @@
import { useQuery } from "@tanstack/react-query";
import { useRef } from "react";
const apiUrl = import.meta.env.VITE_BASEURL;
async function fetchOverviewImage(cameraSide: string) {
const response = await fetch(`${apiUrl}${cameraSide}-preview`);
if (!response.ok) throw new Error("could not fetch overview image");
return response.blob();
}
export function useOverviewVideo() {
const canvasRef = useRef<HTMLCanvasElement | null>(null);
const { isPending, isError, data } = useQuery({
queryKey: ["overviewVideo"],
queryFn: () => fetchOverviewImage("CameraFront"),
refetchInterval: 500,
});
if (isPending) return;
if (isError) return;
const img = new Image();
const imgUrl = URL.createObjectURL(data);
img.src = imgUrl;
const canvas = canvasRef.current;
if (!canvas) return;
const ctx = canvas.getContext("2d");
ctx?.drawImage(img, 0, 0);
}