Some checks failed
Deploy monie-landing (kaniko) / build-and-deploy (push) Failing after 1m46s
151 lines
3.7 KiB
TypeScript
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>
|
|
);
|
|
}
|