teqo-backup/src/components/campaign/MunicipalityCandidateComparisonTable.tsx
Francisco Ignácio Fontoura Solla e2724c10da Remodel the campaign vertical from Praça to Município
Rename the operational unit "Praça"/"Núcleo" to "Município" (code identifier
`municipality`) and land the 2026-07-23 course changes:

- New `candidate` role with unrestricted visibility (`isCampaignStaff` now
  includes it) alongside coordinator/advisor; leader is locked down to the
  supporter contact tool only.
- Demandas become staff-only; dobradinhas modeled via a `stateDeputy` entity.
- Camaçari consolidated to a single município (ZE 170/171 aggregated);
  Salvador keeps its 19 zone municípios.
- Map moves to the staff dashboard; `/campanha/municipios` is list/overview.
- Vote pledges keep the declared vs estimated (scenario) asymmetry; leaders
  never see estimates.

Destructive migration for the campaign vertical (drops nucleus/plaza-era
tables, wipes campaign rows, seeds 435 municípios). Public-site data untouched.

Includes the post-delivery /simplify cleanups: shared reloadStaffActor /
reloadCoordinatorActor helpers, req.context cache for getFreshCampaignUser,
parallelized dashboard loads, candidate dashboard-copy fix, and dead
leader-dashboard / roleKind code removal.
2026-07-23 21:36:20 -03:00

51 lines
1.8 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import { Badge } from '@/components/ui/Badge'
import {
Table,
TableBody,
TableCell,
TableHead,
TableHeader,
TableRow,
} from '@/components/ui/Table'
import { HISTORICAL_SERIES_YEARS } from '@/lib/electionResults'
import type { CandidateComparisonRow } from '@/utilities/municipalityCandidateComparison'
const voteFormatter = new Intl.NumberFormat('pt-BR')
/** Candidates × years vote table for one municipality — the coordination's analysis tool. */
export const MunicipalityCandidateComparisonTable = ({ rows }: { rows: CandidateComparisonRow[] }) => (
<div className="overflow-hidden rounded-xl border">
<Table>
<TableHeader>
<TableRow>
<TableHead>Candidato</TableHead>
{HISTORICAL_SERIES_YEARS.map((year) => (
<TableHead key={year} className="text-right">
{year}
</TableHead>
))}
</TableRow>
</TableHeader>
<TableBody>
{rows.map((row) => (
<TableRow key={row.candidateNumber} data-reference={row.isReference || undefined}>
<TableCell className="whitespace-normal">
<div className="flex flex-wrap items-center gap-2">
<span className={row.isReference ? 'font-semibold' : 'font-medium'}>
{row.name}
</span>
{row.party ? <span className="text-muted-foreground">({row.party})</span> : null}
{row.isReference ? <Badge variant="scope">Nossa campanha</Badge> : null}
</div>
</TableCell>
{HISTORICAL_SERIES_YEARS.map((year) => (
<TableCell key={year} className="text-right tabular-nums">
{voteFormatter.format(row.votesByYear[String(year)] ?? 0)}
</TableCell>
))}
</TableRow>
))}
</TableBody>
</Table>
</div>
)