Files
graff.training/src/components/Main/ContactsForm.tsx
T
2024-08-19 15:06:53 +05:00

239 lines
8.6 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 InputMask from 'react-input-mask';
import { ChangeEvent, FormEvent, useState } from 'react';
import { api } from '../../api/contactsFormInstance';
import { AsteriskIcon } from '../icons/AstreskIcon';
import { LoaderIcon } from '../icons/LoaderIcon';
import { SendIcon } from '../icons/SendIcon';
import { Button } from '../../ui/Button';
import { CheckGradientIcon } from '../icons/CheckGradientIcon';
export function ContactsForm({ inModal = false }: { inModal?: boolean }) {
const [name, setName] = useState('');
const [phone, setPhone] = useState('');
const [email, setEmail] = useState('');
const [description, setDescription] = useState('');
const [isLoading, setIsLoading] = useState(false);
const [isSend, setIsSend] = useState(false);
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 ? (
<form
onSubmit={handleSubmit}
className={
'grid' +
(!inModal
? ' lg:grid-cols-3 sm:grid-cols-2 lg:col-span-9 sm:col-span-full sm:mb-20 mb-14'
: '')
}
>
<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={
(!inModal
? 'sm:border-l-0 lg:border-x-0 border max-sm:border-t-0 '
: 'border-x ') +
'feedback-field bg-transparent rounded-none 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>Телефон</span>
<AsteriskIcon />
</p>
</div>
<div
className={'relative' + (!inModal ? ' sm:max-lg:col-span-2' : '')}
>
<input
required
type="text"
value={email}
onChange={e => setEmail(e.target.value)}
className={
(!inModal ? 'max-lg:border-t-0' : '') +
' feedback-field bg-transparent border rounded-none 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' + (!inModal ? ' lg:col-span-3 sm:col-span-2' : '')
}
>
<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] h-full outline-none outline-1 -outline-offset-1 focus:outline-[#D375FF] transition-all w-full"
></textarea>
</div>
<div
className={
!inModal ? 'col-start-1 max-lg:hidden pt-4 pr-4' : 'hidden'
}
>
<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>
</div>
<div
className={
(!inModal
? 'border sm:border-r-0 max-sm:border-b-0 sm:border-t-0 lg:col-start-2 max-sm:mt-6'
: 'mt-6 border-x') +
' border-[#3D425C] 2xl:p-6 p-4 sm:mt-0 flex items-center'
}
>
<div className="text-xs desktop-figma:text-base leading-tight">
Нажимая кнопку отправить, вы принимаете{' '}
<a
href="https://graff.tech/privacypolicy"
target="_blank"
className="text-[#798FFF] cursor-pointer opacity-95 lg:hover:opacity-100 transition-all"
>
условия использования
</a>{' '}
и{' '}
<a
href="https://graff.tech/privacypolicy"
target="_blank"
className="text-[#798FFF] cursor-pointer opacity-95 lg:hover:opacity-100 transition-all"
>
политику конфиденциальности
</a>
</div>
</div>
<div
className={
(!inModal ? 'sm:border-t-0 border-t lg:col-start-3' : '') +
' border border-[#3D425C] 2xl:p-6 p-4 sm:mt-0 text-xs desktop-figma:text-base flex items-center gap-2 '
}
>
<div className="flex gap-2">
<div className="">
<AsteriskIcon />
</div>
<p></p>
<p>
Звездочкой отмечены обязательные
<br />
для заполнения поля
</p>
</div>
</div>
<div className={(!inModal ? 'lg:hidden sm:pr-4' : '') + ' pt-4'}>
<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>
</div>
</form>
) : (
<div className="flex flex-col gap-4">
<div className="flex justify-between items-center">
<p className="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>
</div>
<div className="flex flex-col gap-2">
<p className="leading-snug lg:text-2xl text-xl font-semibold">
Спасибо за подачу заявки!
</p>
<p className="lg:text-base text-sm">
Мы ценим ваш интерес к нашей компании и в ближайшее время свяжемся
с вами для уточнения деталей проекта.
</p>
</div>
</div>
)}
</>
);
}