- added state to set sound set settings for sightings and NPED hits

- added function to save mute settings
This commit is contained in:
2025-10-08 11:08:41 +01:00
parent a20a0c7019
commit 40909d48b6
8 changed files with 59 additions and 17 deletions

View File

@@ -2,15 +2,14 @@ import { Field, FieldArray, Form, Formik } from "formik";
import FormGroup from "../components/FormGroup";
import type { FormValues, Hotlist } from "../../../types/types";
import { useSoundContext } from "../../../context/SoundContext";
import { useCameraBlackboard } from "../../../hooks/useCameraBlackboard";
import { toast } from "sonner";
const SoundSettingsFields = () => {
const { state, dispatch } = useSoundContext();
const hotlists: Hotlist[] = [
{ name: "hotlist0", sound: "" },
{ name: "hotlist1", sound: "" },
{ name: "hotlist2", sound: "" },
];
const { mutation } = useCameraBlackboard();
const hotlists: Hotlist[] = state.hotlists;
const soundOptions = state?.soundOptions?.map((soundOption) => ({
value: soundOption?.name,
@@ -23,9 +22,18 @@ const SoundSettingsFields = () => {
hotlists,
};
const handleSubmit = (values: FormValues) => {
const handleSubmit = async (values: FormValues) => {
dispatch({ type: "UPDATE", payload: values });
toast.success("Sound settings updated");
const result = await mutation.mutateAsync({
operation: "INSERT",
path: "soundSettings",
value: values,
});
if (result.reason !== "OK") {
toast.error("Cannot update sound settings");
} else {
toast.success("Sound Settings successfully updated");
}
};
return (
<Formik initialValues={initialValues} onSubmit={handleSubmit}>
@@ -68,8 +76,8 @@ const SoundSettingsFields = () => {
name="hotlists"
render={() => (
<div className="w-full m-2">
{values.hotlists.length > 0 ? (
values.hotlists.map((hotlist, index) => (
{values?.hotlists?.length > 0 ? (
values?.hotlists?.map((hotlist, index) => (
<div
key={hotlist.name}
className="flex items-center m-2 w-full justify-between"

View File

@@ -1,13 +1,25 @@
import { faVolumeHigh, faVolumeXmark } from "@fortawesome/free-solid-svg-icons";
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import { useSoundEnabled } from "react-sounds";
import { useCameraBlackboard } from "../../hooks/useCameraBlackboard";
import { useEffect } from "react";
const SoundBtn = () => {
const { mutation, query } = useCameraBlackboard();
const [enabled, setEnabled] = useSoundEnabled();
const handleClick = () => {
setEnabled(!enabled);
const handleClick = async () => {
const newEnabled = !enabled;
setEnabled(newEnabled);
await mutation.mutateAsync({
operation: "INSERT",
path: "soundEnabled",
value: { enabled: newEnabled },
});
};
useEffect(() => {
setEnabled(query?.data?.soundEnabled?.enabled);
}, [query?.data?.soundEnabled?.enabled, setEnabled]);
return (
<button onClick={handleClick}>

View File

@@ -1,6 +1,7 @@
import { useMemo, useReducer, type ReactNode } from "react";
import { useEffect, useMemo, useReducer, type ReactNode } from "react";
import { SoundContext } from "../SoundContext";
import { initialState, reducer } from "../reducers/SoundContextReducer";
import { useCameraBlackboard } from "../../hooks/useCameraBlackboard";
type SoundContextProviderProps = {
children: ReactNode;
@@ -8,6 +9,20 @@ type SoundContextProviderProps = {
const SoundContextProvider = ({ children }: SoundContextProviderProps) => {
const [state, dispatch] = useReducer(reducer, initialState);
const { mutation } = useCameraBlackboard();
useEffect(() => {
const fetchSound = async () => {
const result = await mutation.mutateAsync({
operation: "VIEW",
path: "soundSettings",
});
dispatch({ type: "UPDATE", payload: result.result });
};
fetchSound();
// eslint-disable-next-line react-hooks/exhaustive-deps
}, []);
const value = useMemo(() => ({ state, dispatch }), [state, dispatch]);
return (
<SoundContext.Provider value={value}>{children}</SoundContext.Provider>

View File

@@ -18,7 +18,7 @@ export function reducer(state: SoundState, action: SoundAction): SoundState {
...state,
sightingSound: action.payload.sightingSound,
NPEDsound: action.payload.NPEDsound,
hotlists: action.payload.hotlists.map((hotlist) => ({
hotlists: action.payload.hotlists?.map((hotlist) => ({
name: hotlist.name,
sound: hotlist.sound,
})),

View File

@@ -15,7 +15,7 @@ const getAllBlackboardData = async () => {
};
const viewBlackboardData = async (options: CameraBlackBoardOptions) => {
const response = await fetch(`${CAM_BASE}/api/blackboard`, {
const response = await fetch(`/api/blackboard`, {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify(options),
@@ -45,7 +45,6 @@ export const useCameraBlackboard = () => {
id: "viewBlackboardData",
});
},
onSuccess: () => toast.success("Sighting successfully added to alert list"),
});
useEffect(() => {

View File

@@ -39,7 +39,7 @@ export function useSightingFeed(url: string | undefined) {
return latestRef;
}, [latestRef]);
const soundSrc = useMemo(() => {
return getSoundFileURL(state.sightingSound) ?? switchSound;
return getSoundFileURL(state?.sightingSound) ?? switchSound;
}, [state.sightingSound]);
//use latestref instead of trigger to revert back

View File