@ticketboothapp/booking 1.2.190 → 1.2.193
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/package.json +3 -1
- package/src/components/BackgroundVideo.tsx +6 -3
- package/src/components/booking/AddOnsSection.module.css +6 -2
- package/src/components/booking/AddOnsSection.tsx +4 -4
- package/src/components/booking/AdminChangeReceiptComparison.module.css +16 -0
- package/src/components/booking/AdminChangeReceiptComparison.tsx +14 -4
- package/src/components/booking/BookingDialog.module.css +43 -0
- package/src/components/booking/BookingFlowCollage.tsx +43 -16
- package/src/components/booking/Calendar.module.css +8 -3
- package/src/components/booking/ChangeBookingDialog.tsx +116 -55
- package/src/components/booking/ChangeBookingFlow.tsx +1 -0
- package/src/components/booking/CheckoutForm.module.css +7 -0
- package/src/components/booking/CollapsibleAddOnItem.module.css +3 -2
- package/src/components/booking/MealDrinkAddOnSelector.tsx +4 -4
- package/src/components/booking/PickupLocationDialog.tsx +63 -59
- package/src/components/booking/PickupLocationSelector.tsx +20 -25
- package/src/components/booking/PriceSummary.module.css +19 -0
- package/src/components/booking/PriceSummary.tsx +10 -7
- package/src/components/booking/TourDescription.module.css +6 -1
- package/src/components/booking/TourDescription.tsx +25 -16
- package/src/components/booking/change-booking-compare.module.css +154 -0
- package/src/components/booking/change-booking-compare.tsx +141 -1
- package/src/components/booking/pickup-location-product.ts +24 -0
- package/src/constants/images.ts +1 -1
- package/src/index.ts +11 -0
- package/src/lib/booking/pickup-location-disclaimer.ts +69 -0
- package/src/lib/booking-api.ts +1 -0
- package/src/strings/en.json +140 -68
- package/src/strings/es.json +181 -68
- package/src/strings/fr.json +181 -68
- package/test/change-booking-helpers.test.ts +38 -0
- package/test/pickup-location-disclaimer.test.ts +44 -0
|
@@ -95,3 +95,157 @@
|
|
|
95
95
|
line-height: 1.2;
|
|
96
96
|
color: var(--primary-text, var(--booking-text, #1c1917));
|
|
97
97
|
}
|
|
98
|
+
|
|
99
|
+
.mobileDigest {
|
|
100
|
+
display: none;
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
@media (max-width: 767px) {
|
|
104
|
+
.kickerMobileHidden {
|
|
105
|
+
display: none;
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
.mobileDigest {
|
|
109
|
+
display: block;
|
|
110
|
+
padding: 0 0.25rem;
|
|
111
|
+
font-family: 'Figtree', var(--booking-font-sans, ui-sans-serif), sans-serif;
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
.mobileDigest .mobileDigestToggle {
|
|
115
|
+
display: block;
|
|
116
|
+
width: 100%;
|
|
117
|
+
min-height: 2.75rem;
|
|
118
|
+
margin: 0;
|
|
119
|
+
padding: 0.625rem 0.75rem;
|
|
120
|
+
border: 0;
|
|
121
|
+
border-radius: 0.75rem;
|
|
122
|
+
background: transparent;
|
|
123
|
+
color: var(--primary-text, var(--booking-text, #1c1917));
|
|
124
|
+
font: inherit;
|
|
125
|
+
text-align: left;
|
|
126
|
+
cursor: pointer;
|
|
127
|
+
appearance: none;
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
.mobileDigest .mobileDigestToggle:focus-visible {
|
|
131
|
+
outline: 2px solid var(--accent-orange, #ff4d00);
|
|
132
|
+
outline-offset: 2px;
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
.mobileDigestExpanded .mobileDigestToggle {
|
|
136
|
+
border-radius: 0.75rem 0.75rem 0 0;
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
.mobileDigestHeading,
|
|
140
|
+
.mobileDigestAction,
|
|
141
|
+
.mobileDigestLine,
|
|
142
|
+
.mobileDigestTotalLine {
|
|
143
|
+
display: flex;
|
|
144
|
+
align-items: baseline;
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
.mobileDigestHeading {
|
|
148
|
+
justify-content: space-between;
|
|
149
|
+
gap: 0.75rem;
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
.mobileDigestKicker {
|
|
153
|
+
font-size: 0.625rem;
|
|
154
|
+
font-weight: 700;
|
|
155
|
+
letter-spacing: 0.07em;
|
|
156
|
+
line-height: 1.2;
|
|
157
|
+
text-transform: uppercase;
|
|
158
|
+
color: var(--grey-text, var(--booking-text-muted, #78716c));
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
.mobileDigestAction {
|
|
162
|
+
flex-shrink: 0;
|
|
163
|
+
gap: 0.125rem;
|
|
164
|
+
font-size: 0.75rem;
|
|
165
|
+
font-weight: 600;
|
|
166
|
+
line-height: 1.2;
|
|
167
|
+
color: var(--accent-orange, #ff4d00);
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
.mobileDigestChevron {
|
|
171
|
+
flex-shrink: 0;
|
|
172
|
+
align-self: center;
|
|
173
|
+
transition: transform 160ms ease;
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
.mobileDigestChevronExpanded {
|
|
177
|
+
transform: rotate(180deg);
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
.mobileDigestChanges {
|
|
181
|
+
display: grid;
|
|
182
|
+
gap: 0.125rem;
|
|
183
|
+
margin-top: 0.375rem;
|
|
184
|
+
font-size: 0.8125rem;
|
|
185
|
+
line-height: 1.3;
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
.mobileDigestLine {
|
|
189
|
+
min-width: 0;
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
.mobileDigestArrow {
|
|
193
|
+
margin: 0 0.35rem;
|
|
194
|
+
color: var(--grey-text, var(--booking-text-muted, #78716c));
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
.mobileDigestNewValue {
|
|
198
|
+
font-weight: 700;
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
.mobileDigestMuted {
|
|
202
|
+
color: var(--grey-text, var(--booking-text-muted, #78716c));
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
.mobileDigestTotalLine {
|
|
206
|
+
justify-content: space-between;
|
|
207
|
+
gap: 0.75rem;
|
|
208
|
+
padding-top: 0.125rem;
|
|
209
|
+
font-variant-numeric: tabular-nums;
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
.deltaIncrease,
|
|
213
|
+
.deltaDecrease,
|
|
214
|
+
.deltaSame {
|
|
215
|
+
flex-shrink: 0;
|
|
216
|
+
font-weight: 700;
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
.deltaIncrease {
|
|
220
|
+
color: var(--accent-orange, #ff4d00);
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
.deltaDecrease {
|
|
224
|
+
color: var(--booking-emerald-700, #047857);
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
.deltaSame {
|
|
228
|
+
color: var(--grey-text, var(--booking-text-muted, #78716c));
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
.mobileDigestBaseline {
|
|
232
|
+
display: block;
|
|
233
|
+
margin-top: 0.375rem;
|
|
234
|
+
font-size: 0.8125rem;
|
|
235
|
+
font-weight: 500;
|
|
236
|
+
line-height: 1.3;
|
|
237
|
+
font-variant-numeric: tabular-nums;
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
.visuallyHidden {
|
|
241
|
+
position: absolute;
|
|
242
|
+
width: 1px;
|
|
243
|
+
height: 1px;
|
|
244
|
+
padding: 0;
|
|
245
|
+
margin: -1px;
|
|
246
|
+
overflow: hidden;
|
|
247
|
+
clip: rect(0, 0, 0, 0);
|
|
248
|
+
white-space: nowrap;
|
|
249
|
+
border: 0;
|
|
250
|
+
}
|
|
251
|
+
}
|
|
@@ -6,6 +6,8 @@ export type ItineraryStepLine = { time: string | null; label: string };
|
|
|
6
6
|
|
|
7
7
|
export type ChangeHighlightVariant = 'current' | 'new';
|
|
8
8
|
|
|
9
|
+
export type ChangePriceDeltaDirection = 'increase' | 'decrease' | 'same' | null;
|
|
10
|
+
|
|
9
11
|
/** Same date formatting as manage-booking / ChangeBookingDialog (Mountain Time label). */
|
|
10
12
|
export function formatBookingDateForChangeCompare(dateTime: string | null | undefined): string {
|
|
11
13
|
if (!dateTime) return '—';
|
|
@@ -102,6 +104,7 @@ export function BookingChangeSummaryColumn({
|
|
|
102
104
|
dateChanged = false,
|
|
103
105
|
ticketsChanged = false,
|
|
104
106
|
itineraryStepChanged,
|
|
107
|
+
hideKickerOnMobile = false,
|
|
105
108
|
}: {
|
|
106
109
|
kicker: string;
|
|
107
110
|
tourName: string;
|
|
@@ -114,6 +117,7 @@ export function BookingChangeSummaryColumn({
|
|
|
114
117
|
dateChanged?: boolean;
|
|
115
118
|
ticketsChanged?: boolean;
|
|
116
119
|
itineraryStepChanged?: boolean[];
|
|
120
|
+
hideKickerOnMobile?: boolean;
|
|
117
121
|
}) {
|
|
118
122
|
const dateClass =
|
|
119
123
|
highlightVariant === 'current' && dateChanged
|
|
@@ -130,7 +134,11 @@ export function BookingChangeSummaryColumn({
|
|
|
130
134
|
|
|
131
135
|
return (
|
|
132
136
|
<div className={`booking-change-summary-column ${styles.column}`}>
|
|
133
|
-
<p
|
|
137
|
+
<p
|
|
138
|
+
className={`${styles.kicker} ${hideKickerOnMobile ? styles.kickerMobileHidden : ''}`}
|
|
139
|
+
>
|
|
140
|
+
{kicker}
|
|
141
|
+
</p>
|
|
134
142
|
|
|
135
143
|
{/* Same pattern as manage-booking `BookingDetails`: label + value on one baseline row */}
|
|
136
144
|
<div className={styles.row}>
|
|
@@ -226,3 +234,135 @@ export function BookingChangeSummaryColumn({
|
|
|
226
234
|
</div>
|
|
227
235
|
);
|
|
228
236
|
}
|
|
237
|
+
|
|
238
|
+
export function MobileBookingChangeDigest({
|
|
239
|
+
expanded,
|
|
240
|
+
detailsId,
|
|
241
|
+
showChanges,
|
|
242
|
+
currentDate,
|
|
243
|
+
newDate,
|
|
244
|
+
currentTickets,
|
|
245
|
+
newTickets,
|
|
246
|
+
currentTotal,
|
|
247
|
+
newTotal,
|
|
248
|
+
dateChanged,
|
|
249
|
+
ticketsChanged,
|
|
250
|
+
itineraryChangeCount,
|
|
251
|
+
priceDeltaFormatted,
|
|
252
|
+
priceDeltaDirection,
|
|
253
|
+
pricePending,
|
|
254
|
+
onToggle,
|
|
255
|
+
}: {
|
|
256
|
+
expanded: boolean;
|
|
257
|
+
detailsId: string;
|
|
258
|
+
showChanges: boolean;
|
|
259
|
+
currentDate: string;
|
|
260
|
+
newDate: string;
|
|
261
|
+
currentTickets: string;
|
|
262
|
+
newTickets: string;
|
|
263
|
+
currentTotal: string;
|
|
264
|
+
newTotal: string;
|
|
265
|
+
dateChanged: boolean;
|
|
266
|
+
ticketsChanged: boolean;
|
|
267
|
+
itineraryChangeCount: number;
|
|
268
|
+
priceDeltaFormatted: string | null;
|
|
269
|
+
priceDeltaDirection: ChangePriceDeltaDirection;
|
|
270
|
+
pricePending: boolean;
|
|
271
|
+
onToggle: () => void;
|
|
272
|
+
}) {
|
|
273
|
+
const actionLabel = expanded ? 'Hide details' : showChanges ? 'Review changes' : 'View details';
|
|
274
|
+
const deltaClass =
|
|
275
|
+
priceDeltaDirection === 'increase'
|
|
276
|
+
? styles.deltaIncrease
|
|
277
|
+
: priceDeltaDirection === 'decrease'
|
|
278
|
+
? styles.deltaDecrease
|
|
279
|
+
: styles.deltaSame;
|
|
280
|
+
|
|
281
|
+
return (
|
|
282
|
+
<div
|
|
283
|
+
className={`${styles.mobileDigest} ${expanded ? styles.mobileDigestExpanded : ''}`}
|
|
284
|
+
>
|
|
285
|
+
<button
|
|
286
|
+
type="button"
|
|
287
|
+
className={styles.mobileDigestToggle}
|
|
288
|
+
aria-expanded={expanded}
|
|
289
|
+
aria-controls={detailsId}
|
|
290
|
+
onClick={onToggle}
|
|
291
|
+
>
|
|
292
|
+
<span className={styles.mobileDigestHeading}>
|
|
293
|
+
<span className={styles.mobileDigestKicker}>
|
|
294
|
+
{showChanges ? 'Your changes' : 'Current booking'}
|
|
295
|
+
</span>
|
|
296
|
+
<span className={styles.mobileDigestAction}>
|
|
297
|
+
{actionLabel}
|
|
298
|
+
<svg
|
|
299
|
+
aria-hidden="true"
|
|
300
|
+
className={`${styles.mobileDigestChevron} ${expanded ? styles.mobileDigestChevronExpanded : ''}`}
|
|
301
|
+
width="16"
|
|
302
|
+
height="16"
|
|
303
|
+
viewBox="0 0 20 20"
|
|
304
|
+
fill="none"
|
|
305
|
+
>
|
|
306
|
+
<path
|
|
307
|
+
d="m5 7.5 5 5 5-5"
|
|
308
|
+
stroke="currentColor"
|
|
309
|
+
strokeWidth="1.75"
|
|
310
|
+
strokeLinecap="round"
|
|
311
|
+
strokeLinejoin="round"
|
|
312
|
+
/>
|
|
313
|
+
</svg>
|
|
314
|
+
</span>
|
|
315
|
+
</span>
|
|
316
|
+
|
|
317
|
+
{showChanges ? (
|
|
318
|
+
<span className={styles.mobileDigestChanges}>
|
|
319
|
+
{dateChanged ? (
|
|
320
|
+
<span className={styles.mobileDigestLine}>
|
|
321
|
+
<span>{currentDate}</span>
|
|
322
|
+
<span className={styles.mobileDigestArrow} aria-hidden="true">
|
|
323
|
+
→
|
|
324
|
+
</span>
|
|
325
|
+
<span className={styles.visuallyHidden}>changes to</span>
|
|
326
|
+
<span className={styles.mobileDigestNewValue}>{newDate}</span>
|
|
327
|
+
</span>
|
|
328
|
+
) : null}
|
|
329
|
+
{ticketsChanged ? (
|
|
330
|
+
<span className={styles.mobileDigestLine}>
|
|
331
|
+
<span>{currentTickets}</span>
|
|
332
|
+
<span className={styles.mobileDigestArrow} aria-hidden="true">
|
|
333
|
+
→
|
|
334
|
+
</span>
|
|
335
|
+
<span className={styles.visuallyHidden}>changes to</span>
|
|
336
|
+
<span className={styles.mobileDigestNewValue}>{newTickets}</span>
|
|
337
|
+
</span>
|
|
338
|
+
) : null}
|
|
339
|
+
{itineraryChangeCount > 0 ? (
|
|
340
|
+
<span className={styles.mobileDigestMuted}>
|
|
341
|
+
{itineraryChangeCount}{' '}
|
|
342
|
+
{itineraryChangeCount === 1 ? 'itinerary update' : 'itinerary updates'}
|
|
343
|
+
</span>
|
|
344
|
+
) : null}
|
|
345
|
+
<span className={styles.mobileDigestTotalLine}>
|
|
346
|
+
<span>
|
|
347
|
+
{currentTotal}
|
|
348
|
+
<span className={styles.mobileDigestArrow} aria-hidden="true">
|
|
349
|
+
→
|
|
350
|
+
</span>
|
|
351
|
+
<span className={styles.visuallyHidden}>changes to</span>
|
|
352
|
+
<span className={styles.mobileDigestNewValue}>{newTotal}</span>
|
|
353
|
+
</span>
|
|
354
|
+
<span className={pricePending ? styles.deltaSame : deltaClass}>
|
|
355
|
+
{pricePending ? 'Updating price…' : priceDeltaFormatted}
|
|
356
|
+
</span>
|
|
357
|
+
</span>
|
|
358
|
+
</span>
|
|
359
|
+
) : (
|
|
360
|
+
<span className={styles.mobileDigestBaseline}>
|
|
361
|
+
{currentDate} <span aria-hidden="true">·</span> {currentTickets}{' '}
|
|
362
|
+
<span aria-hidden="true">·</span> {currentTotal}
|
|
363
|
+
</span>
|
|
364
|
+
)}
|
|
365
|
+
</button>
|
|
366
|
+
</div>
|
|
367
|
+
);
|
|
368
|
+
}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import type { Product } from '../../lib/booking-api';
|
|
2
|
+
|
|
3
|
+
export function findProductForPickupLocations(
|
|
4
|
+
products: Product[],
|
|
5
|
+
bookingProductId: string,
|
|
6
|
+
): Product | null {
|
|
7
|
+
for (const product of products) {
|
|
8
|
+
if (product.productId === bookingProductId) return product;
|
|
9
|
+
if (product.pickupLocations?.some((location) => location.id === bookingProductId)) {
|
|
10
|
+
return product;
|
|
11
|
+
}
|
|
12
|
+
if (product.options?.some((option) => option.optionId === bookingProductId)) return product;
|
|
13
|
+
}
|
|
14
|
+
return null;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
/** Keep manage-booking pickup choices aligned with the normal booking flow's static catalog. */
|
|
18
|
+
export function resolvePickupLocationProduct(
|
|
19
|
+
staticProduct: Product | null,
|
|
20
|
+
liveProducts: Product[],
|
|
21
|
+
bookingProductId: string,
|
|
22
|
+
): Product | null {
|
|
23
|
+
return staticProduct ?? findProductForPickupLocations(liveProducts, bookingProductId);
|
|
24
|
+
}
|
package/src/constants/images.ts
CHANGED
package/src/index.ts
CHANGED
|
@@ -64,6 +64,17 @@ export { default as BookingProductGrid } from './components/booking/BookingProdu
|
|
|
64
64
|
export { DefaultTermsContent as TermsContent } from './components/booking/DefaultTermsContent';
|
|
65
65
|
export { BackgroundVideo } from './components/BackgroundVideo';
|
|
66
66
|
export type { BackgroundVideoLoading, BackgroundVideoProps } from './components/BackgroundVideo';
|
|
67
|
+
export {
|
|
68
|
+
BookingFlowCollage,
|
|
69
|
+
type BookingFlowCollageProps,
|
|
70
|
+
} from './components/booking/BookingFlowCollage';
|
|
71
|
+
export {
|
|
72
|
+
TourDescription,
|
|
73
|
+
type TourDescriptionProps,
|
|
74
|
+
type TourDescriptionReview,
|
|
75
|
+
type TourDescriptionSection,
|
|
76
|
+
type TourDescriptionSubsection,
|
|
77
|
+
} from './components/booking/TourDescription';
|
|
67
78
|
|
|
68
79
|
export type {
|
|
69
80
|
BookingAppMode,
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
export interface PickupLocationDisclaimerInput {
|
|
2
|
+
id?: string | null;
|
|
3
|
+
name?: string | null;
|
|
4
|
+
disclaimer?: string | null;
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
export interface PickupLocationDisclaimer {
|
|
8
|
+
title: string;
|
|
9
|
+
message: string;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
const SAMSON_MALL_PICKUP_LOCATION_ID = 'loc_afkvmlNRwRqZ';
|
|
13
|
+
const SAMSON_MALL_PICKUP_LOCATION_NAME = 'samson mall';
|
|
14
|
+
|
|
15
|
+
const LAKE_LOUISE_HOTEL_PICKUP_LOCATIONS = new Map([
|
|
16
|
+
['loc_Ll05oVACjjAx', 'HI Lake Louise Alpine Centre'],
|
|
17
|
+
['loc_VAJ0L8amxnC5', 'Fairmont Lake Louise'],
|
|
18
|
+
['loc_arPLLVG1xKxw', 'Mountaineer Lodge'],
|
|
19
|
+
['loc_9ObwCZ7MxfjC', 'Paradise Lodge and Bungalows'],
|
|
20
|
+
['loc_ieW6EfdVeYd4', 'Post Hotel'],
|
|
21
|
+
]);
|
|
22
|
+
|
|
23
|
+
const LAKE_LOUISE_HOTEL_NAMES = new Set(
|
|
24
|
+
Array.from(LAKE_LOUISE_HOTEL_PICKUP_LOCATIONS.values(), (name) =>
|
|
25
|
+
name.toLowerCase(),
|
|
26
|
+
),
|
|
27
|
+
);
|
|
28
|
+
|
|
29
|
+
const SAMSON_MALL_PARKING_DISCLAIMER =
|
|
30
|
+
'No public parking at this pickup location. This pickup location is meant to serve guests staying at the HI Lake Louise Alpine Hostel, Lake Louise Inn, or Lake Louise Campground and can walk to Samson Mall for pickup due to parking restrictions in the town of Lake Louise.';
|
|
31
|
+
|
|
32
|
+
export function getPickupLocationDisclaimer(
|
|
33
|
+
location: PickupLocationDisclaimerInput,
|
|
34
|
+
): PickupLocationDisclaimer | null {
|
|
35
|
+
const objectDisclaimer = location.disclaimer?.trim();
|
|
36
|
+
if (objectDisclaimer) {
|
|
37
|
+
return {
|
|
38
|
+
title: 'Pickup location note',
|
|
39
|
+
message: objectDisclaimer,
|
|
40
|
+
};
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
const normalizedName = location.name?.trim().toLowerCase() ?? '';
|
|
44
|
+
|
|
45
|
+
if (
|
|
46
|
+
location.id === SAMSON_MALL_PICKUP_LOCATION_ID ||
|
|
47
|
+
normalizedName === SAMSON_MALL_PICKUP_LOCATION_NAME
|
|
48
|
+
) {
|
|
49
|
+
return {
|
|
50
|
+
title: 'Samson Mall pickup note',
|
|
51
|
+
message: SAMSON_MALL_PARKING_DISCLAIMER,
|
|
52
|
+
};
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
const hotelName =
|
|
56
|
+
(location.id
|
|
57
|
+
? LAKE_LOUISE_HOTEL_PICKUP_LOCATIONS.get(location.id)
|
|
58
|
+
: undefined) ??
|
|
59
|
+
(LAKE_LOUISE_HOTEL_NAMES.has(normalizedName)
|
|
60
|
+
? location.name?.trim()
|
|
61
|
+
: undefined);
|
|
62
|
+
|
|
63
|
+
if (!hotelName) return null;
|
|
64
|
+
|
|
65
|
+
return {
|
|
66
|
+
title: 'Hotel guests only',
|
|
67
|
+
message: `This pickup location is only available to guests staying at ${hotelName}. There is no public parking for shuttle guests anywhere in Lake Louise.`,
|
|
68
|
+
};
|
|
69
|
+
}
|
package/src/lib/booking-api.ts
CHANGED