@ticketboothapp/booking 1.2.50 → 1.2.54
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 +7 -2
- package/src/constants/pill-values.ts +210 -0
- package/src/constants/products.ts +155 -30
- package/src/data/product-descriptions/afternoon-delight.en.json +35 -0
- package/src/data/product-descriptions/emerald-lake-escape.en.json +68 -0
- package/src/data/product-descriptions/lake-louise-adventure.en.json +74 -0
- package/src/data/product-descriptions/moraine-lake-adventure.en.json +78 -0
- package/src/data/product-descriptions/moraine-lake-sunrise-lake-louise-golden-hour.en.json +65 -0
- package/src/data/product-descriptions/moraine-lake-sunrise.en.json +64 -0
- package/src/data/product-descriptions/private-tour.en.json +80 -0
- package/src/data/product-descriptions/two-lakes-combo.en.json +65 -0
- package/src/data/products-config.json +101 -0
- package/src/lib/product-descriptions.ts +66 -0
- package/src/lib/products-config.ts +73 -0
- package/ticketboothapp-booking-1.2.50.tgz +0 -0
- package/ticketboothapp-booking-1.2.51.tgz +0 -0
- package/ticketboothapp-booking-1.2.52.tgz +0 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ticketboothapp/booking",
|
|
3
|
-
"version": "1.2.
|
|
3
|
+
"version": "1.2.54",
|
|
4
4
|
"private": false,
|
|
5
5
|
"sideEffects": [
|
|
6
6
|
"**/*.css",
|
|
@@ -16,7 +16,12 @@
|
|
|
16
16
|
"./contexts/booking-app-context": "./src/contexts/BookingAppContext.tsx",
|
|
17
17
|
"./providers/booking-dialog-provider": "./src/providers/booking-dialog-provider.tsx",
|
|
18
18
|
"./hooks/useBookingSourceMetadataFromLocation": "./src/hooks/useBookingSourceMetadataFromLocation.ts",
|
|
19
|
-
"./hooks/useIsBookingLaunchLive": "./src/hooks/useIsBookingLaunchLive.ts"
|
|
19
|
+
"./hooks/useIsBookingLaunchLive": "./src/hooks/useIsBookingLaunchLive.ts",
|
|
20
|
+
"./viavia/catalog": "./src/constants/products.ts",
|
|
21
|
+
"./viavia/images": "./src/constants/images.ts",
|
|
22
|
+
"./viavia/product-descriptions": "./src/lib/product-descriptions.ts",
|
|
23
|
+
"./viavia/products-config": "./src/lib/products-config.ts",
|
|
24
|
+
"./viavia/strings": "./src/strings/index.js"
|
|
20
25
|
},
|
|
21
26
|
"peerDependencies": {
|
|
22
27
|
"next": "^15.0.0",
|
|
@@ -0,0 +1,210 @@
|
|
|
1
|
+
const busIconPath = '/pill-value-icons/bus-icon.svg';
|
|
2
|
+
const clockIconPath = '/pill-value-icons/clock-icon.svg';
|
|
3
|
+
const sunriseIconPath = '/pill-value-icons/sun-icon.svg';
|
|
4
|
+
const cameraIconPath = '/pill-value-icons/camera-icon.svg';
|
|
5
|
+
const moneyIconPath = '/pill-value-icons/money-icon.svg';
|
|
6
|
+
const doubleCheckIconPath = '/pill-value-icons/double-check-icon.svg';
|
|
7
|
+
const hikerIconPath = '/pill-value-icons/hiker-icon.svg';
|
|
8
|
+
const waterIconPath = '/pill-value-icons/water-icon.svg';
|
|
9
|
+
const lunchIconPath = '/pill-value-icons/lunch-icon.svg';
|
|
10
|
+
const croissantIconPath = '/pill-value-icons/croissant-icon.svg';
|
|
11
|
+
const locationPinIconPath = '/pill-value-icons/location-pin-icon.svg';
|
|
12
|
+
const addTimeIconPath = '/pill-value-icons/add-time-icon.svg';
|
|
13
|
+
const coffeeIconPath = '/pill-value-icons/coffee-icon.svg';
|
|
14
|
+
const blanketIconPath = '/pill-value-icons/blanket-icon.svg';
|
|
15
|
+
import defaultStrings from '../strings';
|
|
16
|
+
import { ProductKey } from './products';
|
|
17
|
+
|
|
18
|
+
export type PillValue = {
|
|
19
|
+
icon: string;
|
|
20
|
+
label: string;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export function createDeparturePillValue(productKey: ProductKey, strings = defaultStrings): PillValue {
|
|
24
|
+
return {
|
|
25
|
+
icon: busIconPath,
|
|
26
|
+
label: getDepartureLabel(productKey, strings)
|
|
27
|
+
};
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
function getDepartureLabel(productKey: ProductKey, strings: any): string {
|
|
31
|
+
switch (productKey) {
|
|
32
|
+
case 'two-lakes-combo':
|
|
33
|
+
return strings.pillValues.departurePillValues.twoLakesCombo;
|
|
34
|
+
case 'moraine-lake-adventure':
|
|
35
|
+
return strings.pillValues.departurePillValues.moraineLakeAdventure;
|
|
36
|
+
case 'lake-louise-adventure':
|
|
37
|
+
return strings.pillValues.departurePillValues.lakeLouiseAdventure;
|
|
38
|
+
case 'emerald-lake-escape':
|
|
39
|
+
return strings.pillValues.departurePillValues.emeraldLakeEscapeTour;
|
|
40
|
+
case 'private-tour':
|
|
41
|
+
return strings.pillValues.departurePillValues.privateTour;
|
|
42
|
+
case 'afternoon-delight':
|
|
43
|
+
return strings.pillValues.departurePillValues.afternoonDelight;
|
|
44
|
+
default:
|
|
45
|
+
return '';
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
export function createDurationPillValue(productKey: ProductKey, strings = defaultStrings): PillValue {
|
|
50
|
+
return {
|
|
51
|
+
icon: clockIconPath,
|
|
52
|
+
label: getDurationLabel(productKey, strings)
|
|
53
|
+
};
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
function getDurationLabel(productKey: ProductKey, strings: any): string {
|
|
57
|
+
switch (productKey) {
|
|
58
|
+
case 'moraine-lake-sunrise':
|
|
59
|
+
return strings.pillValues.durationPillValues.moraineLakeSunrise;
|
|
60
|
+
case 'moraine-lake-sunrise-lake-louise-golden-hour-1':
|
|
61
|
+
return strings.pillValues.durationPillValues.moraineLakeSunriseLakeLouiseGoldenHour1;
|
|
62
|
+
case 'moraine-lake-sunrise-lake-louise-golden-hour-2':
|
|
63
|
+
return strings.pillValues.durationPillValues.moraineLakeSunriseLakeLouiseGoldenHour2;
|
|
64
|
+
case 'two-lakes-combo-1':
|
|
65
|
+
return strings.pillValues.durationPillValues.twoLakesCombo1;
|
|
66
|
+
case 'two-lakes-combo-2':
|
|
67
|
+
return strings.pillValues.durationPillValues.twoLakesCombo2;
|
|
68
|
+
case 'moraine-lake-adventure':
|
|
69
|
+
return strings.pillValues.durationPillValues.moraineLakeAdventure;
|
|
70
|
+
case 'lake-louise-adventure':
|
|
71
|
+
return strings.pillValues.durationPillValues.lakeLouiseAdventure;
|
|
72
|
+
case 'emerald-lake-escape':
|
|
73
|
+
return strings.pillValues.durationPillValues.emeraldLakeEscapeTour;
|
|
74
|
+
case 'private-tour':
|
|
75
|
+
return strings.pillValues.durationPillValues.privateTour;
|
|
76
|
+
case 'afternoon-delight1':
|
|
77
|
+
return strings.pillValues.durationPillValues.afternoonDelight1;
|
|
78
|
+
case 'afternoon-delight2':
|
|
79
|
+
return strings.pillValues.durationPillValues.afternoonDelight2;
|
|
80
|
+
default:
|
|
81
|
+
return '';
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
export function createAddTimePillValue(productKey: ProductKey, strings = defaultStrings): PillValue {
|
|
86
|
+
return {
|
|
87
|
+
icon: addTimeIconPath,
|
|
88
|
+
label: getAddTimeLabel(productKey, strings)
|
|
89
|
+
};
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
function getAddTimeLabel(productKey: ProductKey, strings: any): string {
|
|
93
|
+
switch (productKey) {
|
|
94
|
+
case 'moraine-lake-sunrise':
|
|
95
|
+
return strings.pillValues.addTimePillValues.moraineLakeSunrise;
|
|
96
|
+
case 'moraine-lake-sunrise-lake-louise-golden-hour':
|
|
97
|
+
return strings.pillValues.addTimePillValues.moraineLakeSunriseLakeLouiseGoldenHour;
|
|
98
|
+
case 'two-lakes-combo':
|
|
99
|
+
return strings.pillValues.addTimePillValues.twoLakesCombo;
|
|
100
|
+
case 'moraine-lake-adventure':
|
|
101
|
+
return strings.pillValues.addTimePillValues.moraineLakeAdventure;
|
|
102
|
+
case 'lake-louise-adventure':
|
|
103
|
+
return strings.pillValues.addTimePillValues.lakeLouiseAdventure;
|
|
104
|
+
case 'emerald-lake-escape':
|
|
105
|
+
return strings.pillValues.addTimePillValues.emeraldLakeEscapeTour;
|
|
106
|
+
case 'private-tour':
|
|
107
|
+
return strings.pillValues.addTimePillValues.privateTour;
|
|
108
|
+
default:
|
|
109
|
+
return '';
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
export function createMoneyPillValue(productKey: ProductKey, strings = defaultStrings): PillValue {
|
|
114
|
+
return {
|
|
115
|
+
icon: moneyIconPath,
|
|
116
|
+
label: getMoneyLabel(productKey, strings)
|
|
117
|
+
};
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
function getMoneyLabel(productKey: ProductKey, strings: any): string {
|
|
121
|
+
switch (productKey) {
|
|
122
|
+
case 'moraine-lake-sunrise':
|
|
123
|
+
return strings.pillValues.moneyPillValues.moraineLakeSunrise;
|
|
124
|
+
case 'moraine-lake-sunrise-lake-louise-golden-hour':
|
|
125
|
+
return strings.pillValues.moneyPillValues.moraineLakeSunriseLakeLouiseGoldenHour;
|
|
126
|
+
case 'two-lakes-combo':
|
|
127
|
+
return strings.pillValues.moneyPillValues.twoLakesCombo;
|
|
128
|
+
case 'moraine-lake-adventure':
|
|
129
|
+
return strings.pillValues.moneyPillValues.moraineLakeAdventure;
|
|
130
|
+
case 'lake-louise-adventure':
|
|
131
|
+
return strings.pillValues.moneyPillValues.lakeLouiseAdventure;
|
|
132
|
+
case 'emerald-lake-escape':
|
|
133
|
+
return strings.pillValues.moneyPillValues.emeraldLakeEscapeTour;
|
|
134
|
+
case 'private-tour':
|
|
135
|
+
return strings.pillValues.moneyPillValues.privateTour;
|
|
136
|
+
case 'afternoon-delight':
|
|
137
|
+
return strings.pillValues.moneyPillValues.afternoonDelight;
|
|
138
|
+
default:
|
|
139
|
+
return '';
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
export function createemeraldLakeEscapeTourLocationsPillValues(strings = defaultStrings): PillValue[] {
|
|
144
|
+
return Object.values(strings.pillValues.emeraldLakeEscapeTourLocations).map(location => ({
|
|
145
|
+
icon: locationPinIconPath,
|
|
146
|
+
label: location as string
|
|
147
|
+
}));
|
|
148
|
+
}
|
|
149
|
+
export const createSunrisePillValue = (strings = defaultStrings): PillValue => {
|
|
150
|
+
return {
|
|
151
|
+
icon: sunriseIconPath,
|
|
152
|
+
label: strings.pillValues.sunrise
|
|
153
|
+
};
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
export const createTwoLakesInOnePillValue = (strings = defaultStrings): PillValue => {
|
|
157
|
+
return {
|
|
158
|
+
icon: doubleCheckIconPath,
|
|
159
|
+
label: strings.pillValues.twoLakesInOne
|
|
160
|
+
};
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
export const createPhotographyPillValue = (strings = defaultStrings): PillValue => {
|
|
164
|
+
return {
|
|
165
|
+
icon: cameraIconPath,
|
|
166
|
+
label: strings.pillValues.photography
|
|
167
|
+
};
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
export const createHikePillValue = (strings = defaultStrings): PillValue => {
|
|
171
|
+
return {
|
|
172
|
+
icon: hikerIconPath,
|
|
173
|
+
label: strings.pillValues.hike
|
|
174
|
+
};
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
export const createCanoePillValue = (strings = defaultStrings): PillValue => {
|
|
178
|
+
return {
|
|
179
|
+
icon: waterIconPath,
|
|
180
|
+
label: strings.pillValues.canoe
|
|
181
|
+
};
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
export const createLunchPillValue = (strings = defaultStrings): PillValue => {
|
|
185
|
+
return {
|
|
186
|
+
icon: lunchIconPath,
|
|
187
|
+
label: strings.pillValues.lunch
|
|
188
|
+
};
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
export const createCroissantPillValue = (strings = defaultStrings): PillValue => {
|
|
192
|
+
return {
|
|
193
|
+
icon: croissantIconPath,
|
|
194
|
+
label: strings.pillValues.croissant
|
|
195
|
+
};
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
export const createHotDrinksPillValue = (strings = defaultStrings): PillValue => {
|
|
199
|
+
return {
|
|
200
|
+
icon: coffeeIconPath,
|
|
201
|
+
label: strings.pillValues.hotDrinks
|
|
202
|
+
};
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
export const createCozyBlanketsPillValue = (strings = defaultStrings): PillValue => {
|
|
206
|
+
return {
|
|
207
|
+
icon: blanketIconPath,
|
|
208
|
+
label: strings.pillValues.blankets
|
|
209
|
+
};
|
|
210
|
+
}
|
|
@@ -1,33 +1,158 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
shortWebm?: string;
|
|
8
|
-
};
|
|
1
|
+
import { ImageData, IMAGES } from './images';
|
|
2
|
+
import { PillValue, createDeparturePillValue, createDurationPillValue, createSunrisePillValue, createTwoLakesInOnePillValue, createHikePillValue, createCanoePillValue, createMoneyPillValue, createAddTimePillValue, createHotDrinksPillValue, createLunchPillValue, createCroissantPillValue, createemeraldLakeEscapeTourLocationsPillValues, createCozyBlanketsPillValue } from './pill-values';
|
|
3
|
+
export enum ProductTagStyle {
|
|
4
|
+
MOST_POPULAR = 'most-popular',
|
|
5
|
+
NEW = 'new',
|
|
6
|
+
}
|
|
9
7
|
|
|
10
|
-
export
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
}
|
|
8
|
+
export interface ProductTag {
|
|
9
|
+
text: string;
|
|
10
|
+
style: ProductTagStyle;
|
|
11
|
+
}
|
|
14
12
|
|
|
15
|
-
export
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
13
|
+
export interface VideoSources {
|
|
14
|
+
src: string;
|
|
15
|
+
webm: string;
|
|
16
|
+
/** Long version for BookingFlow collage. Falls back to short (src/webm) if omitted. */
|
|
17
|
+
longSrc?: string;
|
|
18
|
+
longWebm?: string;
|
|
19
|
+
}
|
|
19
20
|
|
|
20
|
-
export
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
21
|
+
export interface Product {
|
|
22
|
+
id: string;
|
|
23
|
+
name: string;
|
|
24
|
+
shortName: string;
|
|
25
|
+
images: readonly ImageData[];
|
|
26
|
+
bookingLink: string;
|
|
27
|
+
currentStartTime: string;
|
|
28
|
+
description: string;
|
|
29
|
+
path: string;
|
|
30
|
+
avgPrice: number;
|
|
31
|
+
pillValues: PillValue[];
|
|
32
|
+
tags?: ProductTag[];
|
|
33
|
+
/** Video for expanded view in booking dialog. Place mp4 and webm in public/videos/ named {productId}.mp4 and {productId}.webm */
|
|
34
|
+
videoUrl?: VideoSources;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
// Type for accessing product keys
|
|
38
|
+
export type ProductKey = keyof ReturnType<typeof getProducts>;
|
|
39
|
+
|
|
40
|
+
export const getProducts = (strings: any): Record<string, Product> => ({
|
|
41
|
+
MORAINE_LAKE_SUNRISE_LAKE_LOUISE_GOLDEN_HOUR: {
|
|
42
|
+
id: 'moraine-lake-sunrise-lake-louise-golden-hour',
|
|
43
|
+
videoUrl: { src: '/videos/moraine-lake-sunrise-lake-louise-golden-hour.mp4', webm: '/videos/moraine-lake-sunrise-lake-louise-golden-hour.webm', longSrc: '/videos/moraine-lake-sunrise-lake-louise-golden-hour-long.mp4', longWebm: '/videos/moraine-lake-sunrise-lake-louise-golden-hour-long.webm' },
|
|
44
|
+
name: strings.products.productNames.moraineLakeSunriseLakeLouiseGoldenHour,
|
|
45
|
+
shortName: strings.products.productShortNames.moraineLakeSunriseLakeLouiseGoldenHourShort,
|
|
46
|
+
images: [
|
|
47
|
+
IMAGES.MORAINE_LAKE_CANOES_SUNRISE,
|
|
48
|
+
],
|
|
49
|
+
bookingLink: '#book-now/moraine-lake-sunrise-lake-louise-golden-hour',
|
|
50
|
+
currentStartTime: strings.products.startTimes.moraineLakeSunriseLakeLouiseGoldenHour,
|
|
51
|
+
description: strings.productThemePages.sunriseTours.description,
|
|
52
|
+
path: '/moraine-lake-sunrise-shuttle',
|
|
53
|
+
avgPrice: 159,
|
|
54
|
+
pillValues: [createSunrisePillValue(strings), createDurationPillValue('moraine-lake-sunrise-lake-louise-golden-hour-1', strings), createDurationPillValue('moraine-lake-sunrise-lake-louise-golden-hour-2', strings), createAddTimePillValue('moraine-lake-sunrise-lake-louise-golden-hour', strings), createHotDrinksPillValue(strings), createCozyBlanketsPillValue(strings), createTwoLakesInOnePillValue(strings), createMoneyPillValue('moraine-lake-sunrise-lake-louise-golden-hour', strings)],
|
|
55
|
+
tags: [{
|
|
56
|
+
text: strings.products.productTags.mostPopular,
|
|
57
|
+
style: ProductTagStyle.MOST_POPULAR
|
|
58
|
+
}]
|
|
59
|
+
},
|
|
60
|
+
MORAINE_LAKE_SUNRISE: {
|
|
61
|
+
id: 'moraine-lake-sunrise',
|
|
62
|
+
videoUrl: { src: '/videos/moraine-lake-sunrise.mp4', webm: '/videos/moraine-lake-sunrise.webm', longSrc: '/videos/moraine-lake-sunrise-long.mp4', longWebm: '/videos/moraine-lake-sunrise-long.webm' },
|
|
63
|
+
name: strings.products.productNames.moraineLakeSunrise,
|
|
64
|
+
shortName: strings.products.productShortNames.moraineLakeSunriseShort,
|
|
65
|
+
images: [
|
|
66
|
+
IMAGES.MORAINE_LAKE_SUNRISE_CHEERS,
|
|
67
|
+
],
|
|
68
|
+
bookingLink: '#book-now/moraine-lake-sunrise',
|
|
69
|
+
currentStartTime: strings.products.startTimes.moraineLakeSunrise,
|
|
70
|
+
description: strings.productThemePages.sunriseTours.description,
|
|
71
|
+
path: '/moraine-lake-sunrise-shuttle',
|
|
72
|
+
avgPrice: 129,
|
|
73
|
+
pillValues: [createSunrisePillValue(strings), createDurationPillValue('moraine-lake-sunrise', strings), createAddTimePillValue('moraine-lake-sunrise', strings), createHotDrinksPillValue(strings), createCozyBlanketsPillValue(strings), createMoneyPillValue('moraine-lake-sunrise', strings)]
|
|
74
|
+
},
|
|
75
|
+
TWO_LAKES_COMBO: {
|
|
76
|
+
id: 'two-lakes-combo',
|
|
77
|
+
videoUrl: { src: '/videos/two-lakes-combo.mp4', webm: '/videos/two-lakes-combo.webm', longSrc: '/videos/two-lakes-combo-long.mp4', longWebm: '/videos/two-lakes-combo-long.webm' },
|
|
78
|
+
name: strings.products.productNames.twoLakesCombo,
|
|
79
|
+
shortName: strings.products.productShortNames.twoLakesComboShort,
|
|
80
|
+
images: [
|
|
81
|
+
IMAGES.MORAINE_LAKE_YELLOW_BIKINI,
|
|
82
|
+
],
|
|
83
|
+
bookingLink: '#book-now/two-lakes-combo',
|
|
84
|
+
currentStartTime: strings.products.startTimes.moraineLakeAdventure,
|
|
85
|
+
description: strings.products.productDescriptions.twoLakesCombo,
|
|
86
|
+
path: '/moraine-lake-shuttle',
|
|
87
|
+
avgPrice: 149,
|
|
88
|
+
pillValues: [createDeparturePillValue('two-lakes-combo', strings), createDurationPillValue('two-lakes-combo-1', strings), createDurationPillValue('two-lakes-combo-2', strings), createAddTimePillValue('two-lakes-combo', strings), createTwoLakesInOnePillValue(strings), createMoneyPillValue('two-lakes-combo', strings)],
|
|
89
|
+
tags: [{
|
|
90
|
+
text: strings.products.productTags.mostPopular,
|
|
91
|
+
style: ProductTagStyle.MOST_POPULAR
|
|
92
|
+
}]
|
|
93
|
+
},
|
|
94
|
+
MORAINE_LAKE_ADVENTURE: {
|
|
95
|
+
id: 'moraine-lake-adventure',
|
|
96
|
+
videoUrl: { src: '/videos/moraine-lake-adventure.mp4', webm: '/videos/moraine-lake-adventure.webm', longSrc: '/videos/moraine-lake-adventure-long.mp4', longWebm: '/videos/moraine-lake-adventure-long.webm' },
|
|
97
|
+
name: strings.products.productNames.moraineLakeAdventure,
|
|
98
|
+
shortName: strings.products.productShortNames.moraineLakeAdventureShort,
|
|
99
|
+
images: [
|
|
100
|
+
IMAGES.MORAINE_LAKE_CANOE,
|
|
101
|
+
],
|
|
102
|
+
bookingLink: '#book-now/moraine-lake-adventure',
|
|
103
|
+
currentStartTime: strings.products.startTimes.moraineLakeAdventure,
|
|
104
|
+
description: strings.productThemePages.moraineLakeShuttle.description,
|
|
105
|
+
path: '/moraine-lake-shuttle',
|
|
106
|
+
avgPrice: 95,
|
|
107
|
+
pillValues: [createDeparturePillValue('moraine-lake-adventure', strings), createDurationPillValue('moraine-lake-adventure', strings), createAddTimePillValue('moraine-lake-adventure', strings), createHikePillValue(strings), createCanoePillValue(strings), createMoneyPillValue('moraine-lake-adventure', strings)]
|
|
108
|
+
},
|
|
109
|
+
LAKE_LOUISE_ADVENTURE: {
|
|
110
|
+
id: 'lake-louise-adventure',
|
|
111
|
+
videoUrl: { src: '/videos/lake-louise-adventure.mp4', webm: '/videos/lake-louise-adventure.webm', longSrc: '/videos/lake-louise-adventure-long.mp4', longWebm: '/videos/lake-louise-adventure-long.webm' },
|
|
112
|
+
name: strings.products.productNames.lakeLouiseAdventure,
|
|
113
|
+
shortName: strings.products.productShortNames.lakeLouiseAdventureShort,
|
|
114
|
+
images: [
|
|
115
|
+
IMAGES.LAKE_LOUISE_FLORA,
|
|
116
|
+
],
|
|
117
|
+
bookingLink: '#book-now/lake-louise-adventure',
|
|
118
|
+
currentStartTime: strings.products.startTimes.lakeLouiseAdventure,
|
|
119
|
+
description: strings.productThemePages.lakeLouiseShuttle.description,
|
|
120
|
+
path: '/lake-louise-shuttle',
|
|
121
|
+
avgPrice: 69,
|
|
122
|
+
pillValues: [createDeparturePillValue('lake-louise-adventure', strings), createDurationPillValue('lake-louise-adventure', strings), createAddTimePillValue('lake-louise-adventure', strings), createHikePillValue(strings), createCanoePillValue(strings), createMoneyPillValue('lake-louise-adventure', strings)]
|
|
123
|
+
},
|
|
124
|
+
EMERALD_LAKE_ESCAPE: {
|
|
125
|
+
id: 'emerald-lake-escape',
|
|
126
|
+
videoUrl: { src: '/videos/emerald-lake-escape-tour.mp4', webm: '/videos/emerald-lake-escape-tour.webm', longSrc: '/videos/emerald-lake-escape-tour-long.mp4', longWebm: '/videos/emerald-lake-escape-tour-long.webm' },
|
|
127
|
+
name: strings.products.productNames.emeraldLakeEscapeTour,
|
|
128
|
+
shortName: strings.products.productShortNames.emeraldLakeEscapeTourShort,
|
|
129
|
+
images: [
|
|
130
|
+
IMAGES.EMERALD_LAKE_LODGE_VIEWPOINT,
|
|
131
|
+
],
|
|
132
|
+
bookingLink: '#book-now/emerald-lake-escape',
|
|
133
|
+
currentStartTime: strings.products.startTimes.emeraldLakeEscape,
|
|
134
|
+
description: strings.productThemePages.emeraldLakeShuttle.description,
|
|
135
|
+
path: '/emerald-lake-shuttle',
|
|
136
|
+
avgPrice: 175,
|
|
137
|
+
pillValues: [createDeparturePillValue('emerald-lake-escape', strings), createDurationPillValue('emerald-lake-escape', strings), ...createemeraldLakeEscapeTourLocationsPillValues(strings), createLunchPillValue(strings), createMoneyPillValue('emerald-lake-escape', strings)]
|
|
138
|
+
},
|
|
139
|
+
PRIVATE_TOUR: {
|
|
140
|
+
id: 'private-tour',
|
|
141
|
+
videoUrl: { src: '/videos/private-tour.mp4', webm: '/videos/private-tour.webm', longSrc: '/videos/private-tour-long.mp4', longWebm: '/videos/private-tour-long.webm' },
|
|
142
|
+
name: strings.products.productNames.privateTour,
|
|
143
|
+
shortName: strings.products.productShortNames.privateTourShort,
|
|
144
|
+
images: [
|
|
145
|
+
IMAGES.PRIVATE_TOUR_FAMILY_MORAINE_LAKE,
|
|
146
|
+
],
|
|
147
|
+
bookingLink: '#book-now/private-tour',
|
|
148
|
+
currentStartTime: strings.products.startTimes.privateTour,
|
|
149
|
+
description: strings.productThemePages.privateTours.description,
|
|
150
|
+
path: '/private-shuttle',
|
|
151
|
+
avgPrice: 1699,
|
|
152
|
+
pillValues: [createDeparturePillValue('private-tour', strings), createDurationPillValue('private-tour', strings), createCroissantPillValue(strings), createHotDrinksPillValue(strings), createMoneyPillValue('private-tour', strings)]
|
|
153
|
+
}
|
|
154
|
+
});
|
|
155
|
+
|
|
156
|
+
// Default export for backward compatibility (uses English strings)
|
|
157
|
+
import defaultStrings from '../strings';
|
|
158
|
+
export const PRODUCTS = getProducts(defaultStrings);
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
{
|
|
2
|
+
"shortDescription": "[Replace with short description.]",
|
|
3
|
+
"paragraphs": [
|
|
4
|
+
"[Replace with your full description paragraph 1. Afternoon departure to Moraine Lake and Lake Louise. Describe the relaxed timing—ideal for those who prefer not to wake up early for sunrise.]",
|
|
5
|
+
"[Replace with your full description paragraph 2. Cover the afternoon schedule, pickup locations, and how the tour flows—which lake first, how much time at each.]",
|
|
6
|
+
"[Replace with your full description paragraph 3. Highlight the benefits of an afternoon tour—different light for photography, fewer crowds at certain times, a more leisurely pace.]",
|
|
7
|
+
"[Replace with your full description paragraph 4. Add who this tour suits—late risers, those with morning commitments, or visitors wanting a relaxed day exploring both lakes.]"
|
|
8
|
+
],
|
|
9
|
+
"review": {
|
|
10
|
+
"text": "[Replace with a customer review quote for this tour]",
|
|
11
|
+
"name": "— [Reviewer Name]"
|
|
12
|
+
},
|
|
13
|
+
"sections": [
|
|
14
|
+
{
|
|
15
|
+
"title": "What's included",
|
|
16
|
+
"content": [
|
|
17
|
+
"Afternoon round-trip to both lakes",
|
|
18
|
+
"Guide and park entry",
|
|
19
|
+
"Approximate time at each lake"
|
|
20
|
+
]
|
|
21
|
+
},
|
|
22
|
+
{
|
|
23
|
+
"title": "What to bring",
|
|
24
|
+
"content": [
|
|
25
|
+
"Layers, camera, water, snacks",
|
|
26
|
+
"Comfortable shoes",
|
|
27
|
+
"Sunscreen"
|
|
28
|
+
]
|
|
29
|
+
},
|
|
30
|
+
{
|
|
31
|
+
"title": "Important information",
|
|
32
|
+
"content": "[Replace with key info: afternoon departure time, pickup locations, cancellation policy, return time, etc.]"
|
|
33
|
+
}
|
|
34
|
+
]
|
|
35
|
+
}
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
{
|
|
2
|
+
"shortDescription": "Visit the <b>Big 3 lakes of the Canadian Rockies; Moraine Lake, Lake Louise, and Emerald Lake</b>. On this scenic <b>small-group tour through Banff and Yoho National Park</b>. With <b>pickups in Canmore, Banff, and Lake Louise</b>, relax while our guides handle the driving and logistics. Along the way, we’ll also stop at <b>Natural Bridge</b> and the <b>impressive Takakkaw Falls</b>, giving you the chance to experience the <b>most iconic landscapes</b> of the Rockies <b>in one unforgettable day</b>.",
|
|
3
|
+
"paragraphs": [
|
|
4
|
+
"Visit the <b>3 most iconic lakes of the Canadian Rockies</b> on this scenic small-group tour through Banff and Yoho National Park. <b>Designed for travelers who want to experience the region’s most famous landscapes in a single unforgettable day</b>, this tour takes you to <b>Moraine Lake, Lake Louise, and Emerald Lake</b>, along with several spectacular stops along the way.",
|
|
5
|
+
"Your day begins with <b>convenient pickups in Canmore, Banff, or Lake Louise</b>. Sit back and relax while our local guides handle the driving and logistics, allowing you to enjoy the scenic journey through the mountains. Along the way, our guides will share stories about the region’s wildlife, geology, and history while pointing out some of the most beautiful viewpoints in the Rockies.",
|
|
6
|
+
"You’ll visit three of the most breathtaking lakes in the Canadian Rockies. Experience the world-famous turquoise waters of <b>Moraine Lake</b>, take in the iconic setting of <b>Lake Louise</b>, and discover the vibrant colors of <b>Emerald Lake</b> in Yoho National Park. At Emerald Lake, you’ll enjoy <b>exclusive access to the Emerald Lake Lodge</b>, located on the <b>“island in the Rockies”</b>, a quieter area of the lake with incredible views of the surrounding peaks. Guests also have the option to <b>purchase lunch packages from Emerald Lake Lodge</b>, making it easy to enjoy a meal while taking in the scenery.",
|
|
7
|
+
"Along the way, we’ll also stop at several remarkable natural landmarks. See the powerful cascade of <b>Takakkaw Falls, one of the tallest waterfalls in Canada</b>, and visit the unique rock formations of <b>Natural Bridge</b>, carved by the <b>rushing waters of the Kicking Horse River</b>.",
|
|
8
|
+
"To make the day even more enjoyable, we provide <b>hot drinks including locally roasted coffee, tea, and hot chocolate</b>, as well as water to refill your bottle and small trail snacks during the tour.",
|
|
9
|
+
"With <b>comfortable transportation, knowledgeable local guides, and visits to some of the most spectacular locations in Banff and Yoho National Park</b>, this tour offers a relaxed and memorable way to experience the very best of the Canadian Rockies in one incredible day."
|
|
10
|
+
],
|
|
11
|
+
"review": {
|
|
12
|
+
"text": "Via Via is a fantastic tour company - I went on their Emerald Lake Escape tour yesterday and had the best time! The locations were stunning and the bus was very comfortable. Our leader Léo was kind, personable, professional and a great driver – I was very happy with the service he and his colleagues provided throughout the day.",
|
|
13
|
+
"name": "— Nichole V."
|
|
14
|
+
},
|
|
15
|
+
"sections": [
|
|
16
|
+
{
|
|
17
|
+
"title": "What's included",
|
|
18
|
+
"content": [
|
|
19
|
+
"• Convenient pickup directly at your door in Canmore, Harvie Heights, Banff and Lake Louise 🏨 ",
|
|
20
|
+
"• Experienced local guides with tips and knowledge on the best photo spots, hikes, and view spots 🏔️ ",
|
|
21
|
+
"• Brand new comfortable & luxury shuttles 🚐 ",
|
|
22
|
+
"• Trailsnacks 🍫",
|
|
23
|
+
"• Water to refills - bring your water bottle 💧",
|
|
24
|
+
"• Phone chargers 🔋 ",
|
|
25
|
+
"• Moraine Lake Access Fee 🏞️",
|
|
26
|
+
"• Banff National Park Pass 🏞️",
|
|
27
|
+
"• Yoho National Park Pass 🏞️"
|
|
28
|
+
]
|
|
29
|
+
},
|
|
30
|
+
{
|
|
31
|
+
"title": "Tour highlights",
|
|
32
|
+
"content": [
|
|
33
|
+
"• Visit the Big 3 lakes of the Canadian Rockies in one unforgettable day.",
|
|
34
|
+
"• Experience Moraine Lake, Lake Louise, and Emerald Lake on one scenic tour.",
|
|
35
|
+
"• Stop at the powerful Takakkaw Falls and the unique rock formations of Natural Bridge.",
|
|
36
|
+
"• Exclusive access to the peaceful Emerald Lake Island for incredible views and photos.",
|
|
37
|
+
"• Enjoy hot drinks, trail snacks, and water refills throughout the day.",
|
|
38
|
+
"• Relax on a scenic drive through Banff and Yoho National Park while our guides handle the logistics.",
|
|
39
|
+
"• Learn about the area’s wildlife, history, and hidden gems from our knowledgeable local guides."
|
|
40
|
+
]
|
|
41
|
+
},
|
|
42
|
+
{
|
|
43
|
+
"title": "Additional information",
|
|
44
|
+
"content": [
|
|
45
|
+
"<strong>What to bring:</strong>",
|
|
46
|
+
"Even in the summer, temperatures and weather conditions can change quickly in the mountains and can be below freezing temperatures around sunrise.",
|
|
47
|
+
"✅ Make sure to bring enough layers, sunrise in the mountains can still be pretty chilly!",
|
|
48
|
+
"✅ Bring a beanie and gloves to keep you cozy and comfortable",
|
|
49
|
+
"✅ Bring water and snacks to stay energized throughout the day",
|
|
50
|
+
"✅ Be prepared for quick weather changes in the mountains",
|
|
51
|
+
"✅ Check the current weather conditions via the link in your booking confirmation email before departure!",
|
|
52
|
+
"<strong>Special requirements:</strong>",
|
|
53
|
+
"Children's safety seats are available for children aged 2 and up or weighing 40lbs (18kg) or more.",
|
|
54
|
+
"If your child is <strong>younger than 2</strong> or weighs <strong>less than 40lbs</strong>, a rear-facing safety seat is required, and <strong>customers must bring their own</strong>.",
|
|
55
|
+
"Please inform us in advance if you need a children's safety seat or if you will be bringing your own. The children's safety seat can stay in the shuttle during your lake visit.",
|
|
56
|
+
"<strong>Restrictions:</strong>",
|
|
57
|
+
"Small pets are welcome if they can fit in a carry-on cage on your lap.",
|
|
58
|
+
"Service animals of all sizes are allowed - <strong>please contact us beforehand if you're bringing a service animal</strong>.",
|
|
59
|
+
"<strong>Cancellations:</strong>",
|
|
60
|
+
"We offer standard, flexible, and premium cancellation policies.",
|
|
61
|
+
"<strong>Standard Cancellation:</strong> Guests can cancel their booking up to <strong>7 days prior to their trip</strong> for a <strong>full refund</strong>, cancel up to <strong>72 hours before departure</strong> for a <strong>50% refund</strong>.",
|
|
62
|
+
"<strong>Flexible Cancellation:</strong> Guests can cancel their booking up to <strong>7 days prior to their trip</strong> for a <strong>full refund</strong>, cancel up to <strong>24 hours before departure</strong> for a <strong>75% refund</strong>.",
|
|
63
|
+
"<strong>Premium Cancellation:</strong> Guests can cancel their booking up to <strong>12 hours before departure</strong> for a <strong>full refund</strong>.",
|
|
64
|
+
"Additionally, all guests may make changes to their booking date and time up to <strong>72 hours in advance of their trip</strong> (subject to availability). To cancel your booking, please contact us directly."
|
|
65
|
+
]
|
|
66
|
+
}
|
|
67
|
+
]
|
|
68
|
+
}
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
{
|
|
2
|
+
"shortDescription": "Spend the day <b>exploring Lake Louise</b> and its alpine trails with <b>direct access to the lake</b> - no traffic jams or parking hassles. With <b>convenient pickups in Canmore, Banff, and Lake Louise</b>, relax while our guides handle the driving and logistics. <b>Ideal for hikers</b>, you’ll have <b>five hours</b> to reach the <b>Lake Agnes Tea House</b> for lunch at 7,000 feet, hike the <b>Little Beehive Trail</b>, or explore this iconic place by canoe. Want more time? <b>Extend your stay by 3.5 hours</b>.",
|
|
3
|
+
"paragraphs": [
|
|
4
|
+
"Spend the day <b>exploring Lake Louise</b> and its surrounding alpine trails on this relaxed small-group shuttle. <b>Ideal for hikers and adventurers</b>, this tour gives you <b>direct access</b> to the lake <b>without the hassle of traffic jams or searching for parking</b>, along with plenty of <b>time to experience the area at your own pace</b>.",
|
|
5
|
+
"Your trip begins with <b>convenient pickups in Canmore, Banff, or Lake Louise</b>. Sit back and enjoy the <b>scenic drive through Banff National Park</b> while our local guides handle the logistics and share stories about the mountains, wildlife, and history of the area along the way.",
|
|
6
|
+
"Once at Lake Louise, you’ll have <b>five hours to explore</b> one of the most iconic alpine destinations in the Canadian Rockies. <b>Hike to the famous Lake Agnes Tea House</b> for lunch at 2,135 metres (7,000 feet), continue to the <b>Little Beehive for panoramic views</b>, or take a leisurely <b>walk along the lakeshore</b>. You can also <b>rent a canoe</b> (not included in the tour and available on a first-come, first-served basis) and paddle across the lake’s turquoise waters, or relax and enjoy the stunning mountain scenery.",
|
|
7
|
+
"For a more relaxed visit, stop by the <b>Fairmont Château Lake Louise</b> and enjoy <b>lunch or a classic afternoon “high tea”</b> overlooking the lake.",
|
|
8
|
+
"For those who want even <b>more time to explore</b>, you can <b>extend your stay by an additional 3.5 hours</b>. With comfortable transportation, convenient pickups, and plenty of time to explore, this shuttle offers an easy and memorable way to experience Lake Louise and its incredible alpine surroundings.",
|
|
9
|
+
"<strong>Popular hikes from Lake Louise:</strong>",
|
|
10
|
+
"• Fairview Lookout: 2.4 km / 1.5 mi round trip ~45-60 minutes",
|
|
11
|
+
"• Lake Agnes Tea House: 7.4 km / 4.6 mi round trip ~2-3 hours ",
|
|
12
|
+
"• Little Beehive: 9.2 km / 5.7 mi round trip ~3-4 hours ",
|
|
13
|
+
"• Saddleback Pass: 8.7km / 5.4 mi round trip ~3-5 hours ",
|
|
14
|
+
"<strong>Extended tour option recommended for:</strong>",
|
|
15
|
+
"• Big Beehive: 10.3 km / 6.4 mi round trip ~3-4 hours ",
|
|
16
|
+
"• Plain of Six Glaciers: 13.8 km / 8.6 mi round trip ~4-5 hours ",
|
|
17
|
+
"• Devil’s thumb: 11.4 km / 7 mi round trip ~4-6 hours"
|
|
18
|
+
],
|
|
19
|
+
"review": {
|
|
20
|
+
"text": "With the extended tour, we had more than enough time to do the Beehive hike. Everything went smoothly and the whole experience was very well organized.",
|
|
21
|
+
"name": "— Laura W."
|
|
22
|
+
},
|
|
23
|
+
"sections": [
|
|
24
|
+
{
|
|
25
|
+
"title": "What's included",
|
|
26
|
+
"content": [
|
|
27
|
+
"• Convenient pickup directly at your door in Canmore, Harvie Heights, Banff and Lake Louise 🏨 ",
|
|
28
|
+
"• Experienced local guides with tips and knowledge on the best photo spots, hikes, and view spots 🏔️ ",
|
|
29
|
+
"• Brand new comfortable & luxury shuttles 🚐 ",
|
|
30
|
+
"• Trailsnacks 🍫",
|
|
31
|
+
"• Water to refills - bring your water bottle 💧",
|
|
32
|
+
"• Phone chargers 🔋 ",
|
|
33
|
+
"• Banff National Park Pass 🏞️"
|
|
34
|
+
]
|
|
35
|
+
},
|
|
36
|
+
{
|
|
37
|
+
"title": "Tour highlights",
|
|
38
|
+
"content": [
|
|
39
|
+
"• No hassle with direct access to the iconic Lake Louise for an unforgettable day. ",
|
|
40
|
+
"• Relax on a scenic drive through Banff National Park while our guides handle the logistics. ",
|
|
41
|
+
"• Spend 5 full hours exploring Lake Louise and its surrounding trails. ",
|
|
42
|
+
"• Rent a canoe to explore the glacial waters of Lake Louise",
|
|
43
|
+
"• Extend your tour to take on longer day hikes, and plan a lunch at Lake Agnes Tea House.",
|
|
44
|
+
"• Small-group experience for a more relaxed and personalized tour. ",
|
|
45
|
+
"• Learn about the area’s wildlife, history, and hidden gems from our knowledgeable local guides."
|
|
46
|
+
]
|
|
47
|
+
},
|
|
48
|
+
{
|
|
49
|
+
"title": "Additional information",
|
|
50
|
+
"content": [
|
|
51
|
+
"<strong>What to bring:</strong>",
|
|
52
|
+
"Even in the summer, temperatures and weather conditions can change quickly in the mountains and can be below freezing temperatures around sunrise.",
|
|
53
|
+
"✅ Make sure to bring enough layers, sunrise in the mountains can still be pretty chilly!",
|
|
54
|
+
"✅ Bring a beanie and gloves to keep you cozy and comfortable",
|
|
55
|
+
"✅ Bring water and snacks to stay energized throughout the day",
|
|
56
|
+
"✅ Be prepared for quick weather changes in the mountains",
|
|
57
|
+
"✅ Check the current weather conditions via the link in your booking confirmation email before departure!",
|
|
58
|
+
"<strong>Special requirements:</strong>",
|
|
59
|
+
"Children's safety seats are available for children aged 2 and up or weighing 40lbs (18kg) or more.",
|
|
60
|
+
"If your child is <strong>younger than 2</strong> or weighs <strong>less than 40lbs</strong>, a rear-facing safety seat is required, and <strong>customers must bring their own</strong>.",
|
|
61
|
+
"Please inform us in advance if you need a children's safety seat or if you will be bringing your own. The children's safety seat can stay in the shuttle during your lake visit.",
|
|
62
|
+
"<strong>Restrictions:</strong>",
|
|
63
|
+
"Small pets are welcome if they can fit in a carry-on cage on your lap.",
|
|
64
|
+
"Service animals of all sizes are allowed - <strong>please contact us beforehand if you're bringing a service animal</strong>.",
|
|
65
|
+
"<strong>Cancellations:</strong>",
|
|
66
|
+
"We offer standard, flexible, and premium cancellation policies.",
|
|
67
|
+
"<strong>Standard Cancellation:</strong> Guests can cancel their booking up to <strong>7 days prior to their trip</strong> for a <strong>full refund</strong>, cancel up to <strong>72 hours before departure</strong> for a <strong>50% refund</strong>.",
|
|
68
|
+
"<strong>Flexible Cancellation:</strong> Guests can cancel their booking up to <strong>7 days prior to their trip</strong> for a <strong>full refund</strong>, cancel up to <strong>24 hours before departure</strong> for a <strong>75% refund</strong>.",
|
|
69
|
+
"<strong>Premium Cancellation:</strong> Guests can cancel their booking up to <strong>12 hours before departure</strong> for a <strong>full refund</strong>.",
|
|
70
|
+
"Additionally, all guests may make changes to their booking date and time up to <strong>72 hours in advance of their trip</strong> (subject to availability). To cancel your booking, please contact us directly."
|
|
71
|
+
]
|
|
72
|
+
}
|
|
73
|
+
]
|
|
74
|
+
}
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
{
|
|
2
|
+
"shortDescription": "Spend the day <b>exploring Moraine Lake</b> and its surrounding alpine trails with <b>direct access to the lake</b> - no traffic jams or parking hassles. With <b>convenient pickups in Canmore, Banff, and Lake Louise</b>, relax while our guides handle the driving and logistics. <b>Ideal for hikers</b>, you’ll have up to <b>4 hours to explore</b> the lakeshore, hike to Consolation Lakes, or take in the famous views from the Rockpile. Want more time? Have a look at our <b>extended options</b>.",
|
|
3
|
+
"paragraphs": [
|
|
4
|
+
"Spend the day <b>exploring Moraine Lake</b> and its surrounding alpine trails on this <b>relaxed small-group shuttle</b>. With <b>direct access to the lake</b> - no traffic jams or parking hassles - this tour is ideal for <b>hikers, photographers, and anyone wanting more time to experience one of the most breathtaking places in the Canadian Rockies</b>.",
|
|
5
|
+
"Your trip begins with <b>convenient pickups in Canmore, Harvie Heights, Banff, or Lake Louise</b> in one of our comfortable vehicles. <b>Sit back and enjoy the scenic drive through Banff National Park</b> while our guides handle the logistics and share stories about the mountains, wildlife, and history of the area along the way.",
|
|
6
|
+
"We offer <b>three daily departures at 8 AM, 9 AM, and 1 PM</b>, each giving you <b>3.5 to 4 hours at Moraine Lake to explore the area at your own pace</b>. Walk along the lakeshore, take in the famous view from the Rockpile, rent a canoe on the lake’s turquoise waters, or head into the mountains on one of the many scenic hiking trails surrounding the lake.",
|
|
7
|
+
"For those looking to spend even more time exploring, <b>several extended return options are available</b>, giving hikers the opportunity to <b>complete longer alpine routes or combine multiple hikes in a single visit</b>.",
|
|
8
|
+
"With comfortable transportation, convenient pickups, and plenty of time to explore, this shuttle offers one of the <b>easiest and most flexible ways to experience the beauty of Moraine Lake</b>.",
|
|
9
|
+
|
|
10
|
+
"<strong>Popular hikes from Moraine Lake:</strong>",
|
|
11
|
+
"• Rockpile Trail: 0.8 km / 0.5 mi round trip ~15–30 minutes ",
|
|
12
|
+
"• Moraine Lakeshore Trail: 3 km / 1.9 mi round trip ~45–60 minutes ",
|
|
13
|
+
"• Consolation Lakes: 6 km / 3.7 mi round trip ~1.5–2 hours ",
|
|
14
|
+
"• Tower of Babel: 2.9 km / 1.8 mi round trip ~3-4 hours",
|
|
15
|
+
|
|
16
|
+
"<strong>Extended tour option recommended for:</strong>",
|
|
17
|
+
"• Larch Valley: 8.6 km / 5.3 mi round trip ~3–4 hours ",
|
|
18
|
+
"• Eiffel Lake: 11.6 km / 7.2 mi round trip ~4–5 hours ",
|
|
19
|
+
"• Sentinel Pass via Larch Valley: 11.2 km / 7 mi round trip ~4–6 hours ",
|
|
20
|
+
"• Lake Annette: 13 km / 8 mi round trip ~4–6 hours"
|
|
21
|
+
],
|
|
22
|
+
"review": {
|
|
23
|
+
"text": "Via Via is a great shuttle service to Moraine Lake. Comfortable, efficient, and friendly with lots of tips on where to go and what to see. We had plenty of time to hike around Moraine Lake and really enjoy the area.",
|
|
24
|
+
"name": "— Meyrem A."
|
|
25
|
+
},
|
|
26
|
+
"sections": [
|
|
27
|
+
{
|
|
28
|
+
"title": "What's included",
|
|
29
|
+
"content": [
|
|
30
|
+
"• Convenient pickup directly at your door in Canmore, Harvie Heights, Banff and Lake Louise 🏨 ",
|
|
31
|
+
"• Experienced local guides with tips and knowledge on the best photo spots, hikes, and view spots 🏔️ ",
|
|
32
|
+
"• Brand new comfortable & luxury shuttles 🚐 ",
|
|
33
|
+
"• Trailsnacks 🍫",
|
|
34
|
+
"• Water to refills - bring your water bottle 💧",
|
|
35
|
+
"• Phone chargers 🔋 ",
|
|
36
|
+
"• Moraine Lake Access Fee 🏞️",
|
|
37
|
+
"• Banff National Park Pass 🏞️"
|
|
38
|
+
]
|
|
39
|
+
},
|
|
40
|
+
{
|
|
41
|
+
"title": "Tour highlights",
|
|
42
|
+
"content": [
|
|
43
|
+
"• No hassle with direct access to the magical Moraine Lake for an unforgettable day. ",
|
|
44
|
+
"• Relax on a scenic drive through Banff National Park while our guides handle the logistics. ",
|
|
45
|
+
"• Spend 3.5-4 full hours exploring Lake Louise and its surrounding trails. ",
|
|
46
|
+
"• Rent a canoe to explore the turquoise waters of Moraine Lake.",
|
|
47
|
+
"• Extend your tour to embark on longer day hikes.",
|
|
48
|
+
"• Small-group experience for a more relaxed and personalized tour. ",
|
|
49
|
+
"• Learn about the area’s wildlife, history, and hidden gems from our knowledgeable local guides."
|
|
50
|
+
]
|
|
51
|
+
},
|
|
52
|
+
{
|
|
53
|
+
"title": "Additional information",
|
|
54
|
+
"content": [
|
|
55
|
+
"<strong>What to bring:</strong>",
|
|
56
|
+
"Even in the summer, temperatures and weather conditions can change quickly in the mountains and can be below freezing temperatures around sunrise.",
|
|
57
|
+
"✅ Make sure to bring enough layers, sunrise in the mountains can still be pretty chilly!",
|
|
58
|
+
"✅ Bring a beanie and gloves to keep you cozy and comfortable",
|
|
59
|
+
"✅ Bring water and snacks to stay energized throughout the day",
|
|
60
|
+
"✅ Be prepared for quick weather changes in the mountains",
|
|
61
|
+
"✅ Check the current weather conditions via the link in your booking confirmation email before departure!",
|
|
62
|
+
"<strong>Special requirements:</strong>",
|
|
63
|
+
"Children's safety seats are available for children aged 2 and up or weighing 40lbs (18kg) or more.",
|
|
64
|
+
"If your child is <strong>younger than 2</strong> or weighs <strong>less than 40lbs</strong>, a rear-facing safety seat is required, and <strong>customers must bring their own</strong>.",
|
|
65
|
+
"Please inform us in advance if you need a children's safety seat or if you will be bringing your own. The children's safety seat can stay in the shuttle during your lake visit.",
|
|
66
|
+
"<strong>Restrictions:</strong>",
|
|
67
|
+
"Small pets are welcome if they can fit in a carry-on cage on your lap.",
|
|
68
|
+
"Service animals of all sizes are allowed - <strong>please contact us beforehand if you're bringing a service animal</strong>.",
|
|
69
|
+
"<strong>Cancellations:</strong>",
|
|
70
|
+
"We offer standard, flexible, and premium cancellation policies.",
|
|
71
|
+
"<strong>Standard Cancellation:</strong> Guests can cancel their booking up to <strong>7 days prior to their trip</strong> for a <strong>full refund</strong>, cancel up to <strong>72 hours before departure</strong> for a <strong>50% refund</strong>.",
|
|
72
|
+
"<strong>Flexible Cancellation:</strong> Guests can cancel their booking up to <strong>7 days prior to their trip</strong> for a <strong>full refund</strong>, cancel up to <strong>24 hours before departure</strong> for a <strong>75% refund</strong>.",
|
|
73
|
+
"<strong>Premium Cancellation:</strong> Guests can cancel their booking up to <strong>12 hours before departure</strong> for a <strong>full refund</strong>.",
|
|
74
|
+
"Additionally, all guests may make changes to their booking date and time up to <strong>72 hours in advance of their trip</strong> (subject to availability). To cancel your booking, please contact us directly."
|
|
75
|
+
]
|
|
76
|
+
}
|
|
77
|
+
]
|
|
78
|
+
}
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
{
|
|
2
|
+
"shortDescription": "Experience the <b>magic of sunrise</b> in the Canadian Rockies on our <b>#1-rated tour to Moraine Lake and Lake Louise</b>. With convenient <b>doorstep pickup</b> from <b>Canmore, Banff, or Lake Louise</b>, relax while our expert guides handle all the logistics. Arrive at Moraine Lake <b>before sunrise and ahead of the crowds</b>. Watch the alpenglow light up the Valley of the Ten Peaks while you enjoy <b>warm drinks and blankets</b> at the Rockpile.",
|
|
3
|
+
"paragraphs": [
|
|
4
|
+
"Start your day with an <b>unforgettable sunrise</b> in the Canadian Rockies on our <b>#1-rated small-group tour to Moraine Lake and Lake Louise</b>. Thoughtfully timed to beat the crowds, this experience lets you enjoy <b>two of Banff’s most iconic lakes</b> in their most peaceful moments.",
|
|
5
|
+
"We’ll pick you up from your hotel or accommodation in <b>Canmore, Banff, or Lake Louise</b> so you can relax while our experienced guides take care of the driving and planning. At Moraine Lake, enjoy <b>locally roasted Eclipse coffee, tea, or hot chocolate</b> and <b>cozy blankets</b> as you watch the sunrise from the Rockpile, where the first light hits the Valley of the Ten Peaks and perfectly mirrors in Moraine Lake’s vibrant turquoise waters.",
|
|
6
|
+
"Next, visit the quiet <b>Lake Louise during the so-called golden hour</b>, before the bigger daytime crowds roll in. Stroll along the lakeshore, capture stunning photos, or hike to Fairview Lookout for panoramic views of the lake and surrounding peaks.",
|
|
7
|
+
"With exceptional local guides, comfortable transportation, and seamless planning, this tour offers a <b>fun, relaxed, and unforgettable</b> way to experience one of the <b>most beautiful mornings in the Canadian Rockies</b>."
|
|
8
|
+
],
|
|
9
|
+
"review": {
|
|
10
|
+
"text": "The trip was amazing! So easy to plan & book with lots of details about the day which was really useful! They offer blankets and hot drinks which is a really nice touch!",
|
|
11
|
+
"name": "— Megan"
|
|
12
|
+
},
|
|
13
|
+
"sections": [
|
|
14
|
+
{
|
|
15
|
+
"title": "What's included",
|
|
16
|
+
"content": [
|
|
17
|
+
"• Convenient pickup directly at your door in Canmore, Harvie Heights, Banff and Lake Louise 🏨",
|
|
18
|
+
"• Experienced local guides with tips and knowledge on the best photo spots, hikes, and view spots 🏔️",
|
|
19
|
+
"• Brand new comfortable & luxury shuttles 🚐",
|
|
20
|
+
"• Complimentary hot chocolate, coffee & tea ☕️",
|
|
21
|
+
"• Cozy blankets to keep you warm 🧣",
|
|
22
|
+
"• Headlamps for early mornings 🔦",
|
|
23
|
+
"• Phone chargers 🔋",
|
|
24
|
+
"• Moraine Lake Access Fee 🏞️"
|
|
25
|
+
]
|
|
26
|
+
},
|
|
27
|
+
{
|
|
28
|
+
"title": "Tour highlights",
|
|
29
|
+
"content": [
|
|
30
|
+
"• The most magical sunrise you'll ever witness at Moraine Lake!",
|
|
31
|
+
"• Quiet Golden Hour at the iconic Lake Louise.",
|
|
32
|
+
"• Enjoy this breathtaking sunrise with a hot drink under a cozy blanket!",
|
|
33
|
+
"• Smaller groups for a more intimate & personalized experience.",
|
|
34
|
+
"• Our sunrise shuttle arrives before sunrise - ensuring you get the best spots!",
|
|
35
|
+
"• Learn interesting insights, local tips, and stories from our expert guides.",
|
|
36
|
+
"• Optional: extend your stay and book our extended tour for a later return from Lake Louise."
|
|
37
|
+
]
|
|
38
|
+
},
|
|
39
|
+
{
|
|
40
|
+
"title": "Additional information",
|
|
41
|
+
"content": [
|
|
42
|
+
"<strong>What to bring:</strong>",
|
|
43
|
+
"Even in the summer, temperatures and weather conditions can change quickly in the mountains and can be below freezing temperatures around sunrise.",
|
|
44
|
+
"✅ Make sure to bring enough layers, sunrise in the mountains can still be pretty chilly!",
|
|
45
|
+
"✅ Bring a beanie and gloves to keep you cozy and comfortable",
|
|
46
|
+
"✅ Bring water and snacks to stay energized throughout the day",
|
|
47
|
+
"✅ Be prepared for quick weather changes in the mountains",
|
|
48
|
+
"✅ Check the current weather conditions via the link in your booking confirmation email before departure!",
|
|
49
|
+
"<strong>Special requirements:</strong>",
|
|
50
|
+
"Children's safety seats are available for children aged 2 and up or weighing 40lbs (18kg) or more.",
|
|
51
|
+
"If your child is <strong>younger than 2</strong> or weighs <strong>less than 40lbs</strong>, a rear-facing safety seat is required, and <strong>customers must bring their own</strong>.",
|
|
52
|
+
"Please inform us in advance if you need a children's safety seat or if you will be bringing your own. The children's safety seat can stay in the shuttle during your lake visit.",
|
|
53
|
+
"<strong>Restrictions:</strong>",
|
|
54
|
+
"Small pets are welcome if they can fit in a carry-on cage on your lap.",
|
|
55
|
+
"Service animals of all sizes are allowed - <strong>please contact us beforehand if you're bringing a service animal</strong>.",
|
|
56
|
+
"<strong>Cancellations:</strong>",
|
|
57
|
+
"We offer standard, flexible, and premium cancellation policies.",
|
|
58
|
+
"<strong>Standard Cancellation:</strong> Guests can cancel their booking up to <strong>7 days prior to their trip</strong> for a <strong>full refund</strong>, cancel up to <strong>72 hours before departure</strong> for a <strong>50% refund</strong>.",
|
|
59
|
+
"<strong>Flexible Cancellation:</strong> Guests can cancel their booking up to <strong>7 days prior to their trip</strong> for a <strong>full refund</strong>, cancel up to <strong>24 hours before departure</strong> for a <strong>75% refund</strong>.",
|
|
60
|
+
"<strong>Premium Cancellation:</strong> Guests can cancel their booking up to <strong>12 hours before departure</strong> for a <strong>full refund</strong>.",
|
|
61
|
+
"Additionally, all guests may make changes to their booking date and time up to <strong>72 hours in advance of their trip</strong> (subject to availability). To cancel your booking, please contact us directly."
|
|
62
|
+
]
|
|
63
|
+
}
|
|
64
|
+
]
|
|
65
|
+
}
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
{
|
|
2
|
+
"shortDescription": "See <b>Moraine Lake at sunrise</b> on our <b>top-rated small-group tour</b>. With convenient <b>doorstep pickup</b> from <b>Canmore, Banff, or Lake Louise</b>, relax while our guides handle the logistics. Arrive at Moraine Lake <b>before sunrise and ahead of the crowds</b>. Watch the alpenglow light up the Valley of the Ten Peaks while you enjoy <b>warm drinks and blankets</b> at the Rockpile.",
|
|
3
|
+
"paragraphs": [
|
|
4
|
+
"<b>Start your day at Moraine Lake</b>, one of the most breathtaking places in the Canadian Rockies. This<b> small-group sunrise tour</b> is designed to <b>get you there before the sun rises and before the crowds arrive</b>, so you can experience the lake at its quietest and most beautiful.",
|
|
5
|
+
"We’ll <b>pick you up from your accommodation in Canmore, Banff, or Lake Louise</b>, so you can sit back and relax while our local guides handle the early morning drive. Arriving before sunrise gives you time to <b>take in the stillness of the lake</b> and the surrounding mountains as the sky slowly begins to change.",
|
|
6
|
+
"From the Rockpile, watch the <b>alpenglow and first light</b> illuminate the <b>Valley of the Ten Peaks</b> and <b>reflect across Moraine Lake’s turquoise water</b>. To keep you comfortable in the cool mountain air, <b>we provide warm drinks and cozy blankets while you enjoy the view</b>. Our guides will be nearby for <b>drink refills</b> and are always happy to <b>help take photos</b> so you can capture the moment.",
|
|
7
|
+
"After sunrise, you’ll have time to walk along the lakeshore, take photos, or simply enjoy the peaceful morning atmosphere before the area becomes busy. With comfortable transportation and experienced local guides, <b>this tour offers a relaxed and memorable way to see one of the most iconic sunrises in the Canadian Rockies</b>."
|
|
8
|
+
],
|
|
9
|
+
"review": {
|
|
10
|
+
"text": "What an incredible experience watching the sunrise at Moraine Lake. The Via Via team were so helpful and the early morning was worth it - especially with the complimentary coffee!",
|
|
11
|
+
"name": "— Jack P."
|
|
12
|
+
},
|
|
13
|
+
"sections": [
|
|
14
|
+
{
|
|
15
|
+
"title": "What's included",
|
|
16
|
+
"content": [
|
|
17
|
+
"• Convenient pickup directly at your door in Canmore, Harvie Heights, Banff and Lake Louise 🏨",
|
|
18
|
+
"• Experienced local guides with tips and knowledge on the best photo spots, hikes, and view spots 🏔️",
|
|
19
|
+
"• Brand new comfortable & luxury shuttles 🚐",
|
|
20
|
+
"• Complimentary hot chocolate, coffee & tea ☕️",
|
|
21
|
+
"• Cozy blankets to keep you warm 🧣",
|
|
22
|
+
"• Headlamps for early mornings 🔦",
|
|
23
|
+
"• Phone chargers 🔋",
|
|
24
|
+
"• Moraine Lake Access Fee 🏞️"
|
|
25
|
+
]
|
|
26
|
+
},
|
|
27
|
+
{
|
|
28
|
+
"title": "Tour highlights",
|
|
29
|
+
"content": [
|
|
30
|
+
"• The most magical sunrise you'll ever witness at Moraine Lake!",
|
|
31
|
+
"• Enjoy this breathtaking sunrise with a hot drink under a cozy blanket!",
|
|
32
|
+
"• Smaller groups for a more intimate & personalized experience.",
|
|
33
|
+
"• Our sunrise shuttle arrives before sunrise - ensuring you get the best spots!",
|
|
34
|
+
"• Learn interesting insights, local tips, and stories from our expert guides.",
|
|
35
|
+
"• Optional: extend your stay and book our extended tour for a later return from Lake Louise."
|
|
36
|
+
]
|
|
37
|
+
},
|
|
38
|
+
{
|
|
39
|
+
"title": "Additional information",
|
|
40
|
+
"content": [
|
|
41
|
+
"<strong>What to bring:</strong>",
|
|
42
|
+
"Even in the summer, temperatures and weather conditions can change quickly in the mountains and can be below freezing temperatures around sunrise.",
|
|
43
|
+
"✅ Make sure to bring enough layers, sunrise in the mountains can still be pretty chilly!",
|
|
44
|
+
"✅ Bring a beanie and gloves to keep you cozy and comfortable",
|
|
45
|
+
"✅ Bring water and snacks to stay energized throughout the day",
|
|
46
|
+
"✅ Be prepared for quick weather changes in the mountains",
|
|
47
|
+
"✅ Check the current weather conditions via the link in your booking confirmation email before departure!",
|
|
48
|
+
"<strong>Special requirements:</strong>",
|
|
49
|
+
"Children's safety seats are available for children aged 2 and up or weighing 40lbs (18kg) or more.",
|
|
50
|
+
"If your child is <strong>younger than 2</strong> or weighs <strong>less than 40lbs</strong>, a rear-facing safety seat is required, and <strong>customers must bring their own</strong>.",
|
|
51
|
+
"Please inform us in advance if you need a children's safety seat or if you will be bringing your own. The children's safety seat can stay in the shuttle during your lake visit.",
|
|
52
|
+
"<strong>Restrictions:</strong>",
|
|
53
|
+
"Small pets are welcome if they can fit in a carry-on cage on your lap.",
|
|
54
|
+
"Service animals of all sizes are allowed - <strong>please contact us beforehand if you're bringing a service animal</strong>.",
|
|
55
|
+
"<strong>Cancellations:</strong>",
|
|
56
|
+
"We offer standard, flexible, and premium cancellation policies.",
|
|
57
|
+
"<strong>Standard Cancellation:</strong> Guests can cancel their booking up to <strong>7 days prior to their trip</strong> for a <strong>full refund</strong>, cancel up to <strong>72 hours before departure</strong> for a <strong>50% refund</strong>.",
|
|
58
|
+
"<strong>Flexible Cancellation:</strong> Guests can cancel their booking up to <strong>7 days prior to their trip</strong> for a <strong>full refund</strong>, cancel up to <strong>24 hours before departure</strong> for a <strong>75% refund</strong>.",
|
|
59
|
+
"<strong>Premium Cancellation:</strong> Guests can cancel their booking up to <strong>12 hours before departure</strong> for a <strong>full refund</strong>.",
|
|
60
|
+
"Additionally, all guests may make changes to their booking date and time up to <strong>72 hours in advance of their trip</strong> (subject to availability). To cancel your booking, please contact us directly."
|
|
61
|
+
]
|
|
62
|
+
}
|
|
63
|
+
]
|
|
64
|
+
}
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
{
|
|
2
|
+
"shortDescription": "<b>Build your ideal day</b> in the Canadian Rockies with a <b>fully customizable private tour tailored to your group</b>. With <b>pickups from Kananaskis, Canmore, Banff, or Lake Louise</b>, relax while your local guide handles the driving and logistics. <b>Visit iconic lakes, scenic viewpoints, and hidden gems at your own pace<b>. Our <b>experienced team specializes in crafting personalized experiences</b>, and with our <b>large fleet we can accommodate families, groups, or wedding parties</b>. We can also connect you with trusted <b>local photographers</b> to capture this day.",
|
|
3
|
+
"paragraphs": [
|
|
4
|
+
"<b>Create your perfect day</b> in the Canadian Rockies with a <b>fully customizable private tour designed around your interests, pace, and schedule</b>. Whether you’re looking for a <b>relaxed sightseeing experience, an adventurous day in the mountains, or a special celebration</b> with family and friends, our team will work with you to <b>craft a personalized itinerary</b> that makes the most of your time in the Rockies.",
|
|
5
|
+
"Your private tour can <b>start whenever it suits you</b>, with options ranging <b>from sunrise to sunset</b> experiences. With <b>pickups from Kananaskis, Canmore, Banff, or Lake Louise</b>, simply relax while your dedicated local guide handles the driving, timing, and logistics. Our team has extensive knowledge of the region and will gladly <b>help plan the perfect route based on your interests</b>, ensuring you experience the very best the area has to offer.",
|
|
6
|
+
"With our <b>large fleet of vehicles, we can comfortably accommodate couples, families, larger groups, or wedding parties</b>. We also work with talented <b>local photographers</b> if you’d like to capture special moments during your trip, whether it’s a surprise proposal, family photos, or a scenic photo tour. For those looking for a more active day, we can arrange <b>experienced hiking guides</b>, and we’re <b>happy to accommodate pets, paddle boards, and other gear</b> to make the day truly yours.",
|
|
7
|
+
"Our private tours offer <b>direct access to the most sought-after locations in Banff and Yoho National Park</b>, allowing you to explore the region without the stress of planning routes, navigating busy roads, or searching for parking.",
|
|
8
|
+
"<strong>Popular locations for private tours:</strong>",
|
|
9
|
+
"• Moraine Lake",
|
|
10
|
+
"• Lake Louise",
|
|
11
|
+
"• Emerald Lake",
|
|
12
|
+
"• Takakkaw Falls",
|
|
13
|
+
"• Johnston Canyon",
|
|
14
|
+
"• Peyto Lake",
|
|
15
|
+
"• Bow Lake",
|
|
16
|
+
"• Athabasca Glacier",
|
|
17
|
+
"• Lake Minnewanka",
|
|
18
|
+
"• Minnewanka Boat Cruise",
|
|
19
|
+
"• Vermillion Lakes",
|
|
20
|
+
"• Banff Gondola",
|
|
21
|
+
"• The towns of Banff, Canmore, and Kananaskis",
|
|
22
|
+
"Whether you want to visit iconic lakes, discover hidden gems, enjoy scenic hikes, or simply relax and take in the views, <b>our team specializes in creating memorable private experiences</b> tailored entirely to your group."
|
|
23
|
+
],
|
|
24
|
+
"review": {
|
|
25
|
+
"text": "We had an amazing experience with Via Via visiting Moraine Lake, Lake Louise, and Emerald Lake. Our driver was incredibly friendly, knowledgeable, and made the whole day easy and stress-free. The private group setting felt very personal and we had plenty of time to explore each location. We never felt rushed, and the recommendations on where to go and what to see were spot on. Highly recommend if you want a comfortable and well-organized way to see the best spots in Banff with your group.",
|
|
26
|
+
"name": "— Nichole V."
|
|
27
|
+
},
|
|
28
|
+
"sections": [
|
|
29
|
+
{
|
|
30
|
+
"title": "What's included",
|
|
31
|
+
"content": [
|
|
32
|
+
"• Convenient pickup directly at your door in Canmore, Harvie Heights, Banff and Lake Louise 🏨 ",
|
|
33
|
+
"• Experienced local guides with tips and knowledge on the best photo spots, hikes, and view spots 🏔️ ",
|
|
34
|
+
"• Brand new comfortable & luxury shuttles 🚐 ",
|
|
35
|
+
"• Trailsnacks 🍫",
|
|
36
|
+
"• Water to refills - bring your water bottle 💧",
|
|
37
|
+
"• Complimentary hot chocolate, coffee & tea ☕️",
|
|
38
|
+
"• Fresh croissant from a local french-canadian bakery 🥐",
|
|
39
|
+
"• Lunch options available 🍽️",
|
|
40
|
+
"• Phone chargers 🔋 ",
|
|
41
|
+
"• Moraine Lake Access Fee 🏞️",
|
|
42
|
+
"• Banff National Park Pass 🏞️"
|
|
43
|
+
]
|
|
44
|
+
},
|
|
45
|
+
{
|
|
46
|
+
"title": "Tour highlights",
|
|
47
|
+
"content": [
|
|
48
|
+
"• Completely customized itinerary crafted for your group. ",
|
|
49
|
+
"• No hassle with direct access to all of Banff’s hot spots for an unforgettable day. ",
|
|
50
|
+
"• Relax on a scenic drive through Banff National Park while our guides handle the logistics. ",
|
|
51
|
+
"• Choose between sunrise, sunset, half day, and full day adventures. ",
|
|
52
|
+
"• Private-group experience for a more relaxed and personalized tour. ",
|
|
53
|
+
"• Our large fleet can accommodate bigger groups or wedding parties. ",
|
|
54
|
+
"• Learn about the area’s wildlife, history, and hidden gems from our knowledgeable local guides. "
|
|
55
|
+
]
|
|
56
|
+
},
|
|
57
|
+
{
|
|
58
|
+
"title": "Additional information",
|
|
59
|
+
"content": [
|
|
60
|
+
"<strong>What to bring:</strong>",
|
|
61
|
+
"Even in the summer, temperatures and weather conditions can change quickly in the mountains and can be below freezing temperatures around sunrise.",
|
|
62
|
+
"✅ Make sure to bring enough layers, sunrise in the mountains can still be pretty chilly!",
|
|
63
|
+
"✅ Bring a beanie and gloves to keep you cozy and comfortable",
|
|
64
|
+
"✅ Bring water and snacks to stay energized throughout the day",
|
|
65
|
+
"✅ Be prepared for quick weather changes in the mountains",
|
|
66
|
+
"✅ Check the current weather conditions via the link in your booking confirmation email before departure!",
|
|
67
|
+
"<strong>Special requirements:</strong>",
|
|
68
|
+
"Children's safety seats are available for children aged 2 and up or weighing 40lbs (18kg) or more.",
|
|
69
|
+
"If your child is <strong>younger than 2</strong> or weighs <strong>less than 40lbs</strong>, a rear-facing safety seat is required, and <strong>customers must bring their own</strong>.",
|
|
70
|
+
"Please inform us in advance if you need a children's safety seat or if you will be bringing your own. The children's safety seat can stay in the shuttle during your lake visit.",
|
|
71
|
+
"<strong>Restrictions:</strong>",
|
|
72
|
+
"Small pets are welcome if they can fit in a carry-on cage on your lap.",
|
|
73
|
+
"Service animals of all sizes are allowed - <strong>please contact us beforehand if you're bringing a service animal</strong>.",
|
|
74
|
+
"<strong>Cancellations:</strong>",
|
|
75
|
+
"<strong>Private Shuttle Cancellation:</strong> Guests can cancel their booking up to <strong>14 days prior to their trip</strong> for a <strong>full refund minus deposit</strong>, cancel up to <strong>7 days before departure</strong> for a <strong>50% refund minus deposit</strong>.",
|
|
76
|
+
"Additionally, all guests may make changes to their booking date and time up to <strong>72 hours in advance of their trip</strong> (subject to availability). To cancel your booking, please contact us directly."
|
|
77
|
+
]
|
|
78
|
+
}
|
|
79
|
+
]
|
|
80
|
+
}
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
{
|
|
2
|
+
"shortDescription": "Visit <b>both Moraine Lake and Lake Louise in one day</b> on our <b>most popular Banff day tour</b>. With departures at <b>7:30 AM, 9 AM, and 1 PM</b> from <b>Canmore with pickups in Banff and Lake Louise</b>, sit back, relax, and take in the scenic views while our guides handle the driving and logistics. Spend <b>up to two hours at Moraine Lake</b> exploring the Rockpile and lakeshore, then continue to <b>Lake Louise for more exploration</b>, and to walk the shoreline, canoe, or hike to Fairview Lookout.",
|
|
3
|
+
"paragraphs": [
|
|
4
|
+
"<b>Visit two of the most iconic lakes</b> in the Canadian Rockies on this relaxed small-group tour to <b>Moraine Lake and Lake Louise</b>. Perfect for those who want to <b>experience the highlights</b> of Banff National Park <b>without the stress of driving or parking</b>, this tour gives you plenty of time to explore each location at your own pace.",
|
|
5
|
+
"Your day begins with departures at <b>7:30 AM, 9 AM, or 1 PM</b> from <b>Canmore, with convenient doorstep pickups in Banff and Lake Louise</b>. Sit back and enjoy the scenic drive through the mountains while our local guides handle the logistics and share stories about the area, its wildlife, and the history of the park along the way.",
|
|
6
|
+
"Our <b>first stop is Moraine Lake</b>, where you’ll have up to <b>two hours to explore</b> one of the most photographed lakes in the Canadian Rockies. <b>Walk</b> along the lakeshore, rent a <b>canoe, hike</b> the famous Rockpile for panoramic views of the Valley of the Ten Peaks, or <b>simply relax and take in the incredible alpine scenery</b>.",
|
|
7
|
+
"Afterward, we continue to <b>Lake Louise for up to two hours of free time</b>. Stroll along the shoreline, rent a canoe on the turquoise water, or hike to Fairview Lookout for sweeping views of the lake and surrounding peaks.",
|
|
8
|
+
"With <b>comfortable transportation, knowledgeable local driver-guides, and plenty of time to explore both lakes at your own pace</b>, this tour offers an easy and memorable way to experience two of the most beautiful places in Banff National Park."
|
|
9
|
+
],
|
|
10
|
+
"review": {
|
|
11
|
+
"text": "Our trip to Moraine Lake and Lake Louise with Via Via was wonderful and worry-free. The van was very comfortable and we loved the small group experience. Everything was well organized and we had plenty of time to explore both lakes.",
|
|
12
|
+
"name": "— Pam M."
|
|
13
|
+
},
|
|
14
|
+
"sections": [
|
|
15
|
+
{
|
|
16
|
+
"title": "What's included",
|
|
17
|
+
"content": [
|
|
18
|
+
"• Convenient pickup directly at your door in Canmore, Harvie Heights, Banff and Lake Louise 🏨",
|
|
19
|
+
"• Experienced local guides with tips and knowledge on the best photo spots, hikes, and view spots 🏔️",
|
|
20
|
+
"• Brand new comfortable & luxury shuttles 🚐",
|
|
21
|
+
"• Trailsnacks 🍫",
|
|
22
|
+
"• Water to refills - bring your water bottle 💧",
|
|
23
|
+
"• Phone chargers 🔋",
|
|
24
|
+
"• Moraine Lake Access Fee 🏞️",
|
|
25
|
+
"• Banff National Park Pass 🏞️"
|
|
26
|
+
]
|
|
27
|
+
},
|
|
28
|
+
{
|
|
29
|
+
"title": "Tour highlights",
|
|
30
|
+
"content": [
|
|
31
|
+
"• Visit both Moraine Lake and Lake Louise in one unforgettable day.",
|
|
32
|
+
"• Relax on a scenic drive through Banff National Park while our guides handle the logistics.",
|
|
33
|
+
"• Spend two full hours exploring Moraine Lake and the famous Rockpile viewpoint.",
|
|
34
|
+
"• Enjoy another two hours at Lake Louise to walk the shoreline, canoe, or hike to Fairview Lookout.",
|
|
35
|
+
"• Small-group experience for a more relaxed and personalized tour.",
|
|
36
|
+
"• Learn about the area’s wildlife, history, and hidden gems from our knowledgeable local guides."
|
|
37
|
+
]
|
|
38
|
+
},
|
|
39
|
+
{
|
|
40
|
+
"title": "Additional information",
|
|
41
|
+
"content": [
|
|
42
|
+
"<strong>What to bring:</strong>",
|
|
43
|
+
"Even in the summer, temperatures and weather conditions can change quickly in the mountains and can be below freezing temperatures around sunrise.",
|
|
44
|
+
"✅ Make sure to bring enough layers, sunrise in the mountains can still be pretty chilly!",
|
|
45
|
+
"✅ Bring a beanie and gloves to keep you cozy and comfortable",
|
|
46
|
+
"✅ Bring water and snacks to stay energized throughout the day",
|
|
47
|
+
"✅ Be prepared for quick weather changes in the mountains",
|
|
48
|
+
"✅ Check the current weather conditions via the link in your booking confirmation email before departure!",
|
|
49
|
+
"<strong>Special requirements:</strong>",
|
|
50
|
+
"Children's safety seats are available for children aged 2 and up or weighing 40lbs (18kg) or more.",
|
|
51
|
+
"If your child is <strong>younger than 2</strong> or weighs <strong>less than 40lbs</strong>, a rear-facing safety seat is required, and <strong>customers must bring their own</strong>.",
|
|
52
|
+
"Please inform us in advance if you need a children's safety seat or if you will be bringing your own. The children's safety seat can stay in the shuttle during your lake visit.",
|
|
53
|
+
"<strong>Restrictions:</strong>",
|
|
54
|
+
"Small pets are welcome if they can fit in a carry-on cage on your lap.",
|
|
55
|
+
"Service animals of all sizes are allowed - <strong>please contact us beforehand if you're bringing a service animal</strong>.",
|
|
56
|
+
"<strong>Cancellations:</strong>",
|
|
57
|
+
"We offer standard, flexible, and premium cancellation policies.",
|
|
58
|
+
"<strong>Standard Cancellation:</strong> Guests can cancel their booking up to <strong>7 days prior to their trip</strong> for a <strong>full refund</strong>, cancel up to <strong>72 hours before departure</strong> for a <strong>50% refund</strong>.",
|
|
59
|
+
"<strong>Flexible Cancellation:</strong> Guests can cancel their booking up to <strong>7 days prior to their trip</strong> for a <strong>full refund</strong>, cancel up to <strong>24 hours before departure</strong> for a <strong>75% refund</strong>.",
|
|
60
|
+
"<strong>Premium Cancellation:</strong> Guests can cancel their booking up to <strong>12 hours before departure</strong> for a <strong>full refund</strong>.",
|
|
61
|
+
"Additionally, all guests may make changes to their booking date and time up to <strong>72 hours in advance of their trip</strong> (subject to availability). To cancel your booking, please contact us directly."
|
|
62
|
+
]
|
|
63
|
+
}
|
|
64
|
+
]
|
|
65
|
+
}
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": "1",
|
|
3
|
+
"generatedAt": "2025-03-05T00:00:00Z",
|
|
4
|
+
"companyId": "c_LFU0Vx9hS5v3",
|
|
5
|
+
"products": [
|
|
6
|
+
{
|
|
7
|
+
"productId": "p_qa5keidRoV6H",
|
|
8
|
+
"optionIds": ["po_cSD2wlJfQqc0"],
|
|
9
|
+
"display": {
|
|
10
|
+
"path": "/moraine-lake-shuttle",
|
|
11
|
+
"slug": "moraine-lake-sunrise-lake-louise-golden-hour",
|
|
12
|
+
"imageIds": ["moraine-lake-canoes-sunrise.jpg"],
|
|
13
|
+
"collageImageIds": ["moraine-lake-canoes-sunrise.jpg", "golden-hour-lake-louise.jpg", "moraine-lake-sunrise-couple.jpg", "moraine-lake-sunrise-hotdrink.jpg"],
|
|
14
|
+
"shortName": "Moraine Lake Sunrise & Lake Louise Golden Hour",
|
|
15
|
+
"description": "Catch sunrise at Moraine Lake, then explore Lake Louise during golden hour. Two iconic lakes in one unforgettable morning.",
|
|
16
|
+
"themePage": "moraine-lake",
|
|
17
|
+
"mostPopular": true
|
|
18
|
+
}
|
|
19
|
+
},
|
|
20
|
+
{
|
|
21
|
+
"productId": "p_YKQsLmKhfYFp",
|
|
22
|
+
"optionIds": ["po_82wA2gUZBZ9z"],
|
|
23
|
+
"display": {
|
|
24
|
+
"path": "/moraine-lake-shuttle",
|
|
25
|
+
"slug": "moraine-lake-sunrise",
|
|
26
|
+
"imageIds": ["moraine-lake-sunrise-cheers.jpg"],
|
|
27
|
+
"collageImageIds": ["moraine-lake-canoes-sunrise.jpg", "moraine-lake-sunrise-cheers.jpg", "ml-sunrise-gorp.jpg", "moraine-lake-sunrise-yellow-jacket.jpg"],
|
|
28
|
+
"shortName": "Moraine Lake Sunrise Shuttle",
|
|
29
|
+
"description": "Arrive at Moraine Lake before sunrise. Beat the crowds and capture the iconic turquoise waters at first light.",
|
|
30
|
+
"themePage": "moraine-lake"
|
|
31
|
+
}
|
|
32
|
+
},
|
|
33
|
+
{
|
|
34
|
+
"productId": "p_CUJ4sVvaOkjk",
|
|
35
|
+
"optionIds": ["po_ImWip6rbg0D6", "po_lOO7wz6uMus1", "po_fvrAfalgI673"],
|
|
36
|
+
"display": {
|
|
37
|
+
"path": "/moraine-lake-shuttle",
|
|
38
|
+
"slug": "two-lakes-combo",
|
|
39
|
+
"imageIds": ["moraine-lake-yellow-bikini.jpg"],
|
|
40
|
+
"collageImageIds": ["lake-louise-flora.jpg", "moraine-lake-yellow-bikini.jpg", "couple-moraine-turquoise-reflection.jpg", "lake-louise-canoe.jpg"],
|
|
41
|
+
"shortName": "Two Lakes Combo",
|
|
42
|
+
"description": "Visit both Moraine Lake and Lake Louise in one day. Perfect for those who want to see the best of both.",
|
|
43
|
+
"themePage": "moraine-lake",
|
|
44
|
+
"mostPopular": true
|
|
45
|
+
}
|
|
46
|
+
},
|
|
47
|
+
{
|
|
48
|
+
"productId": "p_wQHE15ITi7TS",
|
|
49
|
+
"optionIds": ["po_FTLSMsahWKjM", "po_nbp2pFQo9AH7", "po_nzlCuOVJU181"],
|
|
50
|
+
"display": {
|
|
51
|
+
"path": "/moraine-lake-shuttle",
|
|
52
|
+
"slug": "moraine-lake-adventure",
|
|
53
|
+
"imageIds": ["moraine-lake-canoe.jpg"],
|
|
54
|
+
"collageImageIds": ["moraine-lake-jump-in.jpg", "moraine-lake-hiking.jpg", "moraine-lake-canoe.jpg", "moraine-lake-rockpile-couple.jpg"],
|
|
55
|
+
"shortName": "Moraine Lake Adventure",
|
|
56
|
+
"description": "Our classic Moraine Lake shuttle. Flexible time at the lake for hiking, canoeing, or simply soaking in the views.",
|
|
57
|
+
"themePage": "moraine-lake"
|
|
58
|
+
}
|
|
59
|
+
},
|
|
60
|
+
{
|
|
61
|
+
"productId": "p_aaD7mhbGaZOi",
|
|
62
|
+
"optionIds": ["po_BOw9d7qIWEhJ"],
|
|
63
|
+
"display": {
|
|
64
|
+
"path": "/lake-louise-shuttle",
|
|
65
|
+
"slug": "lake-louise-adventure",
|
|
66
|
+
"imageIds": ["lake-louise-flora.jpg"],
|
|
67
|
+
"collageImageIds": ["lake-louise-flora.jpg", "lake-louise-fairview-lookout.jpg", "lake-louise-lakefront-friends.jpg", "guests-ll-canada.jpg"],
|
|
68
|
+
"shortName": "Lake Louise Shuttle",
|
|
69
|
+
"description": "Daily shuttles to Lake Louise from Canmore and Banff. Hike, canoe, or explore the iconic chateau.",
|
|
70
|
+
"themePage": "lake-louise"
|
|
71
|
+
}
|
|
72
|
+
},
|
|
73
|
+
{
|
|
74
|
+
"productId": "p_C5jHohBUCwrd",
|
|
75
|
+
"optionIds": ["po_cVr23UWDaC9M"],
|
|
76
|
+
"display": {
|
|
77
|
+
"path": "/emerald-lake-shuttle",
|
|
78
|
+
"slug": "emerald-lake-escape",
|
|
79
|
+
"imageIds": ["emerald-lake-lodge-viewpoint.jpg"],
|
|
80
|
+
"collageImageIds": ["lake-louise-hiker.jpg", "emerald-lake-jump.jpg", "cilantro-on-the-lake-emerald.jpg", "moraine-lake-canoe.jpg"],
|
|
81
|
+
"shortName": "Big 3 Lakes Tour",
|
|
82
|
+
"description": "Full-day adventure to Lake Louise, Emerald Lake, and more. Lunch included. Our most comprehensive tour.",
|
|
83
|
+
"themePage": "emerald-lake"
|
|
84
|
+
}
|
|
85
|
+
},
|
|
86
|
+
{
|
|
87
|
+
"productId": "p_urmbvZepRegd",
|
|
88
|
+
"optionIds": ["po_uO9Ra6NHzwof", "po_44EQlZn24gXg", "po_vuzqpvGk6wVS", "po_nIToR7Qwau3E"],
|
|
89
|
+
"productType": "PRIVATE_SHUTTLE",
|
|
90
|
+
"display": {
|
|
91
|
+
"path": "/private-shuttle",
|
|
92
|
+
"slug": "private-tour",
|
|
93
|
+
"imageIds": ["lower-johnston-canyon-falls.jpg"],
|
|
94
|
+
"collageImageIds": ["takakkaw-falls.jpg", "family-sunrise-moraine-lake.jpg", "via-via-shuttle-view.jpg", "moraine-lake-jump-in.jpg"],
|
|
95
|
+
"shortName": "Private Shuttle",
|
|
96
|
+
"description": "Your own private shuttle. Custom itinerary, your pace, your group. Perfect for special occasions.",
|
|
97
|
+
"themePage": "private"
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
]
|
|
101
|
+
}
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Product description content loader.
|
|
3
|
+
* Loads full tour descriptions from src/data/product-descriptions/{slug}.{locale}.json
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
export interface ProductDescriptionReview {
|
|
7
|
+
text: string;
|
|
8
|
+
name: string;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
/** Section content: string for HTML, string[] for bullet list OR joined HTML (array of lines for readability) */
|
|
12
|
+
export type SectionContent = string | string[];
|
|
13
|
+
|
|
14
|
+
export interface ProductDescriptionResult {
|
|
15
|
+
shortDescription?: string;
|
|
16
|
+
paragraphs: string[];
|
|
17
|
+
review?: ProductDescriptionReview;
|
|
18
|
+
sections: { title: string; content: SectionContent }[];
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
interface ProductDescriptionData {
|
|
22
|
+
shortDescription?: string;
|
|
23
|
+
paragraphs: string[];
|
|
24
|
+
review?: ProductDescriptionReview;
|
|
25
|
+
sections: { title: string; content: SectionContent }[];
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
// Static imports - add new locales here when available
|
|
29
|
+
import moraineLakeSunriseLakeLouiseGoldenHourEn from '../data/product-descriptions/moraine-lake-sunrise-lake-louise-golden-hour.en.json';
|
|
30
|
+
import moraineLakeSunriseEn from '../data/product-descriptions/moraine-lake-sunrise.en.json';
|
|
31
|
+
import twoLakesComboEn from '../data/product-descriptions/two-lakes-combo.en.json';
|
|
32
|
+
import moraineLakeAdventureEn from '../data/product-descriptions/moraine-lake-adventure.en.json';
|
|
33
|
+
import lakeLouiseAdventureEn from '../data/product-descriptions/lake-louise-adventure.en.json';
|
|
34
|
+
import emeraldLakeEscapeEn from '../data/product-descriptions/emerald-lake-escape.en.json';
|
|
35
|
+
import afternoonDelightEn from '../data/product-descriptions/afternoon-delight.en.json';
|
|
36
|
+
import privateTourEn from '../data/product-descriptions/private-tour.en.json';
|
|
37
|
+
|
|
38
|
+
const DESCRIPTIONS: Record<string, Record<string, ProductDescriptionData>> = {
|
|
39
|
+
en: {
|
|
40
|
+
'moraine-lake-sunrise-lake-louise-golden-hour': moraineLakeSunriseLakeLouiseGoldenHourEn as ProductDescriptionData,
|
|
41
|
+
'moraine-lake-sunrise': moraineLakeSunriseEn as ProductDescriptionData,
|
|
42
|
+
'two-lakes-combo': twoLakesComboEn as ProductDescriptionData,
|
|
43
|
+
'moraine-lake-adventure': moraineLakeAdventureEn as ProductDescriptionData,
|
|
44
|
+
'lake-louise-adventure': lakeLouiseAdventureEn as ProductDescriptionData,
|
|
45
|
+
'emerald-lake-escape': emeraldLakeEscapeEn as ProductDescriptionData,
|
|
46
|
+
'afternoon-delight': afternoonDelightEn as ProductDescriptionData,
|
|
47
|
+
'private-tour': privateTourEn as ProductDescriptionData,
|
|
48
|
+
},
|
|
49
|
+
// Add fr, es etc. when files exist:
|
|
50
|
+
// fr: { ... },
|
|
51
|
+
};
|
|
52
|
+
|
|
53
|
+
export function getProductDescription(
|
|
54
|
+
slug: string,
|
|
55
|
+
locale: string
|
|
56
|
+
): ProductDescriptionResult | null {
|
|
57
|
+
const localeData = DESCRIPTIONS[locale] ?? DESCRIPTIONS.en;
|
|
58
|
+
const data = localeData?.[slug];
|
|
59
|
+
if (!data) return null;
|
|
60
|
+
return {
|
|
61
|
+
shortDescription: data.shortDescription,
|
|
62
|
+
paragraphs: data.paragraphs ?? [],
|
|
63
|
+
review: data.review,
|
|
64
|
+
sections: data.sections ?? [],
|
|
65
|
+
};
|
|
66
|
+
}
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Load products config from JSON (build-time / static).
|
|
3
|
+
* Later: can be swapped for API fetch or generated by TicketBooth script.
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import type { ProductsConfig, ProductConfig } from './booking-types';
|
|
7
|
+
import type { Product, ProductOption } from './booking-api';
|
|
8
|
+
import { getImageUrl } from '../constants/images';
|
|
9
|
+
|
|
10
|
+
// Import JSON - Next.js supports this; ensure tsconfig has "resolveJsonModule": true
|
|
11
|
+
import productsConfigJson from '../data/products-config.json';
|
|
12
|
+
|
|
13
|
+
const config = productsConfigJson as ProductsConfig;
|
|
14
|
+
|
|
15
|
+
export function getProductsConfig(): ProductsConfig {
|
|
16
|
+
return config;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export function getProductsForBooking(): ProductConfig[] {
|
|
20
|
+
return config.products;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export function getProductBySlug(slug: string): ProductConfig | null {
|
|
24
|
+
return config.products.find((p) => p.display.slug === slug) ?? null;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
export function getProductByOptionId(optionId: string): ProductConfig | null {
|
|
28
|
+
return (
|
|
29
|
+
config.products.find((p) => p.optionIds.includes(optionId)) ?? null
|
|
30
|
+
);
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
/** Find product by productId, optionId, or slug */
|
|
34
|
+
export function getProductByIdOrSlug(idOrSlug: string): ProductConfig | null {
|
|
35
|
+
const bySlug = getProductBySlug(idOrSlug);
|
|
36
|
+
if (bySlug) return bySlug;
|
|
37
|
+
const byOption = getProductByOptionId(idOrSlug);
|
|
38
|
+
if (byOption) return byOption;
|
|
39
|
+
return config.products.find((p) => p.productId === idOrSlug) ?? null;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* Build a minimal Product from config for immediate availability fetch.
|
|
44
|
+
* Use when API product is still loading - allows get-availabilities to run in parallel with /products.
|
|
45
|
+
*/
|
|
46
|
+
export function buildMinimalProductFromConfig(
|
|
47
|
+
config: ProductConfig,
|
|
48
|
+
companyId: string
|
|
49
|
+
): Product {
|
|
50
|
+
const options: ProductOption[] = config.optionIds.map((optionId) => ({
|
|
51
|
+
optionId,
|
|
52
|
+
name: '',
|
|
53
|
+
description: null,
|
|
54
|
+
pricing: {},
|
|
55
|
+
status: 'ACTIVE',
|
|
56
|
+
}));
|
|
57
|
+
return {
|
|
58
|
+
productId: config.productId,
|
|
59
|
+
companyId,
|
|
60
|
+
name: config.display.shortName,
|
|
61
|
+
description: null,
|
|
62
|
+
status: 'ACTIVE',
|
|
63
|
+
productType: config.productType ?? 'STANDARD',
|
|
64
|
+
options,
|
|
65
|
+
};
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
/** Get image URL for a product (first image from config) */
|
|
69
|
+
export function getProductImageUrl(product: ProductConfig): string {
|
|
70
|
+
const imageId = product.display.imageIds[0];
|
|
71
|
+
if (!imageId) return '';
|
|
72
|
+
return getImageUrl(imageId);
|
|
73
|
+
}
|
|
Binary file
|
|
Binary file
|
|
Binary file
|