upd
This commit is contained in:
@@ -0,0 +1,187 @@
|
||||
import ky from "ky";
|
||||
import { ChangeEvent, FormEvent, useState } from "react";
|
||||
import { Trans, useTranslation } from "react-i18next";
|
||||
import InputMask from "react-input-mask";
|
||||
import AsteriskIcon from "./icons/AsteriskIcon";
|
||||
import SendIcon from "./icons/SendIcon";
|
||||
import CheckGradientIcon from "./icons/CheckGradientIcon";
|
||||
import LoaderIcon from "./icons/LoaderIcon";
|
||||
|
||||
function FeedbackForm() {
|
||||
const { t } = useTranslation();
|
||||
const [name, setName] = useState<string>("");
|
||||
const [phone, setPhone] = useState<string>("");
|
||||
const [email, setEmail] = useState<string>("");
|
||||
const [description, setDescription] = useState<string>("");
|
||||
const [isSend, setIsSend] = useState<boolean>(false);
|
||||
const [isLoading, setIsLoading] = useState<boolean>(false);
|
||||
|
||||
async function sendMail(e: FormEvent<HTMLFormElement>) {
|
||||
e.preventDefault();
|
||||
|
||||
setIsLoading(true);
|
||||
|
||||
try {
|
||||
await ky
|
||||
.post(`https://estate.graff.tech/api/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 (
|
||||
<form
|
||||
className="grid lg:grid-cols-3 sm:grid-cols-2 relative"
|
||||
onSubmit={(e) => void sendMail(e)}
|
||||
>
|
||||
<div className="relative col-span-1">
|
||||
<input
|
||||
required
|
||||
type="text"
|
||||
value={name}
|
||||
onChange={(e) => setName(e.target.value)}
|
||||
className="feedback-field bg-transparent border border-[#3D425C] rounded-none lg:p-6 lg:pt-14 p-4 pt-12 outline-none outline-1 -outline-offset-1 focus:outline-[#D375FF] transition-all w-full"
|
||||
/>
|
||||
<p className="feedback-placeholder lg:text-base text-sm absolute lg:top-4 top-5 left-0 w-full lg:p-6 p-4 opacity-50 transition-all pointer-events-none flex justify-between">
|
||||
<span>
|
||||
<Trans i18nKey={"feedback.form.field1"}>Имя</Trans>
|
||||
</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 sm:border-l-0 sm:border-t border-t-0 border-l border-[#3D425C] lg:p-6 lg:pt-14 p-4 pt-12 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 lg:top-4 top-5 left-0 w-full lg:p-6 p-4 opacity-50 transition-all pointer-events-none flex justify-between">
|
||||
<span>
|
||||
<Trans i18nKey={"feedback.form.field2"}>Телефон</Trans>
|
||||
</span>
|
||||
<AsteriskIcon />
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div className="relative lg:col-span-1 sm:col-span-2 col-span-1">
|
||||
<input
|
||||
required
|
||||
type="text"
|
||||
value={email}
|
||||
onChange={(e) => setEmail(e.target.value)}
|
||||
className="feedback-field bg-transparent border rounded-none lg:border-l-0 lg:border-t border-t-0 border-[#3D425C] lg:p-6 lg:pt-14 p-4 pt-12 outline-none outline-1 -outline-offset-1 focus:outline-[#D375FF] transition-all w-full"
|
||||
/>
|
||||
<p className="feedback-placeholder lg:text-base text-sm absolute lg:top-4 top-5 left-0 w-full lg:p-6 p-4 opacity-50 transition-all pointer-events-none flex justify-between">
|
||||
<span>Email</span>
|
||||
<AsteriskIcon />
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div className="relative lg:col-span-3 sm:col-span-2 h-[194px]">
|
||||
<textarea
|
||||
placeholder={t("feedback.form.field3").toString()}
|
||||
value={description}
|
||||
onChange={(e) => setDescription(e.target.value)}
|
||||
className="feedback-field bg-transparent resize-none border rounded-none border-t-0 border-[#3D425C] lg:p-6 p-4 h-full outline-none outline-1 -outline-offset-1 focus:outline-[#D375FF] transition-all w-full"
|
||||
></textarea>
|
||||
</div>
|
||||
|
||||
<div className="2xl:pt-6 2xl:pr-6 pt-4 sm:pr-4 lg:order-none order-last flex items-center">
|
||||
<button
|
||||
disabled={isLoading}
|
||||
className="group relative px-6 py-4 2xl:text-base text-sm bg-gradient rounded-full font-medium flex justify-between items-center w-full transition-opacity disabled:opacity-75"
|
||||
>
|
||||
<div className="absolute top-0 left-0 w-full h-full rounded-full bg-black opacity-0 group-hover:opacity-10 transition-all"></div>
|
||||
<span className="relative">
|
||||
<Trans i18nKey={"feedback.form.button"}>Отправить</Trans>
|
||||
</span>
|
||||
{!isLoading ? (
|
||||
<SendIcon className="relative 2xl:w-8 2xl:h-8 w-6 h-6" />
|
||||
) : (
|
||||
<LoaderIcon className="relative 2xl:w-8 2xl:h-8 w-6 h-6 animate-spin" />
|
||||
)}
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<div className="border sm:border-t-0 border-t border-[#3D425C] 2xl:p-6 p-4 sm:mt-0 mt-6 flex items-center">
|
||||
<div className="text-xs leading-tight">
|
||||
<Trans i18nKey={"feedback.form.desc1.text1"}>
|
||||
Нажимая кнопку отправить, вы принимаете
|
||||
</Trans>{" "}
|
||||
<a className="text-[#798FFF] cursor-pointer opacity-95 hover:opacity-100 transition-all">
|
||||
<Trans i18nKey={"feedback.form.desc1.link1"}>
|
||||
условия использования
|
||||
</Trans>
|
||||
</a>{" "}
|
||||
<Trans i18nKey={"feedback.form.desc1.text2"}>и</Trans>{" "}
|
||||
<a className="text-[#798FFF] cursor-pointer opacity-95 hover:opacity-100 transition-all">
|
||||
<Trans i18nKey={"feedback.form.desc1.link2"}>
|
||||
политику конфиденциальности
|
||||
</Trans>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="border border-t-0 sm:border-l-0 border-[#3D425C] 2xl:p-6 p-4 text-xs flex items-center gap-2">
|
||||
<div className="flex gap-2">
|
||||
<div className="">
|
||||
<AsteriskIcon />
|
||||
</div>
|
||||
<p>—</p>
|
||||
<p className="leading-tight">
|
||||
<Trans i18nKey={"feedback.form.desc2"}>
|
||||
Звездочкой отмечены обязательные
|
||||
<br />
|
||||
для заполнения поля
|
||||
</Trans>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{isSend && (
|
||||
<div className="absolute top-0 left-0 w-full h-full bg-[#14161F] border border-[#3D425C] p-6 flex flex-col justify-between">
|
||||
<p className="text-gradient text-xl font-gilroy leading-tight font-semibold flex items-center gap-2">
|
||||
<span>Заявка отправлена</span>
|
||||
<CheckGradientIcon className="lg:w-8 lg:h-8 w-6 h-6" />
|
||||
</p>
|
||||
|
||||
<div className="flex flex-col gap-2">
|
||||
<p className="font-gilroy leading-snug lg:text-2xl text-xl font-semibold">
|
||||
Спасибо за подачу заявки!
|
||||
</p>
|
||||
|
||||
<p className="lg:w-1/2 sm:w-2/3 lg:text-base text-sm">
|
||||
Мы ценим ваш интерес к нашей компании и в ближайшее время свяжемся
|
||||
с вами для уточнения деталей проекта.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
</form>
|
||||
);
|
||||
}
|
||||
|
||||
export default FeedbackForm;
|
||||
Reference in New Issue
Block a user