|
1 | 1 | <template>
|
2 | 2 | <div :class="[
|
3 |
| - event?.album ? 'col-span-2' : 'md:col-span-1 col-span-2', |
| 3 | + event?.album ? 'col-span-1' : 'md:col-span-1 col-span-2', |
4 | 4 | isNextMeetup ? 'border-green-600 dark:border-green-500' : 'border-verse-50 dark:border-white/10 ',
|
5 |
| - 'group in-card bg-white dark:bg-verse-700/30 dark:backdrop-blur-sm border-2 rounded-xl overflow-hidden hover:border-verse-500 transition-all duration-300', |
6 |
| - ]" :title="hasAlbum() ? 'has album' : 'no album'"> |
| 5 | + 'group group/event in-card bg-white dark:bg-verse-700/30 dark:backdrop-blur-sm border-2 rounded-xl overflow-hidden hover:border-verse-500 transition-all duration-300', |
| 6 | + ]"> |
7 | 7 | <div
|
8 |
| - class="relative flex flex-col md:flex-row justify-between w-full transition-all duration-300 group-hover[.in-card]:shadow-lg group-hover[.in-card]:border-verse-400"> |
| 8 | + class="relative flex overflow-clip h-full flex-col md:flex-row justify-between w-full transition-all duration-300 group-hover[.in-card]:shadow-lg group-hover[.in-card]:border-red-400"> |
| 9 | + |
| 10 | + <div class="absolute inset-0 z-0 "> |
| 11 | + <CardAlbum :currentAlbum="currentAlbum" :source="photoAlbumSource" /> |
| 12 | + </div> |
| 13 | + |
| 14 | + <div class="inset-0 absolute z-0 bg-gradient-to-r from-white via-white to-transparent" /> |
| 15 | + |
9 | 16 | <NuxtLink class="absolute inset-0 z-10" :href="`/meetup/${event.id}`">
|
10 | 17 | <span class="sr-only">View details for {{ event?.title }}</span>
|
11 | 18 | </NuxtLink>
|
12 |
| - <div class="relative flex flex-col p-4 w-full"> |
13 |
| - <!-- Date --> |
| 19 | + |
| 20 | + <div class="relative z-5 flex flex-col p-4 w-full justify-between gap-4"> |
| 21 | + |
14 | 22 | <template v-if="event.Date">
|
15 | 23 | <div :class="[
|
16 | 24 | !isUpcoming(event.Date) ? 'text-green-600 font-bold' : 'text-verse-900 dark:text-verse-300',
|
17 |
| - 'flex font-mono text-sm font-medium items-center gap-2 w-full justify-between', |
| 25 | + 'flex flex-col font-mono text-sm font-medium gap-2 w-full justify-between', |
18 | 26 | ]">
|
19 |
| - <div> |
20 | 27 |
|
21 |
| - <Icon name="carbon:calendar" class="mr-2 h-6 w-6" /> |
22 |
| - <span>{{ formatDate(new Date(event.Date), 'dd MMM yyyy') }}</span> |
| 28 | + |
| 29 | + <!-- Title --> |
| 30 | + <h3 |
| 31 | + class="leading-2 text-2xl font-semibold text-verse-500 dark:text-verse-100 group-hover[.in-card]:text-verse-500"> |
| 32 | + <div class="w-[300px] md:w-96 focus:outline-none" :title="`Meetup ${event?.title}`"> |
| 33 | + {{ event?.title }} |
| 34 | + </div> |
| 35 | + </h3> |
| 36 | + |
| 37 | + <div class="flex items-center gap-2"> |
| 38 | + |
| 39 | + <!-- Date --> |
| 40 | + <div> |
| 41 | + <Icon name="carbon:calendar" class="mr-2 h-4 w-4" /> |
| 42 | + <span>{{ formatDate(new Date(event.Date), 'dd MMM yyyy') }}</span> |
| 43 | + </div> |
| 44 | + |
| 45 | + <div v-if="event.Venue" |
| 46 | + class="flex gap-1 md:gap-0 items-center justify-start text-base font-medium leading-3 md:leading-5 "> |
| 47 | + <Icon name="carbon:location" class="mr-1.5 h-4 w-4 flex-shrink-0 truncate " aria-hidden="true" /> |
| 48 | + <div class="pt-[2px] line-clamp-1 md:line-clamp-0"> |
| 49 | + {{ event.Venue }} |
| 50 | + </div> |
| 51 | + </div> |
| 52 | + |
| 53 | + |
| 54 | + |
23 | 55 | </div>
|
24 | 56 | <template v-if="isNextMeetup">
|
25 | 57 | <span class="bg-green-700 text-sm font-mono justify-end text-white px-3 rounded-md font-bold">
|
|
29 | 61 | </div>
|
30 | 62 | </template>
|
31 | 63 |
|
32 |
| - <!-- Title --> |
33 |
| - <h3 |
34 |
| - class="leading-2 text-2xl font-semibold flex-1 py-2 text-verse-500 dark:text-verse-100 group-hover[.in-card]:text-verse-500"> |
35 |
| - <div class="w-[300px] md:w-96 focus:outline-none" :title="`Meetup ${event?.title}`"> |
36 |
| - <!-- :style="vTransitionName('session-title', event.id)" --> |
37 |
| - <span class="absolute inset-0" aria-hidden="true"></span> |
38 |
| - {{ event?.title }} |
39 |
| - </div> |
40 |
| - </h3> |
41 |
| - |
42 |
| - <div class="flex gap-4 pr-4 border-gray-100"> |
43 |
| - <template v-if="event.Venue"> |
44 |
| - <div |
45 |
| - class="flex gap-1 md:gap-0 items-center justify-start text-base font-medium leading-3 md:leading-5 text-verse-600 dark:text-verse-200"> |
46 |
| - <Icon name="carbon:location" |
47 |
| - class="mr-1.5 h-[15px] w-[15px] flex-shrink-0 truncate text-verse-600 dark:text-verse-200" |
48 |
| - aria-hidden="true" /> |
49 |
| - <div class="pt-[2px] line-clamp-1 md:line-clamp-0"> |
50 |
| - {{ event.Venue }} |
| 64 | + <div class="flex justify-between items-end"> |
| 65 | + <div class="flex"> |
| 66 | + <template v-for="speaker in allSpeakersForEvent(event)"> |
| 67 | + <div |
| 68 | + class="group-hover/event:-ml-1 transition-all duration-200 -ml-4 flex first:ml-0 group-hover/event:first:ml-0"> |
| 69 | + <Avatar size="base"> |
| 70 | + <AvatarImage :src="`https://github.com/${speaker?.github_account}.png`" |
| 71 | + :alt="speaker?.github_account" /> |
| 72 | + <AvatarFallback>CN</AvatarFallback> |
| 73 | + </Avatar> |
51 | 74 | </div>
|
52 |
| - </div> |
53 |
| - </template> |
| 75 | + </template> |
| 76 | + </div> |
| 77 | + |
54 | 78 |
|
55 |
| - <div |
56 |
| - class="flex gap-1 md:gap-0 items-center justify-start text-base font-medium leading-3 md:leading-5 text-verse-600 dark:text-verse-200"> |
| 79 | + <div class="flex gap-4 border-gray-100 bg-white/70 rounded-full px-2"> |
57 | 80 | <template v-if="event.Attendees">
|
58 | 81 | <div class="flex items-center" title="Attendees">
|
59 |
| - <Icon name="solar:users-group-rounded-bold" |
60 |
| - class="mr-1.5 h-[15px] w-[15px] flex-shrink-0 truncate text-verse-600 dark:text-verse-200" |
61 |
| - aria-hidden="true" /> |
| 82 | + <Icon name="carbon:group" class="mr-1.5 h-4 w-4 flex-shrink-0 truncate " aria-hidden="true" /> |
62 | 83 | <div class="pt-[2px] line-clamp-1 md:line-clamp-0">
|
63 | 84 | {{ event?.Attendees === 0 ? 'No' : event?.Attendees }}
|
64 | 85 | </div>
|
65 | 86 | </div>
|
66 | 87 | </template>
|
67 | 88 | </div>
|
68 | 89 | </div>
|
| 90 | + |
| 91 | + |
| 92 | + |
| 93 | + |
69 | 94 | </div>
|
70 |
| - <div class="max-w-screen-sm"> |
71 |
| - <CardAlbum :currentAlbum="currentAlbum" :source="photoAlbumSource" /> |
72 |
| - </div> |
| 95 | + |
73 | 96 | </div>
|
74 | 97 | </div>
|
75 | 98 | </template>
|
@@ -99,6 +122,28 @@ interface Meetup {
|
99 | 122 | images?: [];
|
100 | 123 | gallery?: [];
|
101 | 124 | album?: string;
|
| 125 | + sessions: Session[]; |
| 126 | +} |
| 127 | +
|
| 128 | +interface Session { |
| 129 | + id: number; |
| 130 | + Events_id: Event; |
| 131 | + Session_id?: SessionDetail; |
| 132 | +} |
| 133 | +
|
| 134 | +interface SessionDetail { |
| 135 | + title: string; |
| 136 | + speakers: Speaker; |
| 137 | +} |
| 138 | +
|
| 139 | +interface Speaker { |
| 140 | + name: string; |
| 141 | + id: string; |
| 142 | + github_account: string; |
| 143 | +} |
| 144 | +
|
| 145 | +interface Speaker { |
| 146 | +
|
102 | 147 | }
|
103 | 148 |
|
104 | 149 | interface Props {
|
@@ -128,11 +173,15 @@ function fetchAlbumDetails() {
|
128 | 173 | const filteredPhotos = albumPhotosParsed.filter((photo) => {
|
129 | 174 | return !photo.endsWith('.mp4');
|
130 | 175 | });
|
131 |
| - return filteredPhotos.slice(0, 4); |
| 176 | + return filteredPhotos.slice(0, 3); |
132 | 177 | }
|
133 | 178 | }
|
134 | 179 | }
|
135 | 180 |
|
| 181 | +function allSpeakersForEvent(event: Meetup) { |
| 182 | + return event.sessions.map((session) => session.Session_id?.speakers); |
| 183 | +} |
| 184 | +
|
136 | 185 | let currentAlbum = fetchAlbumDetails();
|
137 | 186 |
|
138 | 187 | function formatDate(date: Date, formatString: string) {
|
|
0 commit comments