TSX93 linhas3.965 bytes
apps/web/src/components/StatusBadge.tsx
SHA-256
ab6fd1505770565ee72ee9dbbb635bda1100e2379d81874e639227a585504ebf
Somente leiturafonte-acf635076da2
import type { Confianca, SenadorStatus } from '@/lib/types'
const STATUS_LABEL: Record<SenadorStatus, { label: string; tone: string; title: string }> = {
titular_pleno: { label: 'Titular', tone: 'bg-emerald-50 text-emerald-800 border-emerald-200',
title: 'Titular eleito em exercício pleno na Leg. 57' },
titular_voltou: { label: 'Titular (retornou)', tone: 'bg-blue-50 text-blue-800 border-blue-200',
title: 'Titular que esteve afastado e retornou ao mandato' },
suplente_efetivo: { label: 'Suplente', tone: 'bg-indigo-50 text-indigo-800 border-indigo-200',
title: 'Suplente em exercício consolidado (≥12 meses na Leg. 57)' },
suplente_recente: { label: 'Suplente recente', tone: 'bg-amber-50 text-amber-800 border-amber-200',
title: 'Suplente com menos de 12 meses de exercício na Leg. 57' },
recente: { label: 'Recém-empossado', tone: 'bg-orange-50 text-orange-800 border-orange-200',
title: 'Em exercício há menos de 6 meses; score regularizado pela média do grupo' },
afastado: { label: 'Afastado', tone: 'bg-rose-50 text-rose-800 border-rose-200',
title: 'Não exerce o mandato no momento' },
}
const CONFIANCA_LABEL: Record<Confianca, { label: string; title: string; tone: string }> = {
alta: { label: 'confiança alta', tone: 'text-emerald-700', title: 'Score baseado em ≥24 meses de mandato' },
media: { label: 'confiança média', tone: 'text-amber-700', title: '12–23 meses de mandato — score levemente regularizado' },
baixa: { label: 'confiança baixa', tone: 'text-rose-700', title: '<12 meses — score fortemente regularizado pela média do grupo' },
}
export function StatusBadge({ status }: { status?: SenadorStatus }) {
if (!status) return null
// A API pode ganhar valores de status que este bundle ainda não conhece —
// o site publicado não pode quebrar por causa disso (incidente 2026-08-08).
const info = STATUS_LABEL[status]
if (!info) return null
return (
<span
title={info.title}
className={`inline-flex items-center rounded-sm border px-1.5 py-px text-[10px] uppercase tracking-wider font-medium ${info.tone}`}
>
{info.label}
</span>
)
}
/**
* Marca quem exerceu o mandato na Leg. 57 e já saiu. Deriva de `emExercicio`,
* e não de um valor de `status`, justamente para não exigir que a API e o
* frontend publicado estejam sempre na mesma versão.
*/
export function MandatoEncerradoBadge({
emExercicio,
}: {
emExercicio?: boolean
}) {
if (emExercicio !== false) return null
return (
<span
title="Exerceu o mandato na Leg. 57 e já deixou o exercício — continua avaliado para o prêmio da legislatura"
className="inline-flex items-center rounded-sm border border-slate-300 bg-slate-100 px-1.5 py-px text-[10px] uppercase tracking-wider font-medium text-slate-700"
>
mandato encerrado
</span>
)
}
/**
* Marca quem não atinge o mínimo de exercício para concorrer ao prêmio da
* Leg. 57. O score continua sendo exibido — é medido contra a mesma régua dos
* elegíveis —, mas a linha não disputa o prêmio.
*/
export function ForaDeCompeticaoBadge({
elegivel,
meses,
}: {
elegivel?: boolean
meses?: number
}) {
if (elegivel !== false) return null
return (
<span
title={`Exerceu ${meses ?? 0} ${meses === 1 ? 'mês' : 'meses'} na Leg. 57 — mínimo de 12 meses para concorrer ao prêmio`}
className="inline-flex items-center rounded-sm border border-amber-200 bg-amber-50 px-1.5 py-px text-[10px] uppercase tracking-wider font-medium text-amber-800"
>
fora de competição
</span>
)
}
export function ConfiancaBadge({ confianca }: { confianca?: Confianca }) {
if (!confianca) return null
const info = CONFIANCA_LABEL[confianca]
return (
<span title={info.title} className={`text-[10px] font-medium ${info.tone}`}>
{info.label}
</span>
)
}