mirror of
https://github.com/fsolla/teqo.git
synced 2026-11-14 17:43:04 +00:00
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.
51 lines
1.8 KiB
TypeScript
51 lines
1.8 KiB
TypeScript
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>
|
||
)
|