{
  "name": "booking-card",
  "title": "BookingCard",
  "description": "Single booking display with status, time, and action buttons.",
  "type": "component",
  "registryDependencies": [
    "price",
    "cn"
  ],
  "files": [
    {
      "path": "booking-card.tsx",
      "content": "\"use client\";\n\nimport React from \"react\";\nimport type { CustomerBooking, BookingStatus } from \"@cimplify/sdk\";\nimport { Price } from \"@cimplify/sdk/react\";\nimport { cn } from \"@cimplify/sdk/react\";\n\nexport interface BookingCardClassNames {\n  root?: string;\n  service?: string;\n  status?: string;\n  time?: string;\n  confirmationCode?: string;\n  total?: string;\n  actions?: string;\n  cancelButton?: string;\n  rescheduleButton?: string;\n}\n\nexport interface BookingCardProps {\n  /** The booking to display. */\n  booking: CustomerBooking;\n  /** Called when cancel is clicked. */\n  onCancel?: (booking: CustomerBooking) => void;\n  /** Called when reschedule is clicked. */\n  onReschedule?: (booking: CustomerBooking) => void;\n  /** Custom renderer for the booking. */\n  renderBooking?: (booking: CustomerBooking) => React.ReactNode;\n  className?: string;\n  classNames?: BookingCardClassNames;\n}\n\nconst STATUS_LABELS: Record<string, string> = {\n  pending: \"Pending\",\n  confirmed: \"Confirmed\",\n  in_progress: \"In Progress\",\n  completed: \"Completed\",\n  cancelled: \"Cancelled\",\n  no_show: \"No Show\",\n};\n\nfunction isActiveStatus(status: BookingStatus): boolean {\n  const s = String(status).toLowerCase();\n  return s !== \"completed\" && s !== \"cancelled\" && s !== \"no_show\";\n}\n\nfunction getFirstServiceItem(booking: CustomerBooking) {\n  return booking.service_items[0] ?? null;\n}\n\nfunction formatScheduledTime(start?: string | null, end?: string | null): string | null {\n  if (!start) return null;\n  try {\n    const startDate = new Date(start);\n    const options: Intl.DateTimeFormatOptions = {\n      month: \"short\",\n      day: \"numeric\",\n      hour: \"numeric\",\n      minute: \"2-digit\",\n    };\n    let formatted = startDate.toLocaleString(undefined, options);\n    if (end) {\n      const endDate = new Date(end);\n      formatted += ` – ${endDate.toLocaleTimeString(undefined, { hour: \"numeric\", minute: \"2-digit\" })}`;\n    }\n    return formatted;\n  } catch {\n    return start;\n  }\n}\n\nexport function BookingCard({\n  booking,\n  onCancel,\n  onReschedule,\n  renderBooking,\n  className,\n  classNames,\n}: BookingCardProps): React.ReactElement {\n  if (renderBooking) {\n    return (\n      <div\n        data-cimplify-booking-card\n        data-status={booking.status}\n        className={cn(className, classNames?.root)}\n      >\n        {renderBooking(booking)}\n      </div>\n    );\n  }\n\n  const firstItem = getFirstServiceItem(booking);\n  const active = isActiveStatus(booking.status);\n  const scheduledTime = firstItem\n    ? formatScheduledTime(firstItem.scheduled_start, firstItem.scheduled_end)\n    : null;\n\n  return (\n    <div\n      data-cimplify-booking-card\n      data-status={booking.status}\n      className={cn(\n        \"rounded-xl border border-border bg-background p-4 flex flex-col gap-3\",\n        className,\n        classNames?.root,\n      )}\n    >\n      <div data-cimplify-booking-main className=\"flex items-center justify-between gap-2\">\n        <span data-cimplify-booking-service className={cn(\"font-semibold text-foreground\", classNames?.service)}>\n          Booking #{booking.order_id.slice(0, 8)}\n        </span>\n        <span\n          data-cimplify-booking-status\n          data-status={booking.status}\n          className={cn(\n            \"text-xs font-medium px-2 py-0.5 rounded-full\",\n            active ? \"bg-primary/10 text-primary\" : \"bg-muted text-muted-foreground\",\n            classNames?.status,\n          )}\n        >\n          {STATUS_LABELS[booking.status] ?? booking.status}\n        </span>\n      </div>\n\n      {firstItem?.confirmation_code && (\n        <span data-cimplify-booking-code className={cn(\"text-xs font-mono text-muted-foreground tracking-wide\", classNames?.confirmationCode)}>\n          {firstItem.confirmation_code}\n        </span>\n      )}\n\n      {scheduledTime && (\n        <time\n          data-cimplify-booking-time\n          dateTime={firstItem?.scheduled_start ?? undefined}\n          className={cn(\"text-sm text-foreground\", classNames?.time)}\n        >\n          {scheduledTime}\n        </time>\n      )}\n\n      <span data-cimplify-booking-total className={cn(\"text-sm font-medium text-foreground\", classNames?.total)}>\n        <Price amount={booking.total_price} />\n      </span>\n\n      {active && (onCancel || onReschedule) && (\n        <div data-cimplify-booking-actions className={cn(\"flex gap-2 pt-1 border-t border-border mt-1\", classNames?.actions)}>\n          {onReschedule && (\n            <button\n              type=\"button\"\n              onClick={() => onReschedule(booking)}\n              data-cimplify-booking-reschedule\n              className={cn(\n                \"flex-1 text-sm font-medium py-2 rounded-lg border border-border bg-background text-foreground transition-colors hover:bg-muted cursor-pointer\",\n                classNames?.rescheduleButton,\n              )}\n            >\n              Reschedule\n            </button>\n          )}\n          {onCancel && (\n            <button\n              type=\"button\"\n              onClick={() => onCancel(booking)}\n              data-cimplify-booking-cancel\n              className={cn(\n                \"flex-1 text-sm font-medium py-2 rounded-lg border border-border bg-background text-destructive transition-colors hover:bg-destructive/10 cursor-pointer\",\n                classNames?.cancelButton,\n              )}\n            >\n              Cancel\n            </button>\n          )}\n        </div>\n      )}\n    </div>\n  );\n}\n"
    }
  ]
}
