111 lines
		
	
	
		
			4.4 KiB
		
	
	
	
		
			TypeScript
		
	
	
	
	
	
			
		
		
	
	
			111 lines
		
	
	
		
			4.4 KiB
		
	
	
	
		
			TypeScript
		
	
	
	
	
	
| // 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';
 | |
| 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');
 | |
| 
 | |
| const SvgDefs = () => (
 | |
|   <svg style={{ height: 0, width: 0, position: 'absolute' }}>
 | |
|     <defs>
 | |
|       <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">
 | |
|       <SvgDefs />
 | |
|       <div className="panel-estado-recuento">
 | |
|         <div className="estado-item">
 | |
|           <CircularProgressbar
 | |
|             value={estadoRecuento.participacionPorcentaje}
 | |
|             text={formatPercent(estadoRecuento.participacionPorcentaje)}
 | |
|             strokeWidth={12}
 | |
|             circleRatio={0.75}
 | |
|             styles={buildStyles({
 | |
|               textColor: '#333',
 | |
|               pathColor: 'url(#participationGradient)',
 | |
|               trailColor: '#e9ecef',
 | |
|               textSize: '22px',
 | |
|               rotation: 0.625,
 | |
|             })}
 | |
|           />
 | |
|           <span>Participación</span>
 | |
|         </div>
 | |
|         <div className="estado-item">
 | |
|           <CircularProgressbar
 | |
|             value={estadoRecuento.mesasTotalizadasPorcentaje}
 | |
|             text={formatPercent(estadoRecuento.mesasTotalizadasPorcentaje)}
 | |
|             strokeWidth={12}
 | |
|             circleRatio={0.75}
 | |
|             styles={buildStyles({
 | |
|               textColor: '#333',
 | |
|               pathColor: 'url(#scrutinizedGradient)',
 | |
|               trailColor: '#e9ecef',
 | |
|               textSize: '22px',
 | |
|               rotation: 0.625,
 | |
|             })}
 | |
|           />
 | |
|           <span>Escrutado</span>
 | |
|         </div>
 | |
|       </div>
 | |
| 
 | |
|       <div className="panel-partidos-container">
 | |
|         {resultados.map(partido => (
 | |
|           <div
 | |
|             key={partido.id}
 | |
|             className="partido-fila"
 | |
|             style={{ borderLeftColor: partido.color || '#ccc' }}
 | |
|           >
 | |
|             <div className="partido-logo" style={{ backgroundColor: partido.color || '#e9ecef' }}>
 | |
|               <ImageWithFallback src={partido.logoUrl || undefined} fallbackSrc={`${assetBaseUrl}/default-avatar.png`} alt={partido.nombre} />
 | |
|             </div>
 | |
|             <div className="partido-main-content">
 | |
|               <div className="partido-top-row">
 | |
|                 <div className="partido-info-wrapper">
 | |
|                   {partido.nombreCandidato ? (
 | |
|                     <>
 | |
|                       <span className="candidato-nombre">{partido.nombreCandidato}</span>
 | |
|                       <span className="partido-nombre">{partido.nombreCorto || partido.nombre}</span>
 | |
|                     </>
 | |
|                   ) : (
 | |
|                     <span className="partido-nombre">{partido.nombreCorto || partido.nombre}</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>
 | |
|   );
 | |
| }; |