@ticketboothapp/booking 0.1.18 → 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 (152) 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/PickupLocationSelector.tsx +1 -1
  8. package/src/index.ts +3 -1
  9. package/src/app/photo-sessions/photo-packages.ts +0 -75
  10. package/src/assets/icons/minus.svg +0 -7
  11. package/src/assets/icons/partner-logos/getyourguide.svg +0 -8
  12. package/src/assets/icons/plus.svg +0 -3
  13. package/src/colours.css +0 -23
  14. package/src/components/BookingDetails.module.css +0 -1591
  15. package/src/components/BookingDetails.tsx +0 -2264
  16. package/src/components/JobApplicationDialog.module.css +0 -440
  17. package/src/components/JobApplicationDialog.tsx +0 -620
  18. package/src/components/PhoneInputWithCountry.module.css +0 -131
  19. package/src/components/PhoneInputWithCountry.tsx +0 -44
  20. package/src/components/PickupLocationDialog.module.css +0 -360
  21. package/src/components/PickupLocationDialog.tsx +0 -357
  22. package/src/components/PickupLocationMap.tsx +0 -110
  23. package/src/components/PostBookingDependentAddOnUpsell.module.css +0 -174
  24. package/src/components/PostBookingDependentAddOnUpsell.tsx +0 -407
  25. package/src/components/accordion.css +0 -27
  26. package/src/components/accordion.tsx +0 -29
  27. package/src/components/analytics/AnalyticsConsentRestore.tsx +0 -19
  28. package/src/components/analytics/AnalyticsScripts.tsx +0 -106
  29. package/src/components/analytics/CookieConsentBanner.css +0 -86
  30. package/src/components/analytics/CookieConsentBanner.tsx +0 -102
  31. package/src/components/bottom-sheet.module.css +0 -78
  32. package/src/components/bottom-sheet.tsx +0 -60
  33. package/src/components/breadcrumb.module.css +0 -40
  34. package/src/components/breadcrumb.tsx +0 -36
  35. package/src/components/button.css +0 -245
  36. package/src/components/button.tsx +0 -152
  37. package/src/components/client-bottom-sheet.tsx +0 -14
  38. package/src/components/colorable-svg.tsx +0 -29
  39. package/src/components/conditional-footer.tsx +0 -27
  40. package/src/components/contact-us.module.css +0 -147
  41. package/src/components/contact-us.tsx +0 -49
  42. package/src/components/email-signup.css +0 -151
  43. package/src/components/email-signup.tsx +0 -63
  44. package/src/components/faq-wrapper.module.css +0 -47
  45. package/src/components/faq-wrapper.tsx +0 -15
  46. package/src/components/footer.css +0 -187
  47. package/src/components/footer.tsx +0 -143
  48. package/src/components/global-simple-modal.tsx +0 -33
  49. package/src/components/google-review-summary.module.css +0 -77
  50. package/src/components/google-review-summary.tsx +0 -50
  51. package/src/components/hero-image.css +0 -13
  52. package/src/components/hero-image.tsx +0 -44
  53. package/src/components/image.css +0 -29
  54. package/src/components/image.tsx +0 -113
  55. package/src/components/language-aware-link.tsx +0 -72
  56. package/src/components/language-switcher.module.css +0 -124
  57. package/src/components/language-switcher.tsx +0 -75
  58. package/src/components/map-section.css +0 -59
  59. package/src/components/map-section.tsx +0 -63
  60. package/src/components/navbar.module.css +0 -152
  61. package/src/components/navbar.tsx +0 -125
  62. package/src/components/parallax-provider.tsx +0 -11
  63. package/src/components/product-tag.module.css +0 -30
  64. package/src/components/product-tag.tsx +0 -34
  65. package/src/components/product-theme-pages/best-option.module.css +0 -70
  66. package/src/components/product-theme-pages/best-option.tsx +0 -35
  67. package/src/components/product-theme-pages/extended-tour-options.module.css +0 -22
  68. package/src/components/product-theme-pages/extended-tour-options.tsx +0 -11
  69. package/src/components/product-theme-pages/image-modal.tsx +0 -248
  70. package/src/components/product-theme-pages/photo-gallery.module.css +0 -200
  71. package/src/components/product-theme-pages/photo-gallery.tsx +0 -90
  72. package/src/components/product-theme-pages/product-theme-page-layout.module.css +0 -13
  73. package/src/components/product-theme-pages/product-theme-page-layout.tsx +0 -67
  74. package/src/components/product-theme-pages/top-of-fold.module.css +0 -179
  75. package/src/components/product-theme-pages/top-of-fold.tsx +0 -80
  76. package/src/components/product-tile/image-only-product-tile-desktop.module.css +0 -106
  77. package/src/components/product-tile/image-only-product-tile-desktop.tsx +0 -56
  78. package/src/components/product-tile/image-only-product-tile-mobile.module.css +0 -122
  79. package/src/components/product-tile/image-only-product-tile-mobile.tsx +0 -89
  80. package/src/components/product-tile/image-only-product-tile.tsx +0 -44
  81. package/src/components/product-tile/product-tile-card.module.css +0 -84
  82. package/src/components/product-tile/product-tile-card.tsx +0 -61
  83. package/src/components/review-highlights-section.css +0 -85
  84. package/src/components/review-highlights-section.tsx +0 -127
  85. package/src/components/season-closure-overlay.module.css +0 -99
  86. package/src/components/season-closure-overlay.tsx +0 -98
  87. package/src/components/simple-modal.tsx +0 -69
  88. package/src/components/simple-top-of-fold.module.css +0 -76
  89. package/src/components/simple-top-of-fold.tsx +0 -34
  90. package/src/components/spacer.css +0 -41
  91. package/src/components/spacer.tsx +0 -23
  92. package/src/components/star-rating.module.css +0 -74
  93. package/src/components/star-rating.tsx +0 -48
  94. package/src/components/terms/TermsContent.tsx +0 -178
  95. package/src/components/title-subtitle.module.css +0 -10
  96. package/src/components/title-subtitle.tsx +0 -30
  97. package/src/components/translatable-reviews.tsx +0 -75
  98. package/src/components/value-pill.module.css +0 -59
  99. package/src/components/value-pill.tsx +0 -46
  100. package/src/components/value-props.css +0 -185
  101. package/src/components/value-props.tsx +0 -88
  102. package/src/constants/booking-guide-quiz.ts +0 -64
  103. package/src/constants/contact-info.ts +0 -2
  104. package/src/constants/faq.ts +0 -44
  105. package/src/constants/images.ts +0 -556
  106. package/src/constants/json-ld/faq-json-ld.tsx +0 -170
  107. package/src/constants/json-ld/homepage-json-ld.tsx +0 -138
  108. package/src/constants/json-ld/job-posting-json-ld.tsx +0 -92
  109. package/src/constants/json-ld/organization-json-ld.tsx +0 -62
  110. package/src/constants/json-ld/page-json-ld.tsx +0 -6
  111. package/src/constants/json-ld/product-json-ld.tsx +0 -154
  112. package/src/constants/json-ld/review-json-ld.tsx +0 -377
  113. package/src/constants/navigation-links/footer-links.ts +0 -48
  114. package/src/constants/navigation-links/nav-bar-links.ts +0 -41
  115. package/src/constants/navigation-links/navigation-link.ts +0 -6
  116. package/src/constants/pill-values.ts +0 -210
  117. package/src/constants/products.ts +0 -155
  118. package/src/constants/quiz-recommendations.ts +0 -506
  119. package/src/constants/reviews.ts +0 -75
  120. package/src/constants/staff.ts +0 -197
  121. package/src/constants/value-props.ts +0 -58
  122. package/src/data/dap-descriptions/session-couples-families-friends.en.json +0 -61
  123. package/src/data/dap-descriptions/session-elopements.en.json +0 -60
  124. package/src/data/dap-descriptions/session-proposals.en.json +0 -60
  125. package/src/data/product-descriptions/afternoon-delight.en.json +0 -35
  126. package/src/data/product-descriptions/emerald-lake-escape.en.json +0 -68
  127. package/src/data/product-descriptions/lake-louise-adventure.en.json +0 -74
  128. package/src/data/product-descriptions/moraine-lake-adventure.en.json +0 -78
  129. package/src/data/product-descriptions/moraine-lake-sunrise-lake-louise-golden-hour.en.json +0 -65
  130. package/src/data/product-descriptions/moraine-lake-sunrise.en.json +0 -64
  131. package/src/data/product-descriptions/private-tour.en.json +0 -80
  132. package/src/data/product-descriptions/two-lakes-combo.en.json +0 -65
  133. package/src/data/products-config.json +0 -101
  134. package/src/hooks/use-bottom-sheet.tsx +0 -15
  135. package/src/hooks/use-simple-modal.tsx +0 -27
  136. package/src/hooks/useBookingSourceMetadataFromLocation.ts +0 -21
  137. package/src/hooks/useEmailSubscription.tsx +0 -103
  138. package/src/hooks/useEmbeddedInIframe.ts +0 -16
  139. package/src/hooks/useIsBookingLaunchLive.ts +0 -49
  140. package/src/hooks/useQuiz.tsx +0 -210
  141. package/src/providers/bottom-sheet-provider.tsx +0 -40
  142. package/src/providers/dependent-add-on-dialog-provider.tsx +0 -105
  143. package/src/radius.css +0 -5
  144. package/src/spacing.css +0 -7
  145. package/src/strings/en.json +0 -1774
  146. package/src/strings/es.json +0 -1573
  147. package/src/strings/fr.json +0 -1573
  148. package/src/strings/index.js +0 -23
  149. package/src/text-style.css +0 -97
  150. package/src/types/fareharbor.d.ts +0 -12
  151. package/src/types/quiz.ts +0 -59
  152. 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
- }