This commit is contained in:
iqbal024 2025-04-25 21:01:13 +07:00
commit 8c64cacaaa
4 changed files with 57 additions and 32 deletions

View File

@ -28,6 +28,7 @@
"react-dom": "^19.0.0",
"react-hook-form": "^7.56.1",
"react-select": "^5.10.1",
"react-toastify": "^11.0.5",
"swiper": "^11.2.6"
},
"devDependencies": {

View File

@ -6,6 +6,7 @@ import { getDefaultMetadata } from "@/utils/metadata";
import Header from "@/components/layouts/Header";
import Footer from "@/components/layouts/Footer";
import Image from "next/image";
import { ToastContainer } from "react-toastify";
const geistSans = Geist({
variable: "--font-geist-sans",
@ -86,7 +87,8 @@ export default function RootLayout({
<Footer />
</div>
<div className="snackbars" id="form-output-global"></div>
<ToastContainer theme="dark" position="bottom-center" stacked />
{/* <div className="snackbars" id="form-output-global"></div> */}
<InitialScript />
</body>
</html>

View File

@ -10,6 +10,7 @@ import { Button } from "./Button";
import RichText from "./RichText";
import { buildInitialFormState } from "./buildInitialFormState";
import { fields } from "./fields";
import { toast } from "react-toastify";
export type Value = unknown;
@ -63,8 +64,7 @@ export const FormBlock: React.FC<
formState: { errors },
handleSubmit,
register,
// getValues,
// setValue,
reset,
} = formMethods;
const [isLoading, setIsLoading] = useState(false);
@ -75,6 +75,7 @@ export const FormBlock: React.FC<
const onSubmit = useCallback(
(data: Data) => {
let loadingTimerID: ReturnType<typeof setTimeout>;
const submitForm = async () => {
setError(undefined);
@ -83,6 +84,8 @@ export const FormBlock: React.FC<
value,
}));
const toastId = toast.loading("Sending...");
// delay loading indicator by 1s
loadingTimerID = setTimeout(() => {
setIsLoading(true);
@ -107,6 +110,8 @@ export const FormBlock: React.FC<
if (req.status >= 400) {
setIsLoading(false);
toast.error(res.errors?.[0]?.message || "Internal Server Error");
toast.dismiss(toastId);
setError({
message: res.errors?.[0]?.message || "Internal Server Error",
status: res.status,
@ -115,8 +120,11 @@ export const FormBlock: React.FC<
return;
}
toast.success(<RichText content={confirmationMessage} />);
toast.dismiss(toastId);
setIsLoading(false);
setHasSubmitted(true);
reset();
if (confirmationType === "redirect" && redirect) {
const { url } = redirect;
@ -127,9 +135,12 @@ export const FormBlock: React.FC<
}
} catch (err) {
console.warn(err);
toast.error("Something went wrong");
toast.dismiss(toastId);
setIsLoading(false);
setError({
message: "Something went wrong.",
message: "Something went wrong",
});
}
};
@ -144,36 +155,34 @@ export const FormBlock: React.FC<
{!!formFromProps?.title && <h2>{formFromProps.title}</h2>}
<div className="mt-4">
{!!enableIntro && introContent && !hasSubmitted && <RichText content={introContent} />}
{!isLoading && hasSubmitted && confirmationType === "message" && <RichText content={confirmationMessage} />}
{isLoading && !hasSubmitted && <p>Loading, please wait...</p>}
{error && <div className="text-red-500">{`${error.status || "500"}: ${error.message || ""}`}</div>}
{!hasSubmitted && (
<form id={formID} onSubmit={handleSubmit(onSubmit)} className="rd-form">
<div className="row space-y-4">
{formFromProps &&
formFromProps.fields &&
formFromProps.fields.map((field, index) => {
const Field: React.FC<any> = fields?.[field.blockType];
if (Field) {
return (
<React.Fragment key={index}>
<Field
form={formFromProps}
{...field}
{...formMethods}
control={control}
errors={errors}
register={register}
/>
</React.Fragment>
);
}
return null;
})}
</div>
<Button appearance="primary" el="button" form={formID} label={submitButtonLabel} isLoading={isLoading} />
</form>
)}
<form id={formID} onSubmit={handleSubmit(onSubmit)} className="rd-form">
<div className="row space-y-4">
{formFromProps &&
formFromProps.fields &&
formFromProps.fields.map((field, index) => {
const Field: React.FC<any> = fields?.[field.blockType];
if (Field) {
return (
<React.Fragment key={index}>
<Field
form={formFromProps}
{...field}
{...formMethods}
control={control}
errors={errors}
register={register}
/>
</React.Fragment>
);
}
return null;
})}
</div>
<Button appearance="primary" el="button" form={formID} label={submitButtonLabel} isLoading={isLoading} />
</form>
</div>
</div>
);

View File

@ -5059,6 +5059,7 @@ __metadata:
react-dom: "npm:^19.0.0"
react-hook-form: "npm:^7.56.1"
react-select: "npm:^5.10.1"
react-toastify: "npm:^11.0.5"
swiper: "npm:^11.2.6"
tailwindcss: "npm:^4"
typescript: "npm:^5"
@ -8863,6 +8864,18 @@ __metadata:
languageName: node
linkType: hard
"react-toastify@npm:^11.0.5":
version: 11.0.5
resolution: "react-toastify@npm:11.0.5"
dependencies:
clsx: "npm:^2.1.1"
peerDependencies:
react: ^18 || ^19
react-dom: ^18 || ^19
checksum: 10c0/50f5b81323ebb1957b2efd0963fac24aa1407155d16ab756ffd6d0f42f8af17e796b3958a9fce13e9d1b945d6c3a5a9ebf13529478474d8a2af4bf1dd0db67d2
languageName: node
linkType: hard
"react-transition-group@npm:4.4.5, react-transition-group@npm:^4.3.0":
version: 4.4.5
resolution: "react-transition-group@npm:4.4.5"