Add landing page

This commit is contained in:
Jennie Robinson Faber 2025-11-03 11:17:51 +00:00
parent 3fea484585
commit bce86ee840
47 changed files with 7119 additions and 439 deletions

View file

@ -160,14 +160,14 @@
<!-- Series Description -->
<div
v-if="event.series?.isSeriesEvent && event.series.description"
class="mb-6 p-4 bg-purple-500/5 rounded-lg border border-purple-500/20"
class="event-series-description mb-6 p-4 bg-ghost-800/30 dark:bg-ghost-700/20 rounded-lg border border-ghost-600 dark:border-ghost-600"
>
<h3
class="text-lg font-semibold text-purple-800 dark:text-purple-200 mb-2"
class="event-series-description__title text-lg font-semibold text-ghost-100 dark:text-ghost-100 mb-2"
>
About the {{ event.series.title }} Series
</h3>
<p class="text-ghost-200">
<p class="event-series-description__text text-ghost-200">
{{ event.series.description }}
</p>
</div>
@ -227,160 +227,180 @@
<!-- Registration Section -->
<div v-if="!event.isCancelled">
<!-- Already Registered Status -->
<div v-if="registrationStatus === 'registered'">
<!-- Use new ticket system if tickets are enabled -->
<EventTicketPurchase
v-if="event.tickets?.enabled"
:event-id="event._id || event.id"
:event-start-date="event.startDate"
:event-title="event.title"
:user-email="memberData?.email"
@success="handleTicketSuccess"
@error="handleTicketError"
/>
<!-- Legacy registration system (for events without tickets enabled) -->
<div v-else>
<!-- Already Registered Status -->
<div v-if="registrationStatus === 'registered'">
<div
class="p-4 bg-green-100 dark:bg-green-900/20 rounded-lg border border-green-400 dark:border-green-800 mb-6"
>
<div
class="flex flex-col md:flex-row md:items-start md:justify-between gap-4"
>
<div>
<p
class="font-semibold text-green-800 dark:text-green-300"
>
You're registered!
</p>
<p class="text-sm text-green-700 dark:text-green-400">
We've sent a confirmation to your email
</p>
</div>
<UButton
color="error"
size="md"
@click="handleCancelRegistration"
:loading="isCancelling"
>
Cancel Registration
</UButton>
</div>
</div>
</div>
<!-- Logged In - Can Register -->
<div
class="p-4 bg-green-100 dark:bg-green-900/20 rounded-lg border border-green-400 dark:border-green-800 mb-6"
v-else-if="memberData && (!event.membersOnly || isMember)"
class="text-center"
>
<p class="text-lg text-ghost-200 mb-6">
You are logged in, {{ memberData.name }}.
</p>
<UButton
color="primary"
size="xl"
@click="handleRegistration"
:loading="isRegistering"
class="px-12 py-4"
>
{{ isRegistering ? "Registering..." : "Register Now" }}
</UButton>
</div>
<!-- Member Gate Warning -->
<div
v-else-if="event.membersOnly && !isMember"
class="text-center"
>
<div
class="flex flex-col md:flex-row md:items-start md:justify-between gap-4"
class="p-6 bg-amber-900/20 rounded-lg border border-amber-800 mb-6"
>
<p class="font-semibold text-amber-300 text-lg mb-2">
Membership Required
</p>
<p class="text-amber-400">
This event is exclusive to Ghost Guild members. Join any
circle to gain access.
</p>
</div>
<NuxtLink to="/join">
<UButton color="primary" size="xl" class="px-12 py-4">
Become a Member to Register
</UButton>
</NuxtLink>
</div>
<!-- Not Logged In - Show Registration Form -->
<div v-else>
<h3 class="text-xl font-bold text-ghost-100 mb-6">
Register for This Event
</h3>
<form @submit.prevent="handleRegistration" class="space-y-4">
<div>
<p class="font-semibold text-green-800 dark:text-green-300">
You're registered!
</p>
<p class="text-sm text-green-700 dark:text-green-400">
We've sent a confirmation to your email
</p>
</div>
<UButton
color="error"
size="md"
@click="handleCancelRegistration"
:loading="isCancelling"
>
Cancel Registration
</UButton>
</div>
</div>
</div>
<!-- Logged In - Can Register -->
<div
v-else-if="memberData && (!event.membersOnly || isMember)"
class="text-center"
>
<p class="text-lg text-ghost-200 mb-6">
You are logged in, {{ memberData.name }}.
</p>
<UButton
color="primary"
size="xl"
@click="handleRegistration"
:loading="isRegistering"
class="px-12 py-4"
>
{{ isRegistering ? "Registering..." : "Register Now" }}
</UButton>
</div>
<!-- Member Gate Warning -->
<div v-else-if="event.membersOnly && !isMember" class="text-center">
<div
class="p-6 bg-amber-900/20 rounded-lg border border-amber-800 mb-6"
>
<p class="font-semibold text-amber-300 text-lg mb-2">
Membership Required
</p>
<p class="text-amber-400">
This event is exclusive to Ghost Guild members. Join any
circle to gain access.
</p>
</div>
<NuxtLink to="/join">
<UButton color="primary" size="xl" class="px-12 py-4">
Become a Member to Register
</UButton>
</NuxtLink>
</div>
<!-- Not Logged In - Show Registration Form -->
<div v-else>
<h3 class="text-xl font-bold text-ghost-100 mb-6">
Register for This Event
</h3>
<form @submit.prevent="handleRegistration" class="space-y-4">
<div>
<label
for="name"
class="block text-sm font-medium text-ghost-200 mb-2"
>
Full Name
</label>
<UInput
id="name"
v-model="registrationForm.name"
type="text"
required
placeholder="Enter your full name"
/>
</div>
<div>
<label
for="email"
class="block text-sm font-medium text-ghost-200 mb-2"
>
Email Address
</label>
<UInput
id="email"
v-model="registrationForm.email"
type="email"
required
placeholder="Enter your email"
/>
</div>
<div>
<label
for="membershipLevel"
class="block text-sm font-medium text-ghost-200 mb-2"
>
Membership Status
</label>
<USelect
id="membershipLevel"
v-model="registrationForm.membershipLevel"
:options="membershipOptions"
/>
</div>
<div class="pt-4">
<UButton
type="submit"
color="primary"
size="lg"
block
:loading="isRegistering"
>
{{
isRegistering ? "Registering..." : "Register for Event"
}}
</UButton>
</div>
</form>
</div>
<!-- Event Capacity -->
<div
v-if="event.maxAttendees"
class="mt-6 pt-6 border-t border-ghost-700"
>
<div class="flex items-center justify-between">
<span class="text-sm text-ghost-300">Event Capacity</span>
<div class="flex items-center space-x-2">
<span class="text-sm font-semibold text-ghost-100">
{{ event.registeredCount || 0 }} / {{ event.maxAttendees }}
</span>
<div
class="w-24 h-2 bg-ghost-700 rounded-full overflow-hidden"
>
<div
class="h-full bg-blue-500 rounded-full"
:style="`width: ${((event.registeredCount || 0) / event.maxAttendees) * 100}%`"
<label
for="name"
class="block text-sm font-medium text-ghost-200 mb-2"
>
Full Name
</label>
<UInput
id="name"
v-model="registrationForm.name"
type="text"
required
placeholder="Enter your full name"
/>
</div>
<div>
<label
for="email"
class="block text-sm font-medium text-ghost-200 mb-2"
>
Email Address
</label>
<UInput
id="email"
v-model="registrationForm.email"
type="email"
required
placeholder="Enter your email"
/>
</div>
<div>
<label
for="membershipLevel"
class="block text-sm font-medium text-ghost-200 mb-2"
>
Membership Status
</label>
<USelect
id="membershipLevel"
v-model="registrationForm.membershipLevel"
:options="membershipOptions"
/>
</div>
<div class="pt-4">
<UButton
type="submit"
color="primary"
size="lg"
block
:loading="isRegistering"
>
{{
isRegistering ? "Registering..." : "Register for Event"
}}
</UButton>
</div>
</form>
</div>
<!-- Event Capacity -->
<div
v-if="event.maxAttendees"
class="mt-6 pt-6 border-t border-ghost-700"
>
<div class="flex items-center justify-between">
<span class="text-sm text-ghost-300">Event Capacity</span>
<div class="flex items-center space-x-2">
<span class="text-sm font-semibold text-ghost-100">
{{ event.registeredCount || 0 }} /
{{ event.maxAttendees }}
</span>
<div
class="w-24 h-2 bg-ghost-700 rounded-full overflow-hidden"
>
<div
class="h-full bg-blue-500 rounded-full"
:style="`width: ${((event.registeredCount || 0) / event.maxAttendees) * 100}%`"
/>
</div>
</div>
</div>
</div>
</div>
@ -649,6 +669,20 @@ const handleCancelRegistration = async () => {
}
};
// Handle ticket purchase success
const handleTicketSuccess = (response) => {
console.log("Ticket purchased successfully:", response);
// Update registered count if needed
if (event.value.registeredCount !== undefined) {
event.value.registeredCount++;
}
};
// Handle ticket purchase error
const handleTicketError = (error) => {
console.error("Ticket purchase failed:", error);
};
// SEO Meta
useHead(() => ({
title: event.value