'use client' import { useEffect, useRef, useState } from 'react' import { HomeSearchHitRow } from '@/components/campaign/dashboard/HomeSearchHitRow' import { HomeSearchMunicipalityVoteTrailing } from '@/components/campaign/dashboard/HomeSearchMunicipalityVoteTrailing' import { useHomeSearchQuery } from '@/components/campaign/dashboard/useHomeSearchQuery' import { CampaignSearchInput } from '@/components/campaign/shared/CampaignSearchInput' import { CampaignWizardShell } from '@/components/campaign/shared/CampaignWizardShell' import { wizardActionHref } from '@/lib/campaignActionRoutes' import type { HomeSearchMunicipalityHit, WizardMunicipalitySearchSuccessResponse, } from '@/lib/campaignHomeSearchHits' import { HOME_SEARCH_GENERIC_ERROR_MESSAGE } from '@/lib/campaignHomeSearchMessages' import { postCampaignJson } from '@/lib/campaignJsonRequest' import { WIZARD_MUNICIPALITY_SEARCH_EMPTY, WIZARD_MUNICIPALITY_SEARCH_LABEL, WIZARD_MUNICIPALITY_SEARCH_PLACEHOLDER, WIZARD_MUNICIPALITY_STEP_TITLE, wizardFlowTitleForSlug, } from '@/lib/campaignWizardCopy' import { HOME_SEARCH_QUERY_MAX_LENGTH } from '@/lib/schemas/homeSearch' const HOME_SEARCH_ROUTE = '/campanha/home-search' const WIZARD_MUNICIPALITY_SEARCH_INPUT_ID = 'wizardMunicipalitySearchQuery' type WizardSearchResultsState = | { status: 'idle' } | { status: 'loading' } | { status: 'success'; municipalities: HomeSearchMunicipalityHit[] } | { status: 'error'; message: string } type WizardMunicipalitySearchStepProps = { actionSlug: string previousHref: string } export const WizardMunicipalitySearchStep = ({ actionSlug, previousHref, }: WizardMunicipalitySearchStepProps) => { const { query, setRaw, isDebouncing } = useHomeSearchQuery() const [results, setResults] = useState({ status: 'idle' }) const requestSeq = useRef(0) const suggestMode = !query.isActive const searchMode = query.isActive const resultsBusy = isDebouncing || results.status === 'loading' useEffect(() => { if (!suggestMode && !searchMode) { requestSeq.current += 1 setResults({ status: 'idle' }) return } const seq = ++requestSeq.current const controller = new AbortController() setResults({ status: 'loading' }) const body = suggestMode ? ({ mode: 'wizard-municipality-suggest' } as const) : ({ mode: 'wizard-municipality', query: query.debounced } as const) void (async () => { const { ok, payload } = await postCampaignJson( HOME_SEARCH_ROUTE, body, controller.signal, ) if (seq !== requestSeq.current) return if (!ok || payload.status !== 'success') { setResults({ status: 'error', message: HOME_SEARCH_GENERIC_ERROR_MESSAGE }) return } setResults({ status: 'success', municipalities: payload.municipalities }) })().catch((error: unknown) => { if (seq !== requestSeq.current) return if (error instanceof DOMException && error.name === 'AbortError') return setResults({ status: 'error', message: HOME_SEARCH_GENERIC_ERROR_MESSAGE }) }) return () => { controller.abort() } }, [query.debounced, searchMode, suggestMode]) const showEmpty = query.isActive && results.status === 'success' && results.municipalities.length === 0 return (
setRaw(event.target.value)} autoComplete="off" enterKeyHint="search" aria-busy={resultsBusy || undefined} maxLength={HOME_SEARCH_QUERY_MAX_LENGTH} />
{results.status === 'error' ? (

{results.message}

) : null} {results.status === 'success' && results.municipalities.length > 0 ? (
    {results.municipalities.map((hit) => (
  • } />
  • ))}
) : null} {showEmpty ? (

{WIZARD_MUNICIPALITY_SEARCH_EMPTY}

) : null}
) }