| 
									
										
										
										
											2025-09-17 11:31:17 -03:00
										 |  |  | // src/components/common/SenateLayout.tsx
 | 
					
						
							| 
									
										
										
										
											2025-08-30 11:31:45 -03:00
										 |  |  | import React, { useLayoutEffect } from 'react'; | 
					
						
							|  |  |  | import { handleImageFallback } from './imageFallback'; | 
					
						
							| 
									
										
										
										
											2025-09-17 11:31:17 -03:00
										 |  |  | import { assetBaseUrl } from '../../apiService'; | 
					
						
							| 
									
										
										
										
											2025-08-25 10:25:54 -03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-08-29 09:54:22 -03:00
										 |  |  | // Interfaces
 | 
					
						
							| 
									
										
										
										
											2025-08-25 10:25:54 -03:00
										 |  |  | interface SeatFillData { | 
					
						
							|  |  |  |   color: string; | 
					
						
							| 
									
										
										
										
											2025-08-29 09:54:22 -03:00
										 |  |  |   // Añadimos la propiedad opcional 'ocupante'
 | 
					
						
							|  |  |  |   ocupante?: { | 
					
						
							|  |  |  |     nombreOcupante: string; | 
					
						
							|  |  |  |     fotoUrl: string | null; | 
					
						
							|  |  |  |   } | null; | 
					
						
							| 
									
										
										
										
											2025-08-25 10:25:54 -03:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | interface SenateLayoutProps { | 
					
						
							|  |  |  |   seatData: SeatFillData[]; | 
					
						
							|  |  |  |   size?: number; | 
					
						
							| 
									
										
										
										
											2025-08-30 11:31:45 -03:00
										 |  |  |   presidenteBancada?: { color: string | null } | null; | 
					
						
							| 
									
										
										
										
											2025-08-25 10:25:54 -03:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-08-29 09:54:22 -03:00
										 |  |  | const PRESIDENTE_SEAT_INDEX = 45; // El último asiento (índice 45 de 46)
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-08-25 10:25:54 -03:00
										 |  |  | export const SenateLayout: React.FC<SenateLayoutProps> = ({ | 
					
						
							|  |  |  |   seatData, | 
					
						
							|  |  |  |   size = 400, | 
					
						
							| 
									
										
										
										
											2025-08-29 09:54:22 -03:00
										 |  |  |   presidenteBancada, | 
					
						
							| 
									
										
										
										
											2025-08-25 10:25:54 -03:00
										 |  |  | }) => { | 
					
						
							| 
									
										
										
										
											2025-08-30 11:31:45 -03:00
										 |  |  |   // HOOK DE IMAGENES POR DEFECTO
 | 
					
						
							|  |  |  |   useLayoutEffect(() => { | 
					
						
							|  |  |  |     // Se ejecuta después de que el componente y el tooltip se hayan renderizado
 | 
					
						
							| 
									
										
										
										
											2025-09-04 17:39:20 -03:00
										 |  |  |     handleImageFallback('.seat-tooltip img', `${assetBaseUrl}/default-avatar.png`); | 
					
						
							| 
									
										
										
										
											2025-08-30 11:31:45 -03:00
										 |  |  |   }, [seatData, presidenteBancada]); // Dependencias: se vuelve a ejecutar si estos datos cambian
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-08-25 10:25:54 -03:00
										 |  |  |   const uniqueColors = [...new Set(seatData.map(d => d.color).filter(Boolean))]; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-08-29 09:54:22 -03:00
										 |  |  |   // --- NUEVO ARRAY DE ELEMENTOS ORDENADO PARA EL SENADO ---
 | 
					
						
							| 
									
										
										
										
											2025-08-25 10:25:54 -03:00
										 |  |  |   const seatElements = [ | 
					
						
							| 
									
										
										
										
											2025-08-29 09:54:22 -03:00
										 |  |  |     <circle key="senate-seat-0" id="senate-seat-0" r="9" cy="354.956" cx="-121.933" transform="matrix(-1, 0, 0, 1, 0, 0)" />, | 
					
						
							|  |  |  |     <circle key="senate-seat-1" id="senate-seat-1" r="9" cy="354.956" cx="-164.933" transform="matrix(-1, 0, 0, 1, 0, 0)" />, | 
					
						
							|  |  |  |     <circle key="senate-seat-2" id="senate-seat-2" r="9" cy="331.318" cx="-121.933" transform="matrix(-1, 0, 0, 1, 0, 0)" />, | 
					
						
							|  |  |  |     <circle key="senate-seat-3" id="senate-seat-3" r="9" cy="333.318" cx="-164.933" transform="matrix(-1, 0, 0, 1, 0, 0)" />, | 
					
						
							|  |  |  |     <circle key="senate-seat-4" id="senate-seat-4" r="9" cy="307.598" cx="-121.933" transform="matrix(-1, 0, 0, 1, 0, 0)" />, | 
					
						
							|  |  |  |     <circle key="senate-seat-5" id="senate-seat-5" r="9" cy="312.598" cx="-164.933" transform="matrix(-1, 0, 0, 1, 0, 0)" />, | 
					
						
							|  |  |  |     <circle key="senate-seat-6" id="senate-seat-6" r="9" cy="285.358" cx="-121.933" transform="matrix(-1, 0, 0, 1, 0, 0)" />, | 
					
						
							|  |  |  |     <circle key="senate-seat-7" id="senate-seat-7" r="9" cy="292.358" cx="-164.933" transform="matrix(-1, 0, 0, 1, 0, 0)" />, | 
					
						
							|  |  |  |     <circle key="senate-seat-8" id="senate-seat-8" r="9" cy="292.358" cx="-206.672" transform="matrix(-1, 0, 0, 1, 0, 0)" />, | 
					
						
							|  |  |  |     <circle key="senate-seat-9" id="senate-seat-9" r="9" cy="261.241" cx="-121.933" transform="matrix(-1, 0, 0, 1, 0, 0)" />, | 
					
						
							|  |  |  |     <circle key="senate-seat-10" id="senate-seat-10" r="9" cy="269.241" cx="-165.933" transform="matrix(-1, 0, 0, 1, 0, 0)" />, | 
					
						
							|  |  |  |     <circle key="senate-seat-11" id="senate-seat-11" r="9" cy="268.057" cx="-208.672" transform="matrix(-1, 0, 0, 1, 0, 0)" />, | 
					
						
							|  |  |  |     <circle key="senate-seat-12" id="senate-seat-12" r="9" cy="184.514" cx="327.2" transform="matrix(-0.986454, -0.16404, -0.16404, 0.986454, 488.237, 84.441)" />, | 
					
						
							|  |  |  |     <circle key="senate-seat-13" id="senate-seat-13" r="9" cy="246.521" cx="-170.309" transform="matrix(-1, 0, 0, 1, 0, 0)" />, | 
					
						
							|  |  |  |     <circle key="senate-seat-14" id="senate-seat-14" r="9" cy="184.514" cx="327.2" transform="matrix(-0.986454, -0.16404, -0.16404, 0.986454, 507.83, 65.575)" />, | 
					
						
							|  |  |  |     <circle key="senate-seat-15" id="senate-seat-15" r="9" cy="229.407" cx="-183.766" transform="matrix(-1, 0, 0, 1, 0, 0)" />, | 
					
						
							|  |  |  |     <circle key="senate-seat-16" id="senate-seat-16" r="9" cy="184.514" cx="327.2" transform="matrix(-0.986454, -0.16404, -0.16404, 0.986454, 528.776, 52.17)" />, | 
					
						
							|  |  |  |     <circle key="senate-seat-17" id="senate-seat-17" r="9" cy="217.294" cx="-201.175" transform="matrix(-1, 0, 0, 1, 0, 0)" />, | 
					
						
							|  |  |  |     <circle key="senate-seat-18" id="senate-seat-18" r="9" cy="252.557" cx="-227.172" transform="matrix(-1, 0, 0, 1, 0, 0)" />, | 
					
						
							|  |  |  |     <circle key="senate-seat-19" id="senate-seat-19" r="9" cy="170.401" cx="311.791" transform="matrix(-0.986454, -0.16404, -0.16404, 0.986454, 535.427, 55.561)" />, | 
					
						
							|  |  |  |     <circle key="senate-seat-20" id="senate-seat-20" r="9" cy="211.882" cx="-223.172" transform="matrix(-1, 0, 0, 1, 0, 0)" />, | 
					
						
							|  |  |  |     <circle key="senate-seat-21" id="senate-seat-21" r="9" cy="159.989" cx="295.143" transform="matrix(-0.986454, -0.16404, -0.16404, 0.986454, 540.544, 61.56)" />, | 
					
						
							|  |  |  |     <circle key="senate-seat-22" id="senate-seat-22" r="9" cy="159.989" cx="295.143" transform="matrix(0.986454, -0.16404, 0.16404, 0.986454, -54.66, 61.555)" />, | 
					
						
							|  |  |  |     <circle key="senate-seat-23" id="senate-seat-23" r="9" cy="211.882" cx="262.728" />, | 
					
						
							|  |  |  |     <circle key="senate-seat-24" id="senate-seat-24" r="9" cy="252.557" cx="258.729" />, | 
					
						
							|  |  |  |     <circle key="senate-seat-25" id="senate-seat-25" r="9" cy="170.401" cx="311.791" transform="matrix(0.986454, -0.16404, 0.16404, 0.986454, -49.543, 55.556)" />, | 
					
						
							|  |  |  |     <circle key="senate-seat-26" id="senate-seat-26" r="9" cy="217.294" cx="284.726" />, | 
					
						
							|  |  |  |     <circle key="senate-seat-27" id="senate-seat-27" r="9" cy="184.514" cx="327.2" transform="matrix(0.986454, -0.16404, 0.16404, 0.986454, -42.892, 52.164)" />, | 
					
						
							|  |  |  |     <circle key="senate-seat-28" id="senate-seat-28" r="9" cy="184.514" cx="327.2" transform="matrix(0.986454, -0.16404, 0.16404, 0.986454, -21.946, 65.569)" />, | 
					
						
							|  |  |  |     <circle key="senate-seat-29" id="senate-seat-29" r="9" cy="229.407" cx="302.134" />, | 
					
						
							|  |  |  |     <circle key="senate-seat-30" id="senate-seat-30" r="9" cy="268.057" cx="277.228" />, | 
					
						
							|  |  |  |     <circle key="senate-seat-31" id="senate-seat-31" r="9" cy="184.514" cx="327.2" transform="matrix(0.986454, -0.16404, 0.16404, 0.986454, -2.353, 84.436)" />, | 
					
						
							|  |  |  |     <circle key="senate-seat-32" id="senate-seat-32" r="9" cy="246.521" cx="315.591" />, | 
					
						
							|  |  |  |     <circle key="senate-seat-33" id="senate-seat-33" r="9" cy="184.514" cx="327.2" transform="matrix(0.986454, -0.16404, 0.16404, 0.986454, 8.933, 107.941)" />, | 
					
						
							|  |  |  |     <circle key="senate-seat-34" id="senate-seat-34" r="9" cy="269.241" cx="319.968" />, | 
					
						
							|  |  |  |     <circle key="senate-seat-35" id="senate-seat-35" r="9" cy="292.358" cx="279.228" />, | 
					
						
							|  |  |  |     <circle key="senate-seat-36" id="senate-seat-36" r="9" cy="261.241" cx="363.968" />, | 
					
						
							|  |  |  |     <circle key="senate-seat-37" id="senate-seat-37" r="9" cy="292.358" cx="320.968" />, | 
					
						
							|  |  |  |     <circle key="senate-seat-38" id="senate-seat-38" r="9" cy="285.358" cx="363.968" />, | 
					
						
							|  |  |  |     <circle key="senate-seat-39" id="senate-seat-39" r="9" cy="312.598" cx="320.968" />, | 
					
						
							|  |  |  |     <circle key="senate-seat-40" id="senate-seat-40" r="9" cy="307.598" cx="363.968" />, | 
					
						
							|  |  |  |     <circle key="senate-seat-41" id="senate-seat-41" r="9" cy="333.318" cx="320.968" />, | 
					
						
							|  |  |  |     <circle key="senate-seat-42" id="senate-seat-42" r="9" cy="331.318" cx="363.968" />, | 
					
						
							|  |  |  |     <circle key="senate-seat-43" id="senate-seat-43" r="9" cy="354.956" cx="320.968" />, | 
					
						
							|  |  |  |     <circle key="senate-seat-44" id="senate-seat-44" r="9" cy="354.956" cx="363.968" />, | 
					
						
							|  |  |  |     <circle key="senate-seat-45" id="senate-seat-45" r="9" cy="347.619" cx="243.841" />, | 
					
						
							| 
									
										
										
										
											2025-08-25 10:25:54 -03:00
										 |  |  |   ]; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-08-29 09:54:22 -03:00
										 |  |  |   // Creamos una copia mutable de los datos de asientos para poder modificarla.
 | 
					
						
							|  |  |  |   const finalSeatData = [...seatData]; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   // Si hay un presidente y su partido tiene bancas, le quitamos una para asignarla.
 | 
					
						
							|  |  |  |   if (presidenteBancada && presidenteBancada.color) { | 
					
						
							|  |  |  |     const lastSeatIndex = finalSeatData.map(s => s.color).lastIndexOf(presidenteBancada.color); | 
					
						
							|  |  |  |     if (lastSeatIndex !== -1) { | 
					
						
							|  |  |  |       finalSeatData.splice(lastSeatIndex, 1); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-08-25 10:25:54 -03:00
										 |  |  |   const renderedElements = seatElements.map((child, index) => { | 
					
						
							| 
									
										
										
										
											2025-08-29 15:49:13 -03:00
										 |  |  |     // --- CASO ESPECIAL: ASIENTO PRESIDENCIAL ---
 | 
					
						
							| 
									
										
										
										
											2025-08-30 11:31:45 -03:00
										 |  |  |     if (presidenteBancada && index === PRESIDENTE_SEAT_INDEX) { | 
					
						
							| 
									
										
										
										
											2025-08-25 10:25:54 -03:00
										 |  |  |       return React.cloneElement(child, { | 
					
						
							| 
									
										
										
										
											2025-08-30 11:31:45 -03:00
										 |  |  |         fill: presidenteBancada.color || '#A9A9A9', | 
					
						
							| 
									
										
										
										
											2025-08-29 09:54:22 -03:00
										 |  |  |         stroke: '#000000', | 
					
						
							|  |  |  |         strokeWidth: 2, | 
					
						
							| 
									
										
										
										
											2025-08-30 11:31:45 -03:00
										 |  |  |         'data-tooltip-id': 'seat-tooltip' | 
					
						
							| 
									
										
										
										
											2025-08-25 10:25:54 -03:00
										 |  |  |       }); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-08-29 15:49:13 -03:00
										 |  |  |     // --- LÓGICA NORMAL PARA EL RESTO DE ASIENTOS ---
 | 
					
						
							|  |  |  |     // Usamos la copia modificada 'finalSeatData'. Como este array es más corto,
 | 
					
						
							|  |  |  |     // el último asiento electoral no encontrará datos y quedará gris, lo cual es correcto.
 | 
					
						
							|  |  |  |     const seat = finalSeatData[index]; | 
					
						
							| 
									
										
										
										
											2025-08-29 09:54:22 -03:00
										 |  |  | 
 | 
					
						
							|  |  |  |     if (!seat) { | 
					
						
							|  |  |  |       return React.cloneElement(child, { fill: '#E0E0E0', stroke: '#ffffff', strokeWidth: 1.5 }); | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2025-08-25 10:25:54 -03:00
										 |  |  | 
 | 
					
						
							|  |  |  |     return React.cloneElement(child, { | 
					
						
							| 
									
										
										
										
											2025-08-29 09:54:22 -03:00
										 |  |  |       fill: seat.color, | 
					
						
							| 
									
										
										
										
											2025-08-25 10:25:54 -03:00
										 |  |  |       stroke: '#ffffff', | 
					
						
							|  |  |  |       strokeWidth: 1.5, | 
					
						
							| 
									
										
										
										
											2025-08-29 09:54:22 -03:00
										 |  |  |       'data-tooltip-id': seat.ocupante ? 'seat-tooltip' : undefined, | 
					
						
							|  |  |  |       'data-tooltip-html': seat.ocupante | 
					
						
							| 
									
										
										
										
											2025-09-04 17:39:20 -03:00
										 |  |  |         ? `<div class="seat-tooltip"><img src="${seat.ocupante.fotoUrl || `${assetBaseUrl}/default-avatar.png`}" alt="${seat.ocupante.nombreOcupante}" /><p>${seat.ocupante.nombreOcupante}</p></div>` | 
					
						
							| 
									
										
										
										
											2025-08-29 09:54:22 -03:00
										 |  |  |         : undefined, | 
					
						
							| 
									
										
										
										
											2025-08-25 10:25:54 -03:00
										 |  |  |     }); | 
					
						
							|  |  |  |   }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   return ( | 
					
						
							|  |  |  |     <svg viewBox="73.512 141.174 338.86 280.338" width={size} height={size * (280.338 / 338.86)} style={{ display: 'block', margin: 'auto' }}> | 
					
						
							|  |  |  |       <defs> | 
					
						
							|  |  |  |         {uniqueColors.map(color => { | 
					
						
							|  |  |  |           const patternId = `stripes-${color.replace('#', '')}`; | 
					
						
							|  |  |  |           return ( | 
					
						
							|  |  |  |             <pattern key={patternId} id={patternId} patternUnits="userSpaceOnUse" width="4" height="4" patternTransform="rotate(45)"> | 
					
						
							|  |  |  |               <rect width="4" height="4" fill={color}></rect> | 
					
						
							|  |  |  |               <path d="M-1,1 l2,-2 M0,4 l4,-4 M3,5 l2,-2" stroke="rgba(255,255,255,0.7)" strokeWidth="3"></path> | 
					
						
							|  |  |  |             </pattern> | 
					
						
							|  |  |  |           ); | 
					
						
							|  |  |  |         })} | 
					
						
							|  |  |  |       </defs> | 
					
						
							|  |  |  |       <g> | 
					
						
							|  |  |  |         {renderedElements} | 
					
						
							|  |  |  |       </g> | 
					
						
							|  |  |  |     </svg> | 
					
						
							|  |  |  |   ); | 
					
						
							|  |  |  | }; |