Files
Mav-Mobile-UI/src/components/SettingForms/Sound/SoundUpload.tsx

106 lines
3.9 KiB
TypeScript
Raw Normal View History

2025-09-30 13:25:11 +01:00
import { Form, Formik } from "formik";
import FormGroup from "../components/FormGroup";
import type { SoundUploadValue } from "../../../types/types";
import { useSoundContext } from "../../../context/SoundContext";
import { toast } from "sonner";
import { useCameraBlackboard } from "../../../hooks/useCameraBlackboard";
import { useFileUpload } from "../../../hooks/useFileUpload";
2025-09-30 13:25:11 +01:00
const SoundUpload = () => {
const { state, dispatch } = useSoundContext();
const { mutation } = useCameraBlackboard();
const { mutation: fileMutation } = useFileUpload({
queryKey: state.sightingSound ? [state.sightingSound] : undefined,
});
2025-09-30 13:25:11 +01:00
const initialValues: SoundUploadValue = {
name: "",
2025-09-30 13:25:11 +01:00
soundFile: null,
2025-10-20 16:17:37 +01:00
soundFileName: "",
soundUrl: "",
uploadedAt: Date.now(),
2025-09-30 13:25:11 +01:00
};
const handleSubmit = async (values: SoundUploadValue) => {
if (!values.soundFile) {
toast.warning("Please select an audio file");
return;
}
const alreadyExists = state?.soundOptions?.some((soundOption) => soundOption.name === values.name);
if (state.soundOptions?.includes(values) || alreadyExists) {
toast.warning("Sound already in list");
return;
}
2025-10-20 16:17:37 +01:00
const updatedValues = {
...state,
soundOptions: [...(state.soundOptions ?? []), values],
};
const result = await mutation.mutateAsync({
operation: "INSERT",
path: "soundSettings",
value: updatedValues,
});
await fileMutation.mutateAsync(values.soundFile);
if (result.reason !== "OK") {
toast.error("Cannot update sound settings");
}
dispatch({ type: "ADD", payload: values });
2025-09-30 13:25:11 +01:00
};
return (
2025-10-20 10:50:16 +01:00
<Formik initialValues={initialValues} onSubmit={handleSubmit} enableReinitialize>
{({ setFieldValue, errors, setFieldError }) => (
2025-09-30 13:25:11 +01:00
<Form>
2025-10-20 10:50:16 +01:00
<label htmlFor="soundFile" className="">
Sound File
</label>
2025-09-30 13:25:11 +01:00
<FormGroup>
<input
type="file"
name="soundFile"
id="sightingSoundinput"
accept="audio/mpeg"
2025-10-20 10:50:16 +01:00
className="mt-4 w-full flex flex-col items-center justify-center rounded-2xl border border-slate-800 bg-slate-900/40 p-10 text-center file:px-3 file:border file:border-gray-500 file:rounded-lg file:bg-blue-800 file:mr-5"
2025-09-30 13:25:11 +01:00
onChange={(e) => {
2025-10-20 10:50:16 +01:00
if (e.target?.files && e.target?.files[0]?.type === "audio/mpeg") {
2025-10-20 16:17:37 +01:00
const url = URL.createObjectURL(e.target.files[0]);
setFieldValue("soundUrl", url);
setFieldValue("name", e.target.files[0].name);
2025-10-20 16:17:37 +01:00
setFieldValue("soundFileName", e.target.files[0].name);
setFieldValue("soundFile", e.target.files[0]);
setFieldValue("uploadedAt", Date.now());
} else {
setFieldError("soundFile", "Not an mp3 file");
toast.error("Not an mp3 file");
}
2025-09-30 13:25:11 +01:00
}}
/>
</FormGroup>
2025-10-20 10:50:16 +01:00
<div className="mt-4 flex flex-col items-center justify-center rounded-2xl border border-slate-800 bg-slate-900/40 p-10 text-center">
<p className="max-w-md text-slate-300">
Uploaded Sound files will appear in the <span className="font-bold">drop downs</span> once they are
uploaded. They can be used for any <span className="text-blue-400">Sighting,</span>{" "}
<span className="text-emerald-400">Hotlist</span> or <span className="text-amber-600">NPED</span> hits.
</p>
</div>
{errors.soundFile && <p className="text-red-500 text-sm mt-1">Not an mp3 file</p>}
2025-09-30 13:25:11 +01:00
<button
type="submit"
2025-10-20 10:50:16 +01:00
className="w-1/4 text-white bg-green-700 hover:bg-green-800 font-small rounded-lg text-sm px-2 py-2.5 mt-[5%]"
disabled={errors.soundFile ? true : false}
2025-09-30 13:25:11 +01:00
>
Upload
</button>
</Form>
)}
</Formik>
);
};
export default SoundUpload;