@ticketboothapp/booking 0.1.19 → 0.1.20

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (154) hide show
  1. package/package.json +1 -1
  2. package/src/components/BookingWidget.tsx +282 -26
  3. package/src/components/ManageBookingView.tsx +75 -23
  4. package/src/components/booking/BookingProductGrid.tsx +1 -1
  5. package/src/components/booking/Calendar.module.css +3 -3
  6. package/src/components/booking/CheckoutForm.tsx +1 -1
  7. package/src/components/booking/InfoTooltip.tsx +2 -13
  8. package/src/components/booking/PickupLocationSelector.tsx +2 -2
  9. package/src/components/booking/PriceBreakdown.tsx +11 -34
  10. package/src/index.ts +3 -1
  11. package/src/app/photo-sessions/photo-packages.ts +0 -75
  12. package/src/assets/icons/minus.svg +0 -7
  13. package/src/assets/icons/partner-logos/getyourguide.svg +0 -8
  14. package/src/assets/icons/plus.svg +0 -3
  15. package/src/colours.css +0 -23
  16. package/src/components/BookingDetails.module.css +0 -1591
  17. package/src/components/BookingDetails.tsx +0 -2264
  18. package/src/components/JobApplicationDialog.module.css +0 -440
  19. package/src/components/JobApplicationDialog.tsx +0 -620
  20. package/src/components/PhoneInputWithCountry.module.css +0 -131
  21. package/src/components/PhoneInputWithCountry.tsx +0 -44
  22. package/src/components/PickupLocationDialog.module.css +0 -360
  23. package/src/components/PickupLocationDialog.tsx +0 -357
  24. package/src/components/PickupLocationMap.tsx +0 -110
  25. package/src/components/PostBookingDependentAddOnUpsell.module.css +0 -174
  26. package/src/components/PostBookingDependentAddOnUpsell.tsx +0 -407
  27. package/src/components/accordion.css +0 -27
  28. package/src/components/accordion.tsx +0 -29
  29. package/src/components/analytics/AnalyticsConsentRestore.tsx +0 -19
  30. package/src/components/analytics/AnalyticsScripts.tsx +0 -106
  31. package/src/components/analytics/CookieConsentBanner.css +0 -86
  32. package/src/components/analytics/CookieConsentBanner.tsx +0 -102
  33. package/src/components/bottom-sheet.module.css +0 -78
  34. package/src/components/bottom-sheet.tsx +0 -60
  35. package/src/components/breadcrumb.module.css +0 -40
  36. package/src/components/breadcrumb.tsx +0 -36
  37. package/src/components/button.css +0 -245
  38. package/src/components/button.tsx +0 -152
  39. package/src/components/client-bottom-sheet.tsx +0 -14
  40. package/src/components/colorable-svg.tsx +0 -29
  41. package/src/components/conditional-footer.tsx +0 -27
  42. package/src/components/contact-us.module.css +0 -147
  43. package/src/components/contact-us.tsx +0 -49
  44. package/src/components/email-signup.css +0 -151
  45. package/src/components/email-signup.tsx +0 -63
  46. package/src/components/faq-wrapper.module.css +0 -47
  47. package/src/components/faq-wrapper.tsx +0 -15
  48. package/src/components/footer.css +0 -187
  49. package/src/components/footer.tsx +0 -143
  50. package/src/components/global-simple-modal.tsx +0 -33
  51. package/src/components/google-review-summary.module.css +0 -77
  52. package/src/components/google-review-summary.tsx +0 -50
  53. package/src/components/hero-image.css +0 -13
  54. package/src/components/hero-image.tsx +0 -44
  55. package/src/components/image.css +0 -29
  56. package/src/components/image.tsx +0 -113
  57. package/src/components/language-aware-link.tsx +0 -72
  58. package/src/components/language-switcher.module.css +0 -124
  59. package/src/components/language-switcher.tsx +0 -75
  60. package/src/components/map-section.css +0 -59
  61. package/src/components/map-section.tsx +0 -63
  62. package/src/components/navbar.module.css +0 -152
  63. package/src/components/navbar.tsx +0 -125
  64. package/src/components/parallax-provider.tsx +0 -11
  65. package/src/components/product-tag.module.css +0 -30
  66. package/src/components/product-tag.tsx +0 -34
  67. package/src/components/product-theme-pages/best-option.module.css +0 -70
  68. package/src/components/product-theme-pages/best-option.tsx +0 -35
  69. package/src/components/product-theme-pages/extended-tour-options.module.css +0 -22
  70. package/src/components/product-theme-pages/extended-tour-options.tsx +0 -11
  71. package/src/components/product-theme-pages/image-modal.tsx +0 -248
  72. package/src/components/product-theme-pages/photo-gallery.module.css +0 -200
  73. package/src/components/product-theme-pages/photo-gallery.tsx +0 -90
  74. package/src/components/product-theme-pages/product-theme-page-layout.module.css +0 -13
  75. package/src/components/product-theme-pages/product-theme-page-layout.tsx +0 -67
  76. package/src/components/product-theme-pages/top-of-fold.module.css +0 -179
  77. package/src/components/product-theme-pages/top-of-fold.tsx +0 -80
  78. package/src/components/product-tile/image-only-product-tile-desktop.module.css +0 -106
  79. package/src/components/product-tile/image-only-product-tile-desktop.tsx +0 -56
  80. package/src/components/product-tile/image-only-product-tile-mobile.module.css +0 -122
  81. package/src/components/product-tile/image-only-product-tile-mobile.tsx +0 -89
  82. package/src/components/product-tile/image-only-product-tile.tsx +0 -44
  83. package/src/components/product-tile/product-tile-card.module.css +0 -84
  84. package/src/components/product-tile/product-tile-card.tsx +0 -61
  85. package/src/components/review-highlights-section.css +0 -85
  86. package/src/components/review-highlights-section.tsx +0 -127
  87. package/src/components/season-closure-overlay.module.css +0 -99
  88. package/src/components/season-closure-overlay.tsx +0 -98
  89. package/src/components/simple-modal.tsx +0 -69
  90. package/src/components/simple-top-of-fold.module.css +0 -76
  91. package/src/components/simple-top-of-fold.tsx +0 -34
  92. package/src/components/spacer.css +0 -41
  93. package/src/components/spacer.tsx +0 -23
  94. package/src/components/star-rating.module.css +0 -74
  95. package/src/components/star-rating.tsx +0 -48
  96. package/src/components/terms/TermsContent.tsx +0 -178
  97. package/src/components/title-subtitle.module.css +0 -10
  98. package/src/components/title-subtitle.tsx +0 -30
  99. package/src/components/translatable-reviews.tsx +0 -75
  100. package/src/components/value-pill.module.css +0 -59
  101. package/src/components/value-pill.tsx +0 -46
  102. package/src/components/value-props.css +0 -185
  103. package/src/components/value-props.tsx +0 -88
  104. package/src/constants/booking-guide-quiz.ts +0 -64
  105. package/src/constants/contact-info.ts +0 -2
  106. package/src/constants/faq.ts +0 -44
  107. package/src/constants/images.ts +0 -556
  108. package/src/constants/json-ld/faq-json-ld.tsx +0 -170
  109. package/src/constants/json-ld/homepage-json-ld.tsx +0 -138
  110. package/src/constants/json-ld/job-posting-json-ld.tsx +0 -92
  111. package/src/constants/json-ld/organization-json-ld.tsx +0 -62
  112. package/src/constants/json-ld/page-json-ld.tsx +0 -6
  113. package/src/constants/json-ld/product-json-ld.tsx +0 -154
  114. package/src/constants/json-ld/review-json-ld.tsx +0 -377
  115. package/src/constants/navigation-links/footer-links.ts +0 -48
  116. package/src/constants/navigation-links/nav-bar-links.ts +0 -41
  117. package/src/constants/navigation-links/navigation-link.ts +0 -6
  118. package/src/constants/pill-values.ts +0 -210
  119. package/src/constants/products.ts +0 -155
  120. package/src/constants/quiz-recommendations.ts +0 -506
  121. package/src/constants/reviews.ts +0 -75
  122. package/src/constants/staff.ts +0 -197
  123. package/src/constants/value-props.ts +0 -58
  124. package/src/data/dap-descriptions/session-couples-families-friends.en.json +0 -61
  125. package/src/data/dap-descriptions/session-elopements.en.json +0 -60
  126. package/src/data/dap-descriptions/session-proposals.en.json +0 -60
  127. package/src/data/product-descriptions/afternoon-delight.en.json +0 -35
  128. package/src/data/product-descriptions/emerald-lake-escape.en.json +0 -68
  129. package/src/data/product-descriptions/lake-louise-adventure.en.json +0 -74
  130. package/src/data/product-descriptions/moraine-lake-adventure.en.json +0 -78
  131. package/src/data/product-descriptions/moraine-lake-sunrise-lake-louise-golden-hour.en.json +0 -65
  132. package/src/data/product-descriptions/moraine-lake-sunrise.en.json +0 -64
  133. package/src/data/product-descriptions/private-tour.en.json +0 -80
  134. package/src/data/product-descriptions/two-lakes-combo.en.json +0 -65
  135. package/src/data/products-config.json +0 -101
  136. package/src/hooks/use-bottom-sheet.tsx +0 -15
  137. package/src/hooks/use-simple-modal.tsx +0 -27
  138. package/src/hooks/useBookingSourceMetadataFromLocation.ts +0 -21
  139. package/src/hooks/useEmailSubscription.tsx +0 -103
  140. package/src/hooks/useEmbeddedInIframe.ts +0 -16
  141. package/src/hooks/useIsBookingLaunchLive.ts +0 -49
  142. package/src/hooks/useQuiz.tsx +0 -210
  143. package/src/providers/bottom-sheet-provider.tsx +0 -40
  144. package/src/providers/dependent-add-on-dialog-provider.tsx +0 -105
  145. package/src/radius.css +0 -5
  146. package/src/spacing.css +0 -7
  147. package/src/strings/en.json +0 -1774
  148. package/src/strings/es.json +0 -1573
  149. package/src/strings/fr.json +0 -1573
  150. package/src/strings/index.js +0 -23
  151. package/src/text-style.css +0 -97
  152. package/src/types/fareharbor.d.ts +0 -12
  153. package/src/types/quiz.ts +0 -59
  154. package/src/utils/currency-converter.ts +0 -101
@@ -1,90 +0,0 @@
1
- "use client";
2
-
3
- import { ImageData } from "@/constants/images";
4
- import ViaViaImage from "@/components/image";
5
- import styles from "./photo-gallery.module.css";
6
- import { useState, lazy, Suspense, useEffect } from "react";
7
-
8
- // Lazy load the modal component
9
- const ImageModal = lazy(() => import('@/components/product-theme-pages/image-modal'));
10
-
11
- interface PhotoGalleryProps {
12
- photos: ImageData[];
13
- }
14
-
15
- export default function PhotoGallery({ photos }: PhotoGalleryProps) {
16
- const [selectedImage, setSelectedImage] = useState<ImageData | null>(null);
17
- const [currentIndex, setCurrentIndex] = useState<number>(0);
18
- const [isMobile, setIsMobile] = useState(false);
19
- const [isClient, setIsClient] = useState(false);
20
-
21
- useEffect(() => {
22
- setIsClient(true);
23
- setIsMobile(window.innerWidth <= 1023);
24
-
25
- const handleResize = () => {
26
- setIsMobile(window.innerWidth <= 1023);
27
- };
28
-
29
- window.addEventListener('resize', handleResize);
30
- return () => window.removeEventListener('resize', handleResize);
31
- }, []);
32
-
33
- // Only show first 9 photos on mobile
34
- const displayPhotos = isClient && isMobile ? photos.slice(0, 9) : photos;
35
-
36
- const handleImageClick = (photo: ImageData) => {
37
- const index = photos.findIndex(p => p.id === photo.id);
38
- setCurrentIndex(index);
39
- setSelectedImage(photo);
40
- };
41
-
42
- return (
43
- <>
44
- <div className={styles.photoGallery}>
45
- <div className={styles.grid}>
46
- {displayPhotos.map((photo) => (
47
- <div
48
- key={photo.id}
49
- className={styles.photoItem}
50
- onClick={() => handleImageClick(photo)}
51
- >
52
- <ViaViaImage
53
- imageId={photo.id}
54
- alt={photo.alt}
55
- context="GALLERY"
56
- className={styles.galleryImage}
57
- />
58
- </div>
59
- ))}
60
- </div>
61
- </div>
62
-
63
- {selectedImage && (
64
- <Suspense fallback={<div className={styles.modalOverlay}>Loading...</div>}>
65
- <ImageModal
66
- selectedImage={selectedImage}
67
- currentIndex={currentIndex}
68
- totalImages={photos.length}
69
- images={photos}
70
- onClose={() => setSelectedImage(null)}
71
- onNext={() => {
72
- if (currentIndex < photos.length - 1) {
73
- const newIndex = currentIndex + 1;
74
- setCurrentIndex(newIndex);
75
- setSelectedImage(photos[newIndex]);
76
- }
77
- }}
78
- onPrevious={() => {
79
- if (currentIndex > 0) {
80
- const newIndex = currentIndex - 1;
81
- setCurrentIndex(newIndex);
82
- setSelectedImage(photos[newIndex]);
83
- }
84
- }}
85
- />
86
- </Suspense>
87
- )}
88
- </>
89
- );
90
- }
@@ -1,13 +0,0 @@
1
- .productThemePageLayout {
2
- background-color: var(--light-orange-background);
3
- }
4
-
5
- .titleSubtitle {
6
- max-width: 1200px;
7
- padding: var(--spacing-medium);
8
- margin: 0 auto;
9
- }
10
-
11
- .reviewHighlightsSection {
12
- margin-top: var(--spacing-large);
13
- }
@@ -1,67 +0,0 @@
1
- "use client";
2
-
3
- import TopOfFold from "@/components/product-theme-pages/top-of-fold";
4
- import { TopOfFoldProps } from "@/components/product-theme-pages/top-of-fold";
5
- import TitleSubtitle from "../title-subtitle";
6
- import defaultStrings from "@/strings";
7
- import styles from "./product-theme-page-layout.module.css";
8
- import { VALUE_PROPS_KEYS } from "@/constants/value-props";
9
- import ValueProps from "@/components/value-props";
10
- import ReviewHighlightsSection from "@/components/review-highlights-section";
11
- import MapSection from "../map-section";
12
- import FAQWrapper from "@/components/faq-wrapper";
13
- import { faqSection } from "@/constants/faq";
14
- import Navbar from "@/components/navbar";
15
- import BestOption from "./best-option";
16
- import { Product } from "@/constants/products";
17
- import { pageJsonLd } from "@/constants/json-ld/page-json-ld";
18
- import { organizationJsonLd } from "@/constants/json-ld/organization-json-ld";
19
- import { aggregateRatingJsonLd } from "@/constants/json-ld/review-json-ld";
20
- import PhotoGallery from "./photo-gallery";
21
- import { ImageData } from "@/constants/images";
22
- import ExtendedTourOptions from "./extended-tour-options";
23
-
24
- interface ProductThemePageLayoutProps {
25
- topOfFoldProps: TopOfFoldProps;
26
- description: string;
27
- photoGalleryPhotos: ImageData[];
28
- includeExtendedTourOptions: boolean;
29
- valuePropsKeys: VALUE_PROPS_KEYS[];
30
- valuePropsTitle?: string;
31
- faqSection: faqSection;
32
- bestOptionProducts: Product[];
33
- otherProductThemePages: { title: string, path: string }[];
34
- productJsonLd: any[];
35
- }
36
-
37
- export default function ProductThemePageLayout(props: ProductThemePageLayoutProps & { strings?: any }) {
38
- const { topOfFoldProps, description, photoGalleryPhotos, includeExtendedTourOptions, valuePropsKeys, valuePropsTitle, faqSection, bestOptionProducts, otherProductThemePages, strings = defaultStrings } = props;
39
- return (
40
- <div>
41
- <Navbar stickyMode="showAndStickyOrMobileOverlap"/>
42
- <TopOfFold {...topOfFoldProps} />
43
- <div className={styles.productThemePageLayout}>
44
- <TitleSubtitle
45
- className={styles.titleSubtitle}
46
- title={strings.productThemePages.title}
47
- subtitle={strings.productThemePages.subtitle}
48
- description={description}
49
- />
50
- {includeExtendedTourOptions && <ExtendedTourOptions />}
51
- <ValueProps filterKeys={valuePropsKeys} title={valuePropsTitle} strings={strings} />
52
- {photoGalleryPhotos && photoGalleryPhotos.length > 0 && (
53
- <PhotoGallery photos={photoGalleryPhotos} />
54
- )}
55
- <BestOption bestOptionProducts={bestOptionProducts} otherProductThemePages={otherProductThemePages} strings={strings} />
56
- <FAQWrapper faqSection={faqSection} strings={strings} />
57
- <ReviewHighlightsSection className={styles.reviewHighlightsSection} strings={strings} />
58
- <MapSection title={strings.productThemePages.mapSection.title} />
59
- </div>
60
-
61
- <script
62
- type="application/ld+json"
63
- dangerouslySetInnerHTML={{ __html: JSON.stringify(pageJsonLd([organizationJsonLd, aggregateRatingJsonLd, ...props.productJsonLd])) }}
64
- />
65
- </div>
66
- )
67
- }
@@ -1,179 +0,0 @@
1
- .topOfFold {
2
- position: relative;
3
- width: 100vw;
4
- overflow: hidden;
5
- }
6
-
7
- .heroImageWrapper {
8
- position: absolute;
9
- top: 0;
10
- left: 0;
11
- width: 100%;
12
- height: 100%;
13
- z-index: 2;
14
- }
15
-
16
- .heroCenterText {
17
- position: absolute;
18
- top: 50%;
19
- left: 50%;
20
- transform: translate(-50%, -50%);
21
- z-index: 3;
22
- pointer-events: none;
23
- font-size: 3rem;
24
- line-height: 0.7;
25
- font-weight: 900;
26
- color: #fff;
27
- text-shadow: 0 0 8px rgba(0,0,0,0.4);
28
- font-family: 'Snell Roundhand', sans-serif;
29
- text-transform: lowercase;
30
- text-align: center;
31
- }
32
-
33
- .heroOverlayContent {
34
- position: absolute;
35
- top: 7rem;
36
- bottom: 4rem;
37
- left: 0.5rem;
38
- right: 0.5rem;
39
- left: 0;
40
- width: 100%;
41
- z-index: 2;
42
- display: flex;
43
- flex-direction: column;
44
- justify-content: space-between;
45
- align-items: center;
46
- }
47
-
48
- .heroTopContent {
49
- width: 100%;
50
- display: flex;
51
- flex-direction: column;
52
- align-items: center;
53
- display: flex;
54
- justify-content: center;
55
- }
56
-
57
- .heroBottomContent {
58
- width: 100%;
59
- display: flex;
60
- flex-direction: column;
61
- align-items: center;
62
- }
63
-
64
- .heroTitle {
65
- color: var(--accent-white);
66
- font-size: 5rem;
67
- line-height: 1.2;
68
- text-align: center;
69
- text-shadow: 2px 2px 4px rgba(0, 0, 0, 0.5);
70
- text-transform: none;
71
- }
72
-
73
- .heroSubtitle {
74
- color: var(--accent-white);
75
- font-size: 2rem;
76
- text-align: center;
77
- text-shadow: 2px 2px 4px rgba(0, 0, 0, 0.5);
78
- }
79
-
80
- .closureOverlayBackdrop {
81
- position: absolute;
82
- top: 0;
83
- left: 0;
84
- right: 0;
85
- bottom: 0;
86
- background: rgba(0, 0, 0, 0.5);
87
- backdrop-filter: blur(3px);
88
- z-index: 3;
89
- display: flex;
90
- align-items: center;
91
- justify-content: center;
92
- }
93
-
94
- .seasonClosureCallout {
95
- width: 90%;
96
- max-width: 500px;
97
- z-index: 4;
98
- display: flex;
99
- flex-direction: column;
100
- align-items: center;
101
- text-align: center;
102
- gap: 0.5rem;
103
- pointer-events: none;
104
- }
105
-
106
- .seasonClosureCallout * {
107
- pointer-events: auto;
108
- }
109
-
110
- .closureOverlayTop {
111
- display: flex;
112
- flex-direction: column;
113
- align-items: center;
114
- text-align: center;
115
- gap: 0.1rem;
116
- }
117
-
118
- .closureOverlayBottom {
119
- display: flex;
120
- flex-direction: column;
121
- align-items: center;
122
- text-align: center;
123
- }
124
-
125
- .closureTitle {
126
- font-size: 4rem;
127
- line-height: 0.7;
128
- font-weight: 900;
129
- color: #fff;
130
- text-shadow: 0 0 8px rgba(0,0,0,0.4);
131
- font-family: 'Snell Roundhand', sans-serif;
132
- text-transform: lowercase;
133
- text-align: center;
134
- margin-bottom: -0.2rem;
135
- }
136
-
137
- .closureSubtitle {
138
- font-size: 1.8rem;
139
- line-height: 1;
140
- font-weight: 400;
141
- color: #fff;
142
- text-shadow: 0 0 8px rgba(0,0,0,0.4);
143
- letter-spacing: 0.5px;
144
- font-family: 'Northlake', sans-serif;
145
- text-transform: lowercase;
146
- text-align: center;
147
- }
148
-
149
- .closureSubSubtitle {
150
- font-size: 1.2rem;
151
- line-height: 1.1;
152
- font-weight: 400;
153
- color: #fff;
154
- text-shadow: 0 0 8px rgba(0,0,0,0.4);
155
- letter-spacing: 0.5px;
156
- font-family: 'Northlake', sans-serif;
157
- text-transform: lowercase;
158
- text-align: center;
159
- }
160
-
161
- @media (min-width: 1024px) {
162
- .topOfFold {
163
- height: calc(100vh - 98px);
164
- }
165
- }
166
-
167
- @media (max-width: 1023px) {
168
- .heroTitle {
169
- font-size: 3rem;
170
- }
171
-
172
- .heroSubtitle {
173
- font-size: 1.2rem;
174
- }
175
-
176
- .topOfFold {
177
- height: 100vh;
178
- }
179
- }
@@ -1,80 +0,0 @@
1
- "use client";
2
-
3
- import styles from './top-of-fold.module.css';
4
- import { ImageData } from '@/constants/images';
5
- import HeroImage from '@/components/hero-image';
6
- import strings from '@/strings';
7
- import Button, { PresetButtonActions } from '@/components/button';
8
- import GoogleReviewSummary from '@/components/google-review-summary';
9
- import SeasonClosureOverlay from '@/components/season-closure-overlay';
10
- import {
11
- OPEN_BOOKING_FOR_PRODUCT,
12
- OPEN_BOOKING_WITH_FILTER,
13
- type ProductGridFilterId,
14
- } from '@/providers/booking-dialog-provider';
15
- import { useIsBookingLaunchLive } from '@/hooks/useIsBookingLaunchLive';
16
-
17
- export interface TopOfFoldProps {
18
- image: ImageData;
19
- title: string;
20
- subtitle: string;
21
- /** Open product grid with this filter pre-applied (e.g. 'moraine-lake', 'sunrise'). */
22
- bookFilterId?: ProductGridFilterId;
23
- /** Product slug to open directly. Use when page has a single primary product. */
24
- bookProductSlug?: string;
25
- /** Fallback when neither bookFilterId nor bookProductSlug (e.g. home page). */
26
- bookButtonAction?: PresetButtonActions;
27
- }
28
-
29
- export default function TopOfFold(props: TopOfFoldProps) {
30
- const { image, title, subtitle, bookFilterId, bookProductSlug, bookButtonAction = PresetButtonActions.BOOK_ALL } = props;
31
- const isLaunchLive = useIsBookingLaunchLive();
32
-
33
- const handleBookClick = () => {
34
- if (bookFilterId) {
35
- window.dispatchEvent(new CustomEvent(OPEN_BOOKING_WITH_FILTER, { detail: { filterId: bookFilterId } }));
36
- } else if (bookProductSlug) {
37
- window.dispatchEvent(new CustomEvent(OPEN_BOOKING_FOR_PRODUCT, { detail: { productId: bookProductSlug } }));
38
- } else {
39
- window.dispatchEvent(new CustomEvent('openSimpleModal'));
40
- }
41
- };
42
-
43
- const hasCustomBookAction = bookFilterId || bookProductSlug;
44
-
45
- return (
46
- <div className={`${styles.topOfFold} global-top-fold`}>
47
- {isLaunchLive && <div className={styles.heroCenterText}>{strings.home.hero.centerCallout}</div>}
48
- <div className={styles.heroImageWrapper}>
49
- <HeroImage
50
- imageId={image.id}
51
- alt={image.alt}
52
- />
53
- </div>
54
-
55
- <div className={styles.heroOverlayContent}>
56
- <div className={styles.heroTopContent}>
57
- <h1 className={styles.heroTitle}>{title}</h1>
58
- <h2 className={styles.heroSubtitle}>{subtitle}</h2>
59
- </div>
60
-
61
- <div className={styles.heroBottomContent}>
62
- <GoogleReviewSummary strings={strings} />
63
- {hasCustomBookAction ? (
64
- <button
65
- type="button"
66
- onClick={handleBookClick}
67
- className="button button-primary hover-white button-large"
68
- >
69
- {strings.common.bookNow}
70
- </button>
71
- ) : (
72
- <Button isLarge={true} action={bookButtonAction}>{strings.common.bookNow}</Button>
73
- )}
74
- </div>
75
- </div>
76
-
77
- {!isLaunchLive && <SeasonClosureOverlay strings={strings} />}
78
- </div>
79
- );
80
- }
@@ -1,106 +0,0 @@
1
- .productTile {
2
- height: 100%;
3
- width: 100%;
4
- text-decoration: none;
5
- position: relative;
6
- cursor: pointer;
7
- }
8
-
9
- .productTileImageContainer {
10
- width: 100%;
11
- height: 420px;
12
- position: relative;
13
- border-radius: 10px;
14
- overflow: hidden;
15
- }
16
-
17
- .productTileImage {
18
- width: 100%;
19
- height: 100%;
20
- position: relative;
21
- transition: transform 0.3s ease-in-out;
22
- will-change: transform;
23
- }
24
-
25
- .productTile:hover .productTileImage {
26
- transform: scale(1.1);
27
- }
28
-
29
- .productTileImage::after {
30
- content: '';
31
- position: absolute;
32
- bottom: 0;
33
- left: 0;
34
- right: 0;
35
- height: 30%;
36
- background: linear-gradient(to top, rgba(0,0,0,0.5), transparent);
37
- z-index: 1;
38
- }
39
-
40
- .productTileContentOverlay {
41
- position: absolute;
42
- top: 0;
43
- left: 0;
44
- right: 0;
45
- padding: var(--spacing-medium);
46
- z-index: 2;
47
- display: flex;
48
- flex-direction: column;
49
- }
50
-
51
- .productTileTags {
52
- display: flex;
53
- flex-direction: row;
54
- gap: var(--spacing-small);
55
- }
56
-
57
- .productTileTitle {
58
- margin: 0;
59
- color: white;
60
- text-shadow: 0 0 10px rgba(0, 0, 0, 0.5);
61
- line-height: 1.0;
62
- }
63
-
64
- .productStartTime {
65
- position: absolute;
66
- bottom: 0;
67
- right: 0;
68
- color: #FFFFFF;
69
- font-family: 'Northlake', sans-serif;
70
- font-weight: 400;
71
- font-size: 3rem;
72
- text-align: right;
73
- z-index: 2;
74
- line-height: 0.8;
75
- transform: translateZ(0);
76
- backface-visibility: hidden;
77
- -webkit-font-smoothing: antialiased;
78
- will-change: transform;
79
- }
80
-
81
- .productTilePillValuesView {
82
- position: absolute;
83
- top: 0;
84
- left: 0;
85
- width: 100%;
86
- height: 100%;
87
- display: flex;
88
- flex-direction: column;
89
- align-items: center;
90
- justify-content: center;
91
- gap: 8px;
92
- opacity: 0;
93
- transition: opacity 0.3s;
94
- background: rgba(0, 0, 0, 0.7);
95
- z-index: 3;
96
- }
97
-
98
- .productTileImageContainer:hover .productTilePillValuesView {
99
- opacity: 1;
100
- }
101
-
102
- .productTile:hover .productStartTime,
103
- .productTile:hover .productTileTitle {
104
- opacity: 0;
105
- transition: opacity 0.3s ease-in-out;
106
- }
@@ -1,56 +0,0 @@
1
- "use client";
2
-
3
- import { Product } from "@/constants/products"
4
- import ViaViaImage from "../image"
5
- import styles from "./image-only-product-tile-desktop.module.css"
6
- import { PillVariant } from "../value-pill"
7
- import ValuePill from "../value-pill"
8
- import ProductTag from "../product-tag"
9
- import { OPEN_BOOKING_FOR_PRODUCT } from "@/providers/booking-dialog-provider"
10
-
11
- export default function ProductTileDesktop({ product, strings }: { product: Product; strings?: any }) {
12
- const handleClick = (e: React.MouseEvent) => {
13
- e.preventDefault();
14
- window.dispatchEvent(
15
- new CustomEvent(OPEN_BOOKING_FOR_PRODUCT, { detail: { productId: product.id } })
16
- );
17
- };
18
-
19
- return (
20
- <div onClick={handleClick} className={styles.productTile} style={{ cursor: 'pointer' }}>
21
- <div className={styles.productTileImageContainer}>
22
- <ViaViaImage
23
- className={styles.productTileImage}
24
- imageId={product.images[0].id}
25
- alt={product.images[0].alt}
26
- context="GALLERY"
27
- />
28
- <div className={styles.productTileContentOverlay}>
29
- {/* Render tags if they exist */}
30
- {product.tags && (
31
- <div className={styles.productTileTags}>
32
- {product.tags.map((tag, index) => (
33
- <ProductTag
34
- key={`${tag.text}-${index}`}
35
- text={tag.text}
36
- style={tag.style}
37
- />
38
- ))}
39
- </div>
40
- )}
41
- <h3 className={styles.productTileTitle}>{product.shortName}</h3>
42
- </div>
43
- <span className={styles.productStartTime} dangerouslySetInnerHTML={{ __html: product.currentStartTime }} />
44
- <div className={styles.productTilePillValuesView}>
45
- {product.pillValues.map((pillValue, index) => (
46
- <ValuePill
47
- key={`${pillValue.label}-${index}`}
48
- variant={PillVariant.overlay}
49
- pillValue={pillValue}
50
- />
51
- ))}
52
- </div>
53
- </div>
54
- </div>
55
- );
56
- }