@bailierich/booking-components 2.0.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 +319 -0
- package/TENANT_DATA_INTEGRATION.md +402 -0
- package/TENANT_SETUP.md +316 -0
- package/components/BookingFlow/BookingFlow.tsx +790 -0
- package/components/BookingFlow/index.ts +5 -0
- package/components/BookingFlow/steps/AddonsSelection.tsx +118 -0
- package/components/BookingFlow/steps/Confirmation.tsx +185 -0
- package/components/BookingFlow/steps/ContactForm.tsx +292 -0
- package/components/BookingFlow/steps/CycleAwareDateSelection.tsx +277 -0
- package/components/BookingFlow/steps/DateSelection.tsx +473 -0
- package/components/BookingFlow/steps/ServiceSelection.tsx +315 -0
- package/components/BookingFlow/steps/TimeSelection.tsx +230 -0
- package/components/BookingFlow/steps/index.ts +10 -0
- package/components/BottomSheet/index.tsx +120 -0
- package/components/Forms/FormBlock.tsx +283 -0
- package/components/Forms/FormField.tsx +385 -0
- package/components/Forms/FormRenderer.tsx +216 -0
- package/components/Forms/FormValidation.ts +122 -0
- package/components/Forms/index.ts +4 -0
- package/components/HoldTimer/HoldTimer.tsx +266 -0
- package/components/HoldTimer/index.ts +2 -0
- package/components/SectionRenderer.tsx +558 -0
- package/components/Sections/About.tsx +145 -0
- package/components/Sections/BeforeAfter.tsx +81 -0
- package/components/Sections/BookingSection.tsx +76 -0
- package/components/Sections/Contact.tsx +103 -0
- package/components/Sections/FAQSection.tsx +239 -0
- package/components/Sections/FeatureContent.tsx +113 -0
- package/components/Sections/FeaturedLink.tsx +103 -0
- package/components/Sections/FixedInfoCard.tsx +189 -0
- package/components/Sections/Gallery.tsx +83 -0
- package/components/Sections/Header.tsx +78 -0
- package/components/Sections/Hero.tsx +178 -0
- package/components/Sections/ImageSection.tsx +147 -0
- package/components/Sections/InstagramFeed.tsx +38 -0
- package/components/Sections/LinkList.tsx +76 -0
- package/components/Sections/LocationMap.tsx +202 -0
- package/components/Sections/Logo.tsx +61 -0
- package/components/Sections/MinimalFooter.tsx +78 -0
- package/components/Sections/MinimalHeader.tsx +81 -0
- package/components/Sections/MinimalNavigation.tsx +63 -0
- package/components/Sections/Navbar.tsx +258 -0
- package/components/Sections/PricingTable.tsx +106 -0
- package/components/Sections/ScrollingTextDivider.tsx +138 -0
- package/components/Sections/ScrollingTextDivider.tsx.bak +138 -0
- package/components/Sections/ServicesPreview.tsx +129 -0
- package/components/Sections/SocialBar.tsx +177 -0
- package/components/Sections/Team.tsx +80 -0
- package/components/Sections/Testimonials.tsx +92 -0
- package/components/Sections/TextSection.tsx +116 -0
- package/components/Sections/VideoSection.tsx +178 -0
- package/components/Sections/index.ts +57 -0
- package/components/index.ts +21 -0
- package/dist/index-DAai7Glf.d.mts +474 -0
- package/dist/index-DAai7Glf.d.ts +474 -0
- package/dist/index.d.mts +1075 -0
- package/dist/index.d.ts +1075 -0
- package/dist/index.js +22 -0
- package/dist/index.js.map +1 -0
- package/dist/index.mjs +22 -0
- package/dist/index.mjs.map +1 -0
- package/dist/styles/index.d.mts +1 -0
- package/dist/styles/index.d.ts +1 -0
- package/dist/styles/index.js +2 -0
- package/dist/styles/index.js.map +1 -0
- package/dist/styles/index.mjs +2 -0
- package/dist/styles/index.mjs.map +1 -0
- package/docs/API.md +849 -0
- package/docs/CALLBACKS.md +760 -0
- package/docs/COMPLETE_SESSION_SUMMARY.md +404 -0
- package/docs/DATA_SHAPES.md +684 -0
- package/docs/MIGRATION.md +662 -0
- package/docs/PAYMENT_INTEGRATION.md +766 -0
- package/docs/SESSION_SUMMARY.md +185 -0
- package/docs/STYLING.md +735 -0
- package/index.ts +4 -0
- package/lib/storage.ts +239 -0
- package/package.json +59 -0
- package/styles/animations.ts +210 -0
- package/styles/index.ts +1 -0
- package/tsconfig.json +32 -0
- package/tsup.config.ts +13 -0
- package/types/index.ts +369 -0
|
@@ -0,0 +1,662 @@
|
|
|
1
|
+
# Migration Guide
|
|
2
|
+
|
|
3
|
+
Guide for migrating from inline components to the `@oviah/booking-components` package.
|
|
4
|
+
|
|
5
|
+
## Table of Contents
|
|
6
|
+
|
|
7
|
+
- [Why Migrate?](#why-migrate)
|
|
8
|
+
- [Before You Start](#before-you-start)
|
|
9
|
+
- [Migration Steps](#migration-steps)
|
|
10
|
+
- [Breaking Changes](#breaking-changes)
|
|
11
|
+
- [Troubleshooting](#troubleshooting)
|
|
12
|
+
|
|
13
|
+
---
|
|
14
|
+
|
|
15
|
+
## Why Migrate?
|
|
16
|
+
|
|
17
|
+
### Benefits
|
|
18
|
+
|
|
19
|
+
✅ **Reusability** - Use components across dashboard and tenant apps
|
|
20
|
+
✅ **Maintainability** - Single source of truth for updates
|
|
21
|
+
✅ **Type Safety** - Full TypeScript support
|
|
22
|
+
✅ **Performance** - Optimized bundle size
|
|
23
|
+
✅ **Testing** - Easier to test isolated components
|
|
24
|
+
✅ **Documentation** - Comprehensive API docs
|
|
25
|
+
|
|
26
|
+
### What's Different?
|
|
27
|
+
|
|
28
|
+
| Old (Inline) | New (Package) |
|
|
29
|
+
|--------------|---------------|
|
|
30
|
+
| Components in page files | Separate package |
|
|
31
|
+
| Props passed directly | Structured config objects |
|
|
32
|
+
| Scattered settings | Centralized configuration |
|
|
33
|
+
| Duplicate code | Shared components |
|
|
34
|
+
| Hard to maintain | Easy updates |
|
|
35
|
+
|
|
36
|
+
---
|
|
37
|
+
|
|
38
|
+
## Before You Start
|
|
39
|
+
|
|
40
|
+
### 1. Check Your Current Implementation
|
|
41
|
+
|
|
42
|
+
Identify which components you're using:
|
|
43
|
+
|
|
44
|
+
```tsx
|
|
45
|
+
// Old: src/app/[businessId]/page.tsx
|
|
46
|
+
function SectionRenderer({ section, theme }) {
|
|
47
|
+
switch (section.type) {
|
|
48
|
+
case 'logo':
|
|
49
|
+
// Inline logo rendering
|
|
50
|
+
return <div>...</div>;
|
|
51
|
+
case 'hero':
|
|
52
|
+
// Inline hero rendering
|
|
53
|
+
return <div>...</div>;
|
|
54
|
+
// ... more cases
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
### 2. Review Your Configuration
|
|
60
|
+
|
|
61
|
+
Document your current config structure:
|
|
62
|
+
|
|
63
|
+
```typescript
|
|
64
|
+
const currentConfig = {
|
|
65
|
+
sections: [...], // What sections do you have?
|
|
66
|
+
theme: {...}, // What colors/fonts?
|
|
67
|
+
bookingFlow: {...} // What booking steps?
|
|
68
|
+
};
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
### 3. Backup Your Code
|
|
72
|
+
|
|
73
|
+
```bash
|
|
74
|
+
git checkout -b backup-before-migration
|
|
75
|
+
git add .
|
|
76
|
+
git commit -m "Backup before component migration"
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
---
|
|
80
|
+
|
|
81
|
+
## Migration Steps
|
|
82
|
+
|
|
83
|
+
### Step 1: Install the Package
|
|
84
|
+
|
|
85
|
+
```bash
|
|
86
|
+
# From the root of your monorepo
|
|
87
|
+
npm install
|
|
88
|
+
# The package is already in your workspace
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
### Step 2: Update Imports
|
|
92
|
+
|
|
93
|
+
#### Before (Inline Components)
|
|
94
|
+
|
|
95
|
+
```tsx
|
|
96
|
+
// src/app/[businessId]/page.tsx
|
|
97
|
+
'use client';
|
|
98
|
+
|
|
99
|
+
import { useState } from 'react';
|
|
100
|
+
import BookingFlowPreview from '@/components/preview/BookingFlowPreview';
|
|
101
|
+
|
|
102
|
+
function SectionRenderer({ section, theme }) {
|
|
103
|
+
// 1000+ lines of inline rendering logic
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
export default function TenantPage() {
|
|
107
|
+
// Component logic
|
|
108
|
+
}
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
#### After (Package Components)
|
|
112
|
+
|
|
113
|
+
```tsx
|
|
114
|
+
// src/app/[businessId]/page.tsx
|
|
115
|
+
'use client';
|
|
116
|
+
|
|
117
|
+
import { SectionRenderer, BookingFlow } from '@oviah/booking-components';
|
|
118
|
+
|
|
119
|
+
export default function TenantPage() {
|
|
120
|
+
// Much cleaner!
|
|
121
|
+
}
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
---
|
|
125
|
+
|
|
126
|
+
### Step 3: Migrate Section Rendering
|
|
127
|
+
|
|
128
|
+
#### Before
|
|
129
|
+
|
|
130
|
+
```tsx
|
|
131
|
+
function SectionRenderer({ section, theme }) {
|
|
132
|
+
const { type, settings } = section;
|
|
133
|
+
const colors = theme?.colors || {};
|
|
134
|
+
|
|
135
|
+
switch (type) {
|
|
136
|
+
case 'logo':
|
|
137
|
+
return (
|
|
138
|
+
<div className="container mx-auto px-4">
|
|
139
|
+
{settings.logoUrl ? (
|
|
140
|
+
<img src={settings.logoUrl} alt="Logo" />
|
|
141
|
+
) : (
|
|
142
|
+
<div>{settings.fallbackText}</div>
|
|
143
|
+
)}
|
|
144
|
+
</div>
|
|
145
|
+
);
|
|
146
|
+
|
|
147
|
+
case 'hero':
|
|
148
|
+
return (
|
|
149
|
+
<div className="hero">
|
|
150
|
+
<h1>{settings.headline}</h1>
|
|
151
|
+
<p>{settings.subheadline}</p>
|
|
152
|
+
{/* ... more JSX */}
|
|
153
|
+
</div>
|
|
154
|
+
);
|
|
155
|
+
|
|
156
|
+
// ... 20 more cases
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
```
|
|
160
|
+
|
|
161
|
+
#### After
|
|
162
|
+
|
|
163
|
+
```tsx
|
|
164
|
+
import { SectionRenderer } from '@oviah/booking-components';
|
|
165
|
+
|
|
166
|
+
// Just pass section and theme - that's it!
|
|
167
|
+
<SectionRenderer
|
|
168
|
+
section={section}
|
|
169
|
+
theme={theme}
|
|
170
|
+
/>
|
|
171
|
+
```
|
|
172
|
+
|
|
173
|
+
**That's a reduction from 1000+ lines to 5 lines!** 🎉
|
|
174
|
+
|
|
175
|
+
---
|
|
176
|
+
|
|
177
|
+
### Step 4: Migrate Booking Flow
|
|
178
|
+
|
|
179
|
+
#### Before
|
|
180
|
+
|
|
181
|
+
```tsx
|
|
182
|
+
// src/components/preview/BookingFlowPreview.tsx (1200+ lines)
|
|
183
|
+
export default function BookingFlowPreview({ config, colors }) {
|
|
184
|
+
const [currentStep, setCurrentStep] = useState(0);
|
|
185
|
+
const [selectedService, setSelectedService] = useState(null);
|
|
186
|
+
const [selectedDate, setSelectedDate] = useState(null);
|
|
187
|
+
// ... 50+ state variables
|
|
188
|
+
|
|
189
|
+
const renderServiceSelection = () => {
|
|
190
|
+
// 200+ lines of JSX
|
|
191
|
+
};
|
|
192
|
+
|
|
193
|
+
const renderDateSelection = () => {
|
|
194
|
+
// 150+ lines of JSX
|
|
195
|
+
};
|
|
196
|
+
|
|
197
|
+
// ... more render functions
|
|
198
|
+
|
|
199
|
+
return (
|
|
200
|
+
<div>
|
|
201
|
+
{/* Complex flow logic */}
|
|
202
|
+
</div>
|
|
203
|
+
);
|
|
204
|
+
}
|
|
205
|
+
```
|
|
206
|
+
|
|
207
|
+
#### After
|
|
208
|
+
|
|
209
|
+
```tsx
|
|
210
|
+
import { BookingFlow } from '@oviah/booking-components';
|
|
211
|
+
|
|
212
|
+
<BookingFlow
|
|
213
|
+
config={config.booking_flow}
|
|
214
|
+
colors={colors}
|
|
215
|
+
services={services}
|
|
216
|
+
dates={availableDates}
|
|
217
|
+
times={availableTimes}
|
|
218
|
+
addons={addons}
|
|
219
|
+
onComplete={(bookingData) => {
|
|
220
|
+
// Handle booking completion
|
|
221
|
+
}}
|
|
222
|
+
/>
|
|
223
|
+
```
|
|
224
|
+
|
|
225
|
+
**From 1200 lines to 15 lines!** 🚀
|
|
226
|
+
|
|
227
|
+
---
|
|
228
|
+
|
|
229
|
+
### Step 5: Update Configuration Structure
|
|
230
|
+
|
|
231
|
+
Your config structure should remain mostly the same, but here are the key mappings:
|
|
232
|
+
|
|
233
|
+
#### Section Configuration
|
|
234
|
+
|
|
235
|
+
```typescript
|
|
236
|
+
// Your existing config works as-is!
|
|
237
|
+
const section = {
|
|
238
|
+
id: 'hero-1',
|
|
239
|
+
type: 'hero',
|
|
240
|
+
enabled: true,
|
|
241
|
+
position: 0,
|
|
242
|
+
settings: {
|
|
243
|
+
headline: 'Welcome',
|
|
244
|
+
subheadline: 'Book your appointment',
|
|
245
|
+
heroImage: '/hero.jpg',
|
|
246
|
+
layout: 'split'
|
|
247
|
+
}
|
|
248
|
+
};
|
|
249
|
+
|
|
250
|
+
// Just pass it to SectionRenderer
|
|
251
|
+
<SectionRenderer section={section} theme={theme} />
|
|
252
|
+
```
|
|
253
|
+
|
|
254
|
+
#### Booking Flow Configuration
|
|
255
|
+
|
|
256
|
+
```typescript
|
|
257
|
+
// Your existing booking_flow config works!
|
|
258
|
+
const config = {
|
|
259
|
+
booking_flow: {
|
|
260
|
+
steps: {
|
|
261
|
+
service_selection: {
|
|
262
|
+
enabled: true,
|
|
263
|
+
settings: {
|
|
264
|
+
headerContent: { value: 'Choose Service' },
|
|
265
|
+
serviceLayout: 'grid',
|
|
266
|
+
columns: 2
|
|
267
|
+
}
|
|
268
|
+
},
|
|
269
|
+
date_selection: {
|
|
270
|
+
enabled: true,
|
|
271
|
+
settings: {
|
|
272
|
+
headerContent: { value: 'Select Date' },
|
|
273
|
+
calendarView: 'month'
|
|
274
|
+
}
|
|
275
|
+
}
|
|
276
|
+
// ... more steps
|
|
277
|
+
},
|
|
278
|
+
progressBar: { style: 'dots' },
|
|
279
|
+
transitions: { style: 'slide', speed: 'normal' }
|
|
280
|
+
}
|
|
281
|
+
};
|
|
282
|
+
|
|
283
|
+
<BookingFlow config={config.booking_flow} colors={colors} />
|
|
284
|
+
```
|
|
285
|
+
|
|
286
|
+
---
|
|
287
|
+
|
|
288
|
+
### Step 6: Handle Data Fetching
|
|
289
|
+
|
|
290
|
+
#### Before (Inline)
|
|
291
|
+
|
|
292
|
+
```tsx
|
|
293
|
+
// Data fetching mixed with rendering
|
|
294
|
+
export default function TenantPage({ params }) {
|
|
295
|
+
const [config, setConfig] = useState(null);
|
|
296
|
+
const [services, setServices] = useState([]);
|
|
297
|
+
|
|
298
|
+
useEffect(() => {
|
|
299
|
+
// Fetch config and services
|
|
300
|
+
}, []);
|
|
301
|
+
|
|
302
|
+
return (
|
|
303
|
+
<div>
|
|
304
|
+
{/* Render sections */}
|
|
305
|
+
</div>
|
|
306
|
+
);
|
|
307
|
+
}
|
|
308
|
+
```
|
|
309
|
+
|
|
310
|
+
#### After (Separated Concerns)
|
|
311
|
+
|
|
312
|
+
```tsx
|
|
313
|
+
// src/app/[businessId]/page.tsx
|
|
314
|
+
export default function TenantPage({ params }) {
|
|
315
|
+
const { config, services, dates, times, addons } = useBookingData(params.businessId);
|
|
316
|
+
|
|
317
|
+
return (
|
|
318
|
+
<div>
|
|
319
|
+
{sections.map(section => (
|
|
320
|
+
<SectionRenderer
|
|
321
|
+
key={section.id}
|
|
322
|
+
section={section}
|
|
323
|
+
theme={config.theme}
|
|
324
|
+
/>
|
|
325
|
+
))}
|
|
326
|
+
|
|
327
|
+
{showBookingFlow && (
|
|
328
|
+
<BookingFlow
|
|
329
|
+
config={config.booking_flow}
|
|
330
|
+
colors={config.theme.colors}
|
|
331
|
+
services={services}
|
|
332
|
+
dates={dates}
|
|
333
|
+
times={times}
|
|
334
|
+
addons={addons}
|
|
335
|
+
onComplete={handleBookingComplete}
|
|
336
|
+
/>
|
|
337
|
+
)}
|
|
338
|
+
</div>
|
|
339
|
+
);
|
|
340
|
+
}
|
|
341
|
+
```
|
|
342
|
+
|
|
343
|
+
---
|
|
344
|
+
|
|
345
|
+
## Breaking Changes
|
|
346
|
+
|
|
347
|
+
### 1. Import Paths
|
|
348
|
+
|
|
349
|
+
```tsx
|
|
350
|
+
// ❌ Old
|
|
351
|
+
import BookingFlowPreview from '@/components/preview/BookingFlowPreview';
|
|
352
|
+
|
|
353
|
+
// ✅ New
|
|
354
|
+
import { BookingFlow } from '@oviah/booking-components';
|
|
355
|
+
```
|
|
356
|
+
|
|
357
|
+
### 2. Component Names
|
|
358
|
+
|
|
359
|
+
| Old | New |
|
|
360
|
+
|-----|-----|
|
|
361
|
+
| `BookingFlowPreview` | `BookingFlow` |
|
|
362
|
+
| `SectionRenderer` (inline) | `SectionRenderer` (from package) |
|
|
363
|
+
|
|
364
|
+
### 3. Props Structure
|
|
365
|
+
|
|
366
|
+
Some components now expect structured config objects:
|
|
367
|
+
|
|
368
|
+
```tsx
|
|
369
|
+
// ❌ Old (individual props)
|
|
370
|
+
<ServiceSelection
|
|
371
|
+
services={services}
|
|
372
|
+
categories={categories}
|
|
373
|
+
layout="grid"
|
|
374
|
+
columns={2}
|
|
375
|
+
showPricing={true}
|
|
376
|
+
/>
|
|
377
|
+
|
|
378
|
+
// ✅ New (settings object)
|
|
379
|
+
<ServiceSelection
|
|
380
|
+
services={services}
|
|
381
|
+
categories={categories}
|
|
382
|
+
settings={{
|
|
383
|
+
serviceLayout: 'grid',
|
|
384
|
+
columns: 2,
|
|
385
|
+
showPricing: true
|
|
386
|
+
}}
|
|
387
|
+
colors={colors}
|
|
388
|
+
/>
|
|
389
|
+
```
|
|
390
|
+
|
|
391
|
+
### 4. Callback Patterns
|
|
392
|
+
|
|
393
|
+
```tsx
|
|
394
|
+
// ❌ Old
|
|
395
|
+
<BookingFlowPreview
|
|
396
|
+
config={config}
|
|
397
|
+
colors={colors}
|
|
398
|
+
onComplete={() => {
|
|
399
|
+
// Limited data
|
|
400
|
+
}}
|
|
401
|
+
/>
|
|
402
|
+
|
|
403
|
+
// ✅ New (full booking data)
|
|
404
|
+
<BookingFlow
|
|
405
|
+
config={config}
|
|
406
|
+
colors={colors}
|
|
407
|
+
onComplete={(bookingData) => {
|
|
408
|
+
// Full structured data
|
|
409
|
+
console.log(bookingData.service);
|
|
410
|
+
console.log(bookingData.date);
|
|
411
|
+
console.log(bookingData.contact);
|
|
412
|
+
}}
|
|
413
|
+
onStepChange={(index, stepId) => {
|
|
414
|
+
// Track step changes
|
|
415
|
+
}}
|
|
416
|
+
/>
|
|
417
|
+
```
|
|
418
|
+
|
|
419
|
+
---
|
|
420
|
+
|
|
421
|
+
## Step-by-Step Migration Checklist
|
|
422
|
+
|
|
423
|
+
### Phase 1: Preparation
|
|
424
|
+
- [ ] Backup your code
|
|
425
|
+
- [ ] Document current configuration
|
|
426
|
+
- [ ] Review all components you're using
|
|
427
|
+
- [ ] Test current implementation
|
|
428
|
+
|
|
429
|
+
### Phase 2: Install & Setup
|
|
430
|
+
- [ ] Install package (already in workspace)
|
|
431
|
+
- [ ] Update TypeScript paths if needed
|
|
432
|
+
- [ ] Import components in your files
|
|
433
|
+
|
|
434
|
+
### Phase 3: Migrate Sections
|
|
435
|
+
- [ ] Replace inline `SectionRenderer` with package version
|
|
436
|
+
- [ ] Test each section type renders correctly
|
|
437
|
+
- [ ] Verify styling matches
|
|
438
|
+
|
|
439
|
+
### Phase 4: Migrate Booking Flow
|
|
440
|
+
- [ ] Replace `BookingFlowPreview` with `BookingFlow`
|
|
441
|
+
- [ ] Pass data providers (services, dates, times)
|
|
442
|
+
- [ ] Update callbacks
|
|
443
|
+
- [ ] Test complete booking flow
|
|
444
|
+
|
|
445
|
+
### Phase 5: Cleanup
|
|
446
|
+
- [ ] Remove old component files
|
|
447
|
+
- [ ] Remove unused imports
|
|
448
|
+
- [ ] Update tests
|
|
449
|
+
- [ ] Update documentation
|
|
450
|
+
|
|
451
|
+
### Phase 6: Testing
|
|
452
|
+
- [ ] Test all section types
|
|
453
|
+
- [ ] Test booking flow end-to-end
|
|
454
|
+
- [ ] Test on mobile devices
|
|
455
|
+
- [ ] Test payment integration
|
|
456
|
+
- [ ] Performance testing
|
|
457
|
+
|
|
458
|
+
### Phase 7: Deploy
|
|
459
|
+
- [ ] Deploy to staging
|
|
460
|
+
- [ ] QA testing
|
|
461
|
+
- [ ] Deploy to production
|
|
462
|
+
- [ ] Monitor for errors
|
|
463
|
+
|
|
464
|
+
---
|
|
465
|
+
|
|
466
|
+
## Troubleshooting
|
|
467
|
+
|
|
468
|
+
### Issue: Components Not Rendering
|
|
469
|
+
|
|
470
|
+
**Problem:** Components show blank or throw errors
|
|
471
|
+
|
|
472
|
+
**Solution:**
|
|
473
|
+
```tsx
|
|
474
|
+
// Check that you're passing all required props
|
|
475
|
+
<SectionRenderer
|
|
476
|
+
section={section} // ✅ Required
|
|
477
|
+
theme={theme} // ✅ Required
|
|
478
|
+
/>
|
|
479
|
+
|
|
480
|
+
// Check section has required fields
|
|
481
|
+
const section = {
|
|
482
|
+
id: 'hero-1', // ✅ Required
|
|
483
|
+
type: 'hero', // ✅ Required
|
|
484
|
+
settings: {...} // ✅ Required
|
|
485
|
+
};
|
|
486
|
+
```
|
|
487
|
+
|
|
488
|
+
### Issue: TypeScript Errors
|
|
489
|
+
|
|
490
|
+
**Problem:** Type errors on component props
|
|
491
|
+
|
|
492
|
+
**Solution:**
|
|
493
|
+
```tsx
|
|
494
|
+
// Import types
|
|
495
|
+
import type { SectionRendererProps } from '@oviah/booking-components';
|
|
496
|
+
|
|
497
|
+
// Use correct types
|
|
498
|
+
const section: Section = {
|
|
499
|
+
id: 'hero-1',
|
|
500
|
+
type: 'hero',
|
|
501
|
+
enabled: true,
|
|
502
|
+
position: 0,
|
|
503
|
+
settings: {
|
|
504
|
+
headline: 'Welcome'
|
|
505
|
+
}
|
|
506
|
+
};
|
|
507
|
+
```
|
|
508
|
+
|
|
509
|
+
### Issue: Styling Looks Different
|
|
510
|
+
|
|
511
|
+
**Problem:** Components don't match previous styling
|
|
512
|
+
|
|
513
|
+
**Solution:**
|
|
514
|
+
```tsx
|
|
515
|
+
// Ensure colors are passed correctly
|
|
516
|
+
const colors = {
|
|
517
|
+
primary: '#D8C4FF',
|
|
518
|
+
secondary: '#014421',
|
|
519
|
+
text: '#000000',
|
|
520
|
+
// Add all color properties
|
|
521
|
+
};
|
|
522
|
+
|
|
523
|
+
// Check custom CSS isn't overriding
|
|
524
|
+
// The package components use inline styles for theming
|
|
525
|
+
```
|
|
526
|
+
|
|
527
|
+
### Issue: Booking Flow State Not Persisting
|
|
528
|
+
|
|
529
|
+
**Problem:** User loses progress on navigation
|
|
530
|
+
|
|
531
|
+
**Solution:**
|
|
532
|
+
```tsx
|
|
533
|
+
// Save state to localStorage
|
|
534
|
+
useEffect(() => {
|
|
535
|
+
const progress = {
|
|
536
|
+
service: selectedService,
|
|
537
|
+
date: selectedDate,
|
|
538
|
+
// ... other selections
|
|
539
|
+
};
|
|
540
|
+
localStorage.setItem('bookingProgress', JSON.stringify(progress));
|
|
541
|
+
}, [selectedService, selectedDate]);
|
|
542
|
+
|
|
543
|
+
// Restore on mount
|
|
544
|
+
useEffect(() => {
|
|
545
|
+
const saved = localStorage.getItem('bookingProgress');
|
|
546
|
+
if (saved) {
|
|
547
|
+
const progress = JSON.parse(saved);
|
|
548
|
+
// Restore state
|
|
549
|
+
}
|
|
550
|
+
}, []);
|
|
551
|
+
```
|
|
552
|
+
|
|
553
|
+
### Issue: Payment Integration Broken
|
|
554
|
+
|
|
555
|
+
**Problem:** Payment processing fails after migration
|
|
556
|
+
|
|
557
|
+
**Solution:**
|
|
558
|
+
```tsx
|
|
559
|
+
// The Confirmation component is presentational only
|
|
560
|
+
// You need to handle payment logic yourself
|
|
561
|
+
|
|
562
|
+
<Confirmation
|
|
563
|
+
// ... props
|
|
564
|
+
onConfirm={async () => {
|
|
565
|
+
// YOUR payment processing logic here
|
|
566
|
+
await processPayment();
|
|
567
|
+
await createBooking();
|
|
568
|
+
}}
|
|
569
|
+
/>
|
|
570
|
+
```
|
|
571
|
+
|
|
572
|
+
---
|
|
573
|
+
|
|
574
|
+
## Example: Complete Migration
|
|
575
|
+
|
|
576
|
+
### Before (app/[businessId]/page.tsx)
|
|
577
|
+
|
|
578
|
+
```tsx
|
|
579
|
+
// 2000+ lines of code
|
|
580
|
+
'use client';
|
|
581
|
+
|
|
582
|
+
import { use, useEffect, useState } from 'react';
|
|
583
|
+
// ... many imports
|
|
584
|
+
|
|
585
|
+
export default function TenantPage({ params }) {
|
|
586
|
+
// 50+ state variables
|
|
587
|
+
// 500+ lines of logic
|
|
588
|
+
|
|
589
|
+
function SectionRenderer() {
|
|
590
|
+
// 1000+ lines of switch statement
|
|
591
|
+
}
|
|
592
|
+
|
|
593
|
+
return (
|
|
594
|
+
<div>
|
|
595
|
+
{/* Complex rendering logic */}
|
|
596
|
+
</div>
|
|
597
|
+
);
|
|
598
|
+
}
|
|
599
|
+
```
|
|
600
|
+
|
|
601
|
+
### After (app/[businessId]/page.tsx)
|
|
602
|
+
|
|
603
|
+
```tsx
|
|
604
|
+
// ~100 lines of code
|
|
605
|
+
'use client';
|
|
606
|
+
|
|
607
|
+
import { use, useEffect, useState } from 'react';
|
|
608
|
+
import { SectionRenderer, BookingFlow } from '@oviah/booking-components';
|
|
609
|
+
import { useBookingData } from '@/hooks/useBookingData';
|
|
610
|
+
|
|
611
|
+
export default function TenantPage({ params }) {
|
|
612
|
+
const { businessId } = use(params);
|
|
613
|
+
const { config, services, dates, times, addons } = useBookingData(businessId);
|
|
614
|
+
|
|
615
|
+
if (!config) return <Loading />;
|
|
616
|
+
|
|
617
|
+
const { theme, sections, booking_flow } = config;
|
|
618
|
+
|
|
619
|
+
return (
|
|
620
|
+
<div style={{ backgroundColor: config.background?.value }}>
|
|
621
|
+
{sections.map(section => (
|
|
622
|
+
<SectionRenderer
|
|
623
|
+
key={section.id}
|
|
624
|
+
section={section}
|
|
625
|
+
theme={theme}
|
|
626
|
+
/>
|
|
627
|
+
))}
|
|
628
|
+
|
|
629
|
+
{booking_flow && (
|
|
630
|
+
<BookingFlow
|
|
631
|
+
config={booking_flow}
|
|
632
|
+
colors={theme.colors}
|
|
633
|
+
services={services}
|
|
634
|
+
dates={dates}
|
|
635
|
+
times={times}
|
|
636
|
+
addons={addons}
|
|
637
|
+
onComplete={handleBookingComplete}
|
|
638
|
+
/>
|
|
639
|
+
)}
|
|
640
|
+
</div>
|
|
641
|
+
);
|
|
642
|
+
}
|
|
643
|
+
```
|
|
644
|
+
|
|
645
|
+
**Result:** 95% reduction in code! 🎉
|
|
646
|
+
|
|
647
|
+
---
|
|
648
|
+
|
|
649
|
+
## Need Help?
|
|
650
|
+
|
|
651
|
+
- Check [API.md](./API.md) for component reference
|
|
652
|
+
- See [DATA_SHAPES.md](./DATA_SHAPES.md) for data structures
|
|
653
|
+
- Review [CALLBACKS.md](./CALLBACKS.md) for event handling
|
|
654
|
+
- Read [STYLING.md](./STYLING.md) for customization
|
|
655
|
+
|
|
656
|
+
If you encounter issues:
|
|
657
|
+
1. Check the troubleshooting section above
|
|
658
|
+
2. Review the example code in this guide
|
|
659
|
+
3. Verify your configuration matches the data shapes
|
|
660
|
+
4. Test components individually before full integration
|
|
661
|
+
|
|
662
|
+
Happy migrating! 🚀
|