+
{children}
);
diff --git a/src/components/UI/Header.tsx b/src/components/UI/Header.tsx
index 204b671..fd84343 100644
--- a/src/components/UI/Header.tsx
+++ b/src/components/UI/Header.tsx
@@ -1,14 +1,19 @@
import { Link } from "react-router";
import Logo from "/MAV.svg";
+import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
+import { faSliders } from "@fortawesome/free-solid-svg-icons";
const Header = () => {
return (
-
+
);
};
diff --git a/src/context/NPEDUserContext.tsx b/src/context/NPEDUserContext.tsx
new file mode 100644
index 0000000..1acce93
--- /dev/null
+++ b/src/context/NPEDUserContext.tsx
@@ -0,0 +1,17 @@
+import { createContext, useContext, type SetStateAction } from "react";
+import type { NPEDUser } from "../types/types";
+
+type UserContextValue = {
+ user: NPEDUser | null;
+ setUser: React.Dispatch
>;
+};
+
+export const NPEDUserContext = createContext(
+ undefined
+);
+export const useNPEDContext = () => {
+ const ctx = useContext(NPEDUserContext);
+ if (!ctx)
+ throw new Error("useNPEDContext must be used within ");
+ return ctx;
+};
diff --git a/src/context/SightingFeedContext.tsx b/src/context/SightingFeedContext.tsx
index 7f4a1fa..69605c6 100644
--- a/src/context/SightingFeedContext.tsx
+++ b/src/context/SightingFeedContext.tsx
@@ -1,6 +1,5 @@
-import { createContext, useContext, type ReactNode } from "react";
+import { createContext, useContext } from "react";
import type { SightingWidgetType } from "../types/types";
-import { useSightingFeed } from "../hooks/useSightingFeed";
type SightingFeedContextType = {
sightings: (SightingWidgetType | null | undefined)[];
@@ -13,50 +12,10 @@ type SightingFeedContextType = {
noSighting: boolean;
};
-type SightingFeedProviderProps = {
- url: string;
- children: ReactNode;
- side: string;
-};
+export const SightingFeedContext = createContext<
+ SightingFeedContextType | undefined
+>(undefined);
-const SightingFeedContext = createContext(
- undefined
-);
-
-export const SightingFeedProvider = ({
- children,
- url,
- side,
-}: SightingFeedProviderProps) => {
- const {
- sightings,
- selectedRef,
- setSelectedRef,
- effectiveSelected,
- mostRecent,
- isPending,
- noSighting,
- } = useSightingFeed(url);
-
- return (
-
- {children}
-
- );
-};
-
-// eslint-disable-next-line react-refresh/only-export-components
export const useSightingFeedContext = () => {
const ctx = useContext(SightingFeedContext);
if (!ctx)
diff --git a/src/context/providers/NPEDUserContextProvider.tsx b/src/context/providers/NPEDUserContextProvider.tsx
new file mode 100644
index 0000000..b634c57
--- /dev/null
+++ b/src/context/providers/NPEDUserContextProvider.tsx
@@ -0,0 +1,17 @@
+import { useState, type ReactNode } from "react";
+import type { NPEDUser } from "../../types/types";
+import { NPEDUserContext } from "../NPEDUserContext";
+
+type NPEDUserProviderType = {
+ children: ReactNode;
+};
+
+export const NPEDUserProvider = ({ children }: NPEDUserProviderType) => {
+ const [user, setUser] = useState(null);
+
+ return (
+
+ {children}
+
+ );
+};
diff --git a/src/context/providers/SightingFeedProvider.tsx b/src/context/providers/SightingFeedProvider.tsx
new file mode 100644
index 0000000..a0708b1
--- /dev/null
+++ b/src/context/providers/SightingFeedProvider.tsx
@@ -0,0 +1,42 @@
+import type { ReactNode } from "react";
+import { useSightingFeed } from "../../hooks/useSightingFeed";
+import { SightingFeedContext } from "../SightingFeedContext";
+
+type SightingFeedProviderProps = {
+ url: string;
+ children: ReactNode;
+ side: string;
+};
+
+export const SightingFeedProvider = ({
+ children,
+ url,
+ side,
+}: SightingFeedProviderProps) => {
+ const {
+ sightings,
+ selectedRef,
+ setSelectedRef,
+ effectiveSelected,
+ mostRecent,
+ isPending,
+ noSighting,
+ } = useSightingFeed(url);
+
+ return (
+
+ {children}
+
+ );
+};
diff --git a/src/hooks/useNPEDAuh.ts b/src/hooks/useNPEDAuh.ts
deleted file mode 100644
index 258f90d..0000000
--- a/src/hooks/useNPEDAuh.ts
+++ /dev/null
@@ -1,49 +0,0 @@
-import { useMutation } from "@tanstack/react-query";
-import type { NPEDFieldType } from "../types/types";
-
-const url = "https://jsonplaceholder.typicode.com/posts";
-
-async function signIn(loginDetails: NPEDFieldType) {
- console.log(loginDetails);
- const response = await fetch(url, {
- method: "POST",
- body: JSON.stringify(loginDetails),
- });
- if (!response.ok) throw new Error("cannot reach NPED endpoint");
- return response.json();
-}
-
-async function signOut() {
- const response = await fetch(url, { method: "POST" });
- if (!response.ok) throw new Error("cannot reach NPED sign out endpoint");
- return response.json();
-}
-
-function setUserContext(user) {
- console.log(user);
-}
-
-export const useNPEDAuth = () => {
- const signInMutation = useMutation({
- mutationKey: ["NPEDSignin"],
- mutationFn: signIn,
- onSuccess: (data) => setUserContext(data),
- });
-
- const signOutMutation = useMutation({
- mutationKey: ["auth", "NPEDSignOut"],
- mutationFn: signOut,
- onSuccess: () => setUserContext(null),
- });
-
- return {
- signIn: signInMutation.mutate,
- signInAsync: signInMutation.mutateAsync,
- isPending: signInMutation.isPending,
- isError: signInMutation.isError,
- error: signInMutation.error,
- data: signInMutation.data,
-
- signOut: signOutMutation.mutate,
- };
-};
diff --git a/src/hooks/useNPEDAuth.ts b/src/hooks/useNPEDAuth.ts
new file mode 100644
index 0000000..fb93de6
--- /dev/null
+++ b/src/hooks/useNPEDAuth.ts
@@ -0,0 +1,85 @@
+import { useMutation } from "@tanstack/react-query";
+import type { NPEDFieldType } from "../types/types";
+import { useNPEDContext } from "../context/NPEDUserContext";
+
+const base_url = import.meta.env.VITE_OUTSIDE_BASEURL;
+
+async function signIn(loginDetails: NPEDFieldType) {
+ const { frontId, rearId, username, password, clientId } = loginDetails;
+
+ const NPEDLoginURLFront = `${base_url}/update-config?id=${frontId}`;
+ const NPEDLoginURLRear = `${base_url}/update-config?id=${rearId}`;
+
+ const frontCameraPayload = {
+ id: frontId,
+ fields: [
+ { property: "propEnabled", value: true },
+ { property: "propUsername", value: username },
+ { property: "propPassword", value: password },
+ { property: "propClientID", value: clientId },
+ ],
+ };
+
+ const rearCameraPayload = {
+ id: rearId,
+ fields: [
+ { property: "propEnabled", value: true },
+ { property: "propUsername", value: username },
+ { property: "propPassword", value: password },
+ { property: "propClientID", value: clientId },
+ ],
+ };
+
+ const frontCameraResponse = await fetch(NPEDLoginURLFront, {
+ method: "POST",
+ body: JSON.stringify(frontCameraPayload),
+ });
+
+ const rearCameraResponse = await fetch(NPEDLoginURLRear, {
+ method: "POST",
+ body: JSON.stringify(rearCameraPayload),
+ });
+
+ if (!frontCameraResponse.ok) throw new Error("cannot reach NPED endpoint");
+ if (!rearCameraResponse.ok) throw new Error("cannot reach NPED endpoint");
+
+ console.log(frontCameraResponse);
+ console.log(rearCameraResponse);
+ return {
+ frontResponse: frontCameraResponse.json(),
+ rearResponse: rearCameraResponse.json(),
+ };
+}
+
+async function signOut() {
+ const response = await fetch(url, { method: "POST" });
+ if (!response.ok) throw new Error("cannot reach NPED sign out endpoint");
+ return response.json();
+}
+
+export const useNPEDAuth = () => {
+ const { setUser } = useNPEDContext();
+
+ const signInMutation = useMutation({
+ mutationKey: ["NPEDSignin"],
+ mutationFn: signIn,
+ onSuccess: async (data) => setUser(await data.frontResponse),
+ });
+
+ const signOutMutation = useMutation({
+ mutationKey: ["auth", "NPEDSignOut"],
+ mutationFn: signOut,
+ onSuccess: () => setUser(null),
+ });
+
+ return {
+ signIn: signInMutation.mutate,
+ signInAsync: signInMutation.mutateAsync,
+ isPending: signInMutation.isPending,
+ isError: signInMutation.isError,
+ error: signInMutation.error,
+ data: signInMutation.data,
+
+ signOut: signOutMutation.mutate,
+ };
+};
diff --git a/src/pages/Dashboard.tsx b/src/pages/Dashboard.tsx
index ad38ba5..4ad4f56 100644
--- a/src/pages/Dashboard.tsx
+++ b/src/pages/Dashboard.tsx
@@ -2,7 +2,7 @@ import FrontCameraOverviewCard from "../components/FrontCameraOverview/FrontCame
import RearCameraOverviewCard from "../components/RearCameraOverview/RearCameraOverviewCard";
import SightingHistoryWidget from "../components/SightingsWidget/SightingWidget";
-import { SightingFeedProvider } from "../context/SightingFeedContext";
+import { SightingFeedProvider } from "../context/providers/SightingFeedProvider";
const Dashboard = () => {
return (
diff --git a/src/pages/SystemSettings.tsx b/src/pages/SystemSettings.tsx
index 6603d64..11ca42b 100644
--- a/src/pages/SystemSettings.tsx
+++ b/src/pages/SystemSettings.tsx
@@ -3,6 +3,7 @@ import "react-tabs/style/react-tabs.css";
import NPEDCard from "../components/SettingForms/NPED/NPEDCard";
import SettingForms from "../components/SettingForms/SettingForms/SettingForms";
import NPEDHotlistCard from "../components/SettingForms/NPED/NPEDHotlistCard";
+import { Toaster } from "sonner";
const SystemSettings = () => {
return (
@@ -24,6 +25,7 @@ const SystemSettings = () => {
+
);
};
diff --git a/src/types/types.ts b/src/types/types.ts
index 64b3e77..3ecc360 100644
--- a/src/types/types.ts
+++ b/src/types/types.ts
@@ -59,9 +59,11 @@ export type InitialValuesForm = {
};
export type NPEDFieldType = {
+ frontId: string;
username: string;
password: string;
clientId: string;
+ rearId: string;
};
export type HotlistUploadType = {
@@ -97,3 +99,15 @@ export type SightingWidgetType = {
overviewPlateRect?: [number, number, number, number]; // [x,y,w,h] normalized 0..1
plateTrack?: [number, number, number, number][]; // list of rects normalized 0..1
};
+
+export type NPEDUser = {
+ username: string;
+ clientId: string;
+ password?: string;
+};
+
+export type NPEDErrorValues = {
+ username?: string | undefined;
+ password?: string | undefined;
+ clientId?: string | undefined;
+};
diff --git a/vite.config.ts b/vite.config.ts
index 4ff4f8f..672fe08 100644
--- a/vite.config.ts
+++ b/vite.config.ts
@@ -5,4 +5,5 @@ import tailwindcss from "@tailwindcss/vite";
// https://vite.dev/config/
export default defineConfig({
plugins: [react(), tailwindcss()],
+ server: { host: true },
});