@ticketboothapp/booking 0.1.20 → 0.1.23
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 +2 -1
- package/src/assets/icons/minus.svg +7 -0
- package/src/assets/icons/partner-logos/getyourguide.svg +8 -0
- package/src/assets/icons/plus.svg +3 -0
- package/src/colours.css +23 -0
- package/src/components/BookingDetails.module.css +1591 -0
- package/src/components/BookingDetails.tsx +2264 -0
- package/src/components/PhoneInputWithCountry.module.css +131 -0
- package/src/components/PhoneInputWithCountry.tsx +44 -0
- package/src/components/PickupLocationDialog.module.css +360 -0
- package/src/components/PickupLocationDialog.tsx +357 -0
- package/src/components/PostBookingDependentAddOnUpsell.module.css +174 -0
- package/src/components/PostBookingDependentAddOnUpsell.tsx +407 -0
- package/src/components/button.css +245 -0
- package/src/components/button.tsx +152 -0
- package/src/components/colorable-svg.tsx +29 -0
- package/src/components/image.css +29 -0
- package/src/components/image.tsx +113 -0
- package/src/components/product-tag.module.css +30 -0
- package/src/components/product-tag.tsx +34 -0
- package/src/components/product-theme-pages/image-modal.tsx +248 -0
- package/src/components/product-theme-pages/photo-gallery.module.css +200 -0
- package/src/components/terms/TermsContent.tsx +178 -0
- package/src/components/value-pill.module.css +59 -0
- package/src/components/value-pill.tsx +46 -0
- package/src/constants/images.ts +556 -0
- package/src/constants/pill-values.ts +210 -0
- package/src/constants/products.ts +155 -0
- package/src/data/dap-descriptions/session-couples-families-friends.en.json +61 -0
- package/src/data/dap-descriptions/session-elopements.en.json +60 -0
- package/src/data/dap-descriptions/session-proposals.en.json +60 -0
- 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/hooks/useBookingSourceMetadataFromLocation.ts +21 -0
- package/src/hooks/useIsBookingLaunchLive.ts +49 -0
- package/src/lib/photo-packages.ts +75 -0
- package/src/providers/dependent-add-on-dialog-provider.tsx +105 -0
- package/src/radius.css +5 -0
- package/src/spacing.css +7 -0
- package/src/strings/en.json +1774 -0
- package/src/strings/es.json +1573 -0
- package/src/strings/fr.json +1573 -0
- package/src/strings/index.js +23 -0
- package/src/text-style.css +56 -0
- package/src/utils/currency-converter.ts +101 -0
- package/tsconfig.json +1 -1
|
@@ -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
|
+
}
|
|
@@ -0,0 +1,155 @@
|
|
|
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
|
+
import { ProductTagStyle } from '@/components/product-tag';
|
|
4
|
+
|
|
5
|
+
export interface ProductTag {
|
|
6
|
+
text: string;
|
|
7
|
+
style: ProductTagStyle;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
export interface VideoSources {
|
|
11
|
+
src: string;
|
|
12
|
+
webm: string;
|
|
13
|
+
/** Long version for BookingFlow collage. Falls back to short (src/webm) if omitted. */
|
|
14
|
+
longSrc?: string;
|
|
15
|
+
longWebm?: string;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export interface Product {
|
|
19
|
+
id: string;
|
|
20
|
+
name: string;
|
|
21
|
+
shortName: string;
|
|
22
|
+
images: readonly ImageData[];
|
|
23
|
+
bookingLink: string;
|
|
24
|
+
currentStartTime: string;
|
|
25
|
+
description: string;
|
|
26
|
+
path: string;
|
|
27
|
+
avgPrice: number;
|
|
28
|
+
pillValues: PillValue[];
|
|
29
|
+
tags?: ProductTag[];
|
|
30
|
+
/** Video for expanded view in booking dialog. Place mp4 and webm in public/videos/ named {productId}.mp4 and {productId}.webm */
|
|
31
|
+
videoUrl?: VideoSources;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
// Type for accessing product keys
|
|
35
|
+
export type ProductKey = keyof ReturnType<typeof getProducts>;
|
|
36
|
+
|
|
37
|
+
export const getProducts = (strings: any): Record<string, Product> => ({
|
|
38
|
+
MORAINE_LAKE_SUNRISE_LAKE_LOUISE_GOLDEN_HOUR: {
|
|
39
|
+
id: 'moraine-lake-sunrise-lake-louise-golden-hour',
|
|
40
|
+
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' },
|
|
41
|
+
name: strings.products.productNames.moraineLakeSunriseLakeLouiseGoldenHour,
|
|
42
|
+
shortName: strings.products.productShortNames.moraineLakeSunriseLakeLouiseGoldenHourShort,
|
|
43
|
+
images: [
|
|
44
|
+
IMAGES.MORAINE_LAKE_CANOES_SUNRISE,
|
|
45
|
+
],
|
|
46
|
+
bookingLink: '#book-now/moraine-lake-sunrise-lake-louise-golden-hour',
|
|
47
|
+
currentStartTime: strings.products.startTimes.moraineLakeSunriseLakeLouiseGoldenHour,
|
|
48
|
+
description: strings.productThemePages.sunriseTours.description,
|
|
49
|
+
path: '/moraine-lake-sunrise-shuttle',
|
|
50
|
+
avgPrice: 159,
|
|
51
|
+
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)],
|
|
52
|
+
tags: [{
|
|
53
|
+
text: strings.products.productTags.mostPopular,
|
|
54
|
+
style: ProductTagStyle.MOST_POPULAR
|
|
55
|
+
}]
|
|
56
|
+
},
|
|
57
|
+
MORAINE_LAKE_SUNRISE: {
|
|
58
|
+
id: 'moraine-lake-sunrise',
|
|
59
|
+
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' },
|
|
60
|
+
name: strings.products.productNames.moraineLakeSunrise,
|
|
61
|
+
shortName: strings.products.productShortNames.moraineLakeSunriseShort,
|
|
62
|
+
images: [
|
|
63
|
+
IMAGES.MORAINE_LAKE_SUNRISE_CHEERS,
|
|
64
|
+
],
|
|
65
|
+
bookingLink: '#book-now/moraine-lake-sunrise',
|
|
66
|
+
currentStartTime: strings.products.startTimes.moraineLakeSunrise,
|
|
67
|
+
description: strings.productThemePages.sunriseTours.description,
|
|
68
|
+
path: '/moraine-lake-sunrise-shuttle',
|
|
69
|
+
avgPrice: 129,
|
|
70
|
+
pillValues: [createSunrisePillValue(strings), createDurationPillValue('moraine-lake-sunrise', strings), createAddTimePillValue('moraine-lake-sunrise', strings), createHotDrinksPillValue(strings), createCozyBlanketsPillValue(strings), createMoneyPillValue('moraine-lake-sunrise', strings)]
|
|
71
|
+
},
|
|
72
|
+
TWO_LAKES_COMBO: {
|
|
73
|
+
id: 'two-lakes-combo',
|
|
74
|
+
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' },
|
|
75
|
+
name: strings.products.productNames.twoLakesCombo,
|
|
76
|
+
shortName: strings.products.productShortNames.twoLakesComboShort,
|
|
77
|
+
images: [
|
|
78
|
+
IMAGES.MORAINE_LAKE_YELLOW_BIKINI,
|
|
79
|
+
],
|
|
80
|
+
bookingLink: '#book-now/two-lakes-combo',
|
|
81
|
+
currentStartTime: strings.products.startTimes.moraineLakeAdventure,
|
|
82
|
+
description: strings.products.productDescriptions.twoLakesCombo,
|
|
83
|
+
path: '/moraine-lake-shuttle',
|
|
84
|
+
avgPrice: 149,
|
|
85
|
+
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)],
|
|
86
|
+
tags: [{
|
|
87
|
+
text: strings.products.productTags.mostPopular,
|
|
88
|
+
style: ProductTagStyle.MOST_POPULAR
|
|
89
|
+
}]
|
|
90
|
+
},
|
|
91
|
+
MORAINE_LAKE_ADVENTURE: {
|
|
92
|
+
id: 'moraine-lake-adventure',
|
|
93
|
+
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' },
|
|
94
|
+
name: strings.products.productNames.moraineLakeAdventure,
|
|
95
|
+
shortName: strings.products.productShortNames.moraineLakeAdventureShort,
|
|
96
|
+
images: [
|
|
97
|
+
IMAGES.MORAINE_LAKE_CANOE,
|
|
98
|
+
],
|
|
99
|
+
bookingLink: '#book-now/moraine-lake-adventure',
|
|
100
|
+
currentStartTime: strings.products.startTimes.moraineLakeAdventure,
|
|
101
|
+
description: strings.productThemePages.moraineLakeShuttle.description,
|
|
102
|
+
path: '/moraine-lake-shuttle',
|
|
103
|
+
avgPrice: 95,
|
|
104
|
+
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)]
|
|
105
|
+
},
|
|
106
|
+
LAKE_LOUISE_ADVENTURE: {
|
|
107
|
+
id: 'lake-louise-adventure',
|
|
108
|
+
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' },
|
|
109
|
+
name: strings.products.productNames.lakeLouiseAdventure,
|
|
110
|
+
shortName: strings.products.productShortNames.lakeLouiseAdventureShort,
|
|
111
|
+
images: [
|
|
112
|
+
IMAGES.LAKE_LOUISE_FLORA,
|
|
113
|
+
],
|
|
114
|
+
bookingLink: '#book-now/lake-louise-adventure',
|
|
115
|
+
currentStartTime: strings.products.startTimes.lakeLouiseAdventure,
|
|
116
|
+
description: strings.productThemePages.lakeLouiseShuttle.description,
|
|
117
|
+
path: '/lake-louise-shuttle',
|
|
118
|
+
avgPrice: 69,
|
|
119
|
+
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)]
|
|
120
|
+
},
|
|
121
|
+
EMERALD_LAKE_ESCAPE: {
|
|
122
|
+
id: 'emerald-lake-escape',
|
|
123
|
+
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' },
|
|
124
|
+
name: strings.products.productNames.emeraldLakeEscapeTour,
|
|
125
|
+
shortName: strings.products.productShortNames.emeraldLakeEscapeTourShort,
|
|
126
|
+
images: [
|
|
127
|
+
IMAGES.EMERALD_LAKE_LODGE_VIEWPOINT,
|
|
128
|
+
],
|
|
129
|
+
bookingLink: '#book-now/emerald-lake-escape',
|
|
130
|
+
currentStartTime: strings.products.startTimes.emeraldLakeEscape,
|
|
131
|
+
description: strings.productThemePages.emeraldLakeShuttle.description,
|
|
132
|
+
path: '/emerald-lake-shuttle',
|
|
133
|
+
avgPrice: 175,
|
|
134
|
+
pillValues: [createDeparturePillValue('emerald-lake-escape', strings), createDurationPillValue('emerald-lake-escape', strings), ...createemeraldLakeEscapeTourLocationsPillValues(strings), createLunchPillValue(strings), createMoneyPillValue('emerald-lake-escape', strings)]
|
|
135
|
+
},
|
|
136
|
+
PRIVATE_TOUR: {
|
|
137
|
+
id: 'private-tour',
|
|
138
|
+
videoUrl: { src: '/videos/private-tour.mp4', webm: '/videos/private-tour.webm', longSrc: '/videos/private-tour-long.mp4', longWebm: '/videos/private-tour-long.webm' },
|
|
139
|
+
name: strings.products.productNames.privateTour,
|
|
140
|
+
shortName: strings.products.productShortNames.privateTourShort,
|
|
141
|
+
images: [
|
|
142
|
+
IMAGES.PRIVATE_TOUR_FAMILY_MORAINE_LAKE,
|
|
143
|
+
],
|
|
144
|
+
bookingLink: '#book-now/private-tour',
|
|
145
|
+
currentStartTime: strings.products.startTimes.privateTour,
|
|
146
|
+
description: strings.productThemePages.privateTours.description,
|
|
147
|
+
path: '/private-shuttle',
|
|
148
|
+
avgPrice: 1699,
|
|
149
|
+
pillValues: [createDeparturePillValue('private-tour', strings), createDurationPillValue('private-tour', strings), createCroissantPillValue(strings), createHotDrinksPillValue(strings), createMoneyPillValue('private-tour', strings)]
|
|
150
|
+
}
|
|
151
|
+
});
|
|
152
|
+
|
|
153
|
+
// Default export for backward compatibility (uses English strings)
|
|
154
|
+
import defaultStrings from '@/strings';
|
|
155
|
+
export const PRODUCTS = getProducts(defaultStrings);
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
{
|
|
2
|
+
"paragraphs": [
|
|
3
|
+
"Looking to create memories with your loved ones in one of the most breathtaking places on earth? Let us help you turn it into an unforgettable experience.",
|
|
4
|
+
"Whether it's a joyful family gathering, a meaningful moment with friends, or a romantic couples shoot, we know how to blend into the moment while capturing it beautifully - candid, natural, and full of connection."
|
|
5
|
+
],
|
|
6
|
+
"sections": [
|
|
7
|
+
{
|
|
8
|
+
"title": "What's included",
|
|
9
|
+
"content": [
|
|
10
|
+
{
|
|
11
|
+
"title": "30-minute session",
|
|
12
|
+
"items": [
|
|
13
|
+
"📸 20 to 25 minutes of photography time",
|
|
14
|
+
"📍 2 Locations within walking distance",
|
|
15
|
+
"🖼️ 25 professionally edited photos delivered in a personalized online gallery"
|
|
16
|
+
]
|
|
17
|
+
},
|
|
18
|
+
{
|
|
19
|
+
"title": "60-minute session",
|
|
20
|
+
"items": [
|
|
21
|
+
"📸 50 to 55 minutes of photography time",
|
|
22
|
+
"📍 2-3 Locations within walking distance",
|
|
23
|
+
"🖼️ 50 professionally edited photos delivered in a personalized online gallery"
|
|
24
|
+
]
|
|
25
|
+
},
|
|
26
|
+
{
|
|
27
|
+
"title": "90-minute session",
|
|
28
|
+
"items": [
|
|
29
|
+
"📸 80-90 mins of Photography Time",
|
|
30
|
+
"📍 5 Locations within walking distance",
|
|
31
|
+
"🖼️ 75 professionally edited photos delivered in a personalized online gallery"
|
|
32
|
+
]
|
|
33
|
+
},
|
|
34
|
+
{
|
|
35
|
+
"title": "Other details",
|
|
36
|
+
"items": [
|
|
37
|
+
"🖥️ Editing: Basic exposure and lighting adjustments + colour corrections",
|
|
38
|
+
"👭🏽 10 People Max per session"
|
|
39
|
+
]
|
|
40
|
+
}
|
|
41
|
+
]
|
|
42
|
+
},
|
|
43
|
+
{
|
|
44
|
+
"title": "Available add ons",
|
|
45
|
+
"content": [
|
|
46
|
+
"🏃♀️ Express Service - 7 Day turnaround on images - $300",
|
|
47
|
+
"🏃♀️💨 Super Express Service - 48-hour turnaround on images - $900",
|
|
48
|
+
"🔬 Additional Editing: Object Removal / Skin Retouching - $199/item",
|
|
49
|
+
"➕ Additional Images: 15 Additional Images - $99",
|
|
50
|
+
"♾️ The Works - Get ALL additional images taken on the day - $199"
|
|
51
|
+
]
|
|
52
|
+
},
|
|
53
|
+
{
|
|
54
|
+
"title": "Exclusions",
|
|
55
|
+
"content": [
|
|
56
|
+
"💵 Tips or Gratuities",
|
|
57
|
+
"🅿️ Parking Fees"
|
|
58
|
+
]
|
|
59
|
+
}
|
|
60
|
+
]
|
|
61
|
+
}
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
{
|
|
2
|
+
"paragraphs": [
|
|
3
|
+
"Planning to elope in one of the most breathtaking places on earth? Let us help you make it truly unforgettable. We know how to blend into the moment while capturing the joy of an intimate celebration beautifully."
|
|
4
|
+
],
|
|
5
|
+
"sections": [
|
|
6
|
+
{
|
|
7
|
+
"title": "What's included",
|
|
8
|
+
"content": [
|
|
9
|
+
{
|
|
10
|
+
"title": "30-minute session",
|
|
11
|
+
"items": [
|
|
12
|
+
"📸 20 to 25 minutes of photography time",
|
|
13
|
+
"📍 2 Locations within walking distance",
|
|
14
|
+
"🖼️ 25 professionally edited photos delivered in a personalized online gallery"
|
|
15
|
+
]
|
|
16
|
+
},
|
|
17
|
+
{
|
|
18
|
+
"title": "60-minute session",
|
|
19
|
+
"items": [
|
|
20
|
+
"📸 50 to 55 minutes of photography time",
|
|
21
|
+
"📍 2-3 Locations within walking distance",
|
|
22
|
+
"🖼️ 50 professionally edited photos delivered in a personalized online gallery"
|
|
23
|
+
]
|
|
24
|
+
},
|
|
25
|
+
{
|
|
26
|
+
"title": "90-minute session",
|
|
27
|
+
"items": [
|
|
28
|
+
"📸 80-90 mins of Photography Time",
|
|
29
|
+
"📍 5 Locations within walking distance",
|
|
30
|
+
"🖼️ 75 professionally edited photos delivered in a personalized online gallery"
|
|
31
|
+
]
|
|
32
|
+
},
|
|
33
|
+
{
|
|
34
|
+
"title": "Other details",
|
|
35
|
+
"items": [
|
|
36
|
+
"🖥️ Editing: Basic exposure and lighting adjustments + colour corrections",
|
|
37
|
+
"👭🏽 2 People Max per session"
|
|
38
|
+
]
|
|
39
|
+
}
|
|
40
|
+
]
|
|
41
|
+
},
|
|
42
|
+
{
|
|
43
|
+
"title": "Available add ons",
|
|
44
|
+
"content": [
|
|
45
|
+
"🏃♀️ Express Service - 7 Day turnaround on images - $300",
|
|
46
|
+
"🏃♀️💨 Super Express Service - 48-hour turnaround on images - $900",
|
|
47
|
+
"🔬 Additional Editing: Object Removal / Skin Retouching - $199/item",
|
|
48
|
+
"➕ Additional Images: 15 Additional Images - $99",
|
|
49
|
+
"♾️ The Works - Get ALL additional images taken on the day - $199"
|
|
50
|
+
]
|
|
51
|
+
},
|
|
52
|
+
{
|
|
53
|
+
"title": "Exclusions",
|
|
54
|
+
"content": [
|
|
55
|
+
"💵 Tips or Gratuities",
|
|
56
|
+
"🅿️ Parking Fees"
|
|
57
|
+
]
|
|
58
|
+
}
|
|
59
|
+
]
|
|
60
|
+
}
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
{
|
|
2
|
+
"paragraphs": [
|
|
3
|
+
"Planning to propose in one of the most breathtaking places on earth? Let us help you make it truly unforgettable. We know how to blend into the moment while capturing the joy of an intimate celebration beautifully."
|
|
4
|
+
],
|
|
5
|
+
"sections": [
|
|
6
|
+
{
|
|
7
|
+
"title": "What's included",
|
|
8
|
+
"content": [
|
|
9
|
+
{
|
|
10
|
+
"title": "30-minute session",
|
|
11
|
+
"items": [
|
|
12
|
+
"📸 20 to 25 minutes of photography time",
|
|
13
|
+
"📍 2 Locations within walking distance",
|
|
14
|
+
"🖼️ 25 professionally edited photos delivered in a personalized online gallery"
|
|
15
|
+
]
|
|
16
|
+
},
|
|
17
|
+
{
|
|
18
|
+
"title": "60-minute session",
|
|
19
|
+
"items": [
|
|
20
|
+
"📸 50 to 55 minutes of photography time",
|
|
21
|
+
"📍 2-3 Locations within walking distance",
|
|
22
|
+
"🖼️ 50 professionally edited photos delivered in a personalized online gallery"
|
|
23
|
+
]
|
|
24
|
+
},
|
|
25
|
+
{
|
|
26
|
+
"title": "90-minute session",
|
|
27
|
+
"items": [
|
|
28
|
+
"📸 80-90 mins of Photography Time",
|
|
29
|
+
"📍 5 Locations within walking distance",
|
|
30
|
+
"🖼️ 75 professionally edited photos delivered in a personalized online gallery"
|
|
31
|
+
]
|
|
32
|
+
},
|
|
33
|
+
{
|
|
34
|
+
"title": "Other details",
|
|
35
|
+
"items": [
|
|
36
|
+
"🖥️ Editing: Basic exposure and lighting adjustments + colour corrections",
|
|
37
|
+
"👭🏽 2 People Max per session"
|
|
38
|
+
]
|
|
39
|
+
}
|
|
40
|
+
]
|
|
41
|
+
},
|
|
42
|
+
{
|
|
43
|
+
"title": "Available add ons",
|
|
44
|
+
"content": [
|
|
45
|
+
"🏃♀️ Express Service - 7 Day turnaround on images - $300",
|
|
46
|
+
"🏃♀️💨 Super Express Service - 48-hour turnaround on images - $900",
|
|
47
|
+
"🔬 Additional Editing: Object Removal / Skin Retouching - $199/item",
|
|
48
|
+
"➕ Additional Images: 15 Additional Images - $99",
|
|
49
|
+
"♾️ The Works - Get ALL additional images taken on the day - $199"
|
|
50
|
+
]
|
|
51
|
+
},
|
|
52
|
+
{
|
|
53
|
+
"title": "Exclusions",
|
|
54
|
+
"content": [
|
|
55
|
+
"💵 Tips or Gratuities",
|
|
56
|
+
"🅿️ Parking Fees"
|
|
57
|
+
]
|
|
58
|
+
}
|
|
59
|
+
]
|
|
60
|
+
}
|
|
@@ -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
|
+
}
|