# Ticket Tier Select

> Ticket tier selection with quantity controls and order summary. Shows price breakdown with fees.

A shadcn/ui block from the [@manifest](https://ui.manifest.build) registry, listed on [shadcn.exchange](https://shadcn.exchange/r/manifest/ticket-tier-select).

- Page, with a live preview: https://shadcn.exchange/r/manifest/ticket-tier-select
- Screenshot: https://abzjhwgwpdpz7ua5.public.blob.vercel-storage.com/shots/manifest/ticket-tier-select-light-2ed6b8d45b1a3ac1.png
- Registry item: https://ui.manifest.build/r/ticket-tier-select.json
- Categories: events
- Listed: 2026-10-13, source last changed 2026-10-13

## Install

```bash
npx shadcn@latest add https://ui.manifest.build/r/ticket-tier-select.json
```

Run it in a project that has shadcn/ui set up. It adds the files below and installs what they depend on.

## Dependencies

- npm packages: `lucide-react`
- Registry items: `button`

## Files

### `registry/events/ticket-tier-select.tsx`

````tsx
'use client'

import { Button } from '@/components/ui/button'
import { cn } from '@/lib/utils'
import { Minus, Plus, Info } from 'lucide-react'
import { useState } from 'react'
import { demoTicketTiers } from './demo/events'

/**
 * Formats a currency amount.
 * @param {number} amount - Amount to format
 * @param {string} currency - Currency code
 * @returns {string} Formatted currency string
 */
function formatCurrency(amount: number, currency: string = 'USD'): string {
  return new Intl.NumberFormat('en-US', {
    style: 'currency',
    currency,
    minimumFractionDigits: 2
  }).format(amount)
}

/**
 * Represents a ticket tier option.
 * @interface TicketTier
 * @property {string} [name] - Tier name (e.g., "General Admission", "VIP")
 * @property {number} [price] - Base price
 * @property {number} [fee] - Service fee
 * @property {number} [available] - Number available
 * @property {string} [salesEndDate] - When sales end
 * @property {string} [description] - Tier description
 * @property {number} [maxPerOrder] - Maximum tickets per order
 */
export interface TicketTier {
  name?: string
  price?: number
  fee?: number
  available?: number
  salesEndDate?: string
  description?: string
  maxPerOrder?: number
}

/**
 * Represents a selected ticket with quantity.
 * @interface TicketSelection
 * @property {string} tierName - Tier name for display
 * @property {number} quantity - Number of tickets
 * @property {number} price - Base price per ticket
 * @property {number} fee - Fee per ticket
 */
export interface TicketSelection {
  tierName?: string
  quantity: number
  price?: number
  fee?: number
}

export interface TicketTierEvent {
  title?: string
  date?: string
  image?: string
  currency?: string
}

/**
 * ═══════════════════════════════════════════════════════════════════════════
 * TicketTierSelectProps
 * ═══════════════════════════════════════════════════════════════════════════
 *
 * Props for the TicketTierSelect component. Allows selection of multiple
 * ticket tiers with quantity pickers and displays an order summary.
 */
export interface TicketTierSelectProps {
  data?: {
    /** Event information including title, date, and currency. */
    event?: TicketTierEvent
    /** Available ticket tiers with pricing and availability. */
    tiers?: TicketTier[]
  }
  actions?: {
    /** Called when checkout button is clicked with selections and total. */
    onCheckout?: (selections: TicketSelection[], total: number) => void
  }
  appearance?: {
    /**
     * Whether to show the order summary sidebar.
     * @default true
     */
    showOrderSummary?: boolean
  }
  control?: {
    /** Initial ticket selections as a map of tier index to quantity. */
    selections?: Record<number, number>
  }
}

/**
 * A ticket tier selection component with quantity pickers and order summary.
 * Allows users to select quantities for multiple ticket tiers.
 *
 * Features:
 * - Multiple tier selection with quantities
 * - Price and fee breakdown
 * - Sales end date display
 * - Tier descriptions
 * - Order summary sidebar
 * - Checkout button
 *
 * @component
 * @example
 * ```tsx
 * <TicketTierSelect
 *   data={{
 *     event: {
 *       title: "Concert Night",
 *       date: "Friday, Feb 6 · 8pm",
 *       currency: "USD"
 *     },
 *     tiers: [
 *       { name: "General Admission", price: 45, fee: 5, available: 100 },
 *       { name: "VIP", price: 120, fee: 10, available: 50 }
 *     ]
 *   }}
 *   actions={{
 *     onCheckout: (selections, total) => console.log("Checkout:", total),
 *     onSelectionChange: (selections) => console.log("Selections:", selections)
 *   }}
 *   appearance={{ showOrderSummary: true }}
 * />
 * ```
 */
export function TicketTierSelect({ data, actions, appearance, control }: TicketTierSelectProps) {
  const resolved: NonNullable<TicketTierSelectProps['data']> = data ?? { tiers: demoTicketTiers }
  const event = resolved.event
  const tiers = resolved.tiers ?? []
  const currency = event?.currency ?? 'USD'
  const { onCheckout } = actions ?? {}
  const { showOrderSummary = true } = appearance ?? {}

  const [selections, setSelections] = useState<Record<number, number>>(
    control?.selections ?? {}
  )

  const updateQuantity = (tierIndex: number, delta: number) => {
    const tier = tiers[tierIndex]
    if (!tier) return

    const currentQty = selections[tierIndex] || 0
    const newQty = Math.max(0, Math.min(currentQty + delta, tier.maxPerOrder ?? 10, tier.available ?? 100))

    const newSelections = { ...selections, [tierIndex]: newQty }
    if (newQty === 0) {
      delete newSelections[tierIndex]
    }
    setSelections(newSelections)
  }

  const getSelectionsList = (sels: Record<number, number> = selections): TicketSelection[] => {
    return Object.entries(sels)
      .filter(([_, qty]) => qty > 0)
      .map(([indexStr, qty]) => {
        const tierIndex = parseInt(indexStr, 10)
        const tier = tiers[tierIndex]
        return {
          tierName: tier?.name,
          quantity: qty,
          price: tier?.price,
          fee: tier?.fee ?? 0
        }
      })
  }

  const selectionsList = getSelectionsList()
  const hasSelections = selectionsList.length > 0

  const subtotal = selectionsList.reduce((sum, s) => sum + (s.price ?? 0) * s.quantity, 0)
  const totalFees = selectionsList.reduce((sum, s) => sum + (s.fee ?? 0) * s.quantity, 0)
  const total = subtotal + totalFees

  const handleCheckout = () => {
    onCheckout?.(selectionsList, total)
  }

  return (
    <div className="rounded-xl border bg-card p-6">
      <div className="flex flex-col lg:flex-row gap-6">
        {/* Left side - Tier selection */}
        <div className="flex-1">
        {/* Header */}
        {(event?.title || event?.date) && (
          <div className="text-center mb-6">
            {event?.title && <h2 className="text-xl font-semibold">{event.title}</h2>}
            {event?.date && <p className="text-sm text-muted-foreground mt-1">{event.date}</p>}
          </div>
        )}

        {/* Tiers */}
        <div className="space-y-4">
          {tiers.map((tier, index) => {
            const qty = selections[index] || 0
            const isSelected = qty > 0
            const totalPrice = (tier.price ?? 0) + (tier.fee ?? 0)

            return (
              <div
                key={index}
                className={cn(
                  'rounded-lg border p-4 transition-colors',
                  isSelected && 'border-primary ring-1 ring-primary'
                )}
              >
                {/* Tier header */}
                <div className="flex items-center justify-between">
                  {tier.name && <h3 className="font-medium">{tier.name}</h3>}
                  <div className="flex items-center gap-3">
                    <Button
                      variant="outline"
                      size="icon"
                      className={cn(
                        'h-8 w-8 rounded-full',
                        qty === 0 && 'opacity-50'
                      )}
                      onClick={() => updateQuantity(index, -1)}
                      disabled={qty === 0}
                    >
                      <Minus className="h-4 w-4" />
                    </Button>
                    <span className="w-6 text-center font-medium">{qty}</span>
                    <Button
                      size="icon"
                      className="h-8 w-8 rounded-full"
                      onClick={() => updateQuantity(index, 1)}
                      disabled={qty >= (tier.maxPerOrder ?? 10) || qty >= (tier.available ?? 100)}
                    >
                      <Plus className="h-4 w-4" />
                    </Button>
                  </div>
                </div>

                {/* Price info */}
                {tier.price !== undefined && (
                  <div className="mt-3">
                    <div className="flex items-baseline gap-2">
                      <span className="font-semibold">{formatCurrency(totalPrice, currency)}</span>
                      {(tier.fee ?? 0) > 0 && (
                        <span className="text-sm text-muted-foreground">
                          incl. {formatCurrency(tier.fee ?? 0, currency)} Fee
                        </span>
                      )}
                    </div>
                    {tier.salesEndDate && (
                      <p className="text-sm text-muted-foreground mt-1">
                        Sales end on {tier.salesEndDate}
                      </p>
                    )}
                  </div>
                )}

                {/* Description */}
                {tier.description && (
                  <p className="text-sm text-muted-foreground mt-3">
                    {tier.description}
                  </p>
                )}
              </div>
            )
          })}
        </div>

        {/* Checkout button */}
        <div className="mt-6">
          <Button
            className="w-full"
            size="lg"
            onClick={handleCheckout}
            disabled={!hasSelections}
          >
            Check out
          </Button>
        </div>
      </div>

        {/* Right side - Order summary */}
        {showOrderSummary && (
          <div className="w-full lg:w-80 shrink-0">
            {/* Event image */}
            {event?.image && (
              <img
                src={event.image}
                alt={event?.title || 'Event image'}
                className="w-full h-40 object-cover rounded-lg mb-4"
              />
            )}

            <div className="rounded-lg border bg-muted/30 p-4">
              <h3 className="font-semibold mb-4">Order summary</h3>

              {hasSelections ? (
                <>
                  {/* Line items */}
                  <div className="space-y-2">
                    {selectionsList.map((selection, index) => (
                      <div key={index} className="flex justify-between text-sm">
                        <span>{selection.quantity} x {selection.tierName ?? 'Ticket'}</span>
                        <span>{formatCurrency((selection.price ?? 0) * selection.quantity, currency)}</span>
                      </div>
                    ))}
                  </div>

                  {/* Totals */}
                  <div className="mt-4 pt-4 border-t space-y-2">
                    <div className="flex justify-between text-sm">
                      <span>Subtotal</span>
                      <span>{formatCurrency(subtotal, currency)}</span>
                    </div>
                    <div className="flex justify-between text-sm">
                      <span className="flex items-center gap-1">
                        Fees
                        <Info className="h-3 w-3 text-muted-foreground" />
                      </span>
                      <span>{formatCurrency(totalFees, currency)}</span>
                    </div>
                  </div>

                  <div className="mt-4 pt-4 border-t">
                    <div className="flex justify-between font-semibold">
                      <span>Total</span>
                      <span>{formatCurrency(total, currency)}</span>
                    </div>
                  </div>
                </>
              ) : (
                <p className="text-sm text-muted-foreground">No tickets selected</p>
              )}
            </div>
          </div>
        )}
      </div>
    </div>
  )
}
````

### `registry/events/demo/events.ts`

```ts
// Demo data for Events category components
// This file contains sample data used for component previews and documentation

import type { Event, EventDetails } from '../types'

// Helper to generate dates relative to today
function getDateAt(daysFromNow: number, hour: number): string {
  const date = new Date()
  date.setDate(date.getDate() + daysFromNow)
  date.setHours(hour, 0, 0, 0)
  return date.toISOString()
}

// Single event for EventCard default
export const demoEvent: Event = {
  title: 'NEON Vol. 9',
  category: 'Music',
  venue: 'Echoplex',
  neighborhood: 'Echo Park',
  city: 'Los Angeles',
  dateTime: 'Tonight 9:00 PM - 3:00 AM',
  priceRange: '$45 - $150',
  image: 'https://images.unsplash.com/photo-1470225620780-dba8ba36b745?w=800',
  vibeTags: ['High energy', 'Late night', 'Dressy'],
  vibeDescription:
    'Immersive electronic experience with world-class DJs and stunning visuals.',
  aiSummary:
    "Immersive electronic night with world-class DJs and stunning visuals at LA's top-rated venue.",
  lineup: ['DJ Shadow', 'Bonobo', 'Four Tet', 'Caribou'],
  ticketTiers: [
    'General Admission $45',
    'VIP Access $120',
    'Backstage Pass $150'
  ],
  eventSignal: 'going-fast',
  organizerRating: 4.8,
  reviewCount: 12453,
  venueRating: 4.8,
  ageRestriction: '21+',
  hasMultipleDates: true
}

// 15 events for EventList default
export const demoEvents: Event[] = [
  {
    title: 'NEON Vol. 9',
    category: 'Music',
    venue: 'Echoplex',
    neighborhood: 'Echo Park',
    city: 'Los Angeles',
    dateTime: 'Tonight 9:00 PM - 3:00 AM',
    priceRange: '$45 - $150',
    image: 'https://images.unsplash.com/photo-1470225620780-dba8ba36b745?w=800',
    coordinates: { lat: 34.0781, lng: -118.2606 },
    vibeTags: ['High energy', 'Late night'],
    eventSignal: 'going-fast',
    organizerRating: 4.8,
    reviewCount: 12453,
    ageRestriction: '21+'
  },
  {
    title: 'The Midnight Show',
    category: 'Comedy',
    venue: 'The Comedy Underground',
    neighborhood: 'Santa Monica',
    city: 'Los Angeles',
    dateTime: 'Tonight 10:00 PM - 12:00 AM',
    priceRange: '$15 - $35',
    image: 'https://images.unsplash.com/photo-1585699324551-f6c309eedeca?w=800',
    coordinates: { lat: 34.0195, lng: -118.4912 },
    vibeTags: ['Social', 'Late night'],
    eventSignal: 'popular',
    organizerRating: 4.7,
    reviewCount: 3241,
    discount: 'TONIGHT ONLY - 40% OFF'
  },
  {
    title: 'Salsa Sundays @ Echo Park',
    category: 'Classes',
    venue: 'Echo Park Lake',
    neighborhood: 'Echo Park',
    city: 'Los Angeles',
    dateTime: 'Saturday 6:00 PM - 10:00 PM',
    priceRange: 'Free',
    image: 'https://images.unsplash.com/photo-1504609813442-a8924e83f76e?w=800',
    coordinates: { lat: 34.0731, lng: -118.2608 },
    vibeTags: ['High energy', 'Social'],
    eventSignal: 'just-added',
    organizerRating: 4.9,
    reviewCount: 8764
  },
  {
    title: 'Dawn Flow: Griffith Park',
    category: 'Classes',
    venue: 'Griffith Park',
    neighborhood: 'Los Feliz',
    city: 'Los Angeles',
    dateTime: 'Tomorrow 6:00 AM - 8:00 AM',
    priceRange: 'Free',
    image: 'https://images.unsplash.com/photo-1545205597-3d9d02c29597?w=800',
    coordinates: { lat: 34.1365, lng: -118.2943 },
    vibeTags: ['Chill', 'Wellness', 'Outdoor'],
    organizerRating: 4.9,
    reviewCount: 8764,
    discount: 'FREE - First 50 Only'
  },
  {
    title: 'Lakers vs Celtics',
    category: 'Sports',
    venue: 'Crypto.com Arena',
    neighborhood: 'Downtown',
    city: 'Los Angeles',
    dateTime: 'Friday 7:30 PM - 10:30 PM',
    priceRange: '$125 - $850',
    image: 'https://images.unsplash.com/photo-1546519638-68e109498ffc?w=800',
    coordinates: { lat: 34.0430, lng: -118.2673 },
    vibeTags: ['High energy', 'Social', 'Premium'],
    eventSignal: 'sales-end-soon',
    organizerRating: 4.5,
    reviewCount: 2341
  },
  {
    title: 'Smorgasburg LA: Sunday Market',
    category: 'Food & Drink',
    venue: 'ROW DTLA',
    neighborhood: 'Arts District',
    city: 'Los Angeles',
    dateTime: 'Sunday 10:00 AM - 4:00 PM',
    priceRange: 'Free',
    image: 'https://images.unsplash.com/photo-1555939594-58d7cb561ad1?w=800',
    coordinates: { lat: 34.0341, lng: -118.2324 },
    vibeTags: ['Family-friendly', 'Outdoor', 'Social'],
    organizerRating: 4.8,
    reviewCount: 5632
  },
  {
    title: 'LACMA After Hours',
    category: 'Arts',
    venue: 'LACMA',
    neighborhood: 'Miracle Mile',
    city: 'Los Angeles',
    dateTime: 'Friday 7:00 PM - 11:00 PM',
    priceRange: '$35 - $75',
    image: 'https://images.unsplash.com/photo-1531243269054-5ebf6f34081e?w=800',
    coordinates: { lat: 34.0639, lng: -118.3592 },
    vibeTags: ['Chill', 'Date night', 'Sophisticated'],
    organizerRating: 4.7,
    reviewCount: 1234,
    ageRestriction: '21+',
    discount: 'MEMBER PRICE'
  },
  {
    title: 'Blue Note Under Stars',
    category: 'Music',
    venue: 'Hollywood Bowl',
    neighborhood: 'Hollywood Hills',
    city: 'Los Angeles',
    dateTime: 'Saturday 8:00 PM - 11:00 PM',
    priceRange: '$45 - $200',
    image: 'https://images.unsplash.com/photo-1514320291840-2e0a9bf2a9ae?w=800',
    coordinates: { lat: 34.1122, lng: -118.3391 },
    vibeTags: ['Chill', 'Date night', 'Outdoor'],
    lineup: ['Kamasi Washington', 'Thundercat', 'Terrace Martin'],
    organizerRating: 4.8,
    reviewCount: 12453
  },
  {
    title: 'Meraki: Seth Troxler',
    category: 'Nightlife',
    venue: 'Sound Nightclub',
    neighborhood: 'Hollywood',
    city: 'Los Angeles',
    dateTime: 'Saturday 10:00 PM - 4:00 AM',
    priceRange: '$35 - $65',
    image: 'https://images.unsplash.com/photo-1571266028243-e4733b0f0bb0?w=800',
    coordinates: { lat: 34.0928, lng: -118.3287 },
    vibeTags: ['High energy', 'Late night', 'Underground'],
    lineup: ['Amelie Lens', 'I Hate Models', 'FJAAK'],
    organizerRating: 4.6,
    reviewCount: 1876,
    ageRestriction: '21+'
  },
  {
    title: 'Whitney Cummings + Friends',
    category: 'Comedy',
    venue: 'The Laugh Factory',
    neighborhood: 'Hollywood',
    city: 'Los Angeles',
    dateTime: 'In 2 days 8:00 PM - 11:00 PM',
    priceRange: '$25 - $55',
    image: 'https://images.unsplash.com/photo-1527224538127-2104bb71c51b?w=800',
    coordinates: { lat: 34.0901, lng: -118.3615 },
    vibeTags: ['Chill', 'Social', 'Date night'],
    organizerRating: 4.7,
    reviewCount: 3241,
    ageRestriction: '18+'
  },
  {
    title: 'Venice Beach Drum Circle',
    category: 'Music',
    venue: 'Venice Beach Boardwalk',
    neighborhood: 'Venice',
    city: 'Los Angeles',
    dateTime: 'Sunday 4:00 PM - 8:00 PM',
    priceRange: 'Free',
    image: 'https://images.unsplash.com/photo-1506157786151-b8491531f063?w=800',
    coordinates: { lat: 33.9850, lng: -118.4695 },
    vibeTags: ['Outdoor', 'Social', 'Chill'],
    eventSignal: 'popular',
    organizerRating: 4.6,
    reviewCount: 2145
  },
  {
    title: 'Rooftop Cinema: Blade Runner',
    category: 'Film',
    venue: 'Rooftop Cinema Club',
    neighborhood: 'DTLA',
    city: 'Los Angeles',
    dateTime: 'Friday 8:30 PM - 11:00 PM',
    priceRange: '$25 - $45',
    image: 'https://images.unsplash.com/photo-1489599849927-2ee91cede3ba?w=800',
    coordinates: { lat: 34.0407, lng: -118.2468 },
    vibeTags: ['Date night', 'Views', 'Chill'],
    organizerRating: 4.8,
    reviewCount: 892
  },
  {
    title: 'Dodgers vs Giants',
    category: 'Sports',
    venue: 'Dodger Stadium',
    neighborhood: 'Elysian Park',
    city: 'Los Angeles',
    dateTime: 'Saturday 1:10 PM - 4:30 PM',
    priceRange: '$35 - $350',
    image: 'https://images.unsplash.com/photo-1566577739112-5180d4bf9390?w=800',
    coordinates: { lat: 34.0739, lng: -118.2400 },
    vibeTags: ['Family-friendly', 'Social', 'High energy'],
    eventSignal: 'few-tickets-left',
    organizerRating: 4.7,
    reviewCount: 15678
  },
  {
    title: 'Natural Wine Fair',
    category: 'Food & Drink',
    venue: 'Grand Central Market',
    neighborhood: 'Downtown',
    city: 'Los Angeles',
    dateTime: 'Sunday 12:00 PM - 6:00 PM',
    priceRange: '$45 - $85',
    image: 'https://images.unsplash.com/photo-1510812431401-41d2bd2722f3?w=800',
    coordinates: { lat: 34.0508, lng: -118.2490 },
    vibeTags: ['Tasting', 'Social', 'Sophisticated'],
    eventSignal: 'just-added',
    organizerRating: 4.5,
    reviewCount: 567,
    ageRestriction: '21+'
  },
  {
    title: 'Meditation in the Gardens',
    category: 'Wellness',
    venue: 'The Getty Center',
    neighborhood: 'Brentwood',
    city: 'Los Angeles',
    dateTime: 'Sunday 7:00 AM - 9:00 AM',
    priceRange: 'Free',
    image: 'https://images.unsplash.com/photo-1506126613408-eca07ce68773?w=800',
    coordinates: { lat: 34.0780, lng: -118.4741 },
    vibeTags: ['Wellness', 'Outdoor', 'Chill'],
    organizerRating: 4.9,
    reviewCount: 1234
  }
]

// Detailed event for EventDetail default
export const demoEventDetails: EventDetails = {
  title: 'Sunglasses at Night: Underground Techno',
  category: 'Nightlife',
  venue: 'The White Rabbit',
  neighborhood: 'The Woodlands',
  city: 'Houston, TX',
  startDateTime: getDateAt(2, 22),
  endDateTime: getDateAt(3, 4),
  priceRange: '$15 - $30',
  images: [
    'https://images.unsplash.com/photo-1470225620780-dba8ba36b745?w=800',
    'https://images.unsplash.com/photo-1514525253161-7a46d19cd819?w=800',
    'https://images.unsplash.com/photo-1533174072545-7a4b6ad7a6c3?w=800'
  ],
  vibeTags: ['High energy', 'Late night', 'Underground'],
  eventSignal: 'going-fast',
  aiSummary: 'Raw, unfiltered techno in an authentic warehouse setting.',
  description:
    'Experience the raw energy of underground techno. Industrial beats, immersive visuals, and a crowd that lives for the music.',
  lineup: ['Amelie Lens', 'I Hate Models', 'FJAAK'],
  attendeesCount: 537,
  friendsGoing: [
    { name: 'Alex', avatar: 'https://i.pravatar.cc/40?u=alex' },
    { name: 'Sam', avatar: 'https://i.pravatar.cc/40?u=sam' }
  ],
  organizer: {
    name: 'Midnight Lovers',
    image: 'https://i.pravatar.cc/80?u=midnight',
    rating: 4.5,
    reviewCount: 1067,
    verified: true,
    followers: 1200,
    eventsCount: 154,
    hostingYears: 8,
    trackRecord: 'great',
    responseRate: 'very responsive'
  },
  venue_details: {
    name: 'The White Rabbit',
    address: '8827 Nasher Ave',
    city: 'Houston TX',
    coordinates: { lat: 29.7604, lng: -95.3698 }
  },
  tiers: [
    { name: 'General Admission', price: 15, available: 50 },
    {
      name: 'VIP Access',
      price: 30,
      available: 20,
      benefits: ['Skip the line', 'Exclusive lounge']
    }
  ],
  goodToKnow: {
    duration: '2 hours',
    doorsOpen: '7:00 PM',
    showtime: '7:30 PM',
    ageRestriction: '21+',
    dressCode: 'Casual',
    parking: 'Limited, leave early to avoid long queues'
  },
  policies: {
    refund: 'No refunds. Tickets are transferable.',
    entry: 'Open 2 hours before event',
    idRequired: true,
    securityOnSite: true
  },
  faq: [
    {
      question: 'What is the refund policy?',
      answer: 'No refunds. Tickets are transferable.'
    },
    {
      question: 'When do doors open?',
      answer: 'Open 2 hours before event.'
    },
    {
      question: 'Is there parking?',
      answer: 'Limited, leave early to avoid long queues.'
    }
  ],
  relatedTags: ['Houston Events', 'Texas Nightlife', 'Techno Parties']
}

// Ticket tiers for TicketTierSelect
export const demoTicketTiers = [
  {
    id: '1',
    name: 'General Admission',
    price: 45,
    fee: 5,
    available: 100,
    maxPerOrder: 10,
  },
  {
    id: '2',
    name: 'VIP',
    price: 150,
    fee: 15,
    available: 20,
    maxPerOrder: 4,
    description: 'Includes backstage access',
  },
]

// Event confirmation data
export const demoEventConfirmation = {
  orderNumber: 'EVT-12345',
  eventTitle: 'Summer Music Festival',
  ticketCount: 2,
  recipientEmail: 'customer@example.com',
  eventDate: 'Jan 20, 2024',
  eventLocation: 'Central Park, New York',
  organizer: {
    name: 'Live Nation',
  },
}
```
