diff --git a/src/components/PopupSettings/NPEDCategoryPopup.tsx b/src/components/PopupSettings/NPEDCategoryPopup.tsx new file mode 100644 index 0000000..0fa7129 --- /dev/null +++ b/src/components/PopupSettings/NPEDCategoryPopup.tsx @@ -0,0 +1,67 @@ +import Card from "../UI/Card"; +import CardHeader from "../UI/CardHeader"; +import NPEDCatToggle from "../SettingForms/NPED/NPEDCatToggle"; +import FormGroup from "../SettingForms/components/FormGroup"; +import { Form, Formik } from "formik"; +import { useIntegrationsContext } from "../../context/IntegrationsContext"; +import { useCameraBlackboard } from "../../hooks/useCameraBlackboard"; +import type { CategoryPopups } from "../../types/types"; +import { toast } from "sonner"; + +const NPEDCategoryPopup = () => { + const { state, dispatch } = useIntegrationsContext(); + const { mutation } = useCameraBlackboard(); + + const isCatAEnabled = state?.iscatEnabled?.catA; + const isCatBEnabled = state?.iscatEnabled?.catB; + const isCatCEnabled = state?.iscatEnabled?.catC; + const isCatDEnabled = state?.iscatEnabled?.catD; + + const initialValues = { + catA: isCatAEnabled ?? true, + catB: isCatBEnabled ?? true, + catC: isCatCEnabled ?? true, + catD: isCatDEnabled ?? false, + }; + + const handleSubmit = async (values: CategoryPopups) => { + const result = await mutation.mutateAsync({ + operation: "INSERT", + value: values, + path: "CategoryPopup", + }); + if (result?.reason === "OK") toast.success("Pop up settings saved"); + dispatch({ type: "NPEDCATENABLED", payload: values }); + }; + + return ( + + + Allows alerts to pop up to user. + + + + + + + + + + + + + + + + Save + + + + + ); +}; + +export default NPEDCategoryPopup; diff --git a/src/components/SettingForms/Channel1-JSON/ChannelFields.tsx b/src/components/SettingForms/Channel1-JSON/ChannelFields.tsx index 36b505f..e837821 100644 --- a/src/components/SettingForms/Channel1-JSON/ChannelFields.tsx +++ b/src/components/SettingForms/Channel1-JSON/ChannelFields.tsx @@ -234,7 +234,7 @@ const ChannelFields = ({ touched, isSubmitting, format }: ChannelFieldsProps) => {isSubmitting ? "Saving..." : "Save Changes"} diff --git a/src/components/SettingForms/NPED/NPEDCard.tsx b/src/components/SettingForms/NPED/NPEDCard.tsx index a8b2474..34a00a1 100644 --- a/src/components/SettingForms/NPED/NPEDCard.tsx +++ b/src/components/SettingForms/NPED/NPEDCard.tsx @@ -6,7 +6,7 @@ import NPEDIcon from "/NPED.svg"; const NPEDCard = () => { return ( - + ); diff --git a/src/components/SettingForms/NPED/NPEDCatToggle.tsx b/src/components/SettingForms/NPED/NPEDCatToggle.tsx new file mode 100644 index 0000000..d8a627b --- /dev/null +++ b/src/components/SettingForms/NPED/NPEDCatToggle.tsx @@ -0,0 +1,22 @@ +import { Field } from "formik"; + +type NPEDToggleProps = { + name: string; + label: string; +}; + +const NPEDCatToggle = ({ name, label }: NPEDToggleProps) => { + return ( + + {label} + + + + ); +}; + +export default NPEDCatToggle; diff --git a/src/components/SettingForms/NPED/NPEDFields.tsx b/src/components/SettingForms/NPED/NPEDFields.tsx index 795c074..7beb06a 100644 --- a/src/components/SettingForms/NPED/NPEDFields.tsx +++ b/src/components/SettingForms/NPED/NPEDFields.tsx @@ -13,21 +13,19 @@ const NPEDFields = () => { const [showPwd, setShowPwd] = useState(false); const { signIn, signOut } = useNPEDAuth(); - const initialValues = state.npedUser - ? { - username: state.npedUser?.propUsername?.value, - password: state.npedUser?.propPassword?.value, - clientId: state.npedUser?.propClientID?.value, - frontId: "NPED", - rearId: "NPED", - } - : { - username: "", - password: "", - clientId: "", - frontId: "NPED", - rearId: "NPED", - }; + const username = state.npedUser?.propUsername?.value; + const password = state.npedUser?.propPassword?.value; + const clientId = state.npedUser?.propClientID?.value; + const frontId = "NPED"; + const rearId = "NPED"; + + const initialValues = { + username: username ?? "", + password: password ?? "", + clientId: clientId ?? "", + frontId: frontId, + rearId: rearId, + }; const handleSubmit = async (values: NPEDFieldType) => { const valuesToSend = { @@ -100,17 +98,18 @@ const NPEDFields = () => { className="p-1.5 border border-gray-400 rounded-lg" /> + {!state.npedUser?.propClientID?.value ? ( {isSubmitting ? "Logging in..." : "Login"} ) : ( Logout diff --git a/src/components/SettingForms/NPED/NPEDHotlist.tsx b/src/components/SettingForms/NPED/NPEDHotlist.tsx index b33421f..4ae9325 100644 --- a/src/components/SettingForms/NPED/NPEDHotlist.tsx +++ b/src/components/SettingForms/NPED/NPEDHotlist.tsx @@ -47,7 +47,7 @@ const NPEDHotlist = () => { /> Upload diff --git a/src/components/SettingForms/Sound/SoundSettingsFields.tsx b/src/components/SettingForms/Sound/SoundSettingsFields.tsx index c2f1fb1..5e1a79b 100644 --- a/src/components/SettingForms/Sound/SoundSettingsFields.tsx +++ b/src/components/SettingForms/Sound/SoundSettingsFields.tsx @@ -139,7 +139,7 @@ const SoundSettingsFields = () => { Save Settings diff --git a/src/components/SettingForms/Sound/SoundUpload.tsx b/src/components/SettingForms/Sound/SoundUpload.tsx index 30a03e6..3cd0e6e 100644 --- a/src/components/SettingForms/Sound/SoundUpload.tsx +++ b/src/components/SettingForms/Sound/SoundUpload.tsx @@ -96,7 +96,7 @@ const SoundUpload = () => { {errors.soundFile && Not an mp3 file} Upload diff --git a/src/components/SettingForms/System/SystemConfigFields.tsx b/src/components/SettingForms/System/SystemConfigFields.tsx index b830dd2..e58709d 100644 --- a/src/components/SettingForms/System/SystemConfigFields.tsx +++ b/src/components/SettingForms/System/SystemConfigFields.tsx @@ -167,7 +167,7 @@ const SystemConfigFields = () => { {saveSystemSettingsLoading ? "Saving..." : "Save System Settings"} diff --git a/src/components/SettingForms/System/SystemFileUpload.tsx b/src/components/SettingForms/System/SystemFileUpload.tsx index 32fd544..cb7f00b 100644 --- a/src/components/SettingForms/System/SystemFileUpload.tsx +++ b/src/components/SettingForms/System/SystemFileUpload.tsx @@ -52,7 +52,7 @@ const SystemFileUpload = ({ name, selectedFile }: SystemFileUploadProps) => { diff --git a/src/components/SettingForms/WiFi&Modem/ModemSettings.tsx b/src/components/SettingForms/WiFi&Modem/ModemSettings.tsx index a381f2b..723b392 100644 --- a/src/components/SettingForms/WiFi&Modem/ModemSettings.tsx +++ b/src/components/SettingForms/WiFi&Modem/ModemSettings.tsx @@ -178,7 +178,7 @@ const ModemSettings = () => { )} {isSubmitting || modemMutation.isPending ? "Saving..." : "Save Modem settings"} diff --git a/src/components/SightingModal/SightingModal.tsx b/src/components/SightingModal/SightingModal.tsx index f4c2d8f..428b52c 100644 --- a/src/components/SightingModal/SightingModal.tsx +++ b/src/components/SightingModal/SightingModal.tsx @@ -21,6 +21,7 @@ type SightingModalProps = { const SightingModal = ({ isSightingModalOpen, handleClose, sighting, onDelete }: SightingModalProps) => { const { dispatch } = useAlertHitContext(); + const { query, mutation } = useCameraBlackboard(); const hotlistNames = getHotlistName(sighting?.metadata?.hotlistMatches); @@ -160,27 +161,26 @@ const SightingModal = ({ isSightingModalOpen, handleClose, sighting, onDelete }: {sighting?.seenCount ?? "-"} - {sighting?.make || - (sighting?.make.trim() && ( - - Make - {sighting?.make ?? "-"} - - ))} - {sighting?.model || - (!sighting?.model.trim() && ( - - Model - {sighting?.model ?? "-"} - - ))} - {sighting?.color || - (!sighting?.color.trim() && ( - - Colour - {sighting?.color ?? "-"} - - ))} + {sighting?.make && sighting.make.trim() && sighting.make.toLowerCase() !== "disabled" && ( + + Make + {sighting.make} + + )} + + {sighting?.model && sighting.model.trim() && sighting.model.toLowerCase() !== "disabled" && ( + + Model + {sighting.model} + + )} + + {sighting?.color && sighting.color.trim() && sighting.color.toLowerCase() !== "disabled" && ( + + Colour + {sighting.color} + + )} Time diff --git a/src/components/SightingsWidget/SightingWidget.tsx b/src/components/SightingsWidget/SightingWidget.tsx index 7b1059b..fe31fe7 100644 --- a/src/components/SightingsWidget/SightingWidget.tsx +++ b/src/components/SightingsWidget/SightingWidget.tsx @@ -68,6 +68,11 @@ export default function SightingHistoryWidget({ className, title }: SightingHist const hasAutoOpenedRef = useRef(false); const npedRef = useRef(false); + const isCatAEnabled = integrationState?.iscatEnabled?.catA; + const isCatBEnabled = integrationState?.iscatEnabled?.catB; + const isCatCEnabled = integrationState?.iscatEnabled?.catC; + const isCatDEnabled = integrationState?.iscatEnabled?.catD; + const enqueue = useCallback((sighting: SightingType, kind: HitKind) => { const id = sighting.vrm ?? sighting.ref; if (processedRefs.current.has(id)) return; @@ -118,7 +123,11 @@ export default function SightingHistoryWidget({ className, title }: SightingHist if (processedRefs.current.has(id)) continue; const isHotlistHit = checkIsHotListHit(sighting); const npedcategory = sighting?.metadata?.npedJSON?.["NPED CATEGORY"]; - const isNPED = npedcategory === "A" || npedcategory === "B" || npedcategory === "C"; + const isNPED = + (npedcategory === "A" && isCatAEnabled) || + (npedcategory === "B" && isCatBEnabled) || + (npedcategory === "C" && isCatCEnabled) || + (npedcategory === "D" && isCatDEnabled); if (isNPED || isHotlistHit) { enqueue(sighting, isNPED ? "NPED" : "HOTLIST"); // enqueue ONLY @@ -148,7 +157,8 @@ export default function SightingHistoryWidget({ className, title }: SightingHist const isNPEDHitA = cat === "A"; const isNPEDHitB = cat === "B"; const isNPEDHitC = cat === "C"; - return isNPEDHitA || isNPEDHitB || isNPEDHitC; + const isNPEDHitD = cat === "D"; + return isNPEDHitA || isNPEDHitB || isNPEDHitC || isNPEDHitD; }); const firstHot = rows?.find((r) => { const isHotListHit = checkIsHotListHit(r); diff --git a/src/components/UI/Header.tsx b/src/components/UI/Header.tsx index c093949..7d0f34a 100644 --- a/src/components/UI/Header.tsx +++ b/src/components/UI/Header.tsx @@ -1,15 +1,26 @@ import { Link } from "react-router"; import Logo from "/MAV.svg"; import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; -import { faGear, faHome, faListCheck, faMaximize, faMinimize, faRotate } from "@fortawesome/free-solid-svg-icons"; +import { + faBars, + faGear, + faHome, + faListCheck, + faMaximize, + faMinimize, + faRotate, +} from "@fortawesome/free-solid-svg-icons"; import { useState } from "react"; import SoundBtn from "./SoundBtn"; import { useIntegrationsContext } from "../../context/IntegrationsContext"; export default function Header() { const [isFullscreen, setIsFullscreen] = useState(false); + const [isMenuOpen, setIsMenuOpen] = useState(false); const { state } = useIntegrationsContext(); + const toggleMenu = () => setIsMenuOpen(!isMenuOpen); + const sessionStarted = state.sessionStarted; const sessionPaused = state.sessionPaused; @@ -36,7 +47,7 @@ export default function Header() { - + {sessionStarted && sessionPaused ? ( Session Paused ) : ( @@ -44,7 +55,7 @@ export default function Header() { )} - + @@ -59,15 +70,35 @@ export default function Header() { - + + + + + - + + {isMenuOpen && ( + + + setIsMenuOpen(false)}> + + + + + setIsMenuOpen(false)}> + + + + + + + )} ); } diff --git a/src/context/providers/IntegrationsContextProvider.tsx b/src/context/providers/IntegrationsContextProvider.tsx index d12540c..4845b2e 100644 --- a/src/context/providers/IntegrationsContextProvider.tsx +++ b/src/context/providers/IntegrationsContextProvider.tsx @@ -12,17 +12,39 @@ export const IntegrationsProvider = ({ children }: IntegrationsProviderType) => const { mutation } = useCameraBlackboard(); useEffect(() => { - const fetchData = async () => { - const result = await mutation.mutateAsync({ - operation: "VIEW", - path: "sessionStats", - }); - if (!result.result || typeof result.result === "string") return; + let isMounted = true; - dispatch({ type: "UPDATE", payload: result?.result }); + const fetchData = async () => { + try { + const result = await mutation.mutateAsync({ + operation: "VIEW", + path: "sessionStats", + }); + + if (!isMounted) return; + + const catResult = await mutation.mutateAsync({ + operation: "VIEW", + path: "CategoryPopup", + }); + + if (!isMounted) return; + if (!result?.result || typeof result.result === "string") return; + + dispatch({ type: "UPDATE", payload: result.result }); + dispatch({ type: "NPEDCATENABLED", payload: catResult.result }); + } catch (error) { + console.error("Error in fetchData:", error); + } }; + fetchData(); + + return () => { + isMounted = false; + }; }, []); + return ( { }; const updateCameraMode = async (options: { camera: string; mode: string }) => { - console.log(options); const dayNightPayload = { id: options.camera, fields: [ diff --git a/src/index.css b/src/index.css index 92bfa28..77fced0 100644 --- a/src/index.css +++ b/src/index.css @@ -33,7 +33,7 @@ body { } .arrow-outline path { - stroke: black; /* outline color */ - stroke-width: 20px; /* thickness of outline (tweak this) */ + stroke: black; + stroke-width: 20px; stroke-linejoin: round; } diff --git a/src/pages/SystemSettings.tsx b/src/pages/SystemSettings.tsx index 0d38273..ea2941c 100644 --- a/src/pages/SystemSettings.tsx +++ b/src/pages/SystemSettings.tsx @@ -10,6 +10,7 @@ import { Toaster } from "sonner"; import { useNPEDAuth } from "../hooks/useNPEDAuth"; import SoundSettingsCard from "../components/SettingForms/Sound/SoundSettingsCard"; import SoundUploadCard from "../components/SettingForms/Sound/SoundUploadCard"; +import NPEDCategoryPopup from "../components/PopupSettings/NPEDCategoryPopup"; const SystemSettings = () => { useNPEDAuth(); @@ -21,7 +22,7 @@ const SystemSettings = () => { System Output Integrations - WiFi and Modem + WiFi & Modem Sound @@ -38,6 +39,7 @@ const SystemSettings = () => { + diff --git a/src/types/types.ts b/src/types/types.ts index 9d5cfdf..0c9349a 100644 --- a/src/types/types.ts +++ b/src/types/types.ts @@ -423,6 +423,7 @@ export type NPEDSTATE = { sessionPaused: boolean; savedSightings: DedupedSightings; npedUser: NPEDUser; + iscatEnabled: CategoryPopups; }; export type NPEDACTION = { @@ -430,3 +431,10 @@ export type NPEDACTION = { // eslint-disable-next-line @typescript-eslint/no-explicit-any payload: any; }; + +export type CategoryPopups = { + catA: boolean; + catB: boolean; + catC: boolean; + catD: boolean; +};
Allows alerts to pop up to user.
Not an mp3 file
Session Paused