@@ -3,7 +3,7 @@ import { ExternalLink, FileText, ListChecks, Play, Presentation } from 'lucide-r
33import { Card , CardContent , CardFooter } from '@/components/ui/primitives' ;
44import { Button } from '@/components/ui/Button' ;
55import Link from 'next/link' ;
6- import { BeamCall , beamCallsData } from '@/data/beam-calls' ;
6+ import { BeamCall , beamCallsData , determineBeamCallStatus } from '@/data/beam-calls' ;
77
88// Helper function to extract YouTube video ID from URL
99function getYoutubeVideoId ( url : string ) : string | null {
@@ -33,101 +33,107 @@ export function BeamCalls() {
3333 return (
3434 < div className = "grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6" >
3535 { beamCallsData . map ( ( call ) => (
36- < Card
37- key = { call . id }
38- className = { `bg-white border-slate-200 overflow-hidden ${ call . status === 'unscheduled' ? 'filter brightness-100 opacity-25' : '' } ` }
39- >
40- < div className = "relative" >
41- { call . youtubeUrl !== '#' && getYoutubeVideoId ( call . youtubeUrl ) ? (
42- < div className = "w-full h-48" >
43- < iframe
44- src = { `https://www.youtube.com/embed/${ getYoutubeVideoId ( call . youtubeUrl ) } ` }
45- title = { call . title }
46- allow = "accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture"
47- allowFullScreen
48- className = "w-full h-full"
49- />
50- </ div >
51- ) : (
52- < >
53- < Image
54- src = { call . thumbnail || '/placeholder.svg?height=180&width=320' }
55- alt = { call . title }
56- width = { 320 }
57- height = { 180 }
58- className = "w-full h-48 object-cover"
59- />
60- { call . youtubeUrl !== '#' && (
61- < div className = "absolute inset-0 bg-black bg-opacity-30 flex items-center justify-center opacity-0 hover:opacity-100 transition-opacity" >
62- < Link href = { call . youtubeUrl } target = "_blank" >
63- < Button
64- size = "icon"
65- variant = "secondary"
66- className = "rounded-full bg-white bg-opacity-90 h-12 w-12"
67- >
68- < Play className = "h-6 w-6 text-red-600" />
69- </ Button >
70- </ Link >
71- </ div >
72- ) }
73- </ >
74- ) }
36+ < BeamCallCard key = { call . id } call = { call } />
37+ ) ) }
38+ </ div >
39+ ) ;
40+ }
41+
42+ function BeamCallCard ( { call } : { call : BeamCall } ) {
43+ const status = determineBeamCallStatus ( call . date ) ;
44+
45+ return (
46+ < Card
47+ key = { call . id }
48+ className = { `bg-white border-slate-200 overflow-hidden ${ status === 'unscheduled' ? 'filter brightness-100 opacity-25' : '' } ` }
49+ >
50+ < div className = "relative" >
51+ { call . youtubeUrl !== '#' && getYoutubeVideoId ( call . youtubeUrl ) ? (
52+ < div className = "w-full h-48" >
53+ < iframe
54+ src = { `https://www.youtube.com/embed/${ getYoutubeVideoId ( call . youtubeUrl ) } ` }
55+ title = { call . title }
56+ allow = "accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture"
57+ allowFullScreen
58+ className = "w-full h-full"
59+ />
7560 </ div >
76- < CardContent className = "pt-4" >
77- { call . youtubeUrl !== '#' ? (
78- < Link
79- href = { call . youtubeUrl }
80- target = "_blank"
81- className = "font-semibold text-lg mb-1 text-slate-900 hover:text-blue-600"
82- >
83- { call . title }
84- </ Link >
85- ) : (
86- < div className = "flex items-center" >
87- < p className = "font-semibold text-lg mb-1 text-slate-900" > { call . title } </ p >
88- { call . status === 'upcoming' && (
89- < span className = "ml-2 text-xs bg-red-500 text-white rounded-md px-2 py-1" >
90- Soon!
91- </ span >
92- ) }
93- </ div >
94- ) }
95- < p className = "text-xs text-slate-500 mb-2" > { call . date } </ p >
96- < p className = "text-sm text-slate-600" > { call . summary } </ p >
97- { call . resources && call . resources . length > 0 && (
98- < div className = "mt-4 space-y-2" >
99- < p className = "text-sm font-medium text-slate-700" > Resources:</ p >
100- < div className = "flex flex-wrap gap-2" >
101- { call . resources . map ( ( resource , index ) => (
102- < Link
103- key = { index }
104- href = { resource . url }
105- target = "_blank"
106- className = "inline-flex items-center gap-1.5 px-2.5 py-1 text-xs font-medium text-slate-700 bg-slate-100 rounded-full hover:bg-slate-200"
107- >
108- { getResourceIcon ( resource . type ) }
109- { resource . title }
110- </ Link >
111- ) ) }
112- </ div >
61+ ) : (
62+ < >
63+ < Image
64+ src = { call . thumbnail || '/placeholder.svg?height=180&width=320' }
65+ alt = { call . title }
66+ width = { 320 }
67+ height = { 180 }
68+ className = "w-full h-48 object-cover"
69+ />
70+ { call . youtubeUrl !== '#' && (
71+ < div className = "absolute inset-0 bg-black bg-opacity-30 flex items-center justify-center opacity-0 hover:opacity-100 transition-opacity" >
72+ < Link href = { call . youtubeUrl } target = "_blank" >
73+ < Button
74+ size = "icon"
75+ variant = "secondary"
76+ className = "rounded-full bg-white bg-opacity-90 h-12 w-12"
77+ >
78+ < Play className = "h-6 w-6 text-red-600" />
79+ </ Button >
80+ </ Link >
11381 </ div >
11482 ) }
115- </ CardContent >
116- < CardFooter className = "pt-0" >
117- { call . youtubeUrl !== '#' ? (
118- < Link
119- href = { call . youtubeUrl }
120- className = "text-sm font-medium text-slate-700 hover:text-slate-900 flex items-center gap-1"
121- target = "_blank"
122- >
123- Watch on YouTube < ExternalLink className = "h-3.5 w-3.5" />
124- </ Link >
125- ) : (
126- < p className = "text-sm text-slate-400" > Recording not yet available.</ p >
83+ </ >
84+ ) }
85+ </ div >
86+ < CardContent className = "pt-4" >
87+ { call . youtubeUrl !== '#' ? (
88+ < Link
89+ href = { call . youtubeUrl }
90+ target = "_blank"
91+ className = "font-semibold text-lg mb-1 text-slate-900 hover:text-blue-600"
92+ >
93+ { call . title }
94+ </ Link >
95+ ) : (
96+ < div className = "flex items-center" >
97+ < p className = "font-semibold text-lg mb-1 text-slate-900" > { call . title } </ p >
98+ { status === 'upcoming' && (
99+ < span className = "ml-2 text-xs bg-red-500 text-white rounded-md px-2 py-1" > Soon!</ span >
127100 ) }
128- </ CardFooter >
129- </ Card >
130- ) ) }
131- </ div >
101+ </ div >
102+ ) }
103+ < p className = "text-xs text-slate-500 mb-2" > { call . date } </ p >
104+ < p className = "text-sm text-slate-600" > { call . summary } </ p >
105+ { call . resources && call . resources . length > 0 && (
106+ < div className = "mt-4 space-y-2" >
107+ < p className = "text-sm font-medium text-slate-700" > Resources:</ p >
108+ < div className = "flex flex-wrap gap-2" >
109+ { call . resources . map ( ( resource , index ) => (
110+ < Link
111+ key = { index }
112+ href = { resource . url }
113+ target = "_blank"
114+ className = "inline-flex items-center gap-1.5 px-2.5 py-1 text-xs font-medium text-slate-700 bg-slate-100 rounded-full hover:bg-slate-200"
115+ >
116+ { getResourceIcon ( resource . type ) }
117+ { resource . title }
118+ </ Link >
119+ ) ) }
120+ </ div >
121+ </ div >
122+ ) }
123+ </ CardContent >
124+ < CardFooter className = "pt-0" >
125+ { call . youtubeUrl !== '#' ? (
126+ < Link
127+ href = { call . youtubeUrl }
128+ className = "text-sm font-medium text-slate-700 hover:text-slate-900 flex items-center gap-1"
129+ target = "_blank"
130+ >
131+ Watch on YouTube < ExternalLink className = "h-3.5 w-3.5" />
132+ </ Link >
133+ ) : (
134+ < p className = "text-sm text-slate-400" > Recording not yet available.</ p >
135+ ) }
136+ </ CardFooter >
137+ </ Card >
132138 ) ;
133139}
0 commit comments