// Предзаполнение формы заявки из CTA в любой секции. // Маленький store вместо контекста: секции остаются серверными компонентами, // кнопки — клиентскими островками, форма подписывается на store сама. import type { Interest } from '@kvarta/shared/lead'; export const LEAD_SECTION_ID = 'lead'; export const LEAD_NAME_INPUT_ID = 'lead-name'; export type LeadPrefillInput = { interest: Interest; comment?: string; /** id секции, откуда пришла CTA, — пойдёт в submitPage последнего касания */ source?: string; }; export type LeadPrefill = LeadPrefillInput & { seq: number }; type Listener = (prefill: LeadPrefill) => void; let current: LeadPrefill | null = null; const listeners = new Set(); export function getLeadPrefill(): LeadPrefill | null { return current; } export function subscribeLeadPrefill(listener: Listener): () => void { listeners.add(listener); return () => { listeners.delete(listener); }; } /** Выставить значения формы, плавно доскроллить до #lead и поставить фокус в поле имени. */ export function prefillLead(input: LeadPrefillInput): void { current = { ...input, seq: (current?.seq ?? 0) + 1 }; for (const listener of listeners) listener(current); if (typeof document === 'undefined') return; const reduceMotion = window.matchMedia?.('(prefers-reduced-motion: reduce)').matches ?? false; document .getElementById(LEAD_SECTION_ID) ?.scrollIntoView({ behavior: reduceMotion ? 'auto' : 'smooth', block: 'start' }); // preventScroll — чтобы фокус не оборвал плавный скролл рывком к полю document.getElementById(LEAD_NAME_INPUT_ID)?.focus({ preventScroll: true }); } /** * Применить предзаполнение к текущим значениям формы. * Комментарий, который посетитель напечатал сам, не трогаем; свой прошлый предзаполненный — заменяем. */ export function applyPrefill( values: T, prefill: LeadPrefillInput, lastPrefilledComment: string | null, ): { values: T; prefilledComment: string | null } { const typedByVisitor = values.comment.trim() !== '' && values.comment !== lastPrefilledComment; if (typedByVisitor) { return { values: { ...values, interest: prefill.interest }, prefilledComment: lastPrefilledComment }; } const comment = prefill.comment ?? ''; return { values: { ...values, interest: prefill.interest, comment }, prefilledComment: comment === '' ? null : comment, }; }