Skip to main content

Events & Ticketing Module

Events & Ticketing Module

Overview

The Events & Ticketing module provides comprehensive event management capabilities within the Fundraising Hub. It supports a wide range of event types from simple appointment scheduling to complex mission trips and fundraising galas with ticketing, registration, custom fields, checklists, and payment processing.

Location: Fundraising Hub → Events & Ticketing

Access: Parent org and fund users with write permissions to the Fundraising Hub

---

Table of Contents

1. Feature Summary 2. Event Types 3. Components 4. URL Structure 5. Database Schema 6. Edge Functions 7. User Workflows 8. Integration Points 9. Configuration 10. Troubleshooting

---

Feature Summary

Core Capabilities

| Feature | Description |
|---------|-------------|
| **Event Creation** | Multi-step wizard for creating events with dynamic steps based on event type |
| **Ticket Management** | Multiple ticket types with pricing, inventory, and limits |
| **Registration** | Public registration pages with custom fields and promo codes |
| **Payment Processing** | Stripe Checkout integration for paid events |
| **Waitlist** | Automatic waitlist management with promotion when spots open |
| **Checklists** | Pre-event requirements (waivers, uploads, confirmations) |
| **Promo Codes** | Percentage or fixed discounts with usage limits |

Event Types Supported

| Type | Use Case | Key Features |
|------|----------|--------------|
| **Simple** | Shower signup, counseling | Time slots, single capacity |
| **Standard** | Speaker events, courses | Tickets, custom fields |
| **Retreat** | Weekend retreats | Tickets, custom fields, guests, waitlist |
| **Camp** | Horse camps, youth camps | Tickets, checklist requirements, waitlist |
| **Trip** | Mission trips | Tickets, extensive checklists, deposits |
| **Gala** | Fundraising galas | Tickets, tax-deductible portions, table seating |
| **Auction** | Silent/live auctions | Bidding, card-on-file, winner charging |

---

Components

Admin Components

EventsManager (src/features/events/components/EventsManager.tsx)

The main list view for managing events.

Features:

  • Event list with status badges (Draft, Published, Closed, Canceled)
  • Search and filter by status, type, and time (upcoming/past)
  • Quick actions: View, Edit, Copy URL, Publish, End Registration, Delete
  • Registration count and revenue display

Props: None (uses context for entity selection)

State Management:

  • Uses useEvents hook for data fetching with filters
  • Uses useDeleteEvent, usePublishEvent, useCloseEvent mutations

EventBuilder (src/features/events/components/EventBuilder.tsx)

Multi-step wizard for creating and editing events.

Steps (dynamic based on event type): 1. Basics - Name, dates, location, capacity, waitlist settings 2. Tickets - Ticket types with pricing and inventory 3. Fields - Custom registration fields (text, select, checkbox, etc.) 4. Checklist - Pre-event requirements (waivers, uploads, confirmations) 5. Promo - Promo codes with discounts 6. Review - Summary and publish

Key Features:

  • Step validation blocks forward navigation until requirements met
  • Auto-generates URL slug from event name
  • In-Person/Virtual radio selection for location type
  • Ticket type management with add/edit/delete
  • Custom field builder with multiple field types

Props:

interface EventBuilderProps {
  eventId?: string;      // For editing existing events
  onClose: () => void;   // Callback when closing builder
  onSave: () => void;    // Callback after successful save
}

Public Components

PublicEventPage (src/features/events/components/PublicEventPage.tsx)

Public-facing event registration page.

Features:

  • Hero section with event image or gradient
  • Event details (date, time, location/virtual)
  • Ticket selection with quantity controls
  • Promo code input and validation
  • Registration form with custom fields
  • Order summary with Stripe checkout integration
  • Sold out and waitlist states

Props:

interface PublicEventPageProps {
  config: EventConfig;  // Event data from API
}

EventRegistrationSuccess (src/features/events/components/EventRegistrationSuccess.tsx)

Confirmation page after successful registration.

Features:

  • Confirmation number display
  • Event details summary
  • Add to Calendar (ICS download)
  • Share functionality
  • Checklist notice for events with requirements

Props:

interface EventRegistrationSuccessProps {
  config?: EventSuccessConfig;
  registrationId?: string;
  sessionId?: string;
}

PublicEventLoader (src/features/events/components/PublicEventLoader.tsx)

Wrapper component that handles URL parsing and data fetching.

Features:

  • Parses URL segments (org-id-prefix, org-slug, event-slug)
  • Fetches event data from Edge Function
  • Handles loading, error, success, and canceled states
  • Routes to appropriate view (event page or success page)

ChecklistPortal (src/features/events/components/ChecklistPortal.tsx)

Magic link access for registrants to complete checklist items.

Features:

  • Accessed via /checklist/:token URL
  • Displays all checklist items for the registration
  • Complete confirmation items (checkbox)
  • Upload files for upload items
  • Sign waivers (links to waiver system)
  • Progress bar showing completion status
  • Validates token and expiration

Props:

// Uses URL param :token to fetch data

Check-in & Reporting Components

EventCheckIn (src/features/events/components/EventCheckIn.tsx)

Real-time check-in interface for event day operations.

Features:

  • Stats cards showing total attendees, checked in, remaining, and progress percentage
  • Search by name or email
  • Filter by check-in status (all, checked in, not checked in)
  • Individual registrant check-in with one click
  • Guest check-in support (expandable rows)
  • Undo check-in capability
  • Check-in timestamps displayed
  • Refresh button to sync latest data

Props:

interface EventCheckInProps {
  event: EventWithDetails;
  onBack: () => void;
}

UI Layout: 1. Header with event name and refresh button 2. Four stats cards (Total, Checked In, Remaining, Progress) 3. Search and filter controls 4. Registrations list with expandable guest rows

EventDashboard (src/features/events/components/EventDashboard.tsx)

Event metrics and reporting dashboard.

Features:

  • Overview Tab:
  • Ticket breakdown by type with counts and revenue
  • Registration activity chart (last 7 days)
  • Registrations Tab:
  • Full registration list with details
  • Export to CSV functionality
  • Refresh button
  • Tickets Tab:
  • Ticket type cards with inventory status
  • Revenue per ticket type
  • Progress bars for capacity

Quick Stats:

  • Total attendees (with capacity percentage)
  • Total revenue (with average per ticket)
  • Check-in count and rate
  • Registration count (with canceled count)

Props:

interface EventDashboardProps {
  event: EventWithDetails;
  onBack: () => void;
  onCheckIn: () => void;
  onEdit: () => void;
}

Actions:

  • Copy URL - copies public event URL to clipboard
  • Edit Event - navigates to EventBuilder
  • Check-In - navigates to EventCheckIn

---

URL Structure

Public URLs (No Authentication)

Format: /events/{org-id-prefix}/{org-slug}/{event-slug}

| Segment | Description | Example |
|---------|-------------|---------|
| `org-id-prefix` | First 6 characters of organization UUID | `abc123` |
| `org-slug` | Organization slug (human-readable) | `infocus-ministries` |
| `event-slug` | Event slug (auto-generated from name) | `annual-gala-2025` |

Examples:

https://alignmint.app/events/abc123/infocus-ministries/annual-gala-2025
https://alignmint.app/events/abc123/infocus-ministries/annual-gala-2025/success

URL Generation (in code):

// organization_slug is populated via join in fetchEvents/fetchEvent
const orgIdPrefix = event.organization_id.substring(0, 6);
const publicUrl = `https://alignmint.app/events/${orgIdPrefix}/${event.organization_slug}/${event.slug}`;

> Note: The organization_slug field on EventWithDetails is populated by joining the organizations table in fetchEvents() and fetchEvent() in db.ts. This ensures the public URL is always constructed with the correct organization slug.

Routes Configuration (src/main.tsx)

<Route path="/events/:orgIdPrefix/:orgSlug/:eventSlug" element={<PublicEventLoader />} />
<Route path="/events/:orgIdPrefix/:orgSlug/:eventSlug/success" element={<PublicEventLoader />} />

---

Database Schema

Tables

events

Core event record with metadata, dates, capacity, and accounting links.

| Column | Type | Description |
|--------|------|-------------|
| `id` | UUID | Primary key |
| `organization_id` | UUID | FK to organizations |
| `name` | TEXT | Event name |
| `slug` | TEXT | URL-safe identifier |
| `description` | TEXT | Event description |
| `event_type` | TEXT | 'simple', 'standard', 'retreat', 'camp', 'trip', 'gala', 'auction' |
| `start_date` | TIMESTAMPTZ | Event start |
| `end_date` | TIMESTAMPTZ | Event end |
| `timezone` | TEXT | Timezone (e.g., 'America/Chicago') |
| `location_name` | TEXT | Venue name |
| `location_address` | TEXT | Full address |
| `is_virtual` | BOOLEAN | Virtual event flag |
| `virtual_url` | TEXT | Meeting link |
| `capacity` | INTEGER | Max attendees (null = unlimited) |
| `waitlist_enabled` | BOOLEAN | Enable waitlist |
| `waitlist_capacity` | INTEGER | Max waitlist size |
| `status` | TEXT | 'draft', 'published', 'closed', 'canceled' |
| `total_registrations` | INTEGER | Denormalized count |
| `total_revenue` | DECIMAL | Denormalized revenue |
| `fund_id` | UUID | FK to organizations (for director access) |
| `income_account_id` | UUID | FK to chart_of_accounts |

event_ticket_types

Pricing tiers for events.

| Column | Type | Description |
|--------|------|-------------|
| `id` | UUID | Primary key |
| `event_id` | UUID | FK to events |
| `name` | TEXT | Ticket name (e.g., "General Admission") |
| `description` | TEXT | Ticket description |
| `price` | DECIMAL | Ticket price |
| `quantity_available` | INTEGER | Inventory (null = unlimited) |
| `quantity_sold` | INTEGER | Tickets sold |
| `max_per_order` | INTEGER | Limit per registration |
| `tax_deductible_amount` | DECIMAL | Tax-deductible portion (for galas) |
| `is_active` | BOOLEAN | Available for purchase |
| `sort_order` | INTEGER | Display order |

event_custom_fields

Dynamic form fields for registration.

| Column | Type | Description |
|--------|------|-------------|
| `id` | UUID | Primary key |
| `event_id` | UUID | FK to events |
| `name` | TEXT | Field label |
| `field_type` | TEXT | 'text', 'textarea', 'select', 'multiselect', 'checkbox', 'date', 'number' |
| `required` | BOOLEAN | Required field |
| `options` | JSONB | Options for select/multiselect |
| `applies_to` | TEXT | 'registrant', 'guest', 'both' |
| `sort_order` | INTEGER | Display order |

event_checklist_items

Pre-event requirements.

| Column | Type | Description |
|--------|------|-------------|
| `id` | UUID | Primary key |
| `event_id` | UUID | FK to events |
| `name` | TEXT | Item name |
| `description` | TEXT | Instructions |
| `item_type` | TEXT | 'waiver', 'upload', 'confirmation', 'link' |
| `waiver_id` | UUID | FK to waivers (for waiver type) |
| `external_url` | TEXT | Link URL (for link type) |
| `required` | BOOLEAN | Must complete before event |
| `requires_review` | BOOLEAN | Staff must approve |
| `due_date` | DATE | Deadline |
| `sort_order` | INTEGER | Display order |

event_promo_codes

Discount codes.

| Column | Type | Description |
|--------|------|-------------|
| `id` | UUID | Primary key |
| `event_id` | UUID | FK to events |
| `code` | TEXT | Promo code (uppercase) |
| `discount_type` | TEXT | 'percentage', 'fixed' |
| `discount_value` | DECIMAL | Amount (20 = 20% or $20) |
| `max_uses` | INTEGER | Usage limit (null = unlimited) |
| `times_used` | INTEGER | Current usage count |
| `valid_from` | TIMESTAMPTZ | Start validity |
| `valid_until` | TIMESTAMPTZ | End validity |
| `is_active` | BOOLEAN | Currently active |

event_registrations

Registration records.

| Column | Type | Description |
|--------|------|-------------|
| `id` | UUID | Primary key |
| `event_id` | UUID | FK to events |
| `donor_id` | UUID | FK to donors (unified CRM) |
| `registrant_email` | TEXT | Email |
| `registrant_first_name` | TEXT | First name |
| `registrant_last_name` | TEXT | Last name |
| `registrant_phone` | TEXT | Phone |
| `status` | TEXT | 'pending', 'confirmed', 'waitlisted', 'cancelled', 'refunded' |
| `payment_status` | TEXT | 'pending', 'paid', 'refunded', 'failed' |
| `amount_paid` | DECIMAL | Total paid |
| `stripe_payment_intent_id` | TEXT | Stripe reference |
| `promo_code_id` | UUID | FK to event_promo_codes |
| `custom_field_responses` | JSONB | Custom field values |
| `checked_in_at` | TIMESTAMPTZ | Check-in timestamp |
| `access_token` | TEXT | Magic link token for checklist portal |

Database Functions

| Function | Purpose |
|----------|---------|
| `update_event_totals(event_id, amount)` | Increment registration count and revenue |
| `increment_ticket_quantity(ticket_id, quantity)` | Update tickets sold |
| `decrement_event_totals(event_id, amount)` | For refunds/cancellations |
| `check_event_availability(event_id)` | Check capacity and waitlist status |
| `promote_from_waitlist(event_id)` | Auto-promote next waitlisted registrant |

Triggers

| Trigger | Table | Purpose |
|---------|-------|---------|
| `promote_waitlist_on_cancel` | event_registrations | Auto-promote from waitlist when registration cancelled |

---

Edge Functions

create-event-checkout

Creates a Stripe Checkout Session for event registration.

Location: backend/supabase/functions/create-event-checkout/index.ts

Request:

{
  eventId: string;
  eventSlug: string;
  organizationId: string;
  tickets: Array<{ ticketTypeId: string; quantity: number }>;
  registrantEmail: string;
  registrantFirstName: string;
  registrantLastName: string;
  registrantPhone?: string;
  guests?: Array<{ firstName: string; lastName: string; email?: string }>;
  customFields?: Array<{ fieldId: string; value: string }>;
  promoCode?: string;
  successUrl?: string;
  cancelUrl?: string;
}

Response:

{
  sessionId: string;
  url: string;
  registrationId?: string;  // For free events
  free?: boolean;           // True if no payment needed
}

Features:

  • Validates ticket availability
  • Applies promo code discounts
  • Handles free events (100% discount) without Stripe
  • Creates Stripe Checkout Session with metadata

get-public-event

Fetches public event data for registration page.

Location: backend/supabase/functions/get-public-event/index.ts

Request (query params):

?org={org-slug}&slug={event-slug}

Response:

{
  id: string;
  slug: string;
  organizationId: string;
  organizationSlug: string;
  organizationName: string;
  organizationLogo?: string;
  name: string;
  description?: string;
  event_type: string;
  start_date: string;
  end_date?: string;
  timezone: string;
  location_name?: string;
  location_address?: string;
  is_virtual: boolean;
  virtual_url?: string;
  capacity?: number;
  total_registrations: number;
  waitlist_enabled: boolean;
  image_url?: string;
  status: string;
  ticket_types: TicketType[];
  custom_fields: CustomField[];
  has_checklist: boolean;
}

stripe-webhook (Updated)

Handles Stripe webhook events for event registrations.

Location: backend/supabase/functions/stripe-webhook/index.ts

Event Handling:

  • checkout.session.completed with metadata.source = 'event_registration'
  • Creates registration record with access_token for checklist portal
  • Updates ticket quantities sold
  • Creates guest records
  • Updates promo code usage
  • Updates event totals
  • Links to donor record (creates if needed)
  • Sends confirmation email with magic link
  • Creates dashboard notifications for org admins
  • Checks and notifies if event reaches capacity

get-checklist-portal

Fetches registration and checklist items via magic token.

Location: backend/supabase/functions/get-checklist-portal/index.ts

Request (query params):

?token={access_token}

Response:

{
  registration: RegistrationDetails;
  event: EventDetails;
  checklistItems: ChecklistItem[];
  checklistStatus: ChecklistStatus[];
}

update-checklist-status

Updates checklist item completion status.

Location: backend/supabase/functions/update-checklist-status/index.ts

Request:

{
  registrationId: string;
  checklistItemId: string;
  status: 'pending' | 'completed' | 'approved';
  token?: string;  // Magic link token for verification
}

Features:

  • Validates token matches registration
  • Upserts status record
  • Sends notification when all required items complete

upload-checklist-file

Handles file uploads for checklist items.

Location: backend/supabase/functions/upload-checklist-file/index.ts

Request: FormData with file and metadata

Response:

{
  success: boolean;
  fileUrl: string;
  fileName: string;
}

send-event-confirmation

Sends confirmation email with magic link to checklist portal.

Location: backend/supabase/functions/send-event-confirmation/index.ts

Request:

{
  registrationId: string;
  eventId: string;
  organizationId: string;
  registrantEmail: string;
  registrantFirstName: string;
  registrantLastName: string;
  eventName: string;
  eventDate: string;
  eventLocation?: string;
  isVirtual?: boolean;
  accessToken?: string;
  hasChecklist?: boolean;
  amountPaid?: number;
}

Features:

  • Organic theme styling matching email campaigns
  • Magic link to checklist portal (if event has checklist items)
  • Event details and confirmation number
  • Logs to email_logs table

---

User Workflows

Creating an Event

1. Navigate to Marketing Hub → Events & Ticketing 2. Click "Create Event" 3. Select event type (determines available steps) 4. Complete each step:

5. Click "Publish" to make event live

  • Basics: Name, dates, location, capacity
  • Tickets: Add ticket types with pricing
  • Fields: Add custom registration fields (optional)
  • Checklist: Add pre-event requirements (optional)
  • Promo: Add promo codes (optional)
  • Review: Verify and publish

Managing Registrations

1. From event list, click on event to view details 2. View registration list with status filters 3. Actions available:

  • View registration details
  • Check in attendees
  • Process refunds
  • Manage waitlist

Public Registration Flow

1. User visits public event URL 2. Selects tickets and quantities 3. Optionally applies promo code 4. Fills in registration form (name, email, custom fields) 5. Proceeds to Stripe Checkout (or completes directly if free) 6. Redirected to success page with confirmation 7. Receives confirmation email

---

Integration Points

Stripe Integration

  • Uses existing Stripe account connected via Payment Integrations
  • Creates Checkout Sessions for paid registrations
  • Webhook processes successful payments
  • Supports refunds through Stripe Dashboard

Unified CRM (Donors Table)

  • Registrants are linked to donor records
  • Creates new donor if email doesn't exist
  • Updates donor totals after registration

Accounting Integration

  • Events can be linked to income accounts
  • Revenue tracked in event totals
  • Future: Journal entries for event revenue

Waiver System

  • Checklist items can reference existing waivers
  • Reuses waiver signing UI
  • Tracks completion status per registrant

---

Configuration

Environment Variables

| Variable | Required | Description |
|----------|----------|-------------|
| `STRIPE_SECRET_KEY` | Yes | Stripe API key for checkout |
| `STRIPE_WEBHOOK_SECRET` | Yes | Webhook signature verification |
| `SUPABASE_URL` | Yes | Supabase project URL |
| `SUPABASE_SERVICE_ROLE_KEY` | Yes | Service role key for Edge Functions |

Stripe Dashboard Setup

1. Go to Developers → Webhooks 2. Add endpoint: https://{project-ref}.supabase.co/functions/v1/stripe-webhook 3. Select events: checkout.session.completed, invoice.paid 4. Copy signing secret to STRIPE_WEBHOOK_SECRET

---

Troubleshooting

Common Issues

Event not appearing on public page

  • Check event status is "published"
  • Verify URL format includes org-id-prefix
  • Check organization slug matches

Tickets showing as sold out

  • Verify quantity_available vs quantity_sold
  • Check if tickets are marked as active

Promo code not working

  • Verify code is uppercase
  • Check is_active flag
  • Verify validity dates
  • Check usage limits

Payment not completing

  • Check Stripe Dashboard for failed payments
  • Verify webhook is receiving events
  • Check Edge Function logs in Supabase

Logs

  • Edge Function logs: Supabase Dashboard → Edge Functions → Logs
  • Stripe events: Stripe Dashboard → Developers → Events
  • Browser console: Check for API errors

---

Future Enhancements

Completed in Phase 5

  • [x] Check-in interface (EventCheckIn component)
  • [x] Event metrics dashboard (EventDashboard component)
  • [x] Export registrations to CSV

Completed in Phase 6 (Dec 17, 2025)

  • [x] Checklist portal (magic link access for registrants)
  • [x] Email confirmation with magic link
  • [x] Dashboard notifications for org admins
  • [x] Donor/Contact/Prospect integration
  • [x] Waiver integration in checklist

Planned for Future Phases

  • [ ] Auction bidding system (real-time bidding, bid history, winner notification)
  • Components: AuctionBidding.tsx, place-auction-bid Edge Function
  • Features: Real-time bid updates via Supabase Realtime, bid history, winner notification
  • Estimated complexity: Medium-High (~500-800 lines)
  • [ ] QR code scanning for check-in
  • [ ] Table seating for galas
  • [ ] Calendar integration (Google, Outlook)
  • [ ] Bulk check-in operations
  • [ ] Check-in kiosk mode (full-screen, simplified UI)

Synced from IFMmvp-Frontend documentation: pages/marketing/06-EVENTS-TICKETING.md

Ready to Get Started?

See how Alignmint can simplify your nonprofit's operations. Schedule a free demo with our team and we'll walk you through everything.

Questions? Email us at steven@getalignmint.org

Ready to get started?Start Plus Trial