Untitled

 avatar
unknown
plain_text
5 months ago
12 kB
7
Indexable
"use client";
import React, { useEffect, useState } from "react";
import {
  Listbox,
  ListboxButton,
  ListboxOption,
  ListboxOptions,
} from "@headlessui/react";
import { ChevronDown, Check, CloseCross } from "app/icons";
import { positions } from "app/data";
import type {
  AlertType,
  FileAttachment,
  JoinFormData,
  JoinUsModalProps,
  PositionType,
} from "app/types";
import { Modal, ModalContent, ModalHeader, ModalBody } from "@nextui-org/react";
import { Alert, FileUpload, Button, Typography } from "app/design-system";
import { useForm } from "react-hook-form";
import { zodResolver } from "@hookform/resolvers/zod";
import { JoinSchema } from "app/utils/JoinSchema";

const COMPANY_MAIL = process.env.NEXT_PUBLIC_HR_MAIL;

const initialFormData: JoinFormData = {
  "full-name": "",
  email: "",
  phone: "",
  position: "",
  resume: undefined,
};

export default function JoinUsModal({
  isOpen,
  onOpenChange,
}: JoinUsModalProps) {
  const [filePaths, setFilePaths] = useState<FileAttachment[]>([]);
  const [loading, setLoading] = useState<boolean>(false);
  const [selected, setSelected] = useState<PositionType>(positions[0]);
  const [formData, setFormData] = useState<JoinFormData>(initialFormData);
  const [alert, setAlert] = useState<AlertType>({
    show: false,
    type: "",
    message: "",
  });

  const {
    register,
    handleSubmit,
    reset,
    formState: { errors },
  } = useForm<JoinFormData>({
    resolver: zodResolver(JoinSchema),
  });

  const handleFileUploaded = (paths: FileAttachment) => {
    if (Array.isArray(paths)) {
      setFilePaths(paths[0]);
    }
  };

  useEffect(() => {
    // @ts-ignore
    setFormData((prevState) => ({ ...prevState, position: selected?.name }));
  }, [selected]);

  const handleChange = (event: any) => {
    const { name, value } = event.target;
    setFormData((prevState) => ({ ...prevState, [name]: value }));
  };

  const onSubmit = async () => {
    setAlert({ show: false, type: "", message: "" });
    setLoading(true);
    const response = await fetch("/api/send-email", {
      method: "POST",
      headers: { "content-type": "application/json" },
      body: JSON.stringify({
        attachments: [filePaths],
        from: `${formData.email}`,
        to: COMPANY_MAIL,
        subject: `${formData.position}`,
        text: `name: ${formData["full-name"]} \n
      phone: ${formData.phone} \n
      position: ${formData.position}`,
      }),
    });

    if (response.ok) {
      setAlert({
        show: true,
        type: "success",
        message: "Form submitted successfully!",
      });
      setLoading(false);
      reset();
      setFilePaths([]);
    } else {
      setAlert({
        show: true,
        type: "error",
        message: "Failed to submit the form. Please try again.",
      });
      setLoading(false);
    }
  };

  const handleToggle = () => {
    onOpenChange(!isOpen);
    setAlert({ show: false, type: "", message: "" });
  };

  return (
    <Modal
      isOpen={isOpen}
      hideCloseButton
      onOpenChange={onOpenChange}
      radius="md"
      classNames={{
        wrapper: "flex items-center justify-center",
        backdrop:
          "z-50 backdrop-blur-md bg-white/20 w-screen h-screen fixed inset-0",
        base: "my-0 max-w-xs md:max-w-lg space-y-4 duration-300 ease-out data-[closed]:scale-95 data-[closed]:opacity-0 bg-primary-950 p-[24px]",
        header: "!mt-0 py-0 px-0 m-0",
        body: "px-0 py-0 ",
      }}
    >
      <ModalContent>
        <ModalHeader className="flex flex-row justify-between">
          <Typography size={"sh3"}>Join Us</Typography>
          <CloseCross onClick={handleToggle} />
        </ModalHeader>
        <ModalBody>
          <form onSubmit={handleSubmit(onSubmit)}>
            <div className="md:mt-8 grid grid-cols-1 gap-x-6 gap-y-4 sm:grid-cols-6">
              <div className="col-span-full space-y-2">
                <Typography size="label" className="select-none">
                  Full Name <span className="text-red-950">*</span>
                </Typography>
                <div className="mt-2">
                  <input
                    {...register("full-name")}
                    onChange={handleChange}
                    id="full-name"
                    name="full-name"
                    type="text"
                    placeholder="Ahmed"
                    autoComplete="full-name"
                    className="bg-primary-900  focus:border-primary-200 placeholder:text-primary-400 bordered-[4px] h-[48px] border-[1px] border-primary-700 relative w-full rounded-md bordered-[4px] py-1.5 pl-3 pr-10 text-left text-sm text-primary-400 shadow-sm ring-0 focus:ring-transparent ring-inset  focus:outline-none sm:text-sm sm:leading-6"
                  />
                  {errors["full-name"] && (
                    <Typography color="red" size="b4">
                      {errors["full-name"].message}
                    </Typography>
                  )}
                </div>
              </div>
              <div className="col-span-full space-y-2">
                <Typography size="label" className="select-none">
                  Email <span className="text-red-950">*</span>
                </Typography>
                <div className="mt-2">
                  <input
                    {...register("email")}
                    onChange={handleChange}
                    id="email"
                    name="email"
                    type="email"
                    placeholder="example@gmail.com"
                    autoComplete="email"
                    className="bg-primary-900  focus:border-primary-200 bordered-[4px] placeholder:text-primary-400 h-[48px] border-[1px] border-primary-700 relative w-full rounded-md bordered-[4px] py-1.5 pl-3 pr-10 text-left text-sm text-primary-400 shadow-sm ring-0 focus:ring-transparent ring-inset  focus:outline-none sm:text-sm sm:leading-6"
                  />
                  {errors.email && (
                    <Typography color="red" size="b4">
                      {errors.email.message}
                    </Typography>
                  )}
                </div>
              </div>
              <div className="col-span-full space-y-2">
                <Typography size="label" className="select-none">
                  Phone Number <span className="text-red-950">*</span>
                </Typography>
                <div className="mt-2">
                  <input
                    {...register("phone")}
                    onChange={handleChange}
                    id="phone"
                    name="phone"
                    type="tel"
                    autoComplete="phone"
                    placeholder="+971 1112345"
                    className="bg-primary-900  focus:border-primary-200 bordered-[4px] h-[48px] placeholder:text-primary-400 border-[1px] border-primary-700 relative w-full rounded-md bordered-[4px] py-1.5 pl-3 pr-10 text-left text-sm text-primary-400 shadow-sm ring-0 focus:ring-transparent ring-inset  focus:outline-none sm:text-sm sm:leading-6"
                  />
                  {errors.phone && (
                    <Typography color="red" size="b4">
                      {errors.phone.message}
                    </Typography>
                  )}
                </div>
              </div>
              <div className="col-span-full space-y-2 z-20 relative">
                <Listbox as="div" value={selected} onChange={setSelected}>
                  <Typography size="label" className="select-none">
                    Position <span className="text-red-950">*</span>
                  </Typography>
                  <div className="relative mt-2">
                    <ListboxButton className="bg-primary-900  focus:border-primary-200 bordered-[4px] h-[48px] border-[1px] border-primary-700 relative w-full rounded-md bordered-[4px] py-1.5 pl-3 pr-10 text-left text-sm text-primary-400 shadow-sm ring-0 focus:ring-transparent ring-inset  focus:outline-none sm:text-sm sm:leading-6">
                      <span className="block truncate">
                        {selected && selected.name}
                      </span>
                      <span className="pointer-events-none absolute inset-y-0 right-0 flex items-center pr-2">
                        <ChevronDown />
                      </span>
                    </ListboxButton>
                    <ListboxOptions
                      onClick={(e) => e.stopPropagation()}
                      transition
                      className="absolute z-20 mt-1 max-h-60 w-full rounded-md bg-primary-900 py-1 text-base shadow-lg ring-1 ring-black ring-opacity-5 focus:outline-none data-[closed]:data-[leave]:opacity-0 data-[leave]:transition data-[leave]:duration-100 data-[leave]:ease-in sm:text-sm"
                    >
                      {positions.map((position) => (
                        <ListboxOption
                          key={position.id}
                          value={position}
                          onClick={(event) => {
                            event.stopPropagation(); // Prevent event from bubbling up
                          }}
                          className="group relative cursor-pointer select-none py-2 pl-3 pr-9 text-primary-400 data-[focus]:bg-primary-600 data-[focus]:text-white"
                        >
                          <span className="block truncate font-normal group-data-[selected]:font-semibold">
                            {position.name}
                          </span>

                          <span className="absolute inset-y-0 right-0 flex items-center pr-4 text-primary-50 group-data-[focus]:text-white [.group:not([data-selected])_&]:hidden">
                            <Check />
                          </span>
                        </ListboxOption>
                      ))}
                    </ListboxOptions>
                  </div>
                </Listbox>
              </div>
              <div className="col-span-full space-y-2">
                <Typography size="label" className="select-none">
                  Resume <span className="text-red-950">*</span>
                </Typography>
                <div className="mt-2 flex justify-center rounded-lg border border-dashed border-white/25 px-6 py-10">
                  <div className="flex justify-center flex-col items-center text-center">
                    <FileUpload
                      type="file"
                      {...register("resume")}
                      id="resume"
                      name="resume"
                      className="sr-only"
                      accept="application/pdf, application/msword"
                      onChange={handleChange}
                      onFileUploaded={handleFileUploaded}
                    />
                  </div>
                </div>
                {errors.resume && (
                  <Typography color="red" size="b4">
                    {errors.resume.message}
                  </Typography>
                )}
              </div>
            </div>
            <div className="mt-[24px]">
              <Button disabled={loading} block>
                Let’s Talk Now
              </Button>
              <br />
              {alert.show && (
                <Alert type={alert.type} message={alert.message} />
              )}
            </div>
          </form>
        </ModalBody>
      </ModalContent>
    </Modal>
  );
}

// usage
      <JoinUsModal isOpen={isOpen} onOpenChange={onOpenChange} />
Editor is loading...
Leave a Comment