asafefe.dev

Booking Card

New

An appointment picker for barbers, clinics and repair shops. A scrolling day strip, slots that animate in per day, and a booked summary with Add to calendar.

motionlucide-reactutilsavatarbuttonbutton-groupcardemptyitemseparatorskeletonspinner@soultel/use-reduced-motion-safe
SO
Haircut and beard trim
Sam Ortiz·Fade Bros, Main St
$3845 min
 
Pick a time. Takes about 45 min.

Installation

$ pnpm dlx shadcn@latest add @soultel/booking-card

No namespace set up? npx shadcn@latest add https://asafefe.dev/r/booking-card.json works too.

Manual installation
  1. 1. Install the dependencies.
    terminal1 lines
    npm install motion lucide-react
  2. 2. Copy the source from the Code tab into components/booking-card.tsx.

Usage

example.tsx12 lines
import { BookingCard } from "@/components/booking-card"

export function BookACut() {
  return (
    <BookingCard
      service={{ name: "Haircut and beard trim", duration: 45, price: 38, provider: "Sam Ortiz", location: "Fade Bros, Main St" }}
      onConfirm={async (booking) => {
        await fetch("/api/bookings", { method: "POST", body: JSON.stringify(booking) })
      }}
    />
  )
}

Props

PropTypeDefaultDescription
serviceBookingService-name, duration in minutes, and optional price, provider and location.
daysBookingDay[]-Explicit availability: { date: "YYYY-MM-DD", slots: { time: "HH:mm", available }[] }[]. An empty slots array means closed.
getSlots(date: Date) => BookingSlot[]-Generates slots when days is not passed. Defaults to 9 to 5 with a lunch break, stepped by duration, closed Sundays.
startDateDate | stringtodayFirst generated day.
dayCountnumber14Number of generated days.
defaultValue{ date: string; time?: string }-Initial selection.
onConfirm(booking: Booking) => void | Promise<void>-Called on confirm with date, time, start, end and service. A promise shows a pending state; a rejection returns to the picker.
onAddToCalendar(booking: Booking) => void-Replaces the default .ics download.
localestring"en-US"Used for day names and times.
hour12booleantrue12 or 24 hour times.
currencystring"$"Symbol shown before the price.