@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.
Files changed (83) hide show
  1. package/README.md +319 -0
  2. package/TENANT_DATA_INTEGRATION.md +402 -0
  3. package/TENANT_SETUP.md +316 -0
  4. package/components/BookingFlow/BookingFlow.tsx +790 -0
  5. package/components/BookingFlow/index.ts +5 -0
  6. package/components/BookingFlow/steps/AddonsSelection.tsx +118 -0
  7. package/components/BookingFlow/steps/Confirmation.tsx +185 -0
  8. package/components/BookingFlow/steps/ContactForm.tsx +292 -0
  9. package/components/BookingFlow/steps/CycleAwareDateSelection.tsx +277 -0
  10. package/components/BookingFlow/steps/DateSelection.tsx +473 -0
  11. package/components/BookingFlow/steps/ServiceSelection.tsx +315 -0
  12. package/components/BookingFlow/steps/TimeSelection.tsx +230 -0
  13. package/components/BookingFlow/steps/index.ts +10 -0
  14. package/components/BottomSheet/index.tsx +120 -0
  15. package/components/Forms/FormBlock.tsx +283 -0
  16. package/components/Forms/FormField.tsx +385 -0
  17. package/components/Forms/FormRenderer.tsx +216 -0
  18. package/components/Forms/FormValidation.ts +122 -0
  19. package/components/Forms/index.ts +4 -0
  20. package/components/HoldTimer/HoldTimer.tsx +266 -0
  21. package/components/HoldTimer/index.ts +2 -0
  22. package/components/SectionRenderer.tsx +558 -0
  23. package/components/Sections/About.tsx +145 -0
  24. package/components/Sections/BeforeAfter.tsx +81 -0
  25. package/components/Sections/BookingSection.tsx +76 -0
  26. package/components/Sections/Contact.tsx +103 -0
  27. package/components/Sections/FAQSection.tsx +239 -0
  28. package/components/Sections/FeatureContent.tsx +113 -0
  29. package/components/Sections/FeaturedLink.tsx +103 -0
  30. package/components/Sections/FixedInfoCard.tsx +189 -0
  31. package/components/Sections/Gallery.tsx +83 -0
  32. package/components/Sections/Header.tsx +78 -0
  33. package/components/Sections/Hero.tsx +178 -0
  34. package/components/Sections/ImageSection.tsx +147 -0
  35. package/components/Sections/InstagramFeed.tsx +38 -0
  36. package/components/Sections/LinkList.tsx +76 -0
  37. package/components/Sections/LocationMap.tsx +202 -0
  38. package/components/Sections/Logo.tsx +61 -0
  39. package/components/Sections/MinimalFooter.tsx +78 -0
  40. package/components/Sections/MinimalHeader.tsx +81 -0
  41. package/components/Sections/MinimalNavigation.tsx +63 -0
  42. package/components/Sections/Navbar.tsx +258 -0
  43. package/components/Sections/PricingTable.tsx +106 -0
  44. package/components/Sections/ScrollingTextDivider.tsx +138 -0
  45. package/components/Sections/ScrollingTextDivider.tsx.bak +138 -0
  46. package/components/Sections/ServicesPreview.tsx +129 -0
  47. package/components/Sections/SocialBar.tsx +177 -0
  48. package/components/Sections/Team.tsx +80 -0
  49. package/components/Sections/Testimonials.tsx +92 -0
  50. package/components/Sections/TextSection.tsx +116 -0
  51. package/components/Sections/VideoSection.tsx +178 -0
  52. package/components/Sections/index.ts +57 -0
  53. package/components/index.ts +21 -0
  54. package/dist/index-DAai7Glf.d.mts +474 -0
  55. package/dist/index-DAai7Glf.d.ts +474 -0
  56. package/dist/index.d.mts +1075 -0
  57. package/dist/index.d.ts +1075 -0
  58. package/dist/index.js +22 -0
  59. package/dist/index.js.map +1 -0
  60. package/dist/index.mjs +22 -0
  61. package/dist/index.mjs.map +1 -0
  62. package/dist/styles/index.d.mts +1 -0
  63. package/dist/styles/index.d.ts +1 -0
  64. package/dist/styles/index.js +2 -0
  65. package/dist/styles/index.js.map +1 -0
  66. package/dist/styles/index.mjs +2 -0
  67. package/dist/styles/index.mjs.map +1 -0
  68. package/docs/API.md +849 -0
  69. package/docs/CALLBACKS.md +760 -0
  70. package/docs/COMPLETE_SESSION_SUMMARY.md +404 -0
  71. package/docs/DATA_SHAPES.md +684 -0
  72. package/docs/MIGRATION.md +662 -0
  73. package/docs/PAYMENT_INTEGRATION.md +766 -0
  74. package/docs/SESSION_SUMMARY.md +185 -0
  75. package/docs/STYLING.md +735 -0
  76. package/index.ts +4 -0
  77. package/lib/storage.ts +239 -0
  78. package/package.json +59 -0
  79. package/styles/animations.ts +210 -0
  80. package/styles/index.ts +1 -0
  81. package/tsconfig.json +32 -0
  82. package/tsup.config.ts +13 -0
  83. package/types/index.ts +369 -0
@@ -0,0 +1,684 @@
1
+ # Data Shapes & Interfaces
2
+
3
+ Complete reference for all data structures used in `@oviah/booking-components`.
4
+
5
+ ## Table of Contents
6
+
7
+ - [Service Data](#service-data)
8
+ - [Category Data](#category-data)
9
+ - [Booking Data](#booking-data)
10
+ - [Section Configuration](#section-configuration)
11
+ - [Theme Configuration](#theme-configuration)
12
+ - [Step Settings](#step-settings)
13
+
14
+ ---
15
+
16
+ ## Service Data
17
+
18
+ ### Service Object
19
+
20
+ ```typescript
21
+ interface Service {
22
+ id: string;
23
+ name: string;
24
+ description: string;
25
+ price: number;
26
+ duration: number; // in minutes
27
+ category?: string;
28
+ image?: string;
29
+ available?: boolean;
30
+ }
31
+ ```
32
+
33
+ **Example:**
34
+ ```typescript
35
+ const service: Service = {
36
+ id: 'haircut-1',
37
+ name: 'Haircut & Style',
38
+ description: 'Professional haircut with styling',
39
+ price: 65,
40
+ duration: 60,
41
+ category: 'hair',
42
+ image: 'https://example.com/haircut.jpg',
43
+ available: true
44
+ };
45
+ ```
46
+
47
+ ---
48
+
49
+ ## Category Data
50
+
51
+ ### Category Object
52
+
53
+ ```typescript
54
+ interface ServiceCategory {
55
+ id: string;
56
+ name: string;
57
+ description: string;
58
+ services: Service[];
59
+ icon?: string;
60
+ image?: string;
61
+ }
62
+ ```
63
+
64
+ **Example:**
65
+ ```typescript
66
+ const category: ServiceCategory = {
67
+ id: 'hair',
68
+ name: 'Hair Services',
69
+ description: 'Professional hair care and styling',
70
+ services: [
71
+ { id: '1', name: 'Haircut', price: 65, duration: 60, description: '...' },
72
+ { id: '2', name: 'Color', price: 150, duration: 120, description: '...' }
73
+ ],
74
+ icon: '💇',
75
+ image: 'https://example.com/hair-category.jpg'
76
+ };
77
+ ```
78
+
79
+ ---
80
+
81
+ ## Booking Data
82
+
83
+ ### Addon Object
84
+
85
+ ```typescript
86
+ interface Addon {
87
+ id: string;
88
+ name: string;
89
+ description: string;
90
+ price: number;
91
+ duration: number; // in minutes
92
+ image?: string;
93
+ available?: boolean;
94
+ }
95
+ ```
96
+
97
+ ### Contact Information
98
+
99
+ ```typescript
100
+ interface ContactInfo {
101
+ name: string;
102
+ email: string;
103
+ phone: string;
104
+ notes?: string;
105
+ }
106
+ ```
107
+
108
+ ### Complete Booking Data
109
+
110
+ ```typescript
111
+ interface BookingData {
112
+ service: string | null; // Selected service ID
113
+ date: string | null; // ISO date string (YYYY-MM-DD)
114
+ time: string | null; // Time string (e.g., "10:00 AM")
115
+ addons: string[]; // Array of addon IDs
116
+ contact: ContactInfo;
117
+ optIn?: { // Optional opt-in module data
118
+ [key: string]: any;
119
+ };
120
+ }
121
+ ```
122
+
123
+ **Example:**
124
+ ```typescript
125
+ const bookingData: BookingData = {
126
+ service: 'haircut-1',
127
+ date: '2025-01-15',
128
+ time: '10:00 AM',
129
+ addons: ['addon-1', 'addon-2'],
130
+ contact: {
131
+ name: 'Jane Doe',
132
+ email: 'jane@example.com',
133
+ phone: '(555) 123-4567',
134
+ notes: 'Please use low-ammonia products'
135
+ },
136
+ optIn: {
137
+ colorConsultation: {
138
+ currentColor: 'Brown',
139
+ desiredColor: 'Blonde highlights'
140
+ }
141
+ }
142
+ };
143
+ ```
144
+
145
+ ---
146
+
147
+ ## Section Configuration
148
+
149
+ ### Base Section Object
150
+
151
+ ```typescript
152
+ interface Section {
153
+ id: string;
154
+ type: string;
155
+ enabled: boolean;
156
+ position: number;
157
+ settings: any; // Type-specific settings
158
+ }
159
+ ```
160
+
161
+ ### Section Types & Settings
162
+
163
+ #### Logo Section
164
+ ```typescript
165
+ interface LogoSettings {
166
+ logoUrl?: string;
167
+ fallbackText?: string;
168
+ size?: 'small' | 'medium' | 'large';
169
+ alignment?: 'left' | 'center' | 'right';
170
+ }
171
+ ```
172
+
173
+ #### Header Section
174
+ ```typescript
175
+ interface HeaderSettings {
176
+ name?: string;
177
+ title?: string;
178
+ bio?: string;
179
+ showName?: boolean;
180
+ showTitle?: boolean;
181
+ showBio?: boolean;
182
+ }
183
+ ```
184
+
185
+ #### Hero Section
186
+ ```typescript
187
+ interface HeroSettings {
188
+ headline?: string;
189
+ subheadline?: string;
190
+ heroImage?: string;
191
+ ctaButton?: {
192
+ text: string;
193
+ url: string;
194
+ };
195
+ layout?: 'split' | 'full';
196
+ imagePosition?: 'left' | 'right';
197
+ contentDisplay?: 'side' | 'overlay';
198
+ }
199
+ ```
200
+
201
+ #### Gallery Section
202
+ ```typescript
203
+ interface GalleryImage {
204
+ id: string;
205
+ url: string;
206
+ alt?: string;
207
+ caption?: string;
208
+ }
209
+
210
+ interface GallerySettings {
211
+ title?: string;
212
+ images?: GalleryImage[];
213
+ columns?: 2 | 3 | 4;
214
+ }
215
+ ```
216
+
217
+ #### Testimonials Section
218
+ ```typescript
219
+ interface Testimonial {
220
+ id: string | number;
221
+ text: string;
222
+ author: string;
223
+ rating: number; // 1-5
224
+ image?: string;
225
+ date?: string;
226
+ }
227
+
228
+ interface TestimonialsSettings {
229
+ title?: string;
230
+ testimonials?: Testimonial[];
231
+ layout?: 'grid' | 'carousel';
232
+ }
233
+ ```
234
+
235
+ #### Link List Section
236
+ ```typescript
237
+ interface Link {
238
+ id: string;
239
+ label: string;
240
+ url: string;
241
+ }
242
+
243
+ interface LinkListSettings {
244
+ links: Link[];
245
+ style?: 'pill' | 'square' | 'outline';
246
+ }
247
+ ```
248
+
249
+ #### Social Bar Section
250
+ ```typescript
251
+ interface SocialBarSettings {
252
+ platforms: string[]; // ['instagram', 'facebook', 'tiktok', etc.]
253
+ socialLinks?: Record<string, string>;
254
+ style?: 'filled' | 'outline' | 'ghost';
255
+ size?: 'small' | 'medium' | 'large';
256
+ position?: 'center' | 'left-vertical' | 'right-vertical';
257
+ invertIcons?: boolean;
258
+ }
259
+ ```
260
+
261
+ #### Fixed Info Card Section
262
+ ```typescript
263
+ interface FixedInfoCardSettings {
264
+ name?: string;
265
+ subheading?: string;
266
+ bio?: string;
267
+ links?: Link[];
268
+ bookingButtonText?: string;
269
+ bookingButtonUrl?: string;
270
+ showBookingButton?: boolean;
271
+ position?: 'bottom-left' | 'bottom-right' | 'bottom-center';
272
+ cardWidth?: 'small' | 'medium' | 'large';
273
+ cardColor?: string; // hex color
274
+ }
275
+ ```
276
+
277
+ **Complete Example:**
278
+ ```typescript
279
+ const heroSection: Section = {
280
+ id: 'hero-1',
281
+ type: 'hero',
282
+ enabled: true,
283
+ position: 0,
284
+ settings: {
285
+ headline: 'Welcome to Our Salon',
286
+ subheadline: 'Transform your look with our expert stylists',
287
+ heroImage: 'https://example.com/hero.jpg',
288
+ ctaButton: {
289
+ text: 'Book Now',
290
+ url: '/book'
291
+ },
292
+ layout: 'split',
293
+ imagePosition: 'right',
294
+ contentDisplay: 'side'
295
+ }
296
+ };
297
+ ```
298
+
299
+ ---
300
+
301
+ ## Theme Configuration
302
+
303
+ ### Colors Object
304
+
305
+ ```typescript
306
+ interface ColorScheme {
307
+ primary: string; // Main brand color (hex)
308
+ secondary: string; // Secondary brand color (hex)
309
+ text: string; // Main text color (hex)
310
+ bookingText?: string; // Booking widget text color
311
+ linkBackground?: string; // Link button background
312
+ linkText?: string; // Link button text
313
+ buttonText?: string; // Button text color
314
+ }
315
+ ```
316
+
317
+ ### Typography Object
318
+
319
+ ```typescript
320
+ interface TypographyConfig {
321
+ headingFont?: string; // Font family for headings
322
+ bodyFont?: string; // Font family for body text
323
+ bodySize?: string; // Base font size (e.g., "16px")
324
+ }
325
+ ```
326
+
327
+ ### Complete Theme
328
+
329
+ ```typescript
330
+ interface Theme {
331
+ colors: ColorScheme;
332
+ typography: TypographyConfig;
333
+ }
334
+ ```
335
+
336
+ **Example:**
337
+ ```typescript
338
+ const theme: Theme = {
339
+ colors: {
340
+ primary: '#D8C4FF',
341
+ secondary: '#014421',
342
+ text: '#000000',
343
+ bookingText: '#1A1A1A',
344
+ linkBackground: '#D8C4FF',
345
+ linkText: '#FFFFFF',
346
+ buttonText: '#FFFFFF'
347
+ },
348
+ typography: {
349
+ headingFont: 'Geist Sans',
350
+ bodyFont: 'Inter',
351
+ bodySize: '16px'
352
+ }
353
+ };
354
+ ```
355
+
356
+ ---
357
+
358
+ ## Step Settings
359
+
360
+ ### Service Selection Settings
361
+
362
+ ```typescript
363
+ interface ServiceSelectionSettings {
364
+ headerContent?: {
365
+ value: string;
366
+ };
367
+ subheaderContent?: {
368
+ value: string;
369
+ };
370
+ serviceLayout?: 'grid' | 'list';
371
+ columns?: 1 | 2 | 3 | 4;
372
+ showPricing?: boolean;
373
+ showDuration?: boolean;
374
+ showDescription?: boolean;
375
+ enableCategories?: boolean;
376
+ categoryStyle?: 'dropdown' | 'tabs' | 'pills' | 'chips' | 'accordion';
377
+ defaultCategoryView?: 'all' | string; // category ID
378
+ policyImages?: Array<{
379
+ url: string;
380
+ alt: string;
381
+ }>;
382
+ policyText?: string; // HTML string
383
+ imageSpacing?: 'none' | 'small' | 'medium' | 'large';
384
+ imageBorderRadius?: string; // CSS value
385
+ }
386
+ ```
387
+
388
+ ### Date Selection Settings
389
+
390
+ ```typescript
391
+ interface DateSelectionSettings {
392
+ headerContent?: {
393
+ value: string;
394
+ };
395
+ calendarView?: 'month' | 'week';
396
+ minDate?: string; // ISO date
397
+ maxDate?: string; // ISO date
398
+ disabledDates?: string[]; // Array of ISO dates
399
+ }
400
+ ```
401
+
402
+ ### Time Selection Settings
403
+
404
+ ```typescript
405
+ interface TimeSelectionSettings {
406
+ headerContent?: {
407
+ value: string;
408
+ };
409
+ timeFormat?: '12h' | '24h';
410
+ showDuration?: boolean;
411
+ columns?: 2 | 3 | 4;
412
+ slotDuration?: number; // minutes
413
+ }
414
+ ```
415
+
416
+ ### Addon Selection Settings
417
+
418
+ ```typescript
419
+ interface AddonSelectionSettings {
420
+ headerContent?: {
421
+ value: string;
422
+ };
423
+ subheaderContent?: {
424
+ value: string;
425
+ };
426
+ showPricing?: boolean;
427
+ showDuration?: boolean;
428
+ showDescription?: boolean;
429
+ maxAddons?: number; // Maximum number of addons
430
+ }
431
+ ```
432
+
433
+ ### Contact Form Settings
434
+
435
+ ```typescript
436
+ interface ContactFormSettings {
437
+ headerContent?: {
438
+ value: string;
439
+ };
440
+ requiredFields?: string[]; // ['name', 'email', 'phone']
441
+ showNotesField?: boolean;
442
+ notesLabel?: string;
443
+ notesPlaceholder?: string;
444
+ }
445
+ ```
446
+
447
+ ### Opt-In Module Data
448
+
449
+ ```typescript
450
+ interface OptInModule {
451
+ id: string;
452
+ label: string;
453
+ description?: string;
454
+ required?: boolean;
455
+ formFields: Array<{
456
+ id: string;
457
+ label: string;
458
+ type: 'text' | 'textarea' | 'select' | 'checkbox';
459
+ placeholder?: string;
460
+ required?: boolean;
461
+ options?: string[]; // for select fields
462
+ }>;
463
+ }
464
+ ```
465
+
466
+ **Example:**
467
+ ```typescript
468
+ const colorConsultationModule: OptInModule = {
469
+ id: 'color-consultation',
470
+ label: 'I need color consultation services',
471
+ description: 'Provide additional info for your color service',
472
+ required: false,
473
+ formFields: [
474
+ {
475
+ id: 'currentColor',
476
+ label: 'Current Hair Color',
477
+ type: 'text',
478
+ placeholder: 'Natural, dyed, etc.',
479
+ required: true
480
+ },
481
+ {
482
+ id: 'desiredColor',
483
+ label: 'Desired Color/Look',
484
+ type: 'textarea',
485
+ placeholder: 'Describe what you want to achieve...',
486
+ required: true
487
+ },
488
+ {
489
+ id: 'previousTreatments',
490
+ label: 'Previous Chemical Treatments',
491
+ type: 'text',
492
+ placeholder: 'Perms, relaxers, etc.',
493
+ required: false
494
+ }
495
+ ]
496
+ };
497
+ ```
498
+
499
+ ---
500
+
501
+ ## Background Configuration
502
+
503
+ ### Background Object
504
+
505
+ ```typescript
506
+ interface BackgroundConfig {
507
+ type: 'color' | 'gradient' | 'image';
508
+ value: string;
509
+ }
510
+ ```
511
+
512
+ **Examples:**
513
+ ```typescript
514
+ // Solid color
515
+ const colorBg: BackgroundConfig = {
516
+ type: 'color',
517
+ value: '#FFFFFF'
518
+ };
519
+
520
+ // Gradient
521
+ const gradientBg: BackgroundConfig = {
522
+ type: 'gradient',
523
+ value: 'linear-gradient(135deg, #D8C4FF 0%, #014421 100%)'
524
+ };
525
+
526
+ // Image
527
+ const imageBg: BackgroundConfig = {
528
+ type: 'image',
529
+ value: 'https://example.com/background.jpg'
530
+ };
531
+ ```
532
+
533
+ ---
534
+
535
+ ## Payment Configuration
536
+
537
+ ### Payment Provider Config
538
+
539
+ ```typescript
540
+ interface PaymentConfig {
541
+ provider: 'square' | 'stripe';
542
+ depositPercentage?: number; // 0-100
543
+ requireDeposit?: boolean;
544
+ acceptedMethods?: string[]; // ['card', 'apple_pay', 'google_pay']
545
+ }
546
+ ```
547
+
548
+ **Example:**
549
+ ```typescript
550
+ const paymentConfig: PaymentConfig = {
551
+ provider: 'square',
552
+ depositPercentage: 20,
553
+ requireDeposit: true,
554
+ acceptedMethods: ['card', 'apple_pay', 'google_pay']
555
+ };
556
+ ```
557
+
558
+ ---
559
+
560
+ ## Complete Configuration Example
561
+
562
+ ```typescript
563
+ const completeConfig = {
564
+ // Theme
565
+ theme: {
566
+ colors: {
567
+ primary: '#D8C4FF',
568
+ secondary: '#014421',
569
+ text: '#000000'
570
+ },
571
+ typography: {
572
+ headingFont: 'Geist Sans',
573
+ bodyFont: 'Inter',
574
+ bodySize: '16px'
575
+ }
576
+ },
577
+
578
+ // Background
579
+ background: {
580
+ type: 'gradient',
581
+ value: 'linear-gradient(135deg, #D8C4FF 0%, #014421 100%)'
582
+ },
583
+
584
+ // Page sections
585
+ sections: [
586
+ {
587
+ id: 'logo-1',
588
+ type: 'logo',
589
+ enabled: true,
590
+ position: 0,
591
+ settings: {
592
+ logoUrl: 'https://example.com/logo.png',
593
+ size: 'medium',
594
+ alignment: 'center'
595
+ }
596
+ },
597
+ {
598
+ id: 'hero-1',
599
+ type: 'hero',
600
+ enabled: true,
601
+ position: 1,
602
+ settings: {
603
+ headline: 'Welcome',
604
+ subheadline: 'Book your appointment today',
605
+ heroImage: 'https://example.com/hero.jpg',
606
+ ctaButton: {
607
+ text: 'Book Now',
608
+ url: '#booking'
609
+ }
610
+ }
611
+ }
612
+ ],
613
+
614
+ // Booking flow
615
+ booking_flow: {
616
+ steps: {
617
+ service_selection: {
618
+ enabled: true,
619
+ settings: {
620
+ headerContent: { value: 'Choose Your Service' },
621
+ serviceLayout: 'grid',
622
+ columns: 2,
623
+ showPricing: true
624
+ }
625
+ },
626
+ date_selection: {
627
+ enabled: true,
628
+ settings: {
629
+ headerContent: { value: 'Select a Date' },
630
+ calendarView: 'month'
631
+ }
632
+ },
633
+ time_selection: {
634
+ enabled: true,
635
+ settings: {
636
+ headerContent: { value: 'Pick a Time' },
637
+ timeFormat: '12h',
638
+ columns: 3
639
+ }
640
+ },
641
+ addon_selection: {
642
+ enabled: true,
643
+ settings: {
644
+ headerContent: { value: 'Add Extras' },
645
+ showPricing: true
646
+ }
647
+ },
648
+ contact_form: {
649
+ enabled: true,
650
+ settings: {
651
+ headerContent: { value: 'Your Information' }
652
+ }
653
+ }
654
+ },
655
+ progressBar: {
656
+ style: 'dots'
657
+ },
658
+ transitions: {
659
+ style: 'slide',
660
+ speed: 'normal'
661
+ },
662
+ background: {
663
+ type: 'color',
664
+ value: '#FFFFFF'
665
+ }
666
+ }
667
+ };
668
+ ```
669
+
670
+ ---
671
+
672
+ ## Type Safety Tips
673
+
674
+ 1. **Always define interfaces** for your data structures
675
+ 2. **Use TypeScript** for compile-time type checking
676
+ 3. **Validate at runtime** for user-provided data
677
+ 4. **Provide defaults** for optional fields
678
+ 5. **Document required vs optional** fields clearly
679
+
680
+ ## See Also
681
+
682
+ - [API.md](./API.md) - Component API reference
683
+ - [CALLBACKS.md](./CALLBACKS.md) - Callback patterns
684
+ - [STYLING.md](./STYLING.md) - Theme customization