diff --git a/src/features/output/components/OSDFieldToggle.tsx b/src/features/output/components/OSDFieldToggle.tsx new file mode 100644 index 0000000..dadb66f --- /dev/null +++ b/src/features/output/components/OSDFieldToggle.tsx @@ -0,0 +1,27 @@ +import { Field } from "formik"; + +type OSDFieldToggleProps = { + value: string; + label: string; +}; + +const OSDFieldToggle = ({ value, label }: OSDFieldToggleProps) => { + const spacesWords = (label: string) => { + if (label.includes("VRM")) return label.replace("VRM", " VRM"); + return label.replace(/([A-Z])/g, " $1").trim(); + }; + + return ( + + {spacesWords(label)} + + + + ); +}; + +export default OSDFieldToggle; diff --git a/src/features/output/components/OSDFields.tsx b/src/features/output/components/OSDFields.tsx new file mode 100644 index 0000000..3669445 --- /dev/null +++ b/src/features/output/components/OSDFields.tsx @@ -0,0 +1,70 @@ +import { Field, useFormikContext } from "formik"; +import { useOSDConfig } from "../hooks/useOSDConfig"; +import OSDFieldToggle from "./OSDFieldToggle"; +import type { OSDConfigFields } from "../../../types/types"; + +type OSDFieldsProps = { + isOSDLoading: boolean; +}; + +const OSDFields = ({ isOSDLoading }: OSDFieldsProps) => { + const { osdMutation } = useOSDConfig(); + const { values } = useFormikContext(); + + const includeKeys = Object.keys(values as OSDConfigFields).filter((value) => value.includes("include")); + + const handleSubmit = async (values: OSDConfigFields) => { + const result = await osdMutation.mutateAsync(values); + console.log(result); + }; + + if (isOSDLoading) { + return Loading OSD Options...; + } + + return ( + + + + OSD Options + + {includeKeys.map((key) => ( + + ))} + + + Overlay Position + + Top + Bottom + + + + OSD Timestamp Format + + UTC + Local + + + handleSubmit(values)} + className="w-full md:w-1/4 text-white bg-green-700 hover:bg-green-800 font-small rounded-lg text-sm px-2 py-2.5 hover:cursor-pointer" + > + Submit + + + + + ); +}; + +export default OSDFields; diff --git a/src/features/output/components/OSDOptionsCard.tsx b/src/features/output/components/OSDOptionsCard.tsx new file mode 100644 index 0000000..5eb0c61 --- /dev/null +++ b/src/features/output/components/OSDOptionsCard.tsx @@ -0,0 +1,18 @@ +import Card from "../../../ui/Card"; +import CardHeader from "../../../ui/CardHeader"; +import OSDFields from "./OSDFields"; + +type OSDOptionsCardProps = { + isOSDLoading: boolean; +}; + +const OSDOptionsCard = ({ isOSDLoading }: OSDOptionsCardProps) => { + return ( + + + + + ); +}; + +export default OSDOptionsCard; diff --git a/src/features/output/components/OutputForms.tsx b/src/features/output/components/OutputForms.tsx index c26e4d9..cea3a01 100644 --- a/src/features/output/components/OutputForms.tsx +++ b/src/features/output/components/OutputForms.tsx @@ -6,14 +6,25 @@ import { usePostBearerConfig } from "../hooks/useBearer"; import { useDispatcherConfig } from "../hooks/useDispatcherConfig"; import { useOptionalConstants } from "../hooks/useOptionalConstants"; import { useCustomFields } from "../hooks/useCustomFields"; +import OSDOptionsCard from "./OSDOptionsCard"; +import { useOSDConfig } from "../hooks/useOSDConfig"; const OutputForms = () => { const { bearerMutation } = usePostBearerConfig(); const { dispatcherQuery, dispatcherMutation } = useDispatcherConfig(); const { customFieldsQuery, customFieldsMutation } = useCustomFields(); + const { osdQuery } = useOSDConfig(); const isLoading = dispatcherQuery?.isLoading; + const isOSDLoading = osdQuery?.isLoading; + const includeVRM = osdQuery?.data?.propIncludeVRM?.value.toLowerCase() === "true"; + const includeMotion = osdQuery?.data?.propIncludeMotion?.value.toLowerCase() === "true"; + const includeTimeStamp = osdQuery?.data?.propIncludeTimestamp?.value.toLowerCase() === "true"; + const includeCameraName = osdQuery?.data?.propIncludeCameraName?.value.toLowerCase() === "true"; + const overlayPosition = osdQuery?.data?.propOverlayPosition?.value; + const OSDTimestampFormat = osdQuery?.data?.propTimestampFormat?.value; + console.log(includeVRM); const format = dispatcherQuery?.data?.propFormat?.value; const { optionalConstantsQuery, optionalConstantsMutation } = useOptionalConstants(format?.toLowerCase()); const FFID = optionalConstantsQuery?.data?.propFeedIdentifier?.value; @@ -70,6 +81,14 @@ const OutputForms = () => { //custom fields customFields: initialCustomFields, + + // OSD Options + includeVRM: includeVRM ?? false, + includeMotion: includeMotion ?? false, + includeTimeStamp: includeTimeStamp ?? false, + includeCameraName: includeCameraName ?? false, + overlayPosition: overlayPosition ?? "Top", + OSDTimestampFormat: OSDTimestampFormat ?? "UTC", }; const handleSubmit = async (values: FormTypes) => { @@ -128,8 +147,11 @@ const OutputForms = () => { return ( - - + + + + + diff --git a/src/features/output/hooks/useOSDConfig.ts b/src/features/output/hooks/useOSDConfig.ts new file mode 100644 index 0000000..6fc0206 --- /dev/null +++ b/src/features/output/hooks/useOSDConfig.ts @@ -0,0 +1,53 @@ +import { useQuery, useMutation } from "@tanstack/react-query"; +import { CAMBASE } from "../../../utils/config"; +import type { OSDConfigFields } from "../../../types/types"; + +const fetchOSDConfig = async () => { + const response = await fetch(`${CAMBASE}/api/fetch-config?id=SightingAmmend0-overlay`); + + if (!response.ok) { + throw new Error("Network response was not ok"); + } + return response.json(); +}; + +const postOSDConfig = async (data: OSDConfigFields) => { + const fields = [ + { property: "propIncludeVRM", value: data.includeVRM }, + { property: "propIncludeMotion", value: data.includeMotion }, + { property: "propIncludeTimestamp", value: data.includeTimeStamp }, + { property: "propIncludeCameraName", value: data.includeCameraName }, + { property: "propOverlayPosition", value: data.overlayPosition }, + { property: "propTimestampFormat", value: data.OSDTimestampFormat }, + ]; + + const osdConfigPayload = { + id: "SightingAmmend0-overlay", + fields: fields, + }; + + console.log(osdConfigPayload); + const response = await fetch(`${CAMBASE}/api/update-config`, { + method: "POST", + body: JSON.stringify(osdConfigPayload), + }); + + if (!response.ok) { + throw new Error("Failed to post OSD Config"); + } + return response.json(); +}; + +export const useOSDConfig = () => { + const osdQuery = useQuery({ + queryKey: ["osdConfig"], + queryFn: fetchOSDConfig, + }); + + const osdMutation = useMutation({ + mutationFn: postOSDConfig, + mutationKey: ["postOSDConfig"], + }); + + return { osdQuery, osdMutation }; +}; diff --git a/src/types/types.ts b/src/types/types.ts index 79f8827..7d7309b 100644 --- a/src/types/types.ts +++ b/src/types/types.ts @@ -73,7 +73,16 @@ export type InitialValuesFormErrors = { readTimeoutSeconds?: string; }; -export type FormTypes = BearerTypeFields & OptionalConstants & OptionalLaneIDs & CustomFields; +export type OSDConfigFields = { + includeVRM: boolean; + includeMotion: boolean; + includeTimeStamp: boolean; + includeCameraName: boolean; + overlayPosition: "Top" | "Bottom" | "Left" | "Right"; + OSDTimestampFormat: "UTC" | "LOCAL"; +}; + +export type FormTypes = BearerTypeFields & OptionalConstants & OptionalLaneIDs & CustomFields & OSDConfigFields; type FieldProperty = { datatype: string; value: string;