- campoVotes (sem leitor) e classification.fieldHeadroom (duplicava o fator field) removidos - formatTerritorialClassWhy passa a ser mesmo a fonte unica do slice(0,2) e do fallback "sem serie", eliminando o sentinela de string vazia nas duas superficies de detalhe - classe territorial vira um so componente com layout table|card, como os vizinhos - parseExhaustiveEnumParam em campaignListUrl cobre trend e class (o includes era morto: allParamValues ja deduplica) - bloco central caminha o computeVoteRankByYear memoizado do A11 em vez de reordenar os 435 slugs por conta propria - comentarios corrigidos onde afirmavam o contrario do codigo (CampaignCellTooltip e a regra do sem_base por superficie)
24 lines
1.1 KiB
TypeScript
24 lines
1.1 KiB
TypeScript
/**
|
|
* Vote counts are whole votes, including the derived ones (E8's decomposed
|
|
* suggested goal and its deficit are fractional). Without pinning the fraction
|
|
* digits, pt-BR renders a goal of 100.968 votes as "100,968" — read as a
|
|
* hundred thousand by every human in the room.
|
|
*/
|
|
const numberFormatter = new Intl.NumberFormat('pt-BR', { maximumFractionDigits: 0 })
|
|
|
|
/** Shares and multiples: one decimal at most, never a forced trailing zero. */
|
|
export const oneDecimalFormatter = new Intl.NumberFormat('pt-BR', {
|
|
maximumFractionDigits: 1,
|
|
minimumFractionDigits: 0,
|
|
})
|
|
|
|
export const formatElectionNumber = (value: number): string => numberFormatter.format(value)
|
|
|
|
/**
|
|
* A ratio (0..1) as a share label with at most one decimal — the shape used
|
|
* for "% da própria votação estadual". Lives here, not next to the ranking it
|
|
* was written for, so client bundles can format a share without pulling the
|
|
* committed TSE artifact along with it.
|
|
*/
|
|
export const formatVoteSharePercent = (share: number): string =>
|
|
`${oneDecimalFormatter.format(share * 100)}%`
|