@@ -2,18 +2,21 @@ import { clsx } from "clsx"
2
2
import { ScheduleSession } from "@/app/conf/2023/types"
3
3
import { Tag } from "@/app/conf/_design-system/tag"
4
4
import { Button } from "@/app/conf/_design-system/button"
5
+ import { Anchor } from "@/app/conf/_design-system/anchor"
5
6
import { CalendarIcon } from "@/app/conf/_design-system/pixelarticons/calendar-icon"
6
7
import { PinIcon } from "@/app/conf/_design-system/pixelarticons/pin-icon"
7
8
import ClockIcon from "@/app/conf/_design-system/pixelarticons/clock.svg?svgr"
8
9
import PlusIcon from "@/app/conf/_design-system/pixelarticons/plus.svg?svgr"
9
10
import PlayIcon from "@/app/conf/_design-system/pixelarticons/play.svg?svgr"
10
11
import { findVideo } from "../../schedule/[id]/session-video"
11
- import { getEventTitle } from "../../utils"
12
+ import { eventsColors , getEventTitle } from "../../utils"
13
+ import React from "react"
12
14
13
15
export interface LongSessionCardProps
14
16
extends React . HTMLAttributes < HTMLDivElement > {
15
17
session : ScheduleSession
16
18
eventColors ?: Record < string , string >
19
+ year ?: string
17
20
}
18
21
19
22
function formatTime ( dateString : string ) : string {
@@ -33,7 +36,7 @@ function formatDate(dateString: string): string {
33
36
34
37
export function LongSessionCard ( {
35
38
session,
36
- eventColors = { } ,
39
+ year = "2025" ,
37
40
className,
38
41
...props
39
42
} : LongSessionCardProps ) {
@@ -49,101 +52,116 @@ export function LongSessionCard({
49
52
session . speakers ?. map ( s => s . name ) || [ ] ,
50
53
)
51
54
const video = findVideo ( session , eventTitle )
52
- const hasVideo = video !== null
53
55
54
- if ( hasVideo ) {
55
- return (
56
- < div
57
- className = { clsx (
58
- "border border-neu-200 bg-neu-0 p-6 shadow-sm" ,
59
- className ,
60
- ) }
61
- { ...props }
62
- >
63
- < div className = "mb-6 flex flex-col gap-6" >
64
- < div className = "flex items-center justify-between gap-6" >
65
- < Tag color = { eventColors [ session . event_type ] } > { eventType } </ Tag >
66
- < div className = "flex items-center gap-2 border border-neu-400 bg-neu-100 px-2 py-1" >
67
- < span className = "typography-menu text-neu-900" >
68
- { /* todo: find year */ }
69
- GraphQLConf 2024
70
- </ span >
71
- </ div >
72
- </ div >
73
- < div className = "flex flex-col gap-2" >
74
- < div className = "min-h-[120px]" >
75
- < h3 className = "typography-h3 text-neu-900" > { session . name } </ h3 >
76
- </ div >
77
- < div className = "flex items-center justify-between gap-2" >
78
- < span className = "typography-body-sm text-neu-600" >
79
- { session . speakers ?. [ 0 ] ?. name || "Speaker" }
80
- </ span >
81
- < div className = "flex items-center gap-0.5" >
82
- < ClockIcon className = "size-3 text-neu-600" />
83
- < span className = "typography-body-xs text-neu-600" > 25 min</ span >
84
- </ div >
85
- </ div >
86
- </ div >
87
- </ div >
88
- < Button href = "#" variant = "primary" className = "w-full" >
89
- Watch
90
- < PlayIcon className = "size-3" />
91
- </ Button >
92
- </ div >
93
- )
94
- }
56
+ const eventDuration =
57
+ new Date ( session . event_end ) . getTime ( ) -
58
+ new Date ( session . event_start ) . getTime ( )
59
+
60
+ const speakers = session . speakers || [ ]
95
61
96
62
return (
97
63
< div
98
64
className = { clsx (
99
- "flex flex-col gap-6 border border-neu-200 bg-neu-0 p-6 shadow-sm backdrop-blur-md" ,
65
+ "group relative border border-neu-200 bg-neu-0 p-6" ,
66
+ ! ! video && "flex flex-col gap-6 backdrop-blur-md" ,
100
67
className ,
101
68
) }
102
69
{ ...props }
103
70
>
104
- < div className = "flex flex-col gap-6" >
71
+ < Anchor
72
+ href = { `/conf/${ year } /schedule/${ session . id } ?name=${ session . name } ` }
73
+ className = "absolute inset-0 z-[1] ring-inset ring-neu-400 hover:ring-1 dark:ring-neu-100"
74
+ aria-label = { `Read more about "${ eventTitle } " by ${ session . speakers ?. [ 0 ] ?. name || "Speaker" } ` }
75
+ />
76
+
77
+ < div className = { clsx ( "flex flex-col gap-6" , video && "mb-6" ) } >
105
78
< div className = "flex items-center justify-between gap-6" >
106
- < Tag color = { eventColors [ session . event_type ] } > { eventType } </ Tag >
79
+ < Tag
80
+ color = {
81
+ eventsColors [ session . event_type ] || "hsl(var(--color-neu-700))"
82
+ }
83
+ >
84
+ { eventType }
85
+ </ Tag >
86
+ { video && (
87
+ < div className = "flex items-center gap-2 border border-neu-400 bg-neu-100 px-2 py-1" >
88
+ < span className = "typography-menu text-neu-900" >
89
+ { /* todo: find year */ }
90
+ GraphQLConf 2024
91
+ </ span >
92
+ </ div >
93
+ ) }
107
94
</ div >
95
+
108
96
< div className = "flex flex-col gap-2" >
109
97
< div className = "min-h-[120px]" >
110
98
< h3 className = "typography-h3 text-neu-900" > { session . name } </ h3 >
111
99
</ div >
112
- < div className = "flex gap-2" >
113
- < span className = "typography-body-sm text-neu-600" >
114
- { session . speakers ?. [ 0 ] ?. name || "Speaker" }
115
- </ span >
100
+ < div className = "flex items-center justify-between gap-2" >
101
+ { ( speakers ?. length || 0 ) > 0 && (
102
+ < span className = "typography-body-sm" >
103
+ { speakers . map ( ( s , i ) => (
104
+ < React . Fragment key = { s . username || s . name } >
105
+ { s . username ? (
106
+ < Anchor
107
+ href = { `/conf/${ year } /speakers/${ s . username } ` }
108
+ className = "relative z-[2] decoration-neu-600 hover:underline dark:decoration-neu-200"
109
+ >
110
+ { s . name }
111
+ </ Anchor >
112
+ ) : (
113
+ s . name
114
+ ) }
115
+ { i !== speakers . length - 1 && < span > , </ span > }
116
+ </ React . Fragment >
117
+ ) ) }
118
+ </ span >
119
+ ) }
120
+ { video && (
121
+ < div className = "flex items-center gap-0.5" >
122
+ < ClockIcon className = "size-3" />
123
+ < span className = "typography-body-xs text-neu-600" >
124
+ { eventDuration }
125
+ </ span >
126
+ </ div >
127
+ ) }
116
128
</ div >
117
129
</ div >
118
130
</ div >
119
- < div className = "flex items-center" >
120
- < div className = "flex flex-1 items-center gap-6 border-r border-neu-200 pr-6" >
121
- < div className = "flex items-center gap-0.5" >
122
- < CalendarIcon className = "size-3 text-sec-base" />
123
- < span className = "typography-body-xs text-neu-600" >
124
- { formattedDate }
125
- </ span >
126
- </ div >
127
- < div className = "flex items-center gap-0.5" >
128
- < ClockIcon className = "size-3 text-sec-base" />
129
- < span className = "typography-body-xs text-neu-600" >
130
- { formattedTime }
131
- </ span >
131
+
132
+ { video ? (
133
+ < Button
134
+ href = { `https://youtube.com/embed/${ video . id } ` }
135
+ variant = "primary"
136
+ className = "relative z-[2] w-full"
137
+ >
138
+ Watch
139
+ < PlayIcon className = "size-6" />
140
+ </ Button >
141
+ ) : (
142
+ < div className = "flex items-center text-neu-800" >
143
+ < div className = "flex flex-1 items-center gap-6 border-r border-neu-200 pr-6" >
144
+ < div className = "flex items-center gap-0.5" >
145
+ < CalendarIcon className = "size-4 text-sec-dark" />
146
+ < span className = "typography-body-xs" > { formattedDate } </ span >
147
+ </ div >
148
+ < div className = "flex items-center gap-0.5" >
149
+ < ClockIcon className = "size-4 text-sec-dark" />
150
+ < span className = "typography-body-xs" > { formattedTime } </ span >
151
+ </ div >
152
+ < div className = "flex items-center gap-0.5" >
153
+ < PinIcon className = "size-4 text-sec-dark" />
154
+ < span className = "typography-body-xs" > { session . venue } </ span >
155
+ </ div >
132
156
</ div >
133
- < div className = "flex items-center gap-0.5 " >
134
- < PinIcon className = "size-3 text-sec-base" / >
135
- < span className = "typography-body-xs text-neu-600" >
136
- { session . venue }
137
- </ span >
157
+ < div className = "flex flex-col items-center justify-center gap-6 pl-6 " >
158
+ < button className = "relative z-[2] flex items-center gap-0.5 text-neu-800" >
159
+ < PlusIcon className = "size-4 text-sec-dark" / >
160
+ < span className = "typography-body-xs" > Add to calendar </ span >
161
+ </ button >
138
162
</ div >
139
163
</ div >
140
- < div className = "flex flex-col items-center justify-center gap-6 pl-6" >
141
- < button className = "flex items-center gap-0.5 text-neu-600 hover:text-neu-900" >
142
- < PlusIcon className = "size-3 text-sec-base" />
143
- < span className = "typography-body-xs" > Add to calendar</ span >
144
- </ button >
145
- </ div >
146
- </ div >
164
+ ) }
147
165
</ div >
148
166
)
149
167
}
0 commit comments