'use client' /** * `` — thin wrapper around the canonical * ``. Does NOT reimplement form layout / validation / * primitives — it just preconfigures `` for ticket * creation: * * - Hides every contact-only field (name + email from session, * companySize / referralSource / helpCategory irrelevant). * - Slots a Subject `` into `extraTopField` (Subject isn't * part of `ContactSchema`; the wrapper manages it locally and * reads the value back in `onCustomSubmit`). * - Pre-fills the hidden name / email / helpCategory from * `useChatIdentity` so Zod's required-field validators pass even * though those inputs aren't rendered. * - Wires `onCustomSubmit` to `actions.submitTicket(...)` so the * ticket lands through the same optimistic-placeholder flow the * rest of the Help Center uses. * * Why a wrapper instead of inlining `` directly inside * ``: the Subject input needs local state + error * state + validation that conceptually pairs with the form, not the * orchestrator. Keeping that tiny state machine in its own file keeps * `` focused on list/state/pagination concerns. */ import { useState, type ChangeEvent } from 'react' import { Input, Label } from '../ui' import { ContactForm } from '../contact' import type { UseTicketActionsReturn } from './hooks/use-ticket-actions' const SUBJECT_MAX_CHARS = 200 export interface HelpCenterCreateFormProps { /** The full actions bag from `useTicketActions` — we read * `submitTicket` from it. Passing the whole bag (rather than just * the one method) keeps the wiring shape consistent with other * composition points (e.g. `` takes individual * action callbacks because the drawer needs four of them; the form * only needs one but the parent already has the bag in scope). */ actions: UseTicketActionsReturn /** Authoritative session identity, resolved by the parent * (`HelpCenterList`) which already gates rendering on * `identity.isLoading === false`. Passing these in (instead of * calling `useChatIdentity` again here) avoids a subtle race: * `useChatIdentity` is a plain `useState`+`useEffect` hook (no * shared cache), so a second call inside this child would mount * with `user = null` and a stale `sessionEmail = ''`, locking * react-hook-form's `defaultValues.email` to an empty string for * the lifetime of the form — Zod then rejects the submit silently. */ sessionName: string sessionEmail: string /** Disables every input + button when the support backend (HubSpot) * is down. Wired from the parent's * `useTicketActions.onSupportSystemDown` flag. */ supportSystemDown?: boolean } /** * Loading placeholder that mirrors ``'s outer * dimensions PIXEL-FOR-PIXEL so the page chrome doesn't shift when * identity resolves and the real form mounts. * * Verified against live DOM bounding-rect measurements at the lg * breakpoint — every section's top + height matches the real form to * the pixel (skeleton wrapper 556px == real wrapper 556px). Each * section uses the SAME flex / spacing / padding classes the real * form uses, so the gaps propagate identically; only the inner * content swaps an `` / `