66 lines
2.3 KiB
TypeScript
66 lines
2.3 KiB
TypeScript
'use client';
|
|
|
|
import { useState } from 'react';
|
|
import { Field } from '@/components/ui';
|
|
|
|
export function LeadForm({ source = 'contact', compact = false }: { source?: string; compact?: boolean }) {
|
|
const [busy, setBusy] = useState(false);
|
|
const [done, setDone] = useState(false);
|
|
const [error, setError] = useState<string | null>(null);
|
|
|
|
async function onSubmit(e: React.FormEvent<HTMLFormElement>) {
|
|
e.preventDefault();
|
|
setBusy(true);
|
|
setError(null);
|
|
const form = new FormData(e.currentTarget);
|
|
const body = { ...Object.fromEntries(form.entries()), source };
|
|
try {
|
|
const res = await fetch('/api/leads', {
|
|
method: 'POST',
|
|
headers: { 'Content-Type': 'application/json' },
|
|
body: JSON.stringify(body),
|
|
});
|
|
if (!res.ok) {
|
|
const data = (await res.json().catch(() => ({}))) as { error?: string };
|
|
throw new Error(data.error || 'Something went wrong.');
|
|
}
|
|
setDone(true);
|
|
e.currentTarget.reset();
|
|
} catch (err) {
|
|
setError(err instanceof Error ? err.message : 'Something went wrong.');
|
|
} finally {
|
|
setBusy(false);
|
|
}
|
|
}
|
|
|
|
if (done) {
|
|
return (
|
|
<div role="status" className="rounded-lg border border-emerald-500 bg-emerald-50 px-4 py-3 text-sm text-emerald-800">
|
|
Thanks — we'll be in touch shortly.
|
|
</div>
|
|
);
|
|
}
|
|
|
|
return (
|
|
<form className="space-y-4" onSubmit={onSubmit} noValidate>
|
|
{!compact && (
|
|
<Field label="Name" htmlFor={`lead-name-${source}`}>
|
|
<input id={`lead-name-${source}`} name="name" className="input" autoComplete="name" />
|
|
</Field>
|
|
)}
|
|
<Field label="Email" htmlFor={`lead-email-${source}`}>
|
|
<input id={`lead-email-${source}`} name="email" type="email" required className="input" autoComplete="email" />
|
|
</Field>
|
|
{!compact && (
|
|
<Field label="Message" htmlFor={`lead-message-${source}`}>
|
|
<textarea id={`lead-message-${source}`} name="message" rows={4} className="input" />
|
|
</Field>
|
|
)}
|
|
{error && <p className="text-sm text-red-600">{error}</p>}
|
|
<button type="submit" className="btn-primary w-full" disabled={busy}>
|
|
{busy ? 'Sending…' : compact ? 'Subscribe' : 'Send message'}
|
|
</button>
|
|
</form>
|
|
);
|
|
}
|