From c25ab488808a84d14ee4c8945942d1259a5107bc Mon Sep 17 00:00:00 2001 From: Theis Date: Mon, 18 May 2026 19:14:48 +0200 Subject: [PATCH] fully implemented tanstack query --- frontend/src/pages/MainForm.tsx | 96 ++++++++++++++++++--------------- frontend/src/utils/api/form.ts | 26 +++++++++ frontend/src/utils/sender.ts | 33 ------------ 3 files changed, 80 insertions(+), 75 deletions(-) create mode 100644 frontend/src/utils/api/form.ts delete mode 100644 frontend/src/utils/sender.ts diff --git a/frontend/src/pages/MainForm.tsx b/frontend/src/pages/MainForm.tsx index 7c9c3f5..23cfef6 100644 --- a/frontend/src/pages/MainForm.tsx +++ b/frontend/src/pages/MainForm.tsx @@ -18,14 +18,15 @@ import { Modal, ModalDialog, ModalClose, + CircularProgress, } from "@mui/joy"; -import { submitFormData } from "../utils/sender"; +import { submitFormData } from "../utils/api/form"; import type { FormData, Message } from "../config/interfaces.config"; import PersonIcon from "@mui/icons-material/Person"; import QrCodeIcon from "@mui/icons-material/QrCode"; import TranslateIcon from "@mui/icons-material/Translate"; import qrCode from "../assets/PayPal-QR-Code.png"; -import { useQuery } from "@tanstack/react-query"; +import { useQuery, useMutation, useQueryClient } from "@tanstack/react-query"; import { confirmUser, fetchUsers } from "../utils/api/users"; const PAYMENT_METHODS = ["bar", "paypal", "andere"] as const; @@ -83,6 +84,7 @@ const Field = ({ export const MainForm = () => { const { t, i18n } = useTranslation(); + const queryClient = useQueryClient(); const [invoice, setInvoice] = useState(false); const [msg, setMsg] = useState(null); @@ -114,6 +116,32 @@ export const MainForm = () => { queryFn: () => confirmUser(selectedUser), }); + const { + mutate: mutateForm, + isSuccess: mutateFormIsSuccess, + isPending: mutateFormIsPending, + isError: mutateFormIsError, + } = useMutation({ + mutationFn: () => submitFormData(formData, selectedUser), + }); + + // Redirecting to success page if mutation was successful + useEffect(() => { + if (mutateFormIsSuccess) { + queryClient.invalidateQueries({ queryKey: ["user", selectedUser] }); + document.location.href = `/success?id=${nextID}&tickets=${formData.tickets}`; + } + + if (mutateFormIsError) { + queryClient.invalidateQueries({ queryKey: ["user", selectedUser] }); + setMsg({ + type: "danger", + headline: t("error"), + text: t("form-submission-failed"), + }); + } + }, [mutateFormIsSuccess, mutateFormIsError]); + // Setting the nextID after a user is selected useEffect(() => { if (!userData) return; @@ -152,27 +180,6 @@ export const MainForm = () => { } }, [formData.paymentMethod]); - const handleSubmit = async () => { - try { - const result = await submitFormData(formData, selectedUser || ""); - if (result.success) { - document.location.href = `/success?id=${nextID}&tickets=${formData.tickets}`; - } else { - setMsg({ - type: "danger", - headline: t("form-submission-failed"), - text: result.error || t("form-submission-failed"), - }); - } - } catch (error) { - setMsg({ - type: "danger", - headline: t("error"), - text: t("form-submission-failed"), - }); - } - }; - // Shorthand so we don't repeat formData + onChange on every Field usage const fieldProps = { formData, onChange: handleChange }; @@ -258,7 +265,7 @@ export const MainForm = () => {
{ e.preventDefault(); - handleSubmit(); + mutateForm(); }} className="flex flex-col gap-4" > @@ -411,24 +418,29 @@ export const MainForm = () => { )} - {/* Submit button */} - + {mutateFormIsPending ? ( +
+ +
+ ) : ( + + )} {/* Alert message */} {msg && ( diff --git a/frontend/src/utils/api/form.ts b/frontend/src/utils/api/form.ts new file mode 100644 index 0000000..0229d7f --- /dev/null +++ b/frontend/src/utils/api/form.ts @@ -0,0 +1,26 @@ +import { API_BASE } from "../../config/api.config"; +import type { FormData } from "../../config/interfaces.config"; + +export const submitFormData = async (data: FormData, username: string) => { + console.warn("submitFormData is fetching!"); + + await new Promise((resolve) => setTimeout(resolve, 3000)); // Wait 3 seconds + + const response = await fetch( + `${API_BASE}/default/new-entry?username=${username}`, + { + method: "POST", + headers: { + "Content-Type": "application/json", + }, + body: JSON.stringify(data), + }, + ); + + if (!response.ok) { + const error = await response.text(); + throw new Error(error || "Form submission failed"); + } + + return; +}; diff --git a/frontend/src/utils/sender.ts b/frontend/src/utils/sender.ts deleted file mode 100644 index 724447d..0000000 --- a/frontend/src/utils/sender.ts +++ /dev/null @@ -1,33 +0,0 @@ -import { API_BASE } from "../config/api.config"; -import type { FormData } from "../config/interfaces.config"; - -export const submitFormData = async ( - data: FormData, - username: string | null, -) => { - if (username == null) { - return { success: false, errorCode: "x001" }; - } - - try { - const response = await fetch( - `${API_BASE}/default/new-entry?username=${username}`, - { - method: "POST", - headers: { - "Content-Type": "application/json", - }, - body: JSON.stringify(data), - }, - ); - - if (!response.ok) { - const errorText = await response.text(); - return { success: false, error: `Server error: ${errorText}` }; - } - - return { success: true }; - } catch (error) { - return { success: false, error: (error as Error).message }; - } -};