Files
Elecciones-2025/Elecciones-Web/frontend/src/features/legislativas/nacionales/components/PanelResultados.tsx

102 lines
4.4 KiB
TypeScript
Raw Normal View History

// src/features/legislativas/nacionales/components/PanelResultados.tsx
import type { ResultadoTicker, EstadoRecuentoTicker } from '../../../../types/types';
import { ImageWithFallback } from '../../../../components/common/ImageWithFallback';
import { assetBaseUrl } from '../../../../apiService';
import { AnimatedNumber } from './AnimatedNumber';
2025-09-19 17:19:10 -03:00
import { CircularProgressbar, buildStyles } from 'react-circular-progressbar';
import 'react-circular-progressbar/dist/styles.css';
const formatPercent = (num: number) => `${(num || 0).toFixed(2).replace('.', ',')}%`;
const formatVotes = (num: number) => Math.round(num).toLocaleString('es-AR');
2025-09-22 17:56:04 -03:00
const SvgDefs = () => (
<svg style={{ height: 0, width: 0, position: 'absolute' }}>
<defs>
{/* El gradiente ahora se define para que el color oscuro se mantenga en la segunda mitad del recorrido vertical */}
<linearGradient id="participationGradient" gradientTransform="rotate(90)">
<stop offset="0%" stopColor="#e0f3ffff" />
<stop offset="100%" stopColor="#007bff" />
</linearGradient>
<linearGradient id="scrutinizedGradient" gradientTransform="rotate(90)">
<stop offset="0%" stopColor="#e0f3ffff" />
<stop offset="100%" stopColor="#007bff" />
</linearGradient>
</defs>
</svg>
);
interface PanelResultadosProps {
resultados: ResultadoTicker[];
estadoRecuento: EstadoRecuentoTicker;
}
export const PanelResultados = ({ resultados, estadoRecuento }: PanelResultadosProps) => {
return (
<div className="panel-resultados">
2025-09-22 17:56:04 -03:00
<SvgDefs />
2025-09-19 17:19:10 -03:00
<div className="panel-estado-recuento">
<div className="estado-item">
<CircularProgressbar
value={estadoRecuento.participacionPorcentaje}
text={formatPercent(estadoRecuento.participacionPorcentaje)}
2025-09-22 17:56:04 -03:00
strokeWidth={12}
circleRatio={0.75} /* Se convierte en un arco de 270 grados */
2025-09-19 17:19:10 -03:00
styles={buildStyles({
textColor: '#333',
2025-09-22 17:56:04 -03:00
pathColor: 'url(#participationGradient)',
2025-09-19 17:19:10 -03:00
trailColor: '#e9ecef',
2025-09-22 17:56:04 -03:00
textSize: '22px',
rotation: 0.625, /* Rota el inicio para que la apertura quede abajo */
2025-09-19 17:19:10 -03:00
})}
/>
<span>Participación</span>
</div>
<div className="estado-item">
<CircularProgressbar
value={estadoRecuento.mesasTotalizadasPorcentaje}
text={formatPercent(estadoRecuento.mesasTotalizadasPorcentaje)}
2025-09-22 17:56:04 -03:00
strokeWidth={12}
circleRatio={0.75} /* Se convierte en un arco de 270 grados */
2025-09-19 17:19:10 -03:00
styles={buildStyles({
textColor: '#333',
2025-09-22 17:56:04 -03:00
pathColor: 'url(#scrutinizedGradient)',
2025-09-19 17:19:10 -03:00
trailColor: '#e9ecef',
2025-09-22 17:56:04 -03:00
textSize: '22px',
rotation: 0.625, /* Rota el inicio para que la apertura quede abajo */
2025-09-19 17:19:10 -03:00
})}
/>
<span>Escrutado</span>
</div>
</div>
<div className="panel-partidos-container">
{resultados.map(partido => (
2025-09-19 17:19:10 -03:00
<div key={partido.id} className="partido-fila" style={{ borderLeftColor: partido.color || '#888' }}>
<div className="partido-logo">
<ImageWithFallback src={partido.logoUrl || undefined} fallbackSrc={`${assetBaseUrl}/default-avatar.png`} alt={partido.nombre} />
</div>
2025-09-19 17:19:10 -03:00
<div className="partido-main-content">
<div className="partido-top-row">
<div className="partido-info-wrapper">
<span className="partido-nombre">{partido.nombreCorto || partido.nombre}</span>
{partido.nombreCandidato && <span className="candidato-nombre">{partido.nombreCandidato}</span>}
</div>
<div className="partido-stats">
<span className="partido-porcentaje">
<AnimatedNumber value={partido.porcentaje} formatter={formatPercent} />
</span>
<span className="partido-votos">
<AnimatedNumber value={partido.votos} formatter={formatVotes} /> votos
</span>
</div>
</div>
<div className="partido-barra-background">
<div className="partido-barra-foreground" style={{ width: `${partido.porcentaje}%`, backgroundColor: partido.color || '#888' }} />
</div>
</div>
</div>
))}
</div>
</div>
);
};