Iniciativa Cidadã Independente · Transparência Parlamentar
TSX297 linhas11.544 bytes

apps/web/src/app/comparar/page.tsx

SHA-256

a183a53675c63a00502f587009fc6175f200cfe0e8df266b0d0c12030decf606

Somente leiturafonte-acf635076da2
'use client'

import { useEffect, useState, useRef } from 'react'
import { getRanking } from '@/lib/api'
import type { IdsScore } from '@/lib/types'
import SenadorRadar from '@/components/SenadorRadar'
import Link from 'next/link'

const COLORS = ['#1e3a5f', '#b8860b', '#1e7d4a', '#9b2c2c', '#6b4f9a']

export default function CompararPage() {
  const [query, setQuery] = useState('')
  const [allScores, setAllScores] = useState<IdsScore[]>([])
  const [selected, setSelected] = useState<IdsScore[]>([])
  const [suggestions, setSuggestions] = useState<IdsScore[]>([])
  const [loadingAll, setLoadingAll] = useState(true)
  const inputRef = useRef<HTMLInputElement>(null)

  useEffect(() => {
    getRanking()
      .then((r) => setAllScores(r.data))
      .catch(console.error)
      .finally(() => setLoadingAll(false))
  }, [])

  useEffect(() => {
    if (query.trim().length < 2) {
      setSuggestions([])
      return
    }
    const q = query.toLowerCase()
    setSuggestions(
      allScores
        .filter(
          (s) =>
            s.nome.toLowerCase().includes(q) ||
            s.partido.toLowerCase().includes(q) ||
            s.uf.toLowerCase().includes(q),
        )
        .slice(0, 6),
    )
  }, [query, allScores])

  function addSenador(s: IdsScore) {
    if (selected.length >= 5) return
    if (selected.find((x) => x.senadorCod === s.senadorCod)) return
    setSelected((prev) => [...prev, s])
    setQuery('')
    setSuggestions([])
    inputRef.current?.focus()
  }

  function removeSenador(cod: string) {
    setSelected((prev) => prev.filter((s) => s.senadorCod !== cod))
  }

  const dims = [
    { key: 'dimProdutividade', label: 'Produtividade Legislativa' },
    { key: 'dimEfetividade', label: 'Efetividade' },
    { key: 'dimParticipacao', label: 'Participação' },
    { key: 'dimFiscalizacao', label: 'Fiscalização' },
    { key: 'dimCeap', label: 'Eficiência CEAP' },
    { key: 'dimTransparencia', label: 'Transparência' },
  ]

  return (
    <div className="space-y-10 fade-in">
      {/* ============= ABERTURA ============= */}
      <section className="border-b border-border pb-8">
        <p className="eyebrow">Análise Comparativa</p>
        <h1 className="mt-2 font-serif text-4xl font-semibold tracking-tight text-ink">
          Comparação entre Senadores
        </h1>
        <p className="mt-4 max-w-3xl text-base leading-relaxed text-muted">
          Selecione até cinco Senadores para visualizar lado a lado as
          pontuações em cada uma das seis dimensões do Índice de Desempenho
          Senatorial. Esta ferramenta é especialmente útil para análise de
          bancadas, contraste entre titulares e suplentes, ou estudos
          regionais.
        </p>
      </section>

      {/* ============= BUSCA ============= */}
      <section>
        <p className="eyebrow mb-2">Selecionar Parlamentares</p>
        <div className="relative max-w-xl">
          <input
            ref={inputRef}
            type="text"
            value={query}
            onChange={(e) => setQuery(e.target.value)}
            placeholder="Digite o nome, partido ou unidade federativa..."
            className="w-full rounded-sm border border-border bg-surface px-4 py-2.5 text-sm text-ink placeholder-subtle focus:border-primary focus:outline-none focus:ring-1 focus:ring-primary/20"
          />
          {suggestions.length > 0 && (
            <div className="absolute top-full left-0 right-0 z-10 mt-1 rounded-sm border border-border bg-surface shadow-lg">
              {suggestions.map((s) => (
                <button
                  key={s.senadorCod}
                  onClick={() => addSenador(s)}
                  className="flex w-full items-center gap-3 px-4 py-2.5 text-left hover:bg-panel transition-colors border-b border-border last:border-b-0"
                >
                  <span className="text-sm font-medium text-ink">{s.nome}</span>
                  <span className="ml-auto text-xs text-muted">
                    {s.partido} · {s.uf}
                  </span>
                  <span className="text-xs font-mono font-semibold text-primary">
                    IDS {s.idsTotal}
                  </span>
                </button>
              ))}
            </div>
          )}
          {loadingAll && (
            <p className="mt-2 text-xs text-muted">Carregando lista…</p>
          )}
        </div>

        {selected.length > 0 && (
          <div className="mt-4 flex flex-wrap gap-2">
            {selected.map((s, i) => (
              <div
                key={s.senadorCod}
                className="flex items-center gap-2 rounded-sm border bg-surface px-3 py-1.5 text-sm"
                style={{ borderColor: COLORS[i], color: COLORS[i] }}
              >
                <span
                  className="h-2 w-2 rounded-full"
                  style={{ background: COLORS[i] }}
                />
                <span className="font-medium">{s.nome}</span>
                <span className="opacity-70 text-xs">
                  ({s.partido}/{s.uf})
                </span>
                <button
                  onClick={() => removeSenador(s.senadorCod)}
                  className="ml-1 opacity-60 hover:opacity-100 text-base leading-none"
                  aria-label="Remover"
                >
                  ×
                </button>
              </div>
            ))}
          </div>
        )}
      </section>

      {selected.length === 0 && !loadingAll && (
        <div className="rounded-sm border border-border bg-surface p-12 text-center">
          <p className="font-serif text-lg font-semibold text-ink">
            Nenhum Senador selecionado
          </p>
          <p className="mt-2 text-sm text-muted max-w-md mx-auto">
            Utilize o campo de busca acima para adicionar pelo menos dois
            Senadores e iniciar a comparação.
          </p>
        </div>
      )}

      {selected.length === 1 && (
        <div className="rounded-sm border-l-4 border-accent bg-panel px-5 py-4">
          <p className="text-sm text-muted">
            Adicione pelo menos mais um Senador para visualizar a comparação.
          </p>
        </div>
      )}

      {selected.length >= 2 && (
        <>
          {/* ============= RADAR ============= */}
          <section>
            <p className="eyebrow">Perfil Multidimensional</p>
            <h2 className="mt-1 font-serif text-2xl font-semibold text-ink">
              Visualização comparada por dimensão
            </h2>
            <p className="mt-2 text-sm text-muted max-w-2xl">
              O gráfico abaixo permite identificar visualmente os pontos
              fortes e fracos de cada parlamentar nas seis dimensões avaliadas.
            </p>
            <div className="mt-5 card">
              <SenadorRadar
                multiData={selected.map((s, i) => ({
                  name: s.nome,
                  color: COLORS[i],
                  data: [
                    { subject: 'Produtividade', value: s.dimProdutividade },
                    { subject: 'Efetividade', value: s.dimEfetividade },
                    { subject: 'Participação', value: s.dimParticipacao },
                    { subject: 'Fiscalização', value: s.dimFiscalizacao },
                    { subject: 'CEAP', value: s.dimCeap },
                    { subject: 'Transparência', value: s.dimTransparencia },
                  ],
                }))}
              />
            </div>
          </section>

          {/* ============= TABELA ============= */}
          <section>
            <p className="eyebrow">Tabela Comparativa</p>
            <h2 className="mt-1 font-serif text-2xl font-semibold text-ink">
              Pontuação detalhada
            </h2>
            <div className="mt-5 overflow-x-auto rounded-sm border border-border bg-surface">
              <table className="w-full text-sm">
                <thead className="bg-panel">
                  <tr className="border-b border-border">
                    <th className="px-4 py-3 text-left text-[11px] uppercase tracking-wider text-muted font-semibold">
                      Indicador
                    </th>
                    {selected.map((s, i) => (
                      <th
                        key={s.senadorCod}
                        className="px-4 py-3 text-right text-xs font-semibold"
                        style={{ color: COLORS[i] }}
                      >
                        {s.nome.split(' ').slice(0, 2).join(' ')}
                      </th>
                    ))}
                  </tr>
                </thead>
                <tbody>
                  <tr className="border-b border-border bg-panel/50">
                    <td className="px-4 py-3 font-serif font-semibold text-ink">
                      IDS Total
                    </td>
                    {selected.map((s) => (
                      <td
                        key={s.senadorCod}
                        className="px-4 py-3 text-right font-mono font-bold text-base text-ink"
                      >
                        {s.idsTotal}
                      </td>
                    ))}
                  </tr>
                  {dims.map((d) => (
                    <tr
                      key={d.key}
                      className="border-b border-border hover:bg-panel/40 transition-colors"
                    >
                      <td className="px-4 py-3 text-muted">{d.label}</td>
                      {selected.map((s) => {
                        const v = s[d.key as keyof IdsScore] as number
                        return (
                          <td
                            key={s.senadorCod}
                            className="px-4 py-3 text-right font-mono text-ink"
                          >
                            {v}
                          </td>
                        )
                      })}
                    </tr>
                  ))}
                  <tr className="border-b border-border">
                    <td className="px-4 py-3 text-muted text-xs uppercase tracking-wider">
                      Partido
                    </td>
                    {selected.map((s) => (
                      <td key={s.senadorCod} className="px-4 py-3 text-right text-ink">
                        {s.partido}
                      </td>
                    ))}
                  </tr>
                  <tr>
                    <td className="px-4 py-3 text-muted text-xs uppercase tracking-wider">
                      UF
                    </td>
                    {selected.map((s) => (
                      <td key={s.senadorCod} className="px-4 py-3 text-right text-ink">
                        {s.uf}
                      </td>
                    ))}
                  </tr>
                </tbody>
              </table>
            </div>
          </section>

          <section className="flex flex-wrap gap-2 pt-2">
            {selected.map((s, i) => (
              <Link
                key={s.senadorCod}
                href={`/senador?codigo=${s.senadorCod}`}
                className="text-sm rounded-sm border bg-surface px-3 py-1.5 hover:bg-panel transition-colors"
                style={{ borderColor: COLORS[i], color: COLORS[i] }}
              >
                Ver perfil completo de {s.nome.split(' ')[0]} →
              </Link>
            ))}
          </section>
        </>
      )}
    </div>
  )
}