Venue Bookings & Lead Capture
Relevant source files
The following files were used as context for generating this wiki page:
- src/components/sheets/venue-booking-form.tsx
- src/lib/supabase/database.types.ts
- src/lib/venues/submit-venue-booking.test.ts
- src/components/sheets/cafe-booking-sheet.tsx
- src/components/sheets/nightlife-booking-sheet.tsx
- src/lib/venues/venue-booking-status-display.test.ts
- src/lib/venues/venue-booking-form-schema.test.ts
The Venue Bookings and Lead Capture system provides a structured mechanism for users to request visits to various venues (cafés, nightclubs, etc.) and for the platform to capture these intents as actionable leads. Unlike instant reservations, these requests are treated as non-guaranteed "pending" inquiries that require manual review and confirmation via external channels like WhatsApp.
The system is tightly integrated with the platform's discovery features, allowing users to transition from viewing a venue detail panel to submitting a booking request through dedicated UI components and backend API endpoints.
System Architecture & Data Flow
The architecture follows a standard client-server pattern using Next.js for the frontend and Supabase for persistent storage. The process begins in the UI, where a user interacts with a booking sheet, enters their details into a validated form, and submits the request to a backend handler.
Booking Submission Flow
The following sequence diagram illustrates the lifecycle of a venue booking request from the user's initial interaction to the successful storage in the database.
Core Components
VenueBookingForm
The central UI component for capturing booking intent. It requires the user to be authenticated and provides a "Sign in gate" for unauthenticated visitors. It captures critical lead information including name, email, phone number (for WhatsApp), preferred date/time, and party size.
Key features include:
- Authentication Check: Uses
useSessionto verify user status before allowing submission. - Field Validation: Ensures
requestedAtis a valid date andpartySizeis at least 1. - Idempotency: Utilizes
buildVenueBookingIdempotencyKeyto prevent duplicate submissions. - Status Management: Handles loading states (
submitting) and error display.
Sources: src/components/sheets/venue-booking-form.tsx:18-63, src/components/sheets/venue-booking-form.tsx:118-212
Specialized Booking Sheets
The application provides category-specific sheets that wrap the VenueBookingForm to provide context-aware booking experiences:
- CafeBookingSheet: Displays café-specific metadata like Google ratings and "Hours signal" while hosting the form.
- NightlifeBookingSheet: Provides a similar interface for nightclubs, explicitly mapping the
venueKindtonightclub.
Sources: src/components/sheets/cafe-booking-sheet.tsx:44-59, src/components/sheets/nightlife-booking-sheet.tsx:44-53
Data Models & Schema
The system relies on several tables in the Supabase schema to store and track leads and booking requests.
Venue Booking Requests (venue_booking_requests)
This table stores individual visit requests for restaurants and venue anchors.
| Field | Type | Description |
|---|---|---|
id | uuid | Unique identifier for the request |
user_id | uuid | Reference to the requester's profile |
venue_kind | text | Discriminator (e.g., 'cafe', 'nightclub') |
place_id | text | Google Place ID of the target venue |
status | text | Status (default: 'pending') |
requested_at | timestamp | User's preferred visit time |
party_size | integer | Number of attendees |
contact_name | text | Name provided in the form |
contact_email | text | Email for communication |
contact_phone | text | Phone for WhatsApp confirmation |
idempotency_key | text | Prevents duplicate submissions |
Sources: src/lib/supabase/database.types.ts:2516-2558
Leads (leads)
A broader table used for capturing various types of interest, including rental viewings and venue inquiries.
| Field | Type | Description |
|---|---|---|
id | uuid | Unique lead ID |
user_id | uuid | Associated user |
intent | text | The nature of the lead (e.g., 'rental_search') |
status | text | Current status of the lead processing |
score | number | Potential lead quality metric |
metadata | jsonb | Extensible storage for lead-specific data |
Sources: src/lib/supabase/database.types.ts:1669-1701
Logic & State Management
Status Mapping
The system uses a standardized set of statuses to communicate progress to the user. The UI maps internal database statuses to human-readable labels and visual variants.
| Internal Status | UI Label | Variant |
|---|---|---|
pending | Request pending | secondary |
confirmed | Confirmed | default |
declined / cancelled | Request declined | destructive |
reviewing | Under review | secondary |
contacted | Contacted | secondary |
Sources: src/lib/venues/venue-booking-status-display.test.ts:10-34
Kind Mapping
There is a distinction between UI categories and database constraints for venue_kind. For instance, queries for "nightlife" in the UI are mapped to the "nightclub" kind in the backend.
Sources: src/lib/venues/venue-booking-status-display.test.ts:39-47, src/lib/venues/venue-booking-form-schema.test.ts:26-30
Validation & Constraints
The venueBookingRequestSchema (Zod) enforces strict validation on incoming requests:
- Venue Kind: Must be one of the permitted types (e.g., 'cafe' is accepted, while 'nightlife' is rejected in favor of 'nightclub').
- Place ID: Must be present and valid; UI components show a warning if a venue is missing a verified Place ID, disabling booking.
- Contact Info: Name and Email are mandatory; Phone is optional but recommended for WhatsApp.
Sources: src/lib/venues/venue-booking-form-schema.test.ts:15-39, src/components/sheets/cafe-booking-sheet.tsx:60-67
Summary
The Venue Bookings & Lead Capture module serves as the primary bridge between user discovery and manual fulfillment. By capturing detailed lead information and storing it with idempotency protections in Supabase, the system ensures that user interest is reliably recorded as a "pending" request. This allows the platform's operations team to verify details and finalize bookings via WhatsApp, maintaining a high-touch service model for the Medellín discovery platform.