feat(home): seção Sobre com prova por ponto, contato por oferta e hero com a Lavação 047 na tela larga
This commit is contained in:
1 parent
d356c364e0
commit
9fd1570426
33 files changed
+1128
-369
No files matched your search
@@ -5,11 +5,19 @@ import type { FormEvent, MouseEvent, ReactNode } from "react";
|
||||
import { useEffect, useState } from "react";
|
||||
import { trackEmailClick, trackWhatsAppOpen } from "@/lib/analytics";
|
||||
import { CONTACT_EMAIL } from "@/lib/site-navigation";
|
||||
import { buildWhatsAppUrl, getWhatsAppDisplayNumber } from "@/lib/whatsapp";
|
||||
import {
|
||||
buildWhatsAppUrl,
|
||||
getWhatsAppDisplayNumber,
|
||||
OFFER_SUBJECTS,
|
||||
} from "@/lib/whatsapp";
|
||||
import {
|
||||
CONTACT_FORM_ID,
|
||||
CONTACT_KIND_EVENT,
|
||||
CONTACT_KIND_PARAM,
|
||||
CONTACT_KINDS,
|
||||
CONTACT_SUBJECT_OPTIONS,
|
||||
type ContactKind,
|
||||
contactKindForSubject,
|
||||
contactSubjectForKind,
|
||||
DEFAULT_CONTACT_SUBJECT,
|
||||
} from "./contact-subject";
|
||||
@@ -162,13 +170,17 @@ export default function Contact() {
|
||||
message: "",
|
||||
});
|
||||
const [errors, setErrors] = useState<FieldErrors>({});
|
||||
// A oferta que a pessoa escolheu na home (botão ou `?tipo=`); some se ela trocar o tipo no próprio formulário.
|
||||
const [chosenOffer, setChosenOffer] = useState<ContactKind | null>(null);
|
||||
|
||||
// O tipo de projeto pode vir da oferta escolhida na home: pelo endereço (`/?tipo=site#contact`, ao chegar de outra
|
||||
// página) ou pelo evento que o botão da oferta dispara na própria página. Tipo desconhecido não muda nada.
|
||||
useEffect(() => {
|
||||
const choose = (kind: string | null | undefined) => {
|
||||
const subject = contactSubjectForKind(kind);
|
||||
if (subject) setFormData((current) => ({ ...current, subject }));
|
||||
if (!subject) return;
|
||||
setFormData((current) => ({ ...current, subject }));
|
||||
setChosenOffer(contactKindForSubject(subject) ?? null);
|
||||
};
|
||||
choose(new URLSearchParams(window.location.search).get(CONTACT_KIND_PARAM));
|
||||
const onChoose = (event: Event) =>
|
||||
@@ -179,6 +191,7 @@ export default function Contact() {
|
||||
|
||||
const updateField = (field: ContactField | "subject", value: string) => {
|
||||
setFormData((current) => ({ ...current, [field]: value }));
|
||||
if (field === "subject") setChosenOffer(null);
|
||||
if (field !== "subject" && errors[field]) {
|
||||
setErrors((current) => ({ ...current, [field]: undefined }));
|
||||
}
|
||||
@@ -195,6 +208,12 @@ export default function Contact() {
|
||||
return firstInvalid !== undefined;
|
||||
};
|
||||
|
||||
// O link direto de WhatsApp leva o tipo escolhido (o nome da oferta, em frase) na mensagem; sem oferta, fala de "um projeto".
|
||||
const selectedOffer = contactKindForSubject(formData.subject);
|
||||
const directSubject = selectedOffer
|
||||
? OFFER_SUBJECTS[selectedOffer]
|
||||
: undefined;
|
||||
|
||||
const handleSubmit = (e: FormEvent<HTMLFormElement>) => {
|
||||
e.preventDefault();
|
||||
if (hasInvalidField(e.currentTarget)) return;
|
||||
@@ -243,6 +262,7 @@ export default function Contact() {
|
||||
<div className="mt-sp-8 divide-y divide-white/10 border-y border-white/10">
|
||||
<WhatsAppLink
|
||||
placement="contact_direct"
|
||||
service={directSubject}
|
||||
className="group flex min-h-20 items-center gap-sp-4 rounded-sm py-sp-5 text-white no-underline"
|
||||
>
|
||||
<span className="flex h-11 w-11 shrink-0 items-center justify-center rounded-full bg-[#25d366]/10 text-[#25d366]">
|
||||
@@ -283,6 +303,7 @@ export default function Contact() {
|
||||
</div>
|
||||
|
||||
<form
|
||||
id={CONTACT_FORM_ID}
|
||||
onSubmit={handleSubmit}
|
||||
noValidate
|
||||
aria-labelledby="contact-form-title"
|
||||
@@ -358,6 +379,17 @@ export default function Contact() {
|
||||
</select>
|
||||
)}
|
||||
</Field>
|
||||
{/* <output> (role status): o texto muda quando uma oferta da home é escolhida, e o leitor de tela o anuncia; vazio, não ocupa espaço */}
|
||||
<output className="block !mt-sp-2 font-display text-[15px] leading-6 text-white/85 empty:!mt-0">
|
||||
{chosenOffer && (
|
||||
<>
|
||||
Você escolheu:{" "}
|
||||
<strong className="font-semibold text-white">
|
||||
{CONTACT_KINDS[chosenOffer]}
|
||||
</strong>
|
||||
</>
|
||||
)}
|
||||
</output>
|
||||
<Field
|
||||
id="contact-message"
|
||||
label="Contexto do projeto"
|
||||
|
||||
Reference in new issue
Block a user