@forgebuild/hotal-ui 0.2.0 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -77,6 +77,99 @@ reservation-bar {
77
77
  }
78
78
  ```
79
79
 
80
+ ### `<booking-flow>`
81
+
82
+ Search results, a Stripe payment form, booking submission, and confirmation — plus an empty-state calendar when a date has no availability. Decoupled from `<reservation-bar>`: the page mirrors `date`/`guests`/`time` into `<booking-flow>` itself, typically from a `reservation-bar`'s `reservationchange` event or from the page's own URL.
83
+
84
+ ```html
85
+ <script type="module">
86
+ import '@forgebuild/hotal-ui';
87
+
88
+ const flow = document.querySelector('booking-flow');
89
+
90
+ flow.closedWeekdays = [0];
91
+ flow.fetchAvailableDates = async (partySize) => {
92
+ const res = await fetch(`/api/available-dates?party_size=${partySize}`);
93
+ const { dates } = await res.json();
94
+ return dates;
95
+ };
96
+ flow.searchSlots = async (date, guests) => {
97
+ const res = await fetch(`/api/search?date=${date}&party_size=${guests}`);
98
+ const { slots } = await res.json();
99
+ return slots;
100
+ };
101
+ flow.stripePublishableKey = 'pk_test_...';
102
+ flow.stripeAppearance = { theme: 'stripe' };
103
+ flow.createPaymentIntent = async (date, guests) => {
104
+ const res = await fetch('/api/create-payment-intent', {
105
+ method: 'POST',
106
+ headers: { 'Content-Type': 'application/json' },
107
+ body: JSON.stringify({ date, party_size: guests }),
108
+ });
109
+ return res.json();
110
+ };
111
+ flow.book = async (details) => {
112
+ const res = await fetch('/api/book', {
113
+ method: 'POST',
114
+ headers: { 'Content-Type': 'application/json' },
115
+ body: JSON.stringify(details),
116
+ });
117
+ return res.status === 201 ? { ok: true } : { ok: false, status: res.status, message: 'Something went wrong.' };
118
+ };
119
+
120
+ flow.date = '2026-08-20';
121
+ flow.guests = 2;
122
+
123
+ flow.addEventListener('booking-confirmed', (e) => console.log(e.detail));
124
+ </script>
125
+
126
+ <booking-flow></booking-flow>
127
+ ```
128
+
129
+ #### Properties (all JS-only — no HTML attributes, since every property here is either dynamic state or a callback)
130
+
131
+ | Name | Type | Description |
132
+ | --- | --- | --- |
133
+ | `date` | `string` | Current search date (ISO) |
134
+ | `guests` | `number` | Current party size |
135
+ | `preferredTime` | `string` | Used to pre-select the closest available slot |
136
+ | `closedWeekdays` | `number[]` | Same convention as `reservation-bar`: `0`=Sun–`6`=Sat, for the empty-state calendar |
137
+ | `fetchAvailableDates` | `(partySize: number) => Promise<string[]>` | Drives the empty-state calendar's selectable dates |
138
+ | `searchSlots` | `(date: string, guests: number) => Promise<BookingSlot[]>` | Returns available time slots |
139
+ | `stripePublishableKey` | `string` | Stripe publishable key |
140
+ | `stripeAppearance` | `object` | Passed straight through to Stripe's `elements({ appearance })` |
141
+ | `createPaymentIntent` | `(date: string, guests: number) => Promise<PaymentIntentResult>` | Creates the Stripe PaymentIntent to hold |
142
+ | `book` | `(details: BookingDetails) => Promise<BookResult>` | Submits the reservation |
143
+
144
+ ```ts
145
+ interface BookingSlot { time: string; availableTables: number; }
146
+ interface PaymentIntentResult { clientSecret: string; paymentIntentId: string; amountCents: number; }
147
+ interface BookingDetails {
148
+ date: string; startTime: string; timeDisplay: string; partySize: number;
149
+ contactName: string; contactEmail?: string; contactPhone?: string; notes?: string;
150
+ stripePaymentIntentId: string; clerkUserId?: string;
151
+ }
152
+ type BookResult = { ok: true } | { ok: false; status: number; message: string };
153
+ ```
154
+
155
+ #### Events
156
+
157
+ `booking-confirmed` — `CustomEvent<{ date: string; time: string; guests: number }>`, fires once a booking succeeds.
158
+
159
+ #### Theming
160
+
161
+ ```css
162
+ booking-flow {
163
+ --bf-text-color: #1a1a1a;
164
+ --bf-muted-text: rgba(0, 0, 0, 0.6);
165
+ --bf-border-color: rgba(0, 0, 0, 0.15);
166
+ --bf-accent-bg: #1a1a1a;
167
+ --bf-accent-text: #fff;
168
+ --bf-spinner-track: rgba(0, 0, 0, 0.15);
169
+ --bf-spinner-active: #1a1a1a;
170
+ }
171
+ ```
172
+
80
173
  ## Development
81
174
 
82
175
  ```