Files
monie-landing/src/features/request-demo/ui/request-demo-form.tsx
Denis Krylov 014058071a
Some checks failed
Deploy monie-landing (kaniko) / build-and-deploy (push) Failing after 1m46s
chore: initialize project
2026-04-04 21:36:32 +03:00

151 lines
3.7 KiB
TypeScript

import { Button, Field, Input, NativeSelect, Text, Textarea } from "denjs-ui";
import { type FormEvent, useMemo, useState } from "react";
import { useMessages } from "#/shared/lib/i18n";
import { buildDemoRequestMailto } from "../model/build-demo-request-mailto";
import { getSpecializationOptions } from "../model/specialization-options";
export function RequestDemoForm() {
const m = useMessages();
const [submitState, setSubmitState] = useState<
"idle" | "sending" | "success" | "error"
>("idle");
const options = useMemo(() => getSpecializationOptions(m), [m]);
const specializationByValue = useMemo(
() => Object.fromEntries(options.map((item) => [item.value, item.label])),
[options],
);
const onSubmit = (event: FormEvent<HTMLFormElement>) => {
event.preventDefault();
if (typeof window === "undefined") {
setSubmitState("error");
return;
}
setSubmitState("sending");
try {
const formData = new FormData(event.currentTarget);
const name = String(formData.get("name") ?? "").trim();
const phone = String(formData.get("phone") ?? "").trim();
const specializationValue = String(
formData.get("specialization") ?? "",
).trim();
const city = String(formData.get("city") ?? "").trim();
const comment = String(formData.get("comment") ?? "").trim();
const specialization =
specializationByValue[specializationValue] ?? specializationValue;
window.location.href = buildDemoRequestMailto({
name,
phone,
specialization,
city,
comment,
locale: document.documentElement.lang,
pageUrl: window.location.href,
});
setSubmitState("success");
} catch {
setSubmitState("error");
}
};
return (
<form
className="rise-in grid gap-3 rounded-2xl border border-[var(--line)] bg-white/75 p-4 sm:grid-cols-2 sm:p-5"
style={{ animationDelay: "220ms" }}
onSubmit={onSubmit}
>
<Field label={m.form_name_label()} controlId="demo-name" required>
<Input
id="demo-name"
name="name"
placeholder={m.form_name_placeholder()}
/>
</Field>
<Field label={m.form_phone_label()} controlId="demo-phone" required>
<Input
id="demo-phone"
type="tel"
name="phone"
placeholder="+7 (999) 000-00-00"
/>
</Field>
<Field
label={m.form_specialization_label()}
controlId="demo-specialization"
required
>
<NativeSelect
id="demo-specialization"
name="specialization"
options={options}
/>
</Field>
<Field label={m.form_city_label()} controlId="demo-city">
<Input
id="demo-city"
name="city"
placeholder={m.form_city_placeholder()}
/>
</Field>
<Field
label={m.form_comment_label()}
controlId="demo-comment"
className="sm:col-span-2"
>
<Textarea
id="demo-comment"
name="comment"
rows={4}
placeholder={m.form_comment_placeholder()}
resizable={false}
/>
</Field>
<div className="sm:col-span-2 flex flex-wrap items-center justify-between gap-3 pt-1">
<Text
as="p"
size="sm"
tone="muted"
className="m-0 max-w-[36ch] text-xs text-[var(--sea-ink-soft)]"
>
{m.form_privacy_text()}
</Text>
<Button
type="submit"
size="large"
className="rounded-full"
disabled={submitState === "sending"}
>
{submitState === "sending" ? m.form_submit_busy() : m.form_submit()}
</Button>
{submitState === "success" && (
<Text
as="p"
size="sm"
className="m-0 w-full text-xs text-[var(--palm)]"
>
{m.form_submit_success()}
</Text>
)}
{submitState === "error" && (
<Text
as="p"
size="sm"
className="m-0 w-full text-xs text-[var(--coral)]"
>
{m.form_submit_error()}
</Text>
)}
</div>
</form>
);
}