Tickets Components

Headless components for ticket management.

ListUserEventTickets

Display user’s tickets for an event:

import { ListUserEventTickets } from '@meaple/react-headless-components'
 
function MyTickets({ eventId }) {
  return (
    <ListUserEventTickets eventId={eventId}>
      {({ tickets, isLoading, error }) => {
        if (isLoading) return <div>Loading tickets...</div>
        if (error) return <div>Error loading tickets</div>
 
        return (
          <div>
            <h2>My Tickets</h2>
            {tickets?.map(ticket => (
              <div key={ticket.id} className="ticket">
                <h3>{ticket.ticketType}</h3>
                <p>Order: {ticket.orderId}</p>
                <p>Status: {ticket.status}</p>
                <QRCode value={ticket.qrCode} />
              </div>
            ))}
          </div>
        )
      }}
    </ListUserEventTickets>
  )
}

TicketQuantityController

Control ticket quantity:

import { TicketQuantityController } from '@meaple/react-headless-components'
 
function TicketSelector({ ticket }) {
  return (
    <TicketQuantityController
      ticketId={ticket.id}
      maxQuantity={ticket.available}
      minQuantity={0}
    >
      {({ quantity, increment, decrement, setQuantity, canIncrement, canDecrement }) => (
        <div className="quantity-control">
          <button
            onClick={decrement}
            disabled={!canDecrement}
          >
            -
          </button>
 
          <input
            type="number"
            value={quantity}
            onChange={(e) => setQuantity(+e.target.value)}
            min={0}
            max={ticket.available}
          />
 
          <button
            onClick={increment}
            disabled={!canIncrement}
          >
            +
          </button>
 
          <p>{quantity} tickets selected</p>
        </div>
      )}
    </TicketQuantityController>
  )
}

Props

ListUserEventTickets

interface ListUserEventTicketsProps {
  eventId: string;
  children: (props: {
    tickets: UserTicket[];
    isLoading: boolean;
    error: Error | null;
    refetch: () => void;
  }) => React.ReactNode;
}

TicketQuantityController

interface TicketQuantityControllerProps {
  ticketId: string;
  maxQuantity: number;
  minQuantity?: number;
  initialQuantity?: number;
  onChange?: (quantity: number) => void;
  children: (props: {
    quantity: number;
    increment: () => void;
    decrement: () => void;
    setQuantity: (q: number) => void;
    canIncrement: boolean;
    canDecrement: boolean;
  }) => React.ReactNode;
}

Ticket Selection with Cart

import { TicketQuantityController, Cart } from '@meaple/react-headless-components'
 
function TicketSelection({ ticket }) {
  return (
    <Cart>
      {({ addItem, updateQuantity }) => (
        <TicketQuantityController
          ticketId={ticket.id}
          maxQuantity={ticket.available}
          onChange={(quantity) => {
            if (quantity > 0) {
              addItem({
                id: ticket.id,
                name: ticket.name,
                price: ticket.price,
                quantity
              })
            }
          }}
        >
          {({ quantity, increment, decrement }) => (
            <div>
              <h3>{ticket.name}</h3>
              <p>${ticket.price}</p>
              <div>
                <button onClick={decrement}>-</button>
                <span>{quantity}</span>
                <button onClick={increment}>+</button>
              </div>
            </div>
          )}
        </TicketQuantityController>
      )}
    </Cart>
  )
}

Ticket Display Grid

function TicketGrid({ eventId }) {
  return (
    <ListUserEventTickets eventId={eventId}>
      {({ tickets }) => (
        <div className="ticket-grid">
          {tickets?.map(ticket => (
            <TicketCard key={ticket.id} ticket={ticket} />
          ))}
        </div>
      )}
    </ListUserEventTickets>
  )
}
 
function TicketCard({ ticket }) {
  return (
    <div className="ticket-card">
      <div className="ticket-header">
        <h3>{ticket.ticketType}</h3>
        <span className={`status ${ticket.status}`}>
          {ticket.status}
        </span>
      </div>
      <QRCode value={ticket.qrCode} />
      <button>Download</button>
    </div>
  )
}