Snai3i-LandingPage-FormBuilder / frontend / src / pages / FormPage / 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,
  useGetFormQuery,
} from '@/app/backend/endpoints/forms';
import { useParams } from 'react-router-dom';

export default function FormPage() {
  const { id } = useParams();
  const {
    data: dataWrap,
    isLoading: isPending,
    isError,
  } = useGetFormQuery(id!, {
    skip: !id,
  });
  const data = dataWrap?.data;

  const [createResponse, { isLoading }] = useCreateResponseMutation();
  const mutation = (response: FormResponseI[]) => {
    createResponse({ formId: data?._id ?? '', data: response })
      .unwrap()
      .then(() => {
        toast.success('Form submitted successfully');
      })
      .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] bg-slate-50/50">
      <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="bg-white 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>
                {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>
  );
}