Add event series badge component
This commit is contained in:
parent
896ad0336c
commit
260e10d31a
3 changed files with 161 additions and 123 deletions
72
app/components/EventSeriesBadge.vue
Normal file
72
app/components/EventSeriesBadge.vue
Normal file
|
|
@ -0,0 +1,72 @@
|
|||
<template>
|
||||
<div
|
||||
class="p-4 bg-gradient-to-r from-purple-500/10 to-blue-500/10 rounded-xl border border-purple-500/30"
|
||||
>
|
||||
<div class="flex items-start justify-between gap-6">
|
||||
<div class="flex-1 min-w-0">
|
||||
<div class="flex flex-wrap items-center gap-2 mb-2">
|
||||
<span
|
||||
class="text-sm font-semibold text-purple-700 dark:text-purple-300"
|
||||
>
|
||||
Part of a Series
|
||||
</span>
|
||||
<span
|
||||
v-if="totalEvents"
|
||||
class="inline-flex items-center px-2 py-0.5 rounded-md bg-purple-500/20 text-sm font-medium text-purple-700 dark:text-purple-300"
|
||||
>
|
||||
<template v-if="position">
|
||||
Event {{ position }} of {{ totalEvents }}
|
||||
</template>
|
||||
<template v-else>
|
||||
{{ totalEvents }} events in series
|
||||
</template>
|
||||
</span>
|
||||
</div>
|
||||
<h3
|
||||
class="text-lg font-semibold text-purple-800 dark:text-purple-200 mb-2"
|
||||
>
|
||||
{{ title }}
|
||||
</h3>
|
||||
<p
|
||||
v-if="description"
|
||||
class="text-sm text-purple-600 dark:text-purple-400"
|
||||
>
|
||||
{{ description }}
|
||||
</p>
|
||||
</div>
|
||||
<div v-if="seriesId" class="flex-shrink-0 self-start">
|
||||
<UButton
|
||||
:to="`/series/${seriesId}`"
|
||||
color="primary"
|
||||
size="md"
|
||||
label="View Series"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
const props = defineProps({
|
||||
title: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
description: {
|
||||
type: String,
|
||||
default: "",
|
||||
},
|
||||
position: {
|
||||
type: Number,
|
||||
default: null,
|
||||
},
|
||||
totalEvents: {
|
||||
type: Number,
|
||||
default: null,
|
||||
},
|
||||
seriesId: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
});
|
||||
</script>
|
||||
|
|
@ -35,6 +35,20 @@
|
|||
"
|
||||
class="relative h-96 overflow-hidden"
|
||||
>
|
||||
<!-- Members Only Banner -->
|
||||
<div
|
||||
v-if="event.membersOnly"
|
||||
class="absolute top-0 left-0 right-0 z-10 bg-purple-600/95 backdrop-blur-sm py-2"
|
||||
>
|
||||
<UContainer>
|
||||
<div class="flex items-center justify-center">
|
||||
<span class="text-sm font-medium text-white">
|
||||
Members Only Event - Open to all circles and contribution levels
|
||||
</span>
|
||||
</div>
|
||||
</UContainer>
|
||||
</div>
|
||||
|
||||
<img
|
||||
:src="getImageUrl(event.featureImage)"
|
||||
:alt="event.featureImage.alt || event.title"
|
||||
|
|
@ -105,68 +119,15 @@
|
|||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Member-Only Badge -->
|
||||
<div v-if="event.membersOnly" class="mb-8">
|
||||
<div
|
||||
class="inline-flex items-center px-4 py-2 bg-purple-100 dark:bg-purple-900/30 rounded-full"
|
||||
>
|
||||
<span
|
||||
class="text-sm font-medium text-purple-700 dark:text-purple-300"
|
||||
>
|
||||
Members Only Event - Open to all circles and contribution levels
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Series Badge -->
|
||||
<div v-if="event.series?.isSeriesEvent" class="mb-8">
|
||||
<div
|
||||
class="p-4 bg-gradient-to-r from-purple-500/10 to-blue-500/10 rounded-xl border border-purple-500/30"
|
||||
>
|
||||
<div class="flex items-start gap-3">
|
||||
<div
|
||||
class="flex-shrink-0 w-10 h-10 rounded-full bg-purple-500/20 flex items-center justify-center text-purple-600 dark:text-purple-400 font-bold"
|
||||
>
|
||||
{{ event.series.position }}
|
||||
</div>
|
||||
<div class="flex-1">
|
||||
<div class="flex items-center gap-2 mb-1">
|
||||
<span
|
||||
class="text-sm font-semibold text-purple-700 dark:text-purple-300"
|
||||
>
|
||||
Part of a Series
|
||||
</span>
|
||||
<span
|
||||
v-if="event.series.totalEvents"
|
||||
class="text-xs text-purple-600 dark:text-purple-400"
|
||||
>
|
||||
({{ event.series.position }} of
|
||||
{{ event.series.totalEvents }})
|
||||
</span>
|
||||
</div>
|
||||
<NuxtLink
|
||||
:to="`/series/${event.series.id}`"
|
||||
class="text-base font-medium text-purple-800 dark:text-purple-200 hover:underline"
|
||||
>
|
||||
{{ event.series.title }}
|
||||
</NuxtLink>
|
||||
<p
|
||||
v-if="event.series.description"
|
||||
class="text-sm text-purple-600 dark:text-purple-400 mt-1"
|
||||
>
|
||||
{{ event.series.description }}
|
||||
</p>
|
||||
</div>
|
||||
<NuxtLink
|
||||
:to="`/series/${event.series.id}`"
|
||||
class="flex-shrink-0"
|
||||
>
|
||||
<UButton color="purple" variant="ghost" size="sm">
|
||||
View Series
|
||||
</UButton>
|
||||
</NuxtLink>
|
||||
</div>
|
||||
</div>
|
||||
<EventSeriesBadge
|
||||
:title="event.series.title"
|
||||
:description="event.series.description"
|
||||
:position="event.series.position"
|
||||
:total-events="event.series.totalEvents"
|
||||
:series-id="event.series.id"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<!-- Target Circles -->
|
||||
|
|
@ -455,6 +416,11 @@ const { isMember, memberData, checkMemberStatus } = useAuth();
|
|||
onMounted(async () => {
|
||||
await checkMemberStatus();
|
||||
|
||||
// Debug: Log series data
|
||||
if (event.value?.series) {
|
||||
console.log("Series data:", event.value.series);
|
||||
}
|
||||
|
||||
// Pre-fill form if member is logged in
|
||||
if (memberData.value) {
|
||||
registrationForm.value.name = memberData.value.name;
|
||||
|
|
|
|||
|
|
@ -57,16 +57,14 @@
|
|||
{{ event.content }}
|
||||
</p>
|
||||
|
||||
<div
|
||||
v-if="event.series?.isSeriesEvent"
|
||||
class="flex items-center gap-1 text-xs text-purple-600 dark:text-purple-400"
|
||||
>
|
||||
<div
|
||||
class="w-4 h-4 bg-purple-100 dark:bg-purple-900/30 rounded-full flex items-center justify-center text-xs font-bold"
|
||||
>
|
||||
{{ event.series.position }}
|
||||
</div>
|
||||
{{ event.series.title }}
|
||||
<div v-if="event.series?.isSeriesEvent" class="mt-2">
|
||||
<EventSeriesBadge
|
||||
:title="event.series.title"
|
||||
:description="event.series.description"
|
||||
:position="event.series.position"
|
||||
:total-events="event.series.totalEvents"
|
||||
:series-id="event.series.id"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
|
@ -142,62 +140,20 @@
|
|||
v-for="series in activeSeries.slice(0, 6)"
|
||||
:key="series.id"
|
||||
:to="`/series/${series.id}`"
|
||||
class="block bg-ghost-900 rounded-xl p-6 shadow-lg border border-ghost-700 hover:border-purple-500 hover:shadow-xl transition-all duration-300"
|
||||
class="block bg-gradient-to-r from-purple-500/10 to-blue-500/10 rounded-xl p-6 border border-purple-500/30 hover:border-purple-500/50 hover:from-purple-500/15 hover:to-blue-500/15 transition-all duration-300"
|
||||
>
|
||||
<div class="flex items-start justify-between mb-4">
|
||||
<div
|
||||
:class="[
|
||||
'inline-flex items-center px-3 py-1 rounded-full text-xs font-medium',
|
||||
getSeriesTypeBadgeClass(series.type),
|
||||
]"
|
||||
>
|
||||
{{ formatSeriesType(series.type) }}
|
||||
</div>
|
||||
<div class="flex items-center gap-1 text-xs text-ghost-400">
|
||||
<Icon name="heroicons:calendar-days" class="w-4 h-4" />
|
||||
<span>{{ series.eventCount }} events</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<h3
|
||||
class="text-lg font-semibold text-ghost-100 mb-2 hover:text-purple-400 transition-colors"
|
||||
>
|
||||
{{ series.title }}
|
||||
</h3>
|
||||
|
||||
<p class="text-sm text-ghost-300 mb-4 line-clamp-2">
|
||||
{{ series.description }}
|
||||
</p>
|
||||
|
||||
<div class="space-y-2 mb-4">
|
||||
<div
|
||||
v-for="(event, index) in series.events.slice(0, 3)"
|
||||
:key="event.id"
|
||||
class="flex items-center justify-between text-xs"
|
||||
>
|
||||
<div class="flex items-center gap-2">
|
||||
<div
|
||||
class="w-6 h-6 bg-purple-100 dark:bg-purple-900/30 text-purple-600 dark:text-purple-400 rounded-full flex items-center justify-center text-xs font-medium"
|
||||
<span
|
||||
class="text-sm font-semibold text-purple-700 dark:text-purple-300"
|
||||
>
|
||||
{{ event.series?.position || index + 1 }}
|
||||
</div>
|
||||
<span class="text-ghost-300 truncate">{{ event.title }}</span>
|
||||
</div>
|
||||
<span class="text-ghost-400">
|
||||
{{ formatEventDate(event.startDate) }}
|
||||
Event Series
|
||||
</span>
|
||||
</div>
|
||||
<div
|
||||
v-if="series.events.length > 3"
|
||||
class="text-xs text-ghost-400 text-center pt-1"
|
||||
<span
|
||||
class="inline-flex items-center px-2 py-0.5 rounded-md bg-purple-500/20 text-sm font-medium text-purple-700 dark:text-purple-300"
|
||||
>
|
||||
+{{ series.events.length - 3 }} more events
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="flex items-center justify-between text-sm">
|
||||
<div class="text-ghost-400">
|
||||
{{ formatDateRange(series.startDate, series.endDate) }}
|
||||
{{ series.eventCount }} events
|
||||
</span>
|
||||
</div>
|
||||
<span
|
||||
:class="[
|
||||
|
|
@ -212,6 +168,50 @@
|
|||
{{ series.status }}
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<h3
|
||||
class="text-lg font-semibold text-purple-800 dark:text-purple-200 mb-2"
|
||||
>
|
||||
{{ series.title }}
|
||||
</h3>
|
||||
|
||||
<p
|
||||
class="text-sm text-purple-600 dark:text-purple-400 mb-4 line-clamp-2"
|
||||
>
|
||||
{{ series.description }}
|
||||
</p>
|
||||
|
||||
<div class="space-y-2 mb-4">
|
||||
<div
|
||||
v-for="(event, index) in series.events.slice(0, 3)"
|
||||
:key="event.id"
|
||||
class="flex items-center justify-between text-xs"
|
||||
>
|
||||
<div class="flex items-center gap-2">
|
||||
<div
|
||||
class="w-6 h-6 bg-purple-500/20 text-purple-700 dark:text-purple-300 rounded-full flex items-center justify-center text-xs font-medium border border-purple-500/30"
|
||||
>
|
||||
{{ event.series?.position || index + 1 }}
|
||||
</div>
|
||||
<span class="text-purple-700 dark:text-purple-300 truncate">{{
|
||||
event.title
|
||||
}}</span>
|
||||
</div>
|
||||
<span class="text-purple-600 dark:text-purple-400">
|
||||
{{ formatEventDate(event.startDate) }}
|
||||
</span>
|
||||
</div>
|
||||
<div
|
||||
v-if="series.events.length > 3"
|
||||
class="text-xs text-purple-600 dark:text-purple-400 text-center pt-1"
|
||||
>
|
||||
+{{ series.events.length - 3 }} more events
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="text-sm text-purple-600 dark:text-purple-400">
|
||||
{{ formatDateRange(series.startDate, series.endDate) }}
|
||||
</div>
|
||||
</NuxtLink>
|
||||
</div>
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue