Iniciativa Cidadã Independente · Transparência Parlamentar
TSX118 linhas4.791 bytes

apps/web/src/components/senador/AbaVotacoes.tsx

SHA-256

ada6d8cbadd65ce4bfcb663c053f33970d7889b609c7a4e3b7346eedc82091a0

Somente leiturafonte-acf635076da2
'use client'

import { useEffect, useState } from 'react'
import { getVotacoes } from '@/lib/api'
import type { VotacaoItem, ListResultBase } from '@/lib/types'
import Pagination from './Pagination'

const VOTO_TONE: Record<string, string> = {
  'Sim': 'bg-emerald-50 text-emerald-800 border-emerald-200',
  'Não': 'bg-rose-50 text-rose-800 border-rose-200',
  'Nao': 'bg-rose-50 text-rose-800 border-rose-200',
  'Abstenção': 'bg-amber-50 text-amber-800 border-amber-200',
  'Abstencao': 'bg-amber-50 text-amber-800 border-amber-200',
  'Obstrução': 'bg-amber-50 text-amber-800 border-amber-200',
  'Não votou': 'bg-rose-50 text-rose-700 border-rose-200',
}

export default function AbaVotacoes({ codigo }: { codigo: string }) {
  const [data, setData] = useState<ListResultBase<VotacaoItem> | null>(null)
  const [pagina, setPagina] = useState(1)
  const [ano, setAno] = useState<number>(new Date().getFullYear())
  const [loading, setLoading] = useState(true)

  useEffect(() => {
    setLoading(true)
    getVotacoes(codigo, { pagina, porPagina: 25, ano })
      .then(setData)
      .finally(() => setLoading(false))
  }, [codigo, pagina, ano])

  // Agregação simples
  const stats = data?.data ? agregarVotos(data.data) : null

  return (
    <div className="space-y-4">
      <div className="flex items-center gap-3 text-sm">
        <label className="text-muted">Ano:</label>
        <select
          value={ano}
          onChange={(e) => { setAno(Number(e.target.value)); setPagina(1) }}
          className="rounded-sm border border-border bg-surface px-2 py-1 text-sm"
        >
          {[2026, 2025, 2024, 2023].map((a) => <option key={a} value={a}>{a}</option>)}
        </select>
        {data && <span className="text-muted">{data.total} votações</span>}
      </div>

      {stats && (
        <div className="grid grid-cols-2 sm:grid-cols-4 gap-px bg-border border border-border rounded-sm overflow-hidden">
          {Object.entries(stats).map(([k, v]) => (
            <div key={k} className="bg-surface px-3 py-2 text-center">
              <p className="text-[10px] uppercase tracking-wider text-muted font-medium">{k}</p>
              <p className="font-serif text-xl text-ink">{v}</p>
            </div>
          ))}
        </div>
      )}

      {loading ? (
        <div className="space-y-2">
          {Array.from({ length: 5 }).map((_, i) => <div key={i} className="h-16 rounded-sm bg-surface border border-border animate-pulse" />)}
        </div>
      ) : data && data.data.length > 0 ? (
        <>
          <ul className="space-y-2">
            {data.data.map((v) => {
              const tone = VOTO_TONE[v.voto] ?? 'bg-panel text-muted border-border'
              return (
                <li key={`${v.codigoSessao}-${v.codigoVotacao}`} className="rounded-sm border border-border bg-surface p-3">
                  <div className="flex items-start justify-between gap-3">
                    <div className="min-w-0 flex-1">
                      <p className="flex flex-wrap items-baseline gap-2">
                        <span className="font-mono text-sm text-ink">{v.identificacao}</span>
                        <span className="text-xs text-muted">{formatBR(v.dataSessao)}</span>
                      </p>
                      <p className="mt-1 text-sm text-muted leading-snug line-clamp-2">{v.descricaoVotacao}</p>
                      {v.ementa && (
                        <p className="mt-1 text-xs text-subtle leading-snug line-clamp-2">{v.ementa}</p>
                      )}
                    </div>
                    <span className={`shrink-0 inline-flex items-center rounded-sm border px-2 py-0.5 text-[11px] font-medium ${tone}`}>
                      {v.voto || '—'}
                    </span>
                  </div>
                </li>
              )
            })}
          </ul>
          <Pagination pagina={data.pagina} porPagina={data.porPagina} total={data.total} onChange={setPagina} />
        </>
      ) : (
        <p className="text-muted text-sm">Nenhuma votação encontrada para o ano selecionado.</p>
      )}
    </div>
  )
}

function agregarVotos(arr: VotacaoItem[]): Record<string, number> {
  const r: Record<string, number> = { Sim: 0, Não: 0, Abstenção: 0, Outros: 0 }
  for (const v of arr) {
    const norm = (v.voto || '')
      .replace(/Abstencao/i, 'Abstenção')
      .replace(/^Nao$/i, 'Não')
      .toLowerCase()
    if (norm === 'sim') r.Sim += 1
    else if (norm === 'não' || norm === 'nao') r['Não'] += 1
    else if (norm === 'abstenção' || norm === 'abstencao') r['Abstenção'] += 1
    else r.Outros += 1
  }
  return r
}

function formatBR(d: string): string {
  if (!d) return ''
  const [y, m, day] = d.split('-')
  return `${day}/${m}/${y}`
}