11import Image from "next/image" ;
2+ import {
3+ LuCoffee , LuPartyPopper , LuHandshake , LuMic ,
4+ LuWrench , LuMapPin , LuLinkedin
5+ } from "react-icons/lu" ;
26
3- export default function TalkCard ( { talk } ) {
7+ export default function TalkCard ( { talk, showRoom = false } ) {
8+ const { title, time, speaker, speakers, description, tags, type, room } = talk ;
9+
10+ // Normalizar speakers a un array
11+ const normalizedSpeakers = speakers
12+ ? speakers
13+ : speaker
14+ ? [ speaker ]
15+ : [ ] ;
16+
17+ // Mapa de estilos para todos los tipos de eventos
18+ const typeStyles = {
19+ recepcion : {
20+ border : "border-l-green-400" ,
21+ badge : {
22+ label : "Recepción" ,
23+ color : "bg-green-600/30 text-green-100" ,
24+ icon : < LuHandshake size = { 16 } className = "mr-1" /> ,
25+ }
26+ } ,
27+ break : {
28+ border : "border-l-yellow-400" ,
29+ badge : {
30+ label : "Break" ,
31+ color : "bg-yellow-500/30 text-yellow-100" ,
32+ icon : < LuCoffee size = { 16 } className = "mr-1" /> ,
33+ }
34+ } ,
35+ cierre : {
36+ border : "border-l-red-400" ,
37+ badge : {
38+ label : "Cierre" ,
39+ color : "bg-red-600/30 text-red-100" ,
40+ icon : < LuPartyPopper size = { 16 } className = "mr-1" /> ,
41+ }
42+ } ,
43+ charla : {
44+ border : "border-l-blue-400" ,
45+ badge : {
46+ label : "Charla" ,
47+ color : "bg-blue-500/30 text-blue-100" ,
48+ icon : < LuMic size = { 16 } className = "mr-1" /> ,
49+ }
50+ } ,
51+ taller : {
52+ border : "border-l-orange-400" ,
53+ badge : {
54+ label : "Taller" ,
55+ color : "bg-orange-500/30 text-orange-100" ,
56+ icon : < LuWrench size = { 16 } className = "mr-1" /> ,
57+ }
58+ } ,
59+ } ;
60+
61+ const isGeneral = ! normalizedSpeakers . length &&
62+ ( type === 'recepcion' || type === 'break' || type === 'cierre' ) ;
63+
64+ const style = typeStyles [ type ] || typeStyles . charla ; // Default a charla si no se reconoce
65+
466 return (
5- < div className = "bg-black/20 backdrop-blur-sm rounded-lg overflow-hidden shadow-lg hover:shadow-2xl transition-all duration-300 hover:-translate-y-1" >
6- < div className = "p-6" >
7- < div className = "flex items-center space-x-4 mb-4" >
8- < div className = "relative w-12 h-12 rounded-full overflow-hidden bg-purple-700" >
9- { talk . speaker . image && (
10- < Image
11- src = { talk . speaker . image }
12- alt = { talk . speaker . name }
13- fill
14- className = "object-cover"
15- />
67+ < div
68+ className = { `bg-black/20 backdrop-blur-sm rounded-lg overflow-hidden shadow-lg hover:shadow-2xl transition-all duration-300 hover:-translate-y-1
69+ ${ style . border } border-l-4 h-full flex flex-col` }
70+ >
71+ < div className = "p-4 md:p-6 flex flex-col flex-grow" >
72+ { isGeneral ? (
73+ < div className = "flex flex-col md:flex-row md:items-center justify-between mb-3" >
74+ < div className = "mb-2 md:mb-0" >
75+ < p className = "text-xs md:text-sm font-medium opacity-80" > { time } </ p >
76+ < h3 className = "font-bold text-base md:text-lg" > { title } </ h3 >
77+ { showRoom && room && (
78+ < div className = "flex items-center mt-1 text-xs opacity-70" >
79+ < LuMapPin size = { 12 } className = "mr-1" />
80+ < span > { room } </ span >
81+ </ div >
82+ ) }
83+ </ div >
84+ < div
85+ className = { `px-2 py-1 rounded-full text-xs md:text-sm flex items-center font-semibold ${ style . badge . color } self-start md:self-auto` }
86+ >
87+ { style . badge . icon }
88+ { style . badge . label }
89+ </ div >
90+ </ div >
91+ ) : (
92+ < div className = "mb-4" >
93+ { /* Fila de tiempo y badge */ }
94+ < div className = "flex justify-between items-start mb-2" >
95+ < p className = "text-xs md:text-sm font-medium opacity-80" > { time } </ p >
96+ < div
97+ className = { `px-2 py-1 rounded-full text-xs flex items-center font-semibold ${ style . badge . color } ` }
98+ >
99+ { style . badge . icon }
100+ { style . badge . label }
101+ </ div >
102+ </ div >
103+
104+ { /* Título */ }
105+ < h3 className = "font-bold text-base md:text-lg mb-2" > { title } </ h3 >
106+
107+ { /* Speakers con imágenes */ }
108+ { normalizedSpeakers . length > 0 && (
109+ < div className = "flex flex-wrap items-center gap-3 mb-3" >
110+ { normalizedSpeakers . map ( ( spkr , idx ) => (
111+ < div key = { idx } className = "flex items-center" >
112+ { /* Imagen optimizada para webp 320x320 */ }
113+ < div className = "relative w-14 h-14 md:w-16 md:h-16 rounded-full overflow-hidden bg-purple-700 flex-shrink-0" >
114+ { spkr . image && (
115+ < Image
116+ src = { spkr . image }
117+ alt = { spkr . name }
118+ fill
119+ className = "object-cover"
120+ sizes = "(max-width: 640px) 56px, 64px"
121+ quality = { 85 }
122+ />
123+ ) }
124+ </ div >
125+ < div className = "ml-2 min-w-0" >
126+ < p className = "text-xs md:text-sm font-medium truncate" > { spkr . name } </ p >
127+
128+ { /* Solo LinkedIn */ }
129+ { spkr . socials ?. linkedin && (
130+ < a
131+ href = { spkr . socials . linkedin }
132+ target = "_blank"
133+ rel = "noopener noreferrer"
134+ className = "flex items-center mt-1 text-xs opacity-70 hover:opacity-100 transition-opacity"
135+ title = "Perfil de LinkedIn"
136+ >
137+ < LuLinkedin size = { 12 } className = "mr-1 flex-shrink-0" />
138+ < span className = "hidden sm:inline truncate" > LinkedIn</ span >
139+ </ a >
140+ ) }
141+ </ div >
142+ </ div >
143+ ) ) }
144+ </ div >
145+ ) }
146+
147+ { /* Sala */ }
148+ { showRoom && room && (
149+ < div className = "flex items-center mb-2 text-xs opacity-70" >
150+ < LuMapPin size = { 12 } className = "mr-1" />
151+ < span > { room } </ span >
152+ </ div >
16153 ) }
17154 </ div >
18- < div >
19- < p className = "text-sm font-medium opacity-80" > { talk . time } </ p >
20- < h3 className = "font-bold text-lg" > { talk . title } </ h3 >
21- < p className = "text-sm" > { talk . speaker . name } </ p >
155+ ) }
156+
157+ { /* Descripción */ }
158+ { description && (
159+ < p className = "text-xs md:text-sm opacity-80 mb-3 flex-grow" >
160+ { description }
161+ </ p >
162+ ) }
163+
164+ { /* Tags */ }
165+ { tags && tags . length > 0 && (
166+ < div className = "mt-auto flex flex-wrap gap-1 md:gap-2" >
167+ { tags . map ( ( tag , index ) => (
168+ < span
169+ key = { index }
170+ className = "text-xs bg-green-600/40 hover:bg-green-600/60 px-2 py-1 rounded-full transition-colors cursor-pointer whitespace-nowrap"
171+ >
172+ { tag }
173+ </ span >
174+ ) ) }
22175 </ div >
23- </ div >
24- < p className = "text-sm opacity-80 line-clamp-2" > { talk . description } </ p >
25- < div className = "mt-4 flex flex-wrap gap-2" >
26- { talk . tags . map ( ( tag , index ) => (
27- < span
28- key = { index }
29- className = "text-xs bg-green-600/40 hover:bg-green-600/60 px-2 py-1 rounded-full transition-colors cursor-pointer"
30- >
31- { tag }
32- </ span >
33- ) ) }
34- </ div >
176+ ) }
35177 </ div >
36178 </ div >
37179 ) ;
38- }
180+ }
0 commit comments