Untitled
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