@times-components/ts-components 1.146.2-be27d508c972211ad80599875cd69c63bf67d4b1.45 → 1.146.2-c12ed7999a41984c2ba8c437357e7a5df1914881.48
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/dist/components/trip-cards/TripCard.js +17 -5
- package/dist/components/trip-cards/TripCardsLayout.js +10 -3
- package/dist/components/trip-cards/__tests__/TripCard.test.js +71 -1
- package/dist/components/trip-cards/__tests__/TripCardsLayout.test.js +41 -2
- package/dist/components/trip-cards/__tests__/helpers.test.js +2 -1
- package/dist/components/trip-cards/__tests__/index.test.js +5 -1
- package/dist/components/trip-cards/helpers.d.ts +1 -1
- package/dist/components/trip-cards/helpers.js +9 -3
- package/dist/components/trip-cards/index.js +3 -3
- package/dist/components/trip-cards/types.d.ts +3 -1
- package/dist/utils/cookie.d.ts +1 -0
- package/dist/utils/cookie.js +8 -1
- package/package.json +3 -3
- package/rnw.js +1 -1
- package/src/components/trip-cards/TripCard.tsx +33 -1
- package/src/components/trip-cards/TripCardsLayout.tsx +17 -0
- package/src/components/trip-cards/__tests__/TripCard.test.tsx +135 -0
- package/src/components/trip-cards/__tests__/TripCardsLayout.test.tsx +89 -1
- package/src/components/trip-cards/__tests__/helpers.test.ts +1 -0
- package/src/components/trip-cards/__tests__/index.test.tsx +4 -0
- package/src/components/trip-cards/helpers.ts +14 -9
- package/src/components/trip-cards/index.tsx +3 -2
- package/src/components/trip-cards/types.ts +3 -1
- package/src/utils/cookie.ts +8 -0
|
@@ -26,6 +26,8 @@ import {
|
|
|
26
26
|
StyledLink
|
|
27
27
|
} from './styles';
|
|
28
28
|
import { MoonIcon, LocationIcon, BoatIcon, CalendarIcon } from './assets';
|
|
29
|
+
import { tealiumTrackingHandler } from '../../helpers/tracking/TrackingHandler';
|
|
30
|
+
import { getPreferredEdition } from '../../utils/cookie';
|
|
29
31
|
|
|
30
32
|
export const TripCard: FC<TripCardProps> = ({
|
|
31
33
|
card,
|
|
@@ -33,10 +35,37 @@ export const TripCard: FC<TripCardProps> = ({
|
|
|
33
35
|
imgHeight = {}
|
|
34
36
|
}) => {
|
|
35
37
|
const [imageLoaded, setImageLoaded] = useState(false);
|
|
38
|
+
const trackEvent = (eventName: string) => {
|
|
39
|
+
tealiumTrackingHandler(
|
|
40
|
+
eventName,
|
|
41
|
+
'navigation',
|
|
42
|
+
'click',
|
|
43
|
+
card.headline,
|
|
44
|
+
undefined,
|
|
45
|
+
{
|
|
46
|
+
app_content_location: getPreferredEdition()
|
|
47
|
+
}
|
|
48
|
+
);
|
|
49
|
+
};
|
|
50
|
+
|
|
51
|
+
const handleCardClick = (type: 'headline' | 'img') => () =>
|
|
52
|
+
type === 'headline'
|
|
53
|
+
? trackEvent(`trip card: ${card.headline}`)
|
|
54
|
+
: trackEvent('trip card: img click');
|
|
55
|
+
|
|
56
|
+
const handleCTAClick = () =>
|
|
57
|
+
trackEvent(`trip card: ${card.cta_text || 'View Itinerary'}`);
|
|
58
|
+
|
|
59
|
+
const handleLogoClick = () => trackEvent(`trip card: ${card.logo_name}`);
|
|
36
60
|
|
|
37
61
|
return (
|
|
38
62
|
<CardContainer>
|
|
39
|
-
<StyledLink
|
|
63
|
+
<StyledLink
|
|
64
|
+
href={card.cta_url}
|
|
65
|
+
target="_blank"
|
|
66
|
+
rel="noopener noreferrer"
|
|
67
|
+
onClick={handleCardClick('img')}
|
|
68
|
+
>
|
|
40
69
|
<ImageContainer isStaticGrid={isStaticGrid} {...imgHeight}>
|
|
41
70
|
{!imageLoaded && <Placeholder />}
|
|
42
71
|
<CardImage
|
|
@@ -56,6 +85,7 @@ export const TripCard: FC<TripCardProps> = ({
|
|
|
56
85
|
href={card.cta_url}
|
|
57
86
|
target="_blank"
|
|
58
87
|
rel="noopener noreferrer"
|
|
88
|
+
onClick={handleCardClick('headline')}
|
|
59
89
|
>
|
|
60
90
|
<Headline>{card.headline}</Headline>
|
|
61
91
|
</StyledLink>
|
|
@@ -119,6 +149,7 @@ export const TripCard: FC<TripCardProps> = ({
|
|
|
119
149
|
href={card.logo_url}
|
|
120
150
|
target="_blank"
|
|
121
151
|
rel="noopener noreferrer"
|
|
152
|
+
onClick={handleLogoClick}
|
|
122
153
|
>
|
|
123
154
|
<img src={card.logo} alt="Partner logo" />
|
|
124
155
|
</a>
|
|
@@ -130,6 +161,7 @@ export const TripCard: FC<TripCardProps> = ({
|
|
|
130
161
|
href={card.cta_url}
|
|
131
162
|
target="_blank"
|
|
132
163
|
rel="noopener noreferrer"
|
|
164
|
+
onClick={handleCTAClick}
|
|
133
165
|
>
|
|
134
166
|
{card.cta_text || 'View Itinerary'}
|
|
135
167
|
</CTAButton>
|
|
@@ -13,6 +13,8 @@ import {
|
|
|
13
13
|
StyledLink
|
|
14
14
|
} from './styles';
|
|
15
15
|
import { ChevronRightIcon } from './assets';
|
|
16
|
+
import { tealiumTrackingHandler } from '../../helpers/tracking/TrackingHandler';
|
|
17
|
+
import { getPreferredEdition } from '../../utils/cookie';
|
|
16
18
|
|
|
17
19
|
export const TripCardsLayout: FC<TripCardsLayoutProps> = ({
|
|
18
20
|
element,
|
|
@@ -75,6 +77,19 @@ export const TripCardsLayout: FC<TripCardsLayoutProps> = ({
|
|
|
75
77
|
const shouldUseCarousel =
|
|
76
78
|
(isTabletMobile && items.length >= 3) || !isStaticGrid || hasOverflow;
|
|
77
79
|
|
|
80
|
+
const onTitleClick = () => {
|
|
81
|
+
tealiumTrackingHandler(
|
|
82
|
+
`trip cards component ${title}`,
|
|
83
|
+
'navigation',
|
|
84
|
+
'click',
|
|
85
|
+
undefined,
|
|
86
|
+
undefined,
|
|
87
|
+
{
|
|
88
|
+
app_content_location: getPreferredEdition()
|
|
89
|
+
}
|
|
90
|
+
);
|
|
91
|
+
};
|
|
92
|
+
|
|
78
93
|
return (
|
|
79
94
|
<Container data-testid="trip-cards-container" {...widthContainerConfig}>
|
|
80
95
|
<TitleSection data-testid="title-section">
|
|
@@ -88,6 +103,7 @@ export const TripCardsLayout: FC<TripCardsLayoutProps> = ({
|
|
|
88
103
|
href={titleurl}
|
|
89
104
|
target="_blank"
|
|
90
105
|
rel="noopener noreferrer"
|
|
106
|
+
onClick={onTitleClick}
|
|
91
107
|
data-testid="trip-cards-title-link"
|
|
92
108
|
>
|
|
93
109
|
<Title data-testid="trip-cards-title">{title}</Title>
|
|
@@ -103,6 +119,7 @@ export const TripCardsLayout: FC<TripCardsLayoutProps> = ({
|
|
|
103
119
|
target="_blank"
|
|
104
120
|
rel="noopener noreferrer"
|
|
105
121
|
data-testid="title-link"
|
|
122
|
+
onClick={onTitleClick}
|
|
106
123
|
>
|
|
107
124
|
<ChevronRightIcon />
|
|
108
125
|
</TitleLink>
|
|
@@ -3,6 +3,11 @@ import { render, screen, fireEvent } from '@testing-library/react';
|
|
|
3
3
|
import '@testing-library/jest-dom';
|
|
4
4
|
import { TripCard } from '../TripCard';
|
|
5
5
|
import { TripCardApiData } from '../types';
|
|
6
|
+
import { tealiumTrackingHandler } from '../../../helpers/tracking/TrackingHandler';
|
|
7
|
+
|
|
8
|
+
jest.mock('../../../helpers/tracking/TrackingHandler', () => ({
|
|
9
|
+
tealiumTrackingHandler: jest.fn()
|
|
10
|
+
}));
|
|
6
11
|
|
|
7
12
|
const mockCard: TripCardApiData = {
|
|
8
13
|
cruise_id: '2074350',
|
|
@@ -15,11 +20,16 @@ const mockCard: TripCardApiData = {
|
|
|
15
20
|
price: '£2000',
|
|
16
21
|
logo: 'https://example.com/logo.png',
|
|
17
22
|
logo_url: 'https://example.com',
|
|
23
|
+
logo_name: 'MSC Cruises',
|
|
18
24
|
cta_url: 'https://example.com/cruise',
|
|
19
25
|
cta_text: 'View Itinerary'
|
|
20
26
|
};
|
|
21
27
|
|
|
22
28
|
describe('TripCard', () => {
|
|
29
|
+
beforeEach(() => {
|
|
30
|
+
jest.clearAllMocks();
|
|
31
|
+
});
|
|
32
|
+
|
|
23
33
|
it('renders card with all required data', () => {
|
|
24
34
|
render(<TripCard card={mockCard} />);
|
|
25
35
|
|
|
@@ -117,4 +127,129 @@ describe('TripCard', () => {
|
|
|
117
127
|
fireEvent.load(cardImage);
|
|
118
128
|
expect(cardImage).toHaveStyle({ display: 'block' });
|
|
119
129
|
});
|
|
130
|
+
|
|
131
|
+
describe('Tracking', () => {
|
|
132
|
+
it('calls tealiumTrackingHandler when headline is clicked', () => {
|
|
133
|
+
render(<TripCard card={mockCard} />);
|
|
134
|
+
|
|
135
|
+
const headlineLink = screen.getAllByRole('link')[1];
|
|
136
|
+
fireEvent.click(headlineLink);
|
|
137
|
+
|
|
138
|
+
expect(tealiumTrackingHandler).toHaveBeenCalledWith(
|
|
139
|
+
'trip card: Mediterranean from Barcelona',
|
|
140
|
+
'navigation',
|
|
141
|
+
'click',
|
|
142
|
+
'Mediterranean from Barcelona',
|
|
143
|
+
undefined,
|
|
144
|
+
{
|
|
145
|
+
app_content_location: expect.any(String)
|
|
146
|
+
}
|
|
147
|
+
);
|
|
148
|
+
});
|
|
149
|
+
|
|
150
|
+
it('calls tealiumTrackingHandler when image is clicked', () => {
|
|
151
|
+
render(<TripCard card={mockCard} />);
|
|
152
|
+
|
|
153
|
+
const imageLink = screen.getAllByRole('link')[0];
|
|
154
|
+
fireEvent.click(imageLink);
|
|
155
|
+
|
|
156
|
+
expect(tealiumTrackingHandler).toHaveBeenCalledWith(
|
|
157
|
+
'trip card: img click',
|
|
158
|
+
'navigation',
|
|
159
|
+
'click',
|
|
160
|
+
'Mediterranean from Barcelona',
|
|
161
|
+
undefined,
|
|
162
|
+
{
|
|
163
|
+
app_content_location: expect.any(String)
|
|
164
|
+
}
|
|
165
|
+
);
|
|
166
|
+
});
|
|
167
|
+
|
|
168
|
+
it('calls tealiumTrackingHandler when CTA button is clicked', () => {
|
|
169
|
+
render(<TripCard card={mockCard} />);
|
|
170
|
+
|
|
171
|
+
const ctaButton = screen.getByText('View Itinerary');
|
|
172
|
+
fireEvent.click(ctaButton);
|
|
173
|
+
|
|
174
|
+
expect(tealiumTrackingHandler).toHaveBeenCalledWith(
|
|
175
|
+
'trip card: View Itinerary',
|
|
176
|
+
'navigation',
|
|
177
|
+
'click',
|
|
178
|
+
'Mediterranean from Barcelona',
|
|
179
|
+
undefined,
|
|
180
|
+
{
|
|
181
|
+
app_content_location: expect.any(String)
|
|
182
|
+
}
|
|
183
|
+
);
|
|
184
|
+
});
|
|
185
|
+
|
|
186
|
+
it('calls tealiumTrackingHandler with default CTA text when not provided', () => {
|
|
187
|
+
const cardWithoutCTAText = {
|
|
188
|
+
...mockCard,
|
|
189
|
+
cta_text: undefined
|
|
190
|
+
};
|
|
191
|
+
|
|
192
|
+
render(<TripCard card={cardWithoutCTAText} />);
|
|
193
|
+
|
|
194
|
+
const ctaButton = screen.getByText('View Itinerary');
|
|
195
|
+
fireEvent.click(ctaButton);
|
|
196
|
+
|
|
197
|
+
expect(tealiumTrackingHandler).toHaveBeenCalledWith(
|
|
198
|
+
'trip card: View Itinerary',
|
|
199
|
+
'navigation',
|
|
200
|
+
'click',
|
|
201
|
+
'Mediterranean from Barcelona',
|
|
202
|
+
undefined,
|
|
203
|
+
{
|
|
204
|
+
app_content_location: expect.any(String)
|
|
205
|
+
}
|
|
206
|
+
);
|
|
207
|
+
});
|
|
208
|
+
|
|
209
|
+
it('calls tealiumTrackingHandler when logo is clicked with empty logo_name', () => {
|
|
210
|
+
const cardWithoutLogoName = {
|
|
211
|
+
...mockCard,
|
|
212
|
+
logo_name: ''
|
|
213
|
+
};
|
|
214
|
+
|
|
215
|
+
render(<TripCard card={cardWithoutLogoName} />);
|
|
216
|
+
|
|
217
|
+
const logoLink = screen.getByRole('link', { name: /partner logo/i });
|
|
218
|
+
fireEvent.click(logoLink);
|
|
219
|
+
|
|
220
|
+
expect(tealiumTrackingHandler).toHaveBeenCalledWith(
|
|
221
|
+
'trip card: ',
|
|
222
|
+
'navigation',
|
|
223
|
+
'click',
|
|
224
|
+
'Mediterranean from Barcelona',
|
|
225
|
+
undefined,
|
|
226
|
+
{
|
|
227
|
+
app_content_location: expect.any(String)
|
|
228
|
+
}
|
|
229
|
+
);
|
|
230
|
+
});
|
|
231
|
+
|
|
232
|
+
it('calls tealiumTrackingHandler with logo_name when provided', () => {
|
|
233
|
+
const cardWithLogoName = {
|
|
234
|
+
...mockCard,
|
|
235
|
+
logo_name: 'MSC Cruises'
|
|
236
|
+
};
|
|
237
|
+
|
|
238
|
+
render(<TripCard card={cardWithLogoName} />);
|
|
239
|
+
|
|
240
|
+
const logoLink = screen.getByRole('link', { name: /partner logo/i });
|
|
241
|
+
fireEvent.click(logoLink);
|
|
242
|
+
|
|
243
|
+
expect(tealiumTrackingHandler).toHaveBeenCalledWith(
|
|
244
|
+
'trip card: MSC Cruises',
|
|
245
|
+
'navigation',
|
|
246
|
+
'click',
|
|
247
|
+
'Mediterranean from Barcelona',
|
|
248
|
+
undefined,
|
|
249
|
+
{
|
|
250
|
+
app_content_location: expect.any(String)
|
|
251
|
+
}
|
|
252
|
+
);
|
|
253
|
+
});
|
|
254
|
+
});
|
|
120
255
|
});
|
|
@@ -1,8 +1,13 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
|
-
import { render, screen } from '@testing-library/react';
|
|
2
|
+
import { render, screen, fireEvent } from '@testing-library/react';
|
|
3
3
|
import '@testing-library/jest-dom';
|
|
4
4
|
import { TripCardsLayout } from '../TripCardsLayout';
|
|
5
5
|
import { TripCardApiData } from '../types';
|
|
6
|
+
import { tealiumTrackingHandler } from '../../../helpers/tracking/TrackingHandler';
|
|
7
|
+
|
|
8
|
+
jest.mock('../../../helpers/tracking/TrackingHandler', () => ({
|
|
9
|
+
tealiumTrackingHandler: jest.fn()
|
|
10
|
+
}));
|
|
6
11
|
|
|
7
12
|
const mockElement = {
|
|
8
13
|
class: 'trip-cards',
|
|
@@ -33,6 +38,7 @@ global.ResizeObserver = class ResizeObserver {
|
|
|
33
38
|
|
|
34
39
|
describe('TripCardsLayout', () => {
|
|
35
40
|
beforeEach(() => {
|
|
41
|
+
jest.clearAllMocks();
|
|
36
42
|
Element.prototype.scrollTo = jest.fn();
|
|
37
43
|
|
|
38
44
|
// Mock matchMedia for each test
|
|
@@ -52,6 +58,10 @@ describe('TripCardsLayout', () => {
|
|
|
52
58
|
});
|
|
53
59
|
});
|
|
54
60
|
|
|
61
|
+
afterEach(() => {
|
|
62
|
+
jest.clearAllMocks();
|
|
63
|
+
});
|
|
64
|
+
|
|
55
65
|
describe('Rendering', () => {
|
|
56
66
|
it('renders with title and description', () => {
|
|
57
67
|
const items = [
|
|
@@ -245,6 +255,7 @@ describe('TripCardsLayout', () => {
|
|
|
245
255
|
price: '£1000',
|
|
246
256
|
logo: 'logo.png',
|
|
247
257
|
logo_url: 'https://example.com',
|
|
258
|
+
logo_name: 'Test Cruise Line',
|
|
248
259
|
cta_url: 'https://example.com',
|
|
249
260
|
cta_text: 'View'
|
|
250
261
|
};
|
|
@@ -400,6 +411,7 @@ describe('TripCardsLayout', () => {
|
|
|
400
411
|
price: '£2000',
|
|
401
412
|
logo: 'logo.png',
|
|
402
413
|
logo_url: 'https://example.com',
|
|
414
|
+
logo_name: 'Test Cruise Line',
|
|
403
415
|
cta_url: 'https://example.com',
|
|
404
416
|
cta_text: 'Book'
|
|
405
417
|
};
|
|
@@ -580,4 +592,80 @@ describe('TripCardsLayout', () => {
|
|
|
580
592
|
}
|
|
581
593
|
});
|
|
582
594
|
});
|
|
595
|
+
|
|
596
|
+
describe('Tracking', () => {
|
|
597
|
+
it('calls tealiumTrackingHandler when title link is clicked', () => {
|
|
598
|
+
const items = [{ id: '1', data: undefined }];
|
|
599
|
+
|
|
600
|
+
render(
|
|
601
|
+
<TripCardsLayout
|
|
602
|
+
element={mockElement}
|
|
603
|
+
items={items}
|
|
604
|
+
CardComponent={MockCard}
|
|
605
|
+
itemsPerPage={2}
|
|
606
|
+
/>
|
|
607
|
+
);
|
|
608
|
+
|
|
609
|
+
const titleLink = screen.getByTestId('trip-cards-title-link');
|
|
610
|
+
fireEvent.click(titleLink);
|
|
611
|
+
|
|
612
|
+
expect(tealiumTrackingHandler).toHaveBeenCalledWith(
|
|
613
|
+
'trip cards component Test Cruises',
|
|
614
|
+
'navigation',
|
|
615
|
+
'click',
|
|
616
|
+
undefined,
|
|
617
|
+
undefined,
|
|
618
|
+
{
|
|
619
|
+
app_content_location: 'uk'
|
|
620
|
+
}
|
|
621
|
+
);
|
|
622
|
+
});
|
|
623
|
+
|
|
624
|
+
it('calls tealiumTrackingHandler when icon link is clicked', () => {
|
|
625
|
+
const items = [{ id: '1', data: undefined }];
|
|
626
|
+
|
|
627
|
+
render(
|
|
628
|
+
<TripCardsLayout
|
|
629
|
+
element={mockElement}
|
|
630
|
+
items={items}
|
|
631
|
+
CardComponent={MockCard}
|
|
632
|
+
itemsPerPage={2}
|
|
633
|
+
/>
|
|
634
|
+
);
|
|
635
|
+
|
|
636
|
+
const iconLink = screen.getByTestId('title-link');
|
|
637
|
+
fireEvent.click(iconLink);
|
|
638
|
+
|
|
639
|
+
expect(tealiumTrackingHandler).toHaveBeenCalledWith(
|
|
640
|
+
'trip cards component Test Cruises',
|
|
641
|
+
'navigation',
|
|
642
|
+
'click',
|
|
643
|
+
undefined,
|
|
644
|
+
undefined,
|
|
645
|
+
{
|
|
646
|
+
app_content_location: 'uk'
|
|
647
|
+
}
|
|
648
|
+
);
|
|
649
|
+
});
|
|
650
|
+
|
|
651
|
+
it('does not call tealiumTrackingHandler when title link is not clicked', () => {
|
|
652
|
+
const elementWithoutLink = {
|
|
653
|
+
...mockElement,
|
|
654
|
+
titleurl: undefined
|
|
655
|
+
};
|
|
656
|
+
|
|
657
|
+
const items = [{ id: '1', data: undefined }];
|
|
658
|
+
|
|
659
|
+
render(
|
|
660
|
+
<TripCardsLayout
|
|
661
|
+
element={elementWithoutLink}
|
|
662
|
+
items={items}
|
|
663
|
+
CardComponent={MockCard}
|
|
664
|
+
itemsPerPage={2}
|
|
665
|
+
/>
|
|
666
|
+
);
|
|
667
|
+
|
|
668
|
+
expect(tealiumTrackingHandler).not.toHaveBeenCalled();
|
|
669
|
+
});
|
|
670
|
+
});
|
|
583
671
|
});
|
|
@@ -61,6 +61,7 @@ describe('transformApiResult', () => {
|
|
|
61
61
|
price: '£2000',
|
|
62
62
|
logo: 'https://example.com/msc-logo.png',
|
|
63
63
|
logo_url: 'https://example.com/cruise-lines/msc-cruises/',
|
|
64
|
+
logo_name: 'MSC Cruises',
|
|
64
65
|
cta_url: 'https://example.com/cruises/mediterranean-from-barcelona',
|
|
65
66
|
cta_text: 'View Itinerary'
|
|
66
67
|
});
|
|
@@ -34,6 +34,7 @@ describe('TripCards', () => {
|
|
|
34
34
|
original_price: undefined,
|
|
35
35
|
logo: 'logo1.png',
|
|
36
36
|
logo_url: 'https://example.com',
|
|
37
|
+
logo_name: 'Mock Line 1',
|
|
37
38
|
cta_url: 'link1',
|
|
38
39
|
cta_text: 'View'
|
|
39
40
|
},
|
|
@@ -49,6 +50,7 @@ describe('TripCards', () => {
|
|
|
49
50
|
original_price: undefined,
|
|
50
51
|
logo: 'logo2.png',
|
|
51
52
|
logo_url: 'https://example.com',
|
|
53
|
+
logo_name: 'Mock Line 2',
|
|
52
54
|
cta_url: 'link2',
|
|
53
55
|
cta_text: 'View'
|
|
54
56
|
},
|
|
@@ -64,6 +66,7 @@ describe('TripCards', () => {
|
|
|
64
66
|
original_price: undefined,
|
|
65
67
|
logo: 'logo3.png',
|
|
66
68
|
logo_url: 'https://example.com',
|
|
69
|
+
logo_name: 'Mock Line 3',
|
|
67
70
|
cta_url: 'link3',
|
|
68
71
|
cta_text: 'View'
|
|
69
72
|
}
|
|
@@ -429,6 +432,7 @@ describe('TripCards', () => {
|
|
|
429
432
|
original_price: undefined,
|
|
430
433
|
logo: 'logo3.png',
|
|
431
434
|
logo_url: 'https://example.com',
|
|
435
|
+
logo_name: 'Mock Line 3',
|
|
432
436
|
cta_url: 'link3',
|
|
433
437
|
cta_text: 'View'
|
|
434
438
|
}
|
|
@@ -87,6 +87,7 @@ export const transformApiResult = (
|
|
|
87
87
|
),
|
|
88
88
|
logo: (result.cruise_line && result.cruise_line.logo) || '',
|
|
89
89
|
logo_url: (result.cruise_line && result.cruise_line.link) || '',
|
|
90
|
+
logo_name: (result.cruise_line && result.cruise_line.name) || '',
|
|
90
91
|
cta_url: result.link || '',
|
|
91
92
|
cta_text: 'View Itinerary'
|
|
92
93
|
};
|
|
@@ -139,19 +140,23 @@ const isValidOffer = (result: ApiCruiseResult): boolean => {
|
|
|
139
140
|
};
|
|
140
141
|
|
|
141
142
|
export const fetchCruiseCards = async (
|
|
142
|
-
cruiseIds: number[]
|
|
143
|
+
cruiseIds: number[],
|
|
144
|
+
hostName?: string
|
|
143
145
|
): Promise<TripCardApiData[]> => {
|
|
144
146
|
const formData = new FormData();
|
|
145
147
|
formData.append('action', 'results');
|
|
146
148
|
formData.append('cruise_ids', cruiseIds.join(','));
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
'
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
149
|
+
const url =
|
|
150
|
+
hostName &&
|
|
151
|
+
hostName.includes('thetimes.com') &&
|
|
152
|
+
!hostName.includes('-thetimes')
|
|
153
|
+
? 'https://www.thetimes.com/holidays/wp-admin/admin-ajax.php'
|
|
154
|
+
: 'https://www.staging-thetimes.com/holidays/wp-admin/admin-ajax.php';
|
|
155
|
+
|
|
156
|
+
const response = await fetch(url, {
|
|
157
|
+
method: 'POST',
|
|
158
|
+
body: formData
|
|
159
|
+
});
|
|
155
160
|
|
|
156
161
|
if (!response.ok) {
|
|
157
162
|
throw new Error(`HTTP error! status: ${response.status}`);
|
|
@@ -13,7 +13,8 @@ export const TripCards: FC<TripCardsProps> = ({
|
|
|
13
13
|
widthItemConfig,
|
|
14
14
|
maxWidthItemConfig,
|
|
15
15
|
imgHeight,
|
|
16
|
-
forceStaticGrid
|
|
16
|
+
forceStaticGrid,
|
|
17
|
+
hostName
|
|
17
18
|
}) => {
|
|
18
19
|
const [cards, setCards] = useState<TripCardApiData[]>([]);
|
|
19
20
|
const [loading, setLoading] = useState(true);
|
|
@@ -39,7 +40,7 @@ export const TripCards: FC<TripCardsProps> = ({
|
|
|
39
40
|
}
|
|
40
41
|
|
|
41
42
|
try {
|
|
42
|
-
const transformedCards = await fetchCruiseCards(allIds);
|
|
43
|
+
const transformedCards = await fetchCruiseCards(allIds, hostName);
|
|
43
44
|
setCards(transformedCards);
|
|
44
45
|
} catch (e) {
|
|
45
46
|
setError(e instanceof Error ? e.message : 'Failed to load cruises');
|
|
@@ -35,6 +35,7 @@ export interface TripCardsProps {
|
|
|
35
35
|
maxWidthItemConfig?: ResponsiveConfig;
|
|
36
36
|
imgHeight?: ImageHeightConfig;
|
|
37
37
|
forceStaticGrid?: boolean;
|
|
38
|
+
hostName?: string;
|
|
38
39
|
}
|
|
39
40
|
|
|
40
41
|
export interface DecodedTripCard {
|
|
@@ -55,8 +56,9 @@ export interface TripCardApiData {
|
|
|
55
56
|
price: string;
|
|
56
57
|
logo: string;
|
|
57
58
|
logo_url: string;
|
|
59
|
+
logo_name: string;
|
|
58
60
|
cta_url: string;
|
|
59
|
-
cta_text
|
|
61
|
+
cta_text?: string;
|
|
60
62
|
}
|
|
61
63
|
|
|
62
64
|
export interface TripCardProps {
|
package/src/utils/cookie.ts
CHANGED
|
@@ -1,3 +1,11 @@
|
|
|
1
1
|
export const hasCookieConsent = () =>
|
|
2
2
|
typeof window !== 'undefined' &&
|
|
3
3
|
window.document.cookie.indexOf('nuk-consent-personalisation=1') >= 0;
|
|
4
|
+
|
|
5
|
+
export const getPreferredEdition = () => {
|
|
6
|
+
if (!window || !window.nuk) {
|
|
7
|
+
return 'uk';
|
|
8
|
+
}
|
|
9
|
+
const edition = window.nuk.getCookieValue('nuk_preferred_edition') || 'uk';
|
|
10
|
+
return edition.toLowerCase();
|
|
11
|
+
};
|