Snai3i-LandingPage-FormBuilder / frontend / src / components / RegisterForm / index.tsx
index.tsx
Raw
import { useEffect } from "react";
import { toast } from "sonner";
import { useForm } from "react-hook-form";

import { Button } from "@/components/ui/formsButton";
import Fallback from "@/components/Fallback";
// import useTitle from '../hooks/useTitle';
import FormElementCard from "@/components/Forms/CreateForm/FormElementCard";
import { Form, FormControl, FormField, FormItem } from "@/components/ui/form";
import { useCreateResponseMutation } from "@/app/backend/endpoints/forms";
import { useGetRegisterFormQuery } from "@/app/backend/endpoints/registerForms";
import { useNavigate } from "react-router-dom";

export default function RegisterForm({
  formName,
  afterSubmit,
  generateCode,
}: {
  formName: string;
  afterSubmit?: (() => void) | null;
  generateCode?: (({ email }: { email: string }) => void) | null;
}) {
  const navigate = useNavigate();
  const {
    data: dataWrap,
    isLoading: isPending,
    isError,
  } = useGetRegisterFormQuery(formName);
  const data = dataWrap?.data;

  const [createResponse, { isLoading }] = useCreateResponseMutation();
  // interface FormResponseI {
  //   elementType: string;
  //   question: string;
  //   answer: unknown;
  // }
  const mutation = (response: FormResponseI[]) => {
    createResponse({ formId: data?._id ?? "", data: response })
      .unwrap()
      .then(() => {
        // map response and get answer where question is email

        if (generateCode) {
          const email = response?.map((r) => {
            if (r.question === "email" || r.question === "Email")
              return r.answer;
          })[0] as string;
          if (!email) {
            toast.error("Error submitting form");
          } else {
            generateCode({
              email,
            });
          }
        } else {
          toast.success("Form submitted successfully");
          if (afterSubmit) afterSubmit();
        }
      })
      .catch(() => toast.error("Error submitting form"));
  };

  // useTitle(data?.name || 'Form Builder');

  const form = useForm();

  useEffect(() => {
    if (!data) return;
    const defaultValues: { [x: string]: unknown } = {};
    data.elements.forEach(({ id, type }) => {
      if (["switch", "checkbox"].includes(type)) defaultValues[id] = false;
      else if (type === "checklist") defaultValues[id] = [];
      else defaultValues[id] = null;
    });
    form.reset(defaultValues);
  }, [data, form]);

  const onSubmit = (values: { [x: string]: string }) => {
    if (!data) return;

    for (const { id, required, type } of data.elements) {
      if (
        required &&
        (!values[id] || (type === "checklist" && values[id].length === 0))
      ) {
        toast.error("Please fill all required fields");
        return;
      }
    }

    const response = data.elements
      .filter(({ type }) => !["heading", "description"].includes(type))
      .map(({ id, label, options, type }) => ({
        elementType: type,
        question: label,
        answer:
          options && type !== "checklist"
            ? options.find(({ value }) => value === values[id])?.label ?? null
            : values[id] ?? null,
      }));

    mutation(response);
  };

  return (
    <div className="px-[1.5rem] py-2 lg:px-[3.25rem] xl:px-[6.25rem]">
      <Form {...form}>
        <form
          className="flex min-h-[calc(100dvh-240px)] lg:min-h-[calc(100dvh-230px)]  flex-col"
          onSubmit={form.handleSubmit(onSubmit)}
        >
          {isPending ? (
            <div className="my-24">
              <Fallback />
            </div>
          ) : isError ? (
            <div className="my-24">{/* <Error fullScreen={false} /> */}</div>
          ) : (
            <div className="m-auto rounded-lg py-10 shadow-md border-t-1 border border-black/5 border-x-0 h-full w-full max-w-[500px] p-1 md:p-5">
              {/* space-y-2 */}
              <ul className=" space-y-6">
                <li className="rounded-md pb-6 text-4xl font-medium text-center">
                  {data?.name}
                </li>
                {generateCode && (
                  <li>
                    <span>
                      If you already registered,{" "}
                      <a
                        className="underline cursor-pointer"
                        onClick={() => navigate("/storm/course")}
                      >
                        click here to enroll
                      </a>
                    </span>
                  </li>
                )}
                {data?.elements.map((element) => (
                  <li key={element.id}>
                    <FormField
                      control={form.control}
                      name={element.id}
                      render={({ field }) => (
                        <FormItem>
                          <FormControl>
                            <FormElementCard
                              formElement={element}
                              isView
                              field={field}
                            />
                          </FormControl>
                        </FormItem>
                      )}
                    />
                  </li>
                ))}
                {data?.isActive ? null : (
                  <li className="text-sm font-medium text-rose-700">
                    * Note: The form is closed.
                  </li>
                )}
                <li className="pt-2 flex px-5 justify-between">
                  {/* <ClearFormButton
                    onClear={() => form.reset()}
                    disabled={isLoading}
                    
                  /> */}
                  <Button
                    className="w-full"
                    disabled={!data?.isActive}
                    isLoading={isLoading}
                  >
                    Submit Form
                  </Button>
                </li>
              </ul>
            </div>
          )}
        </form>
      </Form>
    </div>
  );
}