Files
Travel-policy-/frontend/src/pages/ApplicationForm/Form.jsx
ANUJ7MADKE cd43f0e98e code base
2025-07-13 22:49:55 +05:30

205 lines
5.8 KiB
JavaScript

import React, { useEffect, useState } from "react";
import { Formik } from "formik";
import Input from "./Input";
import {
useSubmit,
useRouteLoaderData,
useNavigation,
useParams,
} from "react-router-dom";
import { studentFormFeilds, facultyFormFeilds } from "./FormFeilds";
import * as yup from "yup";
function Form({
prefilledData,
applicantDesignation,
resubmission = false,
onValuesChange,
}) {
const { role, user } =
useRouteLoaderData("Applicant-Root")?.data ||
useRouteLoaderData("Validator-Root")?.data;
const applicationId = useParams().applicationId || "";
const submit = useSubmit("upsertApplicationAction");
const navigation = useNavigation();
const isSubmittingNav = navigation.state === "submitting";
let formFeilds = [];
let toBeFormFeilds = [];
let designation;
const applicant = useRouteLoaderData("Applicant-Root");
if (applicantDesignation) {
designation = applicantDesignation;
} else {
designation = applicant?.data?.user?.designation; //Faculty or Student
}
if (designation === "STUDENT") {
toBeFormFeilds = studentFormFeilds;
} else {
toBeFormFeilds = facultyFormFeilds;
}
if (prefilledData) {
formFeilds = toBeFormFeilds?.map((section) => {
return {
...section,
fields: section?.fields?.map((field) => ({
...field,
disabled:
role === "Validator"
? true
: resubmission && field?.name == "expenses"
? false
: true,
})),
};
});
} else {
formFeilds = toBeFormFeilds;
}
const createIntialValuesScheme = (formFields) => {
const schema = {};
formFields?.forEach((section) => {
section?.fields?.forEach((field) => {
if (prefilledData) {
if (field.type === "miniForm") {
schema[field.name] = JSON.parse(prefilledData[field.name]);
} else if (field.type === "checkbox") {
schema[field.name] = JSON.parse(
prefilledData[field.name] || "false"
);
} else if (field.type === "number") {
schema[field.name] = parseInt(prefilledData[field.name]);
} else {
schema[field.name] = prefilledData[field.name];
}
} else if (field.type === "checkbox") {
schema[field.name] = false;
} else if (field.type === "miniForm") {
schema[field.name] = [];
} else {
schema[field.name] = "";
}
});
});
return schema;
};
const intialValuesSchema = createIntialValuesScheme(formFeilds);
const createValidationSchema = (formFields) => {
const schema = {};
formFields?.forEach((section) => {
section.fields?.forEach((field) => {
if (field.validation) {
schema[field.name] = field.validation;
}
});
});
return yup.object().shape(schema);
};
const validationSchema = createValidationSchema(formFeilds);
const handleSubmit = async (values, { setSubmitting }) => {
const formDataToSend = new FormData();
for (const key in values) {
if (key === "expenses") {
// Serialize the expenses array as a JSON string and append
const expenses = JSON.stringify(values[key]);
formDataToSend.append("expenses", expenses);
// Append expenseProof files separately (as file objects)
values[key].forEach((expense, index) => {
if (expense.expenseProof) {
formDataToSend.append(
`expenses[${index}].expenseProof`,
expense.expenseProof
);
}
});
} else {
// For other fields, just append normally
formDataToSend.append(key, values[key]);
}
}
formDataToSend.append("resubmission", resubmission);
formDataToSend.append("applicationId", applicationId);
try {
submit(formDataToSend, {
method: "POST",
encType: "multipart/form-data", // Specify the encoding type
});
} catch (error) {
console.error("Error uploading form:", error.message);
} finally {
setSubmitting(false); // Reset the submitting state after request is done
}
};
return (
<Formik
initialValues={intialValuesSchema}
validationSchema={validationSchema}
onSubmit={handleSubmit}
>
{({
values,
errors,
touched,
handleChange,
handleBlur,
handleSubmit,
setFieldValue, // Use setFieldValue for file handling
isSubmitting,
}) => {
// Notify parent about values change
useEffect(() => {
if (onValuesChange) {
onValuesChange(values);
}
}, [values, onValuesChange]);
return (
<form
onSubmit={handleSubmit}
className="p-2 my-4 overflow-y-auto bg-transparent"
>
<Input
values={values}
errors={errors}
touched={touched}
handleChange={handleChange}
handleBlur={handleBlur}
setFieldValue={setFieldValue} // Pass setFieldValue for file handling
formFeilds={formFeilds}
/>
{(resubmission || !prefilledData) && role != "Validator" && (
<button
type="submit"
disabled={isSubmitting || isSubmittingNav}
className="w-full flex items-center justify-center bg-gradient-to-r from-red-600 to-red-800 hover:from-red-800 hover:to-red-600 text-white font-semibold py-2 px-4 rounded-lg shadow-lg transform transition duration-300 ease-in-out disabled:bg-gray-400"
>
{isSubmitting || isSubmittingNav ? "Submitting" : "Submit"}
</button>
)}
</form>
);
}}
</Formik>
);
}
export default Form;