teqo/src/lib/campaignHomeSearchHits.ts
Cursor Agent 1ed65d0d81
B92 — wizard idle suggest: rank + loader + UI
Add wizard-municipality-suggest mode to home-search with cold-first
ranking (signal → E14 → trend → E10 class → 2022 votes). Wizard
municipality step now fetches suggestions when query is idle.

Co-authored-by: Francisco Solla <fsolla@users.noreply.github.com>
2026-08-01 07:01:19 +00:00

123 lines
3.2 KiB
TypeScript

import {
DEFAULT_VOTE_RANK_YEAR,
getMunicipalityVoteRank,
type MunicipalityVoteRankEntry,
} from '@/lib/municipalityVoteRank'
export type HomeSearchMunicipalityHit = {
kind: 'municipality'
slug: string
name: string
region: string
priority: 'alta' | 'normal' | null
votePosition2022: MunicipalityVoteRankEntry | null
}
export type HomeSearchTerritoryHit = {
kind: 'territory'
region: string
votes2022: number
}
export type HomeSearchAdvisorHit = {
id: number
name: string
phone: string | null
municipalityCount: number
}
export type HomeSearchLeadershipHit = {
kind: 'leadership'
id: number
name: string
phone: string | null
municipalitiesSummary: string
}
export type HomeSearchStateDeputyHit = {
slug: string
name: string
party: string | null
municipalityCount: number
}
export type HomeSearchActivityHit = {
id: number
slug: string
title: string
secondary: string
}
export type HomeSearchDemandHit = {
id: number
slug: string
title: string
secondary: string
}
type HomeSearchResultKind = 'search' | 'suggest'
export type HomeSearchSuccessResponse = {
status: 'success'
resultKind: HomeSearchResultKind
municipalities: HomeSearchMunicipalityHit[]
territories: HomeSearchTerritoryHit[]
advisors: HomeSearchAdvisorHit[]
leaderships: HomeSearchLeadershipHit[]
stateDeputies: HomeSearchStateDeputyHit[]
activities: HomeSearchActivityHit[]
demands: HomeSearchDemandHit[]
}
export const homeSearchMunicipalityGroupHasHits = (
data: Pick<HomeSearchSuccessResponse, 'municipalities' | 'territories'>,
): boolean => data.municipalities.length > 0 || data.territories.length > 0
export const homeSearchLeadershipGroupHasHits = (
data: Pick<HomeSearchSuccessResponse, 'leaderships'>,
): boolean => data.leaderships.length > 0
export const homeSearchStateDeputyGroupHasHits = (
data: Pick<HomeSearchSuccessResponse, 'stateDeputies'>,
): boolean => data.stateDeputies.length > 0
export const homeSearchActivityGroupHasHits = (
data: Pick<HomeSearchSuccessResponse, 'activities'>,
): boolean => data.activities.length > 0
export const homeSearchDemandGroupHasHits = (
data: Pick<HomeSearchSuccessResponse, 'demands'>,
): boolean => data.demands.length > 0
export const formatHomeSearchMunicipalityCount = (count: number): string => {
if (count === 1) return '1 município'
return `${count} municípios`
}
export const toHomeSearchMunicipalityHit = (doc: {
slug: string
name: string
region: string
priority?: 'alta' | 'normal' | null
}): HomeSearchMunicipalityHit => ({
kind: 'municipality',
slug: doc.slug,
name: doc.name,
region: doc.region,
priority: doc.priority ?? null,
votePosition2022: getMunicipalityVoteRank(doc.slug, DEFAULT_VOTE_RANK_YEAR),
})
export const homeSearchHasAnyHits = (data: HomeSearchSuccessResponse): boolean =>
homeSearchMunicipalityGroupHasHits(data) ||
data.advisors.length > 0 ||
homeSearchLeadershipGroupHasHits(data) ||
homeSearchStateDeputyGroupHasHits(data) ||
homeSearchActivityGroupHasHits(data) ||
homeSearchDemandGroupHasHits(data)
export type WizardMunicipalitySearchSuccessResponse = {
status: 'success'
resultKind?: 'wizard-suggest'
municipalities: HomeSearchMunicipalityHit[]
}