Files
graff.estate-nextjs/src/components/ContactsForm.tsx
T
2024-03-18 13:38:16 +05:00

213 lines
8.4 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import { ChangeEvent, FormEvent, useState } from "react";
import AsteriskIcon from "./icons/AsteriskIcon";
import InputMask from "react-input-mask";
import "./ContactsForm.css";
import Button from "./Button";
import SendIcon from "./icons/SendIcon";
import LoaderIcon from "./icons/LoaderIcon";
import api from "../utils/api";
import CheckGradientIcon from "./icons/CheckGradientIcon";
import useModalStore from "../stores/useModalStore";
import Close2Icon from "./icons/Close2Icon";
function ContactsForm() {
const [name, setName] = useState<string>("");
const [phone, setPhone] = useState<string>("");
const [email, setEmail] = useState<string>("");
const [description, setDescription] = useState<string>("");
const [isLoading, setIsLoading] = useState<boolean>(false);
const [isSend, setIsSend] = useState<boolean>(false);
const [setModal] = useModalStore((state) => [state.setModal]);
function handleSubmit(e: FormEvent<HTMLFormElement>) {
e.preventDefault();
sendMail();
}
async function sendMail() {
setIsLoading(true);
try {
await api
.post("mail", {
json: {
fullname: name,
phone,
email,
request: description,
},
})
.json();
setIsSend(true);
setIsLoading(false);
} catch (error) {
setIsLoading(false);
if (error instanceof Error) {
alert(error.message);
}
}
}
return (
<>
{!isSend ? (
<div className="flex flex-col gap-5">
<div className="flex justify-between items-center">
<p className="font-gilroy text-gradient sm:text-2xl text-xl w-fit font-semibold">
Свяжитесь с нами
</p>
<button
onClick={() => setModal(null)}
className="p-2 hover:bg-white hover:bg-opacity-10 transition-colors rounded-full"
>
<Close2Icon />
</button>
</div>
<form onSubmit={handleSubmit} className="flex flex-col gap-6">
<div>
<div className="relative">
<input
required
type="text"
value={name}
onChange={(e) => setName(e.target.value)}
className="feedback-field bg-transparent border border-[#3D425C] rounded-none sm:pt-12 sm:pb-4 sm:px-4 pt-8 pb-3 px-3 outline-none outline-1 -outline-offset-1 focus:outline-[#D375FF] transition-all w-full"
/>
<p className="feedback-placeholder lg:text-base text-sm absolute sm:pt-4 sm:pb-4 sm:px-4 sm:top-4 pt-3 pb-3 px-3 top-3 w-full opacity-50 transition-all pointer-events-none flex justify-between items-center">
<span>Имя</span>
<AsteriskIcon />
</p>
</div>
<div className="relative">
<InputMask
required
type="tel"
mask={"+999999999999999"}
maskChar={null}
value={phone}
onChange={(e: ChangeEvent<HTMLInputElement>) =>
setPhone(e.target.value)
}
className={[
"feedback-field bg-transparent border rounded-none border-t-0 border-[#3D425C] sm:pt-12 sm:pb-4 sm:px-4 pt-8 pb-3 px-3 outline-none outline-1 -outline-offset-1 focus:outline-[#D375FF] transition-all w-full",
].join(" ")}
/>
<p className="feedback-placeholder lg:text-base text-sm absolute sm:pt-4 sm:pb-4 sm:px-4 sm:top-4 pt-3 pb-3 px-3 top-3 w-full opacity-50 transition-all pointer-events-none flex justify-between items-center">
<span>Телефон</span>
<AsteriskIcon />
</p>
</div>
<div className="relative">
<input
required
type="text"
value={email}
onChange={(e) => setEmail(e.target.value)}
className="feedback-field bg-transparent border rounded-none border-t-0 border-[#3D425C] sm:pt-12 sm:pb-4 sm:px-4 pt-8 pb-3 px-3 outline-none outline-1 -outline-offset-1 focus:outline-[#D375FF] transition-all w-full"
/>
<p className="feedback-placeholder lg:text-base text-sm absolute sm:pt-4 sm:pb-4 sm:px-4 sm:top-4 pt-3 pb-3 px-3 top-3 w-full opacity-50 transition-all pointer-events-none flex justify-between items-center">
<span>Email</span>
<AsteriskIcon />
</p>
</div>
<div className="relative">
<textarea
placeholder="Опишите вашу задачу"
value={description}
onChange={(e) => setDescription(e.target.value)}
className="feedback-field bg-transparent resize-none border rounded-none border-t-0 border-[#3D425C] p-4 sm:min-h-[192px] min-h-[128px] outline-none outline-1 -outline-offset-1 focus:outline-[#D375FF] transition-all w-full"
></textarea>
</div>
<div
className="border border-t-0 border-[#3D425C] 2xl:p-6 p-4 sm:mt-0 flex items-center"
style={{ marginTop: "-6px" }}
>
<div className="text-xs leading-tight">
Нажимая кнопку отправить, вы принимаете{" "}
<a
href="https://graff.tech/privacypolicy"
target="_blank"
className="text-[#798FFF] cursor-pointer opacity-95 hover:opacity-100 transition-all"
>
условия использования
</a>{" "}
и{" "}
<a
href="https://graff.tech/privacypolicy"
target="_blank"
className="text-[#798FFF] cursor-pointer opacity-95 hover:opacity-100 transition-all"
>
политику конфиденциальности
</a>
</div>
</div>
<div className="border border-t-0 border-[#3D425C] 2xl:p-6 p-4 sm:mt-0 text-xs flex items-center gap-2">
<div className="flex gap-2">
<div className="">
<AsteriskIcon />
</div>
<p></p>
<p>
Звездочкой отмечены обязательные
<br />
для заполнения поля
</p>
</div>
</div>
</div>
<Button
width="full"
disabled={isLoading}
icon={
isLoading ? (
<LoaderIcon className="relative 2xl:w-8 2xl:h-8 w-6 h-6 animate-spin" />
) : (
<SendIcon className="relative 2xl:w-8 2xl:h-8 w-6 h-6" />
)
}
className="py-4"
>
Отправить
</Button>
</form>
</div>
) : (
<div className="flex flex-col gap-4">
<div className="flex justify-between items-center">
<p className="font-gilroy text-gradient sm:text-2xl text-xl w-fit font-semibold flex items-center gap-2">
<span>Заявка отправлена</span>
<CheckGradientIcon className="lg:w-8 lg:h-8 w-6 h-6" />
</p>
<button
onClick={() => setModal(null)}
className="p-2 hover:bg-white hover:bg-opacity-10 transition-colors rounded-full"
>
<Close2Icon />
</button>
</div>
<div className="flex flex-col gap-2">
<p className="font-gilroy leading-snug lg:text-2xl text-xl font-semibold">
Спасибо за подачу заявки!
</p>
<p className="lg:text-base text-sm">
Мы ценим ваш интерес к нашей компании и в ближайшее время свяжемся
с вами для уточнения деталей проекта.
</p>
</div>
</div>
)}
</>
);
}
export default ContactsForm;