diff --git a/app/api/events/[slug]/register/route.ts b/app/api/events/[slug]/register/route.ts index 9ab37477..00598310 100644 --- a/app/api/events/[slug]/register/route.ts +++ b/app/api/events/[slug]/register/route.ts @@ -13,7 +13,7 @@ export async function POST( ) { try { const { slug } = await params; - + // Check environment variables before creating Supabase client if (!process.env.NEXT_PUBLIC_SUPABASE_URL || !process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY) { return NextResponse.json( @@ -21,7 +21,7 @@ export async function POST( { status: 503 } ); } - + let supabase; try { supabase = await createClient(); @@ -31,10 +31,10 @@ export async function POST( { status: 503 } ); } - + // Get the current user const { data: { user }, error: authError } = await supabase.auth.getUser(); - + if (authError || !user) { return NextResponse.json( { error: 'Authentication required' }, @@ -45,7 +45,7 @@ export async function POST( // Get the event by slug const { data: event, error: eventError } = await supabase .from('events') - .select('id, title, capacity, registered, registration_required, price, payment') + .select('id, title, slug, capacity, registered, registration_required, price, payment, date, time, location, organizer, company_id, companies(email)') .eq('slug', slug) .single(); @@ -105,7 +105,7 @@ export async function POST( // Update event registration count await supabase .from('events') - .update({ + .update({ registered: event.registered + 1, updated_at: new Date().toISOString() }) @@ -120,6 +120,36 @@ export async function POST( // Don't fail the registration if analytics tracking fails } + // Send confirmation emails + try { + const { sendEventRegistrationEmails } = await import('@/lib/email/event-emails'); + + // Get company email if available + const companyEmail = Array.isArray(event.companies) && event.companies.length > 0 + ? event.companies[0]?.email + : undefined; + + await sendEventRegistrationEmails({ + userEmail: user.email!, + userName: user.user_metadata?.full_name || user.email!, + event: { + title: event.title, + date: event.date, + time: event.time, + location: event.location, + slug: event.slug, + organizer: event.organizer, + capacity: event.capacity, + registered: event.registered + 1, + organizerEmail: companyEmail + }, + registrationId: registration.id.toString() + }); + } catch (emailError) { + console.error('Error sending registration emails:', emailError); + // Don't fail the registration if email sending fails + } + return NextResponse.json({ success: true, data: registration, @@ -142,7 +172,7 @@ export async function DELETE( ) { try { const { slug } = await params; - + // Check environment variables before creating Supabase client if (!process.env.NEXT_PUBLIC_SUPABASE_URL || !process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY) { return NextResponse.json( @@ -150,7 +180,7 @@ export async function DELETE( { status: 503 } ); } - + let supabase; try { supabase = await createClient(); @@ -160,10 +190,10 @@ export async function DELETE( { status: 503 } ); } - + // Get the current user const { data: { user }, error: authError } = await supabase.auth.getUser(); - + if (authError || !user) { return NextResponse.json( { error: 'Authentication required' }, @@ -195,7 +225,7 @@ export async function DELETE( // Update event registration count await supabase .from('events') - .update({ + .update({ registered: Math.max(0, event.registered - 1), updated_at: new Date().toISOString() }) diff --git a/lib/email/event-emails.ts b/lib/email/event-emails.ts new file mode 100644 index 00000000..25a2e673 --- /dev/null +++ b/lib/email/event-emails.ts @@ -0,0 +1,387 @@ +// Email templates for event registration notifications + +import { Resend } from 'resend' + +interface EmailParams { + to: string + subject: string + html: string +} + +// Base email template matching existing Codeunia style +const getEmailTemplate = (content: string) => ` + + + + + + Codeunia + + + + + + +
+ + + + + + + + + + + + + + + +
+

Codeunia

+
+ ${content} +
+

+ Need help? Contact us at support@codeunia.com +

+

+ © ${new Date().getFullYear()} Codeunia. All rights reserved. +

+
+
+ + +` + +// User confirmation email template +export const getEventRegistrationConfirmationEmail = (params: { + userName: string + eventTitle: string + eventDate: string + eventTime: string + eventLocation: string + eventSlug: string + organizer?: string +}) => { + const eventUrl = `https://codeunia.com/events/${params.eventSlug}` + const calendarUrl = `https://codeunia.com/events/${params.eventSlug}/calendar` + + const content = ` +

+ ✅ Registration Confirmed! +

+ +

+ Hi ${params.userName}, +

+ +

+ Great news! You're successfully registered for ${params.eventTitle}. +

+ +
+

+ ✓ Your registration is confirmed
+ ✓ You'll receive event updates via email
+ ✓ Add this event to your calendar +

+
+ +
+

Event Details

+ + + + + + + + + + + + + + ${params.organizer ? ` + + + + + ` : ''} +
+ 📅 Date: + + ${new Date(params.eventDate).toLocaleDateString('en-US', { weekday: 'long', year: 'numeric', month: 'long', day: 'numeric' })} +
+ 🕐 Time: + + ${params.eventTime} +
+ 📍 Location: + + ${params.eventLocation} +
+ 👤 Organizer: + + ${params.organizer} +
+
+ +
+ + 📅 Add to Calendar + + + View Event Details + +
+ +
+

📝 What's Next?

+ +
+ +

+ Looking forward to seeing you at the event! +

+ +

+ Best regards,
+ Codeunia Team +

+ ` + + return { + subject: `✅ Registration Confirmed: ${params.eventTitle}`, + html: getEmailTemplate(content) + } +} + +// Organizer notification email template +export const getEventOrganizerNotificationEmail = (params: { + eventTitle: string + eventSlug: string + participantName: string + participantEmail: string + currentRegistrations: number + capacity: number +}) => { + const eventUrl = `https://codeunia.com/events/${params.eventSlug}` + const dashboardUrl = `https://codeunia.com/dashboard/company` + const registrationsUrl = `${eventUrl}/registrations` + + const percentageFilled = Math.round((params.currentRegistrations / params.capacity) * 100) + + const content = ` +

+ 🎉 New Event Registration! +

+ +

+ Great news! Someone just registered for your event ${params.eventTitle}. +

+ +
+

Participant Details

+ + + + + + + + + +
+ Name: + + ${params.participantName} +
+ Email: + + ${params.participantEmail} +
+
+ +
+

Registration Status

+

+ ${params.currentRegistrations} / ${params.capacity} +

+
+
+
+

+ ${percentageFilled}% filled • ${params.capacity - params.currentRegistrations} spots remaining +

+
+ + ${percentageFilled >= 80 ? ` +
+

+ ⚠️ Almost Full! Your event is ${percentageFilled}% full. Consider increasing capacity or preparing a waitlist. +

+
+ ` : ''} + +
+ + View All Registrations + + + Go to Dashboard + +
+ +

+ Keep up the great work! Your event is attracting interest. +

+ ` + + return { + subject: `🎉 New Registration: ${params.eventTitle} (${params.currentRegistrations}/${params.capacity})`, + html: getEmailTemplate(content) + } +} + +// Send event registration emails +export async function sendEventRegistrationEmails(params: { + userEmail: string + userName: string + event: { + title: string + date: string + time: string + location: string + slug: string + organizer?: string + capacity?: number + registered?: number + organizerEmail?: string + } + registrationId: string +}) { + try { + // Check if Resend is configured + if (!process.env.RESEND_API_KEY) { + console.warn('⚠️ RESEND_API_KEY not configured. Emails not sent:', { + userEmail: params.userEmail, + eventTitle: params.event.title, + }) + return { success: false, error: 'Email service not configured' } + } + + const resend = new Resend(process.env.RESEND_API_KEY) + + // Send confirmation email to user + const confirmationTemplate = getEventRegistrationConfirmationEmail({ + userName: params.userName, + eventTitle: params.event.title, + eventDate: params.event.date, + eventTime: params.event.time, + eventLocation: params.event.location, + eventSlug: params.event.slug, + organizer: params.event.organizer + }) + + const { data: confirmationData, error: confirmationError } = await resend.emails.send({ + from: 'Codeunia ', + to: params.userEmail, + subject: confirmationTemplate.subject, + html: confirmationTemplate.html, + }) + + if (confirmationError) { + console.error('❌ Failed to send confirmation email:', confirmationError) + } else { + console.log('✅ Confirmation email sent:', { + to: params.userEmail, + eventTitle: params.event.title, + id: confirmationData?.id + }) + } + + // Send notification to organizer (if email is available) + if (params.event.organizerEmail && params.event.capacity && params.event.registered !== undefined) { + const organizerTemplate = getEventOrganizerNotificationEmail({ + eventTitle: params.event.title, + eventSlug: params.event.slug, + participantName: params.userName, + participantEmail: params.userEmail, + currentRegistrations: params.event.registered, + capacity: params.event.capacity + }) + + const { data: organizerData, error: organizerError } = await resend.emails.send({ + from: 'Codeunia ', + to: params.event.organizerEmail, + subject: organizerTemplate.subject, + html: organizerTemplate.html, + }) + + if (organizerError) { + console.error('❌ Failed to send organizer notification:', organizerError) + } else { + console.log('✅ Organizer notification sent:', { + to: params.event.organizerEmail, + eventTitle: params.event.title, + id: organizerData?.id + }) + } + } + + return { + success: true, + confirmationSent: !confirmationError, + organizerNotified: params.event.organizerEmail ? !confirmationError : false + } + } catch (error) { + console.error('❌ Error sending event registration emails:', error) + return { success: false, error: String(error) } + } +} + +// Send email function (generic) +export async function sendEventEmail(params: EmailParams) { + try { + if (!process.env.RESEND_API_KEY) { + console.warn('⚠️ RESEND_API_KEY not configured. Email not sent:', { + to: params.to, + subject: params.subject, + }) + return { success: false, error: 'Email service not configured' } + } + + const resend = new Resend(process.env.RESEND_API_KEY) + + const { data, error } = await resend.emails.send({ + from: 'Codeunia ', + to: params.to, + subject: params.subject, + html: params.html, + }) + + if (error) { + console.error('❌ Failed to send event email:', error) + return { success: false, error: error.message } + } + + console.log('✅ Event email sent successfully:', { + to: params.to, + subject: params.subject, + id: data?.id + }) + + return { success: true, data } + } catch (error) { + console.error('❌ Error sending event email:', error) + return { success: false, error: String(error) } + } +}