@ticketboothapp/booking 0.1.22 → 1.2.24

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 (158) hide show
  1. package/package.json +2 -29
  2. package/src/index.ts +0 -79
  3. package/tsconfig.json +2 -8
  4. package/src/assets/icons/minus.svg +0 -7
  5. package/src/assets/icons/partner-logos/getyourguide.svg +0 -8
  6. package/src/assets/icons/plus.svg +0 -3
  7. package/src/colours.css +0 -23
  8. package/src/components/BookingDetails.module.css +0 -1591
  9. package/src/components/BookingDetails.tsx +0 -2264
  10. package/src/components/BookingWidget.tsx +0 -302
  11. package/src/components/ManageBookingView.tsx +0 -437
  12. package/src/components/PhoneInputWithCountry.module.css +0 -131
  13. package/src/components/PhoneInputWithCountry.tsx +0 -44
  14. package/src/components/PickupLocationDialog.module.css +0 -360
  15. package/src/components/PickupLocationDialog.tsx +0 -357
  16. package/src/components/PostBookingDependentAddOnUpsell.module.css +0 -174
  17. package/src/components/PostBookingDependentAddOnUpsell.tsx +0 -407
  18. package/src/components/booking/AddOnsSection.module.css +0 -10
  19. package/src/components/booking/AddOnsSection.tsx +0 -184
  20. package/src/components/booking/AdminPaymentChoiceModal.tsx +0 -98
  21. package/src/components/booking/BookingDialog.module.css +0 -643
  22. package/src/components/booking/BookingDialog.tsx +0 -356
  23. package/src/components/booking/BookingFlow.tsx +0 -4385
  24. package/src/components/booking/BookingFlowCollage.module.css +0 -148
  25. package/src/components/booking/BookingFlowCollage.tsx +0 -184
  26. package/src/components/booking/BookingFlowPlaceholder.module.css +0 -27
  27. package/src/components/booking/BookingFlowPlaceholder.tsx +0 -25
  28. package/src/components/booking/BookingFlowPreview.tsx +0 -51
  29. package/src/components/booking/BookingProductGrid.module.css +0 -359
  30. package/src/components/booking/BookingProductGrid.tsx +0 -497
  31. package/src/components/booking/Calendar.module.css +0 -616
  32. package/src/components/booking/Calendar.tsx +0 -1123
  33. package/src/components/booking/CancellationPolicySelector.module.css +0 -124
  34. package/src/components/booking/CancellationPolicySelector.tsx +0 -142
  35. package/src/components/booking/ChangeBookingDialog.tsx +0 -562
  36. package/src/components/booking/CheckoutForm.module.css +0 -244
  37. package/src/components/booking/CheckoutForm.tsx +0 -364
  38. package/src/components/booking/CheckoutModal.tsx +0 -451
  39. package/src/components/booking/CurrencySwitcher.tsx +0 -81
  40. package/src/components/booking/DapFlowCollage.tsx +0 -88
  41. package/src/components/booking/DapTourDescription.tsx +0 -35
  42. package/src/components/booking/DependentAddOnBookingDialog.tsx +0 -1350
  43. package/src/components/booking/DependentAddOnPaymentForm.tsx +0 -124
  44. package/src/components/booking/ErrorBoundary.tsx +0 -63
  45. package/src/components/booking/InfoTooltip.tsx +0 -108
  46. package/src/components/booking/ItineraryBox.module.css +0 -258
  47. package/src/components/booking/ItineraryBox.tsx +0 -550
  48. package/src/components/booking/ItineraryBuilder.tsx +0 -82
  49. package/src/components/booking/ItineraryPlaceholder.module.css +0 -45
  50. package/src/components/booking/ItineraryPlaceholder.tsx +0 -26
  51. package/src/components/booking/MealDrinkAddOnSelector.tsx +0 -338
  52. package/src/components/booking/PickupLocationSelector.module.css +0 -124
  53. package/src/components/booking/PickupLocationSelector.tsx +0 -1566
  54. package/src/components/booking/PickupTimeSelector.module.css +0 -134
  55. package/src/components/booking/PickupTimeSelector.tsx +0 -112
  56. package/src/components/booking/PriceBreakdown.tsx +0 -154
  57. package/src/components/booking/PriceSummary.tsx +0 -234
  58. package/src/components/booking/PrivateShuttleBookingFlow.module.css +0 -357
  59. package/src/components/booking/PrivateShuttleBookingFlow.tsx +0 -2662
  60. package/src/components/booking/PromoCodeInput.module.css +0 -166
  61. package/src/components/booking/PromoCodeInput.tsx +0 -99
  62. package/src/components/booking/ReturnTimeSelector.module.css +0 -173
  63. package/src/components/booking/ReturnTimeSelector.tsx +0 -145
  64. package/src/components/booking/TermsAcceptance.tsx +0 -111
  65. package/src/components/booking/TicketSelector.module.css +0 -164
  66. package/src/components/booking/TicketSelector.tsx +0 -199
  67. package/src/components/booking/TourDescription.module.css +0 -304
  68. package/src/components/booking/TourDescription.tsx +0 -273
  69. package/src/components/booking/booking-flow-ui.ts +0 -38
  70. package/src/components/booking/booking-flow.css +0 -944
  71. package/src/components/button.css +0 -245
  72. package/src/components/button.tsx +0 -152
  73. package/src/components/colorable-svg.tsx +0 -29
  74. package/src/components/image.css +0 -29
  75. package/src/components/image.tsx +0 -113
  76. package/src/components/partner/PartnerBookingPage.module.css +0 -130
  77. package/src/components/partner/PartnerBookingPage.tsx +0 -390
  78. package/src/components/partner/PartnerBookingPageWithBrowserMetadata.tsx +0 -45
  79. package/src/components/product-tag.module.css +0 -30
  80. package/src/components/product-tag.tsx +0 -34
  81. package/src/components/product-theme-pages/image-modal.tsx +0 -248
  82. package/src/components/product-theme-pages/photo-gallery.module.css +0 -200
  83. package/src/components/terms/TermsContent.tsx +0 -178
  84. package/src/components/value-pill.module.css +0 -59
  85. package/src/components/value-pill.tsx +0 -46
  86. package/src/constants/images.ts +0 -556
  87. package/src/constants/pill-values.ts +0 -210
  88. package/src/constants/products.ts +0 -155
  89. package/src/contexts/AvailabilitiesCacheContext.tsx +0 -125
  90. package/src/contexts/BookingAppContext.tsx +0 -134
  91. package/src/contexts/CompanyContext.tsx +0 -70
  92. package/src/data/dap-descriptions/session-couples-families-friends.en.json +0 -61
  93. package/src/data/dap-descriptions/session-elopements.en.json +0 -60
  94. package/src/data/dap-descriptions/session-proposals.en.json +0 -60
  95. package/src/data/product-descriptions/afternoon-delight.en.json +0 -35
  96. package/src/data/product-descriptions/emerald-lake-escape.en.json +0 -68
  97. package/src/data/product-descriptions/lake-louise-adventure.en.json +0 -74
  98. package/src/data/product-descriptions/moraine-lake-adventure.en.json +0 -78
  99. package/src/data/product-descriptions/moraine-lake-sunrise-lake-louise-golden-hour.en.json +0 -65
  100. package/src/data/product-descriptions/moraine-lake-sunrise.en.json +0 -64
  101. package/src/data/product-descriptions/private-tour.en.json +0 -80
  102. package/src/data/product-descriptions/two-lakes-combo.en.json +0 -65
  103. package/src/data/products-config.json +0 -101
  104. package/src/hooks/useBookingSourceMetadataFromLocation.ts +0 -21
  105. package/src/hooks/useIsBookingLaunchLive.ts +0 -49
  106. package/src/lib/analytics.ts +0 -197
  107. package/src/lib/booking/booking-source.ts +0 -51
  108. package/src/lib/booking/checkout-breakdown.ts +0 -69
  109. package/src/lib/booking/correlation-id.ts +0 -46
  110. package/src/lib/booking/i18n/config.ts +0 -21
  111. package/src/lib/booking/i18n/index.tsx +0 -144
  112. package/src/lib/booking/i18n/messages/en.json +0 -236
  113. package/src/lib/booking/i18n/messages/fr.json +0 -236
  114. package/src/lib/booking/itinerary-display.ts +0 -36
  115. package/src/lib/booking/itinerary-labels.ts +0 -70
  116. package/src/lib/booking/location-calculations.ts +0 -43
  117. package/src/lib/booking/location-utils.ts +0 -165
  118. package/src/lib/booking/map-utils.ts +0 -153
  119. package/src/lib/booking/marker-icons.ts +0 -113
  120. package/src/lib/booking/normalize-booking-product-id.ts +0 -21
  121. package/src/lib/booking/pickup-location-types.ts +0 -25
  122. package/src/lib/booking/places-api.ts +0 -154
  123. package/src/lib/booking/pricing.ts +0 -466
  124. package/src/lib/booking/product-option-id.ts +0 -35
  125. package/src/lib/booking/source-metadata.ts +0 -226
  126. package/src/lib/booking/sunday-week.ts +0 -14
  127. package/src/lib/booking/theme.ts +0 -83
  128. package/src/lib/booking/trace-context.ts +0 -62
  129. package/src/lib/booking/utils.ts +0 -9
  130. package/src/lib/booking-api.ts +0 -1793
  131. package/src/lib/booking-constants.ts +0 -23
  132. package/src/lib/booking-ref.ts +0 -13
  133. package/src/lib/booking-types.ts +0 -36
  134. package/src/lib/currency.ts +0 -81
  135. package/src/lib/dap-descriptions.ts +0 -50
  136. package/src/lib/dap-itinerary-preview.ts +0 -315
  137. package/src/lib/dependent-add-on-api.ts +0 -434
  138. package/src/lib/env.ts +0 -96
  139. package/src/lib/firebase.ts +0 -20
  140. package/src/lib/job-application-api.ts +0 -83
  141. package/src/lib/manage-booking-embed-print.ts +0 -16
  142. package/src/lib/manage-booking-post-checkout.ts +0 -68
  143. package/src/lib/photo-dap-config.ts +0 -228
  144. package/src/lib/photo-packages.ts +0 -75
  145. package/src/lib/pickup/map-utils.ts +0 -56
  146. package/src/lib/pickup/marker-icons.ts +0 -19
  147. package/src/lib/product-descriptions.ts +0 -66
  148. package/src/lib/products-config.ts +0 -73
  149. package/src/providers/booking-dialog-provider.tsx +0 -282
  150. package/src/providers/dependent-add-on-dialog-provider.tsx +0 -105
  151. package/src/radius.css +0 -5
  152. package/src/spacing.css +0 -7
  153. package/src/strings/en.json +0 -1774
  154. package/src/strings/es.json +0 -1573
  155. package/src/strings/fr.json +0 -1573
  156. package/src/strings/index.js +0 -23
  157. package/src/text-style.css +0 -97
  158. package/src/utils/currency-converter.ts +0 -101
@@ -1,390 +0,0 @@
1
- 'use client';
2
-
3
- import { useState, useEffect, useRef, useCallback, useMemo } from 'react';
4
- import defaultStrings from '@/strings';
5
- import BookingProductGrid, { type FilterId } from '@/components/booking/BookingProductGrid';
6
- import { BookingFlow } from '@/components/booking/BookingFlow';
7
- import { PrivateShuttleBookingFlow } from '@/components/booking/PrivateShuttleBookingFlow';
8
- import { getProductByIdOrSlug, buildMinimalProductFromConfig } from '@/lib/products-config';
9
- import { getProduct, type Product } from '@/lib/booking-api';
10
- import { ENV } from '@/lib/env';
11
- import type { BookingFlowUiOptions } from '@/components/booking/booking-flow-ui';
12
- import type { BookingSourceMetadata } from '@/lib/booking/source-metadata';
13
- import dialogStyles from '@/components/booking/BookingDialog.module.css';
14
- import styles from './PartnerBookingPage.module.css';
15
- import { BOOKING_FLOW_ABANDON_EVENT } from '@/providers/booking-dialog-provider';
16
-
17
- type PartnerScreen =
18
- | { type: 'product-grid'; filterId?: string }
19
- | { type: 'book-flow'; productId: string };
20
-
21
- function PartnerBookFlowScreen({
22
- productId,
23
- onBack,
24
- autoAppliedPromoCode,
25
- calendarDiscountPercent,
26
- highlightedPickupLocationIds,
27
- flowUi,
28
- onBookingFlowSuccess,
29
- bookingSourceAttribution,
30
- partnerPortalBooking = false,
31
- availabilityPricingProfileId,
32
- availabilityCancellationPolicyProfileId,
33
- }: {
34
- productId: string;
35
- onBack: () => void;
36
- autoAppliedPromoCode?: string;
37
- calendarDiscountPercent?: number;
38
- highlightedPickupLocationIds?: string[];
39
- flowUi?: BookingFlowUiOptions;
40
- /** Partner portal: after deferred-invoice confirmation, refetch bookings / switch tab. */
41
- onBookingFlowSuccess?: (data: { reservationReference: string; bookingReference?: string }) => void;
42
- bookingSourceAttribution: Partial<BookingSourceMetadata>;
43
- partnerPortalBooking?: boolean;
44
- availabilityPricingProfileId?: string | null;
45
- availabilityCancellationPolicyProfileId?: string | null;
46
- }) {
47
- const [product, setProduct] = useState<Product | null>(null);
48
- const [error, setError] = useState<string | null>(null);
49
- const contentRef = useRef<HTMLDivElement>(null);
50
-
51
- const config = getProductByIdOrSlug(productId);
52
- const apiProductId = config?.productId ?? productId;
53
-
54
- const minimalProduct = config
55
- ? buildMinimalProductFromConfig(config, ENV.COMPANY_ID)
56
- : null;
57
-
58
- useEffect(() => {
59
- let cancelled = false;
60
- setError(null);
61
- getProduct(apiProductId, ENV.COMPANY_ID)
62
- .then((p) => {
63
- if (!cancelled && p) setProduct(p);
64
- else if (!cancelled && !p && !config) setError('Product not found');
65
- })
66
- .catch((err) => {
67
- if (!cancelled) {
68
- setError(
69
- err instanceof Error ? err.message : 'Failed to load product',
70
- );
71
- }
72
- });
73
- return () => {
74
- cancelled = true;
75
- };
76
- }, [apiProductId, config]);
77
-
78
- if (!config) {
79
- if (error) {
80
- return (
81
- <div className={`${styles.screen} booking-flow-preflight`}>
82
- <div className="flex flex-col items-center justify-center py-16 gap-4">
83
- <p className="text-red-600">{error}</p>
84
- <button
85
- type="button"
86
- onClick={onBack}
87
- className="text-emerald-600 hover:underline"
88
- >
89
- Go back
90
- </button>
91
- </div>
92
- </div>
93
- );
94
- }
95
- return (
96
- <div className={`${styles.screen} booking-flow-preflight`}>
97
- <div className="flex items-center justify-center py-16">
98
- <div className="text-stone-600">
99
- {defaultStrings.common.chooseYourExperience} — Loading...
100
- </div>
101
- </div>
102
- </div>
103
- );
104
- }
105
-
106
- const displayProduct = product ?? minimalProduct!;
107
-
108
- if (error && !product) {
109
- return (
110
- <div className={`${styles.screen} booking-flow-preflight`}>
111
- <div className="flex flex-col items-center justify-center py-16 gap-4">
112
- <p className="text-red-600">{error}</p>
113
- <button
114
- type="button"
115
- onClick={onBack}
116
- className="text-emerald-600 hover:underline"
117
- >
118
- Go back
119
- </button>
120
- </div>
121
- </div>
122
- );
123
- }
124
-
125
- return (
126
- <div className={`${dialogStyles.screen} booking-flow-preflight`}>
127
- {displayProduct.productType === 'PRIVATE_SHUTTLE' ? (
128
- <PrivateShuttleBookingFlow
129
- product={displayProduct}
130
- productId={productId}
131
- onBack={onBack}
132
- currency="CAD"
133
- contentRef={contentRef}
134
- highlightedPickupLocationIds={highlightedPickupLocationIds}
135
- flowUi={flowUi}
136
- bookingSourceAttribution={bookingSourceAttribution}
137
- partnerPortalBooking={partnerPortalBooking}
138
- availabilityPricingProfileId={availabilityPricingProfileId}
139
- availabilityCancellationPolicyProfileId={availabilityCancellationPolicyProfileId}
140
- onSuccess={(data) => {
141
- onBookingFlowSuccess?.(data);
142
- if (typeof window !== 'undefined') {
143
- window.scrollTo({ top: 0, behavior: 'smooth' });
144
- }
145
- }}
146
- />
147
- ) : (
148
- <BookingFlow
149
- product={displayProduct}
150
- productId={productId}
151
- onBack={onBack}
152
- currency="CAD"
153
- contentRef={contentRef}
154
- useWindowScroll
155
- autoAppliedPromoCode={autoAppliedPromoCode}
156
- calendarDiscountPercent={calendarDiscountPercent}
157
- highlightedPickupLocationIds={highlightedPickupLocationIds}
158
- flowUi={flowUi}
159
- bookingSourceAttribution={bookingSourceAttribution}
160
- partnerPortalBooking={partnerPortalBooking}
161
- availabilityPricingProfileId={availabilityPricingProfileId}
162
- availabilityCancellationPolicyProfileId={availabilityCancellationPolicyProfileId}
163
- onSuccess={(data) => {
164
- onBookingFlowSuccess?.(data);
165
- if (typeof window !== 'undefined') {
166
- window.scrollTo({ top: 0, behavior: 'smooth' });
167
- }
168
- }}
169
- />
170
- )}
171
- </div>
172
- );
173
- }
174
-
175
- export interface PartnerBookingPageProps {
176
- /** Optional initial filter for the product grid (e.g. 'moraine-lake', 'all'). */
177
- initialFilterId?: FilterId;
178
- /** Optional custom title for the grid view header. */
179
- headerTitle?: string;
180
- /** Partner logo URL (e.g. from public folder or CDN). */
181
- partnerLogoUrl?: string;
182
- /** Accessible alt text for the partner logo. */
183
- partnerLogoAlt?: string;
184
- /** Via Via logo URL (fallback could be your standard logo). */
185
- viaViaLogoUrl?: string;
186
- /** Accessible alt text for the Via Via logo. */
187
- viaViaLogoAlt?: string;
188
- /** Promo code to auto-apply on this partner page. */
189
- autoAppliedPromoCode?: string;
190
- /** Extra discount percent shown in calendar date badges for this partner page. */
191
- calendarDiscountPercent?: number;
192
- /** Pickup location IDs to prioritize and highlight as partner-preferred. */
193
- highlightedPickupLocationIds?: string[];
194
- /**
195
- * When true, render only the booking header + content (no outer page shell or card).
196
- * Use inside a parent that already provides layout (e.g. partner portal).
197
- */
198
- embedded?: boolean;
199
- /** Hide the top title row on the product grid only (filters stay visible). */
200
- hideProductGridHeader?: boolean;
201
- /** Product tile opens book flow directly (requires stable `onBookProduct` / embedded routing). */
202
- bookOnTileClick?: boolean;
203
- flowUi?: BookingFlowUiOptions;
204
- /** Embedded partner portal: called after booking completes (e.g. deferred invoice). */
205
- onBookingFlowSuccess?: (data: { reservationReference: string; bookingReference?: string }) => void;
206
- /** Required explicit attribution base (URL + optional merge); prefer `PartnerBookingPageWithBrowserMetadata` when deriving from the browser. */
207
- bookingSourceAttribution: Partial<BookingSourceMetadata>;
208
- /** Set on the dedicated partner portal app only — reserves use PARTNER_PORTAL source. */
209
- partnerPortalBooking?: boolean;
210
- /** Partner pricing profile for get-availabilities (when API supports it). */
211
- availabilityPricingProfileId?: string | null;
212
- /** Partner cancellation-policy profile for get-availabilities policy filtering. */
213
- availabilityCancellationPolicyProfileId?: string | null;
214
- }
215
-
216
- export function PartnerBookingPage({
217
- initialFilterId = 'all',
218
- headerTitle,
219
- partnerLogoUrl,
220
- partnerLogoAlt,
221
- viaViaLogoUrl = 'https://viaviamorainelake.b-cdn.net/logo512.png',
222
- viaViaLogoAlt = 'Via Via Moraine Lake Shuttle logo',
223
- autoAppliedPromoCode,
224
- calendarDiscountPercent,
225
- highlightedPickupLocationIds,
226
- embedded = false,
227
- hideProductGridHeader = false,
228
- bookOnTileClick = false,
229
- flowUi,
230
- onBookingFlowSuccess,
231
- bookingSourceAttribution,
232
- partnerPortalBooking = false,
233
- availabilityPricingProfileId,
234
- availabilityCancellationPolicyProfileId,
235
- }: PartnerBookingPageProps) {
236
- const [screen, setScreen] = useState<PartnerScreen>({ type: 'product-grid' });
237
- const cardRef = useRef<HTMLDivElement>(null);
238
- const contentRef = useRef<HTMLDivElement>(null);
239
- const handleBackToProductGrid = useCallback(() => {
240
- if (typeof window !== 'undefined') {
241
- window.dispatchEvent(new Event(BOOKING_FLOW_ABANDON_EVENT));
242
- }
243
- setScreen({ type: 'product-grid' });
244
- }, []);
245
-
246
- useEffect(() => {
247
- if (screen.type === 'book-flow' && typeof window !== 'undefined') {
248
- window.scrollTo({ top: 0, behavior: 'smooth' });
249
- }
250
- }, [screen.type, screen.type === 'book-flow' ? screen.productId : null]);
251
-
252
- const bookFlowProductDisplayName = useMemo(() => {
253
- if (screen.type !== 'book-flow') return '';
254
- const cfg = getProductByIdOrSlug(screen.productId);
255
- const short = cfg?.display.shortName?.trim();
256
- if (short) return short;
257
- const slug = cfg?.display.slug?.trim();
258
- if (slug) {
259
- return slug
260
- .split('-')
261
- .filter(Boolean)
262
- .map((w) => w.charAt(0).toUpperCase() + w.slice(1).toLowerCase())
263
- .join(' ');
264
- }
265
- return screen.productId;
266
- }, [screen]);
267
-
268
- const currentTitle =
269
- screen.type === 'product-grid'
270
- ? headerTitle ?? defaultStrings.common.chooseYourExperience
271
- : null;
272
-
273
- const showTopHeader =
274
- screen.type === 'book-flow' || !hideProductGridHeader;
275
-
276
- const bookSection = (
277
- <>
278
- {showTopHeader && (
279
- <header className={styles.header}>
280
- <div className={styles.headerLeft}>
281
- {screen.type === 'book-flow' ? (
282
- <button
283
- type="button"
284
- className={styles.backButton}
285
- onClick={handleBackToProductGrid}
286
- aria-label="Go back"
287
- >
288
- <svg
289
- width="24"
290
- height="24"
291
- viewBox="0 0 24 24"
292
- fill="none"
293
- stroke="currentColor"
294
- strokeWidth="2"
295
- strokeLinecap="round"
296
- strokeLinejoin="round"
297
- >
298
- <path d="M19 12H5M12 19l-7-7 7-7" />
299
- </svg>
300
- </button>
301
- ) : (
302
- <span className={styles.headerSpacer} aria-hidden />
303
- )}
304
- </div>
305
- {screen.type === 'product-grid' ? (
306
- <h1 className={styles.titleProductGrid}>{currentTitle}</h1>
307
- ) : (
308
- <h1 className={styles.titleBookFlow}>
309
- <span className={styles.titleBookPrefix}>{defaultStrings.common.book}</span>
310
- <span className={styles.titleBookSeparator}> - </span>
311
- <span className={styles.titleBookProduct}>{bookFlowProductDisplayName}</span>
312
- </h1>
313
- )}
314
- <div className={styles.headerRight}>
315
- {/* No close button on dedicated partner page */}
316
- <span className={styles.headerSpacer} aria-hidden />
317
- </div>
318
- </header>
319
- )}
320
-
321
- <div
322
- ref={contentRef}
323
- className={embedded ? styles.contentEmbedded : styles.content}
324
- >
325
- {screen.type === 'product-grid' && (
326
- <div className={dialogStyles.screen}>
327
- <BookingProductGrid
328
- contentRef={contentRef}
329
- initialFilterId={initialFilterId}
330
- onBookProduct={(productId: string) =>
331
- setScreen({ type: 'book-flow', productId })
332
- }
333
- bookOnTileClick={bookOnTileClick}
334
- />
335
- </div>
336
- )}
337
- {screen.type === 'book-flow' && (
338
- <PartnerBookFlowScreen
339
- productId={screen.productId}
340
- onBack={handleBackToProductGrid}
341
- autoAppliedPromoCode={autoAppliedPromoCode}
342
- highlightedPickupLocationIds={highlightedPickupLocationIds}
343
- calendarDiscountPercent={calendarDiscountPercent}
344
- flowUi={flowUi}
345
- onBookingFlowSuccess={onBookingFlowSuccess}
346
- bookingSourceAttribution={bookingSourceAttribution}
347
- partnerPortalBooking={partnerPortalBooking}
348
- availabilityPricingProfileId={availabilityPricingProfileId}
349
- availabilityCancellationPolicyProfileId={availabilityCancellationPolicyProfileId}
350
- />
351
- )}
352
- </div>
353
- </>
354
- );
355
-
356
- if (embedded) {
357
- return bookSection;
358
- }
359
-
360
- return (
361
- <div>
362
- <main className="booking-flow-root">
363
- <div className={styles.root}>
364
- {partnerLogoUrl && viaViaLogoUrl && (
365
- <div className={styles.logoRow}>
366
- <img
367
- src={partnerLogoUrl}
368
- alt={partnerLogoAlt || 'Partner logo'}
369
- className={styles.partnerLogo}
370
- />
371
- <span className={styles.logoDivider}>x</span>
372
- <img
373
- src={viaViaLogoUrl}
374
- alt={viaViaLogoAlt}
375
- className={styles.viaViaLogo}
376
- />
377
- </div>
378
- )}
379
-
380
- <div ref={cardRef} className={styles.card}>
381
- {bookSection}
382
- </div>
383
- </div>
384
- </main>
385
- </div>
386
- );
387
- }
388
-
389
- export default PartnerBookingPage;
390
-
@@ -1,45 +0,0 @@
1
- 'use client';
2
-
3
- import { useMemo } from 'react';
4
- import { usePathname } from 'next/navigation';
5
- import PartnerBookingPage, { type PartnerBookingPageProps } from '@/components/partner/PartnerBookingPage';
6
- import {
7
- buildBookingSourceMetadataFromLocation,
8
- mergeBookingSourceMetadata,
9
- type BookingSourceMetadata,
10
- } from '@/lib/booking/source-metadata';
11
-
12
- export type PartnerBookingPageWithBrowserMetadataProps = Omit<PartnerBookingPageProps, 'bookingSourceAttribution'> & {
13
- /**
14
- * Route-level identity (e.g. `partnerSlug`) so attribution works on localhost and when the URL
15
- * does not carry `/partner/:slug`. Merged after browser URL fields; portal/session layer wins last.
16
- */
17
- canonicalAttribution: Partial<BookingSourceMetadata>;
18
- /** Partner portal: org `par_…` + agent merged on top of URL + canonical. */
19
- bookingSourceAttributionMerge?: Partial<BookingSourceMetadata> | null;
20
- };
21
-
22
- /**
23
- * Partner surfaces: **canonical** route metadata + optional browser URL supplements + optional portal merge.
24
- */
25
- export default function PartnerBookingPageWithBrowserMetadata({
26
- canonicalAttribution,
27
- bookingSourceAttributionMerge,
28
- ...rest
29
- }: PartnerBookingPageWithBrowserMetadataProps) {
30
- const pathname = usePathname() ?? '';
31
- const mergeKey = JSON.stringify(bookingSourceAttributionMerge ?? {});
32
- const canonicalKey = JSON.stringify(canonicalAttribution ?? {});
33
-
34
- const bookingSourceAttribution = useMemo(
35
- () =>
36
- mergeBookingSourceMetadata(
37
- buildBookingSourceMetadataFromLocation(),
38
- canonicalAttribution,
39
- bookingSourceAttributionMerge,
40
- ),
41
- [pathname, mergeKey, canonicalKey],
42
- );
43
-
44
- return <PartnerBookingPage {...rest} bookingSourceAttribution={bookingSourceAttribution} />;
45
- }
@@ -1,30 +0,0 @@
1
- .tag {
2
- display: inline-flex;
3
- align-items: center;
4
- justify-content: center;
5
- padding: 0.4rem 0.8rem;
6
- font-size: 0.75rem;
7
- font-weight: 700;
8
- text-transform: uppercase;
9
- letter-spacing: 0.5px;
10
- z-index: 4;
11
- text-align: center;
12
- line-height: 1.2;
13
- border-radius: 4px;
14
- box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
15
- margin-bottom: 8px;
16
- white-space: nowrap;
17
- overflow: hidden;
18
- text-overflow: ellipsis;
19
- }
20
-
21
- /* Style variants */
22
- .most_popular {
23
- background-color: var(--accent-orange);
24
- color: white;
25
- text-shadow: 0 1px 2px rgba(0, 0, 0, 0.1);
26
- }
27
-
28
- .custom {
29
- /* Custom styles will be applied via inline styles */
30
- }
@@ -1,34 +0,0 @@
1
- import styles from './product-tag.module.css';
2
-
3
- export enum ProductTagStyle {
4
- MOST_POPULAR = 'MOST_POPULAR',
5
- CUSTOM = 'CUSTOM',
6
- }
7
-
8
- interface ProductTagProps {
9
- text: string;
10
- style: ProductTagStyle;
11
- backgroundColor?: string;
12
- textColor?: string;
13
- }
14
-
15
- export default function ProductTag({
16
- text,
17
- style,
18
- backgroundColor,
19
- textColor
20
- }: ProductTagProps) {
21
- const customStyles = style === ProductTagStyle.CUSTOM ? {
22
- backgroundColor: backgroundColor || '#000000',
23
- color: textColor || '#ffffff',
24
- } : {};
25
-
26
- return (
27
- <div
28
- className={`${styles.tag} ${styles[style.toLowerCase()]}`}
29
- style={customStyles}
30
- >
31
- {text}
32
- </div>
33
- );
34
- }