@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
package/TENANT_SETUP.md
ADDED
|
@@ -0,0 +1,316 @@
|
|
|
1
|
+
# Using @oviah/booking-components in Your Tenant Template
|
|
2
|
+
|
|
3
|
+
Quick guide for importing and using the booking/landing page components in your tenant template project.
|
|
4
|
+
|
|
5
|
+
## Step-by-Step Setup
|
|
6
|
+
|
|
7
|
+
### 1. Choose Your Installation Method
|
|
8
|
+
|
|
9
|
+
#### Recommended: Local Link (for development)
|
|
10
|
+
|
|
11
|
+
This is the easiest for development since it auto-updates when you rebuild.
|
|
12
|
+
|
|
13
|
+
**Terminal 1 - In stylink-saas-dashboard:**
|
|
14
|
+
```bash
|
|
15
|
+
cd /Users/queenb/Desktop/stylink-saas-dashboard/packages/booking-components
|
|
16
|
+
npm run build # Build the package
|
|
17
|
+
npm link # Create global symlink
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
**Terminal 2 - In your tenant template project:**
|
|
21
|
+
```bash
|
|
22
|
+
cd /path/to/your/tenant-template
|
|
23
|
+
npm link @oviah/booking-components
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
Done! The package is now available in your tenant project.
|
|
27
|
+
|
|
28
|
+
### 2. Import Components
|
|
29
|
+
|
|
30
|
+
In your tenant template's page component:
|
|
31
|
+
|
|
32
|
+
```tsx
|
|
33
|
+
// app/[slug]/page.tsx or wherever you render the tenant page
|
|
34
|
+
|
|
35
|
+
import { SectionRenderer, BookingFlow } from '@oviah/booking-components';
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
### 3. Render the Landing Page
|
|
39
|
+
|
|
40
|
+
```tsx
|
|
41
|
+
'use client';
|
|
42
|
+
|
|
43
|
+
import { SectionRenderer } from '@oviah/booking-components';
|
|
44
|
+
|
|
45
|
+
export default function TenantLandingPage({ params }) {
|
|
46
|
+
// Fetch config from your API or database
|
|
47
|
+
const config = await fetchTenantConfig(params.slug);
|
|
48
|
+
|
|
49
|
+
const { theme, sections } = config;
|
|
50
|
+
|
|
51
|
+
return (
|
|
52
|
+
<div
|
|
53
|
+
className="min-h-screen"
|
|
54
|
+
style={{
|
|
55
|
+
backgroundColor: config.background?.value || '#FFFFFF',
|
|
56
|
+
color: theme.colors.text,
|
|
57
|
+
fontFamily: theme.typography.bodyFont
|
|
58
|
+
}}
|
|
59
|
+
>
|
|
60
|
+
{sections
|
|
61
|
+
.filter(s => s.enabled)
|
|
62
|
+
.sort((a, b) => a.position - b.position)
|
|
63
|
+
.map((section) => (
|
|
64
|
+
<SectionRenderer
|
|
65
|
+
key={section.id}
|
|
66
|
+
section={section}
|
|
67
|
+
theme={theme}
|
|
68
|
+
enableInlineEditing={false}
|
|
69
|
+
/>
|
|
70
|
+
))}
|
|
71
|
+
</div>
|
|
72
|
+
);
|
|
73
|
+
}
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
### 4. Render the Booking Flow
|
|
77
|
+
|
|
78
|
+
```tsx
|
|
79
|
+
// app/[slug]/book/page.tsx
|
|
80
|
+
|
|
81
|
+
'use client';
|
|
82
|
+
|
|
83
|
+
import { BookingFlow } from '@oviah/booking-components';
|
|
84
|
+
|
|
85
|
+
export default function BookingPage() {
|
|
86
|
+
const config = {
|
|
87
|
+
progressBar: {
|
|
88
|
+
type: 'stepped',
|
|
89
|
+
showStepNames: true
|
|
90
|
+
},
|
|
91
|
+
steps: {
|
|
92
|
+
service: { enabled: true },
|
|
93
|
+
datetime: { enabled: true },
|
|
94
|
+
contact: { enabled: true }
|
|
95
|
+
}
|
|
96
|
+
};
|
|
97
|
+
|
|
98
|
+
const colors = {
|
|
99
|
+
primary: '#D8C4FF',
|
|
100
|
+
secondary: '#014421',
|
|
101
|
+
text: '#000000'
|
|
102
|
+
};
|
|
103
|
+
|
|
104
|
+
return (
|
|
105
|
+
<div className="container mx-auto px-4 py-16">
|
|
106
|
+
<BookingFlow
|
|
107
|
+
config={config}
|
|
108
|
+
colors={colors}
|
|
109
|
+
services={[
|
|
110
|
+
{ id: '1', name: 'Haircut', price: 50, duration: 60 }
|
|
111
|
+
]}
|
|
112
|
+
dates={['2025-10-15', '2025-10-16']}
|
|
113
|
+
times={['09:00', '10:00', '11:00']}
|
|
114
|
+
addons={[]}
|
|
115
|
+
onComplete={(bookingData) => {
|
|
116
|
+
console.log('Booking submitted:', bookingData);
|
|
117
|
+
// Handle booking submission to your API
|
|
118
|
+
}}
|
|
119
|
+
/>
|
|
120
|
+
</div>
|
|
121
|
+
);
|
|
122
|
+
}
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
## Important Notes
|
|
126
|
+
|
|
127
|
+
### Peer Dependencies
|
|
128
|
+
|
|
129
|
+
Make sure your tenant template has these dependencies:
|
|
130
|
+
|
|
131
|
+
```json
|
|
132
|
+
{
|
|
133
|
+
"dependencies": {
|
|
134
|
+
"react": "^18.0.0 || ^19.0.0",
|
|
135
|
+
"react-dom": "^18.0.0 || ^19.0.0"
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
```
|
|
139
|
+
|
|
140
|
+
The package bundles `framer-motion`, `lucide-react`, and `clsx`, so you don't need to install them separately.
|
|
141
|
+
|
|
142
|
+
### Rebuilding the Package
|
|
143
|
+
|
|
144
|
+
Whenever you make changes to the components in stylink-saas-dashboard:
|
|
145
|
+
|
|
146
|
+
```bash
|
|
147
|
+
cd /Users/queenb/Desktop/stylink-saas-dashboard/packages/booking-components
|
|
148
|
+
npm run build
|
|
149
|
+
```
|
|
150
|
+
|
|
151
|
+
Your tenant template will automatically use the updated version (with `npm link`).
|
|
152
|
+
|
|
153
|
+
### TypeScript Support
|
|
154
|
+
|
|
155
|
+
The package includes full TypeScript definitions:
|
|
156
|
+
|
|
157
|
+
```tsx
|
|
158
|
+
import type {
|
|
159
|
+
Section,
|
|
160
|
+
BookingFlowConfig,
|
|
161
|
+
Theme
|
|
162
|
+
} from '@oviah/booking-components';
|
|
163
|
+
|
|
164
|
+
const section: Section = {
|
|
165
|
+
id: 'hero-1',
|
|
166
|
+
type: 'hero',
|
|
167
|
+
enabled: true,
|
|
168
|
+
position: 0,
|
|
169
|
+
settings: {
|
|
170
|
+
headline: 'Welcome'
|
|
171
|
+
}
|
|
172
|
+
};
|
|
173
|
+
```
|
|
174
|
+
|
|
175
|
+
## Example: Complete Tenant Page
|
|
176
|
+
|
|
177
|
+
```tsx
|
|
178
|
+
// app/[slug]/page.tsx
|
|
179
|
+
|
|
180
|
+
'use client';
|
|
181
|
+
|
|
182
|
+
import { use, useEffect, useState } from 'react';
|
|
183
|
+
import { SectionRenderer } from '@oviah/booking-components';
|
|
184
|
+
|
|
185
|
+
export default function TenantPage({ params }) {
|
|
186
|
+
const { slug } = use(params);
|
|
187
|
+
const [config, setConfig] = useState(null);
|
|
188
|
+
const [loading, setLoading] = useState(true);
|
|
189
|
+
|
|
190
|
+
useEffect(() => {
|
|
191
|
+
async function loadConfig() {
|
|
192
|
+
try {
|
|
193
|
+
const res = await fetch(`/api/config/${slug}`);
|
|
194
|
+
const data = await res.json();
|
|
195
|
+
setConfig(data);
|
|
196
|
+
} catch (error) {
|
|
197
|
+
console.error('Failed to load config:', error);
|
|
198
|
+
} finally {
|
|
199
|
+
setLoading(false);
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
loadConfig();
|
|
203
|
+
}, [slug]);
|
|
204
|
+
|
|
205
|
+
if (loading) {
|
|
206
|
+
return <div>Loading...</div>;
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
if (!config) {
|
|
210
|
+
return <div>Tenant not found</div>;
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
const { theme, background, sections } = config;
|
|
214
|
+
|
|
215
|
+
// Calculate background style
|
|
216
|
+
const backgroundStyle =
|
|
217
|
+
background?.type === 'gradient'
|
|
218
|
+
? { background: background.value }
|
|
219
|
+
: background?.type === 'image'
|
|
220
|
+
? {
|
|
221
|
+
backgroundImage: `url(${background.value})`,
|
|
222
|
+
backgroundSize: 'cover',
|
|
223
|
+
backgroundPosition: 'center'
|
|
224
|
+
}
|
|
225
|
+
: { backgroundColor: background?.value || '#FFFFFF' };
|
|
226
|
+
|
|
227
|
+
return (
|
|
228
|
+
<div
|
|
229
|
+
className="min-h-screen"
|
|
230
|
+
style={{
|
|
231
|
+
...backgroundStyle,
|
|
232
|
+
color: theme.colors.text,
|
|
233
|
+
fontFamily: theme.typography.bodyFont,
|
|
234
|
+
fontSize: theme.typography.bodySize
|
|
235
|
+
}}
|
|
236
|
+
>
|
|
237
|
+
{sections
|
|
238
|
+
.filter(s => s.enabled)
|
|
239
|
+
.sort((a, b) => a.position - b.position)
|
|
240
|
+
.map((section) => {
|
|
241
|
+
const marginTop = section.settings?.marginTop || 0;
|
|
242
|
+
const marginBottom = section.settings?.marginBottom || 0;
|
|
243
|
+
const paddingTop = section.settings?.paddingTop || 0;
|
|
244
|
+
const paddingBottom = section.settings?.paddingBottom || 0;
|
|
245
|
+
|
|
246
|
+
return (
|
|
247
|
+
<div
|
|
248
|
+
key={section.id}
|
|
249
|
+
style={{
|
|
250
|
+
marginTop: `${marginTop}px`,
|
|
251
|
+
marginBottom: `${marginBottom}px`,
|
|
252
|
+
paddingTop: `${paddingTop}px`,
|
|
253
|
+
paddingBottom: `${paddingBottom}px`
|
|
254
|
+
}}
|
|
255
|
+
>
|
|
256
|
+
<SectionRenderer
|
|
257
|
+
section={section}
|
|
258
|
+
theme={theme}
|
|
259
|
+
enableInlineEditing={false}
|
|
260
|
+
/>
|
|
261
|
+
</div>
|
|
262
|
+
);
|
|
263
|
+
})}
|
|
264
|
+
</div>
|
|
265
|
+
);
|
|
266
|
+
}
|
|
267
|
+
```
|
|
268
|
+
|
|
269
|
+
## Troubleshooting
|
|
270
|
+
|
|
271
|
+
### "Module not found: @oviah/booking-components"
|
|
272
|
+
|
|
273
|
+
Make sure you've linked the package:
|
|
274
|
+
```bash
|
|
275
|
+
npm link @oviah/booking-components
|
|
276
|
+
```
|
|
277
|
+
|
|
278
|
+
### "React version mismatch"
|
|
279
|
+
|
|
280
|
+
Ensure your tenant template uses React 18 or 19:
|
|
281
|
+
```bash
|
|
282
|
+
npm install react@^19 react-dom@^19
|
|
283
|
+
```
|
|
284
|
+
|
|
285
|
+
### Changes not reflecting
|
|
286
|
+
|
|
287
|
+
Rebuild the package:
|
|
288
|
+
```bash
|
|
289
|
+
cd /Users/queenb/Desktop/stylink-saas-dashboard/packages/booking-components
|
|
290
|
+
npm run build
|
|
291
|
+
```
|
|
292
|
+
|
|
293
|
+
### Want to use the file path method instead?
|
|
294
|
+
|
|
295
|
+
**In your tenant template's package.json:**
|
|
296
|
+
```json
|
|
297
|
+
{
|
|
298
|
+
"dependencies": {
|
|
299
|
+
"@oviah/booking-components": "file:../stylink-saas-dashboard/packages/booking-components"
|
|
300
|
+
}
|
|
301
|
+
}
|
|
302
|
+
```
|
|
303
|
+
|
|
304
|
+
Then:
|
|
305
|
+
```bash
|
|
306
|
+
npm install
|
|
307
|
+
```
|
|
308
|
+
|
|
309
|
+
## Next Steps
|
|
310
|
+
|
|
311
|
+
1. Set up your API endpoints to fetch tenant configs
|
|
312
|
+
2. Implement booking submission logic
|
|
313
|
+
3. Add payment integration
|
|
314
|
+
4. Customize styling to match your tenant's brand
|
|
315
|
+
|
|
316
|
+
For more details, see the main [README.md](./README.md).
|