import { useEffect, useState, type FormEvent } from 'react'; import { useSearchParams } from 'react-router'; import { truth } from '../../../src/authority/select-public-facts'; const SERVICES: Array<{ value: string; label: string }> = [ { value: 'itsupport', label: 'IT Services — support, endpoints, infrastructure, deployment' }, { value: 'govweb', label: 'Government Solutions — planning, requirements, contracting, delivery' }, { value: 'security', label: 'Cyber Security — monitoring, review, response, protection' }, { value: 'general', label: 'Something else' }, ]; type Outcome = 'validation_failed' | 'rate_limited' | 'abuse_refused' | 'provider_accepted' | 'provider_rejected' | 'delivery_unknown'; interface ApiResponse { outcome: Outcome; requestId: string; title: string; message: string; fields: Record; duplicate: boolean } type Status = { kind: 'idle' } | { kind: 'sending' } | { kind: 'done'; response: ApiResponse } | { kind: 'failed'; message: string }; /** * Plain HTML form posting to the same-origin inquiry endpoint; it works with JavaScript off (303 to the generic receipt). * With JavaScript, the same POST is made with fetch and the backend's outcome is shown verbatim — success only on provider acceptance. */ export function InquiryForm({ delivery, onOutcome }: { delivery: 'connected' | 'not-connected'; onOutcome?: (outcome: Outcome) => void }) { const [params] = useSearchParams(); const preset = params.get('project') ?? 'general'; const from = params.get('from') ?? ''; const [status, setStatus] = useState({ kind: 'idle' }); // Prerendered HTML has no query string; adopt the door's intent after hydration instead of relying on mount-only defaults. const [service, setService] = useState('general'); const [origin, setOrigin] = useState(''); useEffect(() => { setService(SERVICES.some(s => s.value === preset) ? preset : 'general'); setOrigin(from); }, [preset, from]); const fields = status.kind === 'done' ? status.response.fields : {}; async function submit(event: FormEvent) { if (delivery !== 'connected') return; event.preventDefault(); const form = event.currentTarget; const data = Object.fromEntries(new FormData(form).entries()) as Record; setStatus({ kind: 'sending' }); try { const response = await fetch(form.action, { method: 'POST', headers: { 'content-type': 'application/json', accept: 'application/json' }, body: JSON.stringify(data), credentials: 'same-origin' }); const body = (await response.json()) as ApiResponse; setStatus({ kind: 'done', response: body }); onOutcome?.(body.outcome); if (body.outcome === 'provider_accepted') form.reset(); } catch { setStatus({ kind: 'failed', message: 'The request could not be sent from this browser. Nothing was stored. Call or write to the address in the footer.' }); } } const done = status.kind === 'done' ? status.response : null; const accepted = done?.outcome === 'provider_accepted'; return (

{delivery === 'connected' ? 'Non-sensitive inquiries only. No passwords, incident files or sensitive government material.' : `Demo host: the inquiry service is not connected here, so this form cannot send. Call ${truth.org.telephoneDisplay || truth.org.telephone} or write to ${truth.org.email}.`}

{done && (
{done.title} {done.message}{done.duplicate ? ' (This message had already been received.)' : ''} Reference {done.requestId}
)} {status.kind === 'failed' &&
{status.message}
}
{fields.name &&

{fields.name}

}
{fields.email &&

{fields.email}

}