@qite/tide-booking-component 1.4.97 → 1.4.98

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.
@@ -1,4 +1,4 @@
1
- import { BookingPackage, FlightSearchResponseItem, WebsiteConfigurationSearchConfiguration } from '@qite/tide-client';
1
+ import { BookingPackage, FlightSearchResponseItem, PackagingEntry, WebsiteConfigurationSearchConfiguration } from '@qite/tide-client';
2
2
  import { ReactNode } from 'react';
3
3
  export type FlightSelectionMode = 'paired' | 'independent';
4
4
  export interface SearchResultsConfiguration {
@@ -36,6 +36,7 @@ export interface SearchResultsConfiguration {
36
36
  alt: string;
37
37
  };
38
38
  onBook?: (result: BookingPackage) => void;
39
+ packagingEntry?: PackagingEntry;
39
40
  }
40
41
  export type FilterType = 'checkbox' | 'toggle' | 'slider' | 'star-rating';
41
42
  export type FilterProperty = 'regime' | 'accommodation' | 'max-duration' | 'price' | 'rating' | 'theme';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@qite/tide-booking-component",
3
- "version": "1.4.97",
3
+ "version": "1.4.98",
4
4
  "description": "React Booking wizard & Booking product component for Tide",
5
5
  "main": "build/build-cjs/index.js",
6
6
  "types": "build/build-cjs/src/index.d.ts",
@@ -1,13 +1,12 @@
1
- import React, { useContext } from 'react';
1
+ import React, { useContext, useMemo } from 'react';
2
+ import { differenceInCalendarDays, format } from 'date-fns';
3
+ import { first, isEmpty, last } from 'lodash';
4
+ import { PackagingEntryLine, PackagingEntryLineFlightLine } from '@qite/tide-client';
5
+
2
6
  import Icon from '../icon';
3
7
  import Spinner from '../spinner/spinner';
4
- import { SearchResultsRootState } from '../../store/search-results-store';
5
- import { useSelector } from 'react-redux';
6
- import { first, isEmpty, last } from 'lodash';
7
- import { formatPrice, getTranslations } from '../../../shared/utils/localization-util';
8
- import { differenceInCalendarDays, format } from 'date-fns';
9
- import { EntryLineLight } from '@qite/tide-client';
10
8
  import SearchResultsConfigurationContext from '../../search-results-configuration-context';
9
+ import { formatPrice, getTranslations } from '../../../shared/utils/localization-util';
11
10
 
12
11
  interface ItineraryProps {
13
12
  isOpen: boolean;
@@ -15,295 +14,331 @@ interface ItineraryProps {
15
14
  isLoading?: boolean;
16
15
  }
17
16
 
18
- const getDepartureTime = (flight?: EntryLineLight): string => {
19
- if (isEmpty(flight?.metaDatas)) return '';
20
-
21
- try {
22
- const config = first(flight?.metaDatas)?.configuration;
23
- if (!config) return '';
24
-
25
- const parsed = JSON.parse(config);
26
- const line = first(parsed?.FlightLines);
17
+ const FLIGHT_SERVICE_TYPE = 7;
18
+ const ACCOMMODATION_SERVICE_TYPE = 3;
27
19
 
28
- return (line as any)?.DepartureTime ?? '';
29
- } catch {
30
- return '';
31
- }
20
+ const getFlightLines = (flight?: PackagingEntryLine): PackagingEntryLineFlightLine[] => {
21
+ return flight?.flightInformation?.flightLines ?? [];
32
22
  };
33
23
 
34
- const getArrivalTime = (flight?: EntryLineLight): string => {
35
- if (isEmpty(flight?.metaDatas)) return '';
24
+ const getDepartureTime = (flight?: PackagingEntryLine): string => {
25
+ const firstLine = first(getFlightLines(flight));
26
+ if (!firstLine?.departureTime) return '';
36
27
 
37
- try {
38
- const config = first(flight?.metaDatas)?.configuration;
39
- if (!config) return '';
28
+ return firstLine.departureTime.slice(0, 5);
29
+ };
40
30
 
41
- const parsed = JSON.parse(config);
42
- const line = last(parsed?.FlightLines);
31
+ const getArrivalTime = (flight?: PackagingEntryLine): string => {
32
+ const lastLine = last(getFlightLines(flight));
33
+ if (!lastLine?.arrivalTime) return '';
43
34
 
44
- return (line as any)?.ArrivalTime ?? '';
45
- } catch {
46
- return '';
47
- }
35
+ return lastLine.arrivalTime.slice(0, 5);
48
36
  };
49
37
 
50
- const getDuration = (flight?: EntryLineLight): string => {
51
- if (isEmpty(flight?.metaDatas)) return '';
38
+ const getDuration = (flight?: PackagingEntryLine): string => {
39
+ const lines = getFlightLines(flight);
40
+ if (!lines.length) return '';
41
+
42
+ const totalTicks = lines.reduce((sum, line) => sum + (line.durationInTicks ?? 0), 0) || 0;
52
43
 
53
- try {
54
- const config = first(flight?.metaDatas)?.configuration;
55
- if (!config) return '';
44
+ if (!totalTicks) return '';
56
45
 
57
- const parsed = JSON.parse(config);
58
- const ticks = parsed?.DurationInTicks;
46
+ const seconds = totalTicks / 10_000_000;
47
+ const hours = Math.floor(seconds / 3600);
48
+ const minutes = Math.floor((seconds % 3600) / 60);
59
49
 
60
- if (!ticks) return '';
50
+ return `${hours}h ${minutes.toString().padStart(2, '0')}m`;
51
+ };
61
52
 
62
- const seconds = ticks / 10_000_000;
63
- const hours = Math.floor(seconds / 3600);
64
- const minutes = Math.floor((seconds % 3600) / 60);
53
+ const numberOfNights = (segment: PackagingEntryLine) => {
54
+ return differenceInCalendarDays(new Date(segment.to), new Date(segment.from));
55
+ };
65
56
 
66
- return `${hours}h ${minutes.toString().padStart(2, '0')}m`;
67
- } catch {
68
- return '';
57
+ const getSegmentIcon = (segment: PackagingEntryLine) => {
58
+ switch (segment.serviceType) {
59
+ case 3:
60
+ return <Icon name="ui-bed" width={15} height={15} />;
61
+ case 4:
62
+ return <Icon name="ui-ticket" width={15} height={15} />;
63
+ case 11:
64
+ return <Icon name="ui-ship" width={15} height={15} />;
65
+ case 13:
66
+ case 17:
67
+ case 22:
68
+ return <Icon name="ui-car" width={15} height={15} />;
69
+ default:
70
+ return <Icon name="ui-location" width={15} height={15} />;
69
71
  }
70
72
  };
71
73
 
72
- const numberOfNights = (segment: EntryLineLight) => {
73
- return differenceInCalendarDays(new Date(segment.endDate), new Date(segment.startDate));
74
+ const getSegmentTitle = (segment: PackagingEntryLine) => {
75
+ if (segment.accommodationName) return segment.accommodationName;
76
+ return segment.productName;
74
77
  };
75
78
 
76
79
  const Itinerary: React.FC<ItineraryProps> = ({ isOpen, handleSetIsOpen, isLoading }) => {
77
80
  const context = useContext(SearchResultsConfigurationContext);
78
81
  const translations = getTranslations(context?.languageCode ?? 'en-GB');
79
82
 
80
- const { entry } = useSelector((state: SearchResultsRootState) => state.searchResults);
83
+ const packagingEntry = context?.packagingEntry;
84
+
85
+ const sortedLines = useMemo(() => {
86
+ return [...(packagingEntry?.lines ?? [])].sort((a, b) => {
87
+ const orderA = a.order ?? Infinity;
88
+ const orderB = b.order ?? Infinity;
89
+
90
+ // First sort by order
91
+ if (orderA !== orderB) {
92
+ return orderA - orderB;
93
+ }
81
94
 
82
- if (isLoading || !entry) {
95
+ // Fallback to date
96
+ return new Date(a.from).getTime() - new Date(b.from).getTime();
97
+ });
98
+ }, [packagingEntry]);
99
+
100
+ if (!packagingEntry) {
83
101
  return null;
84
102
  }
85
103
 
86
- const firstEntryLine = first(entry?.items);
87
- const lastEntryLine = last(entry?.items);
104
+ const firstEntryLine = first(sortedLines);
105
+ const lastEntryLine = last(sortedLines);
106
+
107
+ const accommodationLine = sortedLines.find((line) => line.serviceType === ACCOMMODATION_SERVICE_TYPE) ?? firstEntryLine;
108
+
109
+ const country = accommodationLine?.country?.name ?? firstEntryLine?.country?.name;
110
+ const location = accommodationLine?.location?.name ?? accommodationLine?.oord?.name ?? accommodationLine?.region?.name ?? firstEntryLine?.location?.name;
111
+
112
+ const flightSegments = sortedLines.filter((item) => item.serviceType === FLIGHT_SERVICE_TYPE);
113
+ const outboundFlight = first(flightSegments);
114
+ const returnFlight = flightSegments.length > 1 ? last(flightSegments) : undefined;
115
+
116
+ const otherSegments = sortedLines.filter((item) => item.serviceType !== FLIGHT_SERVICE_TYPE);
88
117
 
89
- const country = firstEntryLine?.countryName;
90
- const location = firstEntryLine?.locationName;
118
+ console.log('other segments', otherSegments);
91
119
 
92
- const outboundFlight = entry?.items.find((item) => item.productType === 7 && !item.isReturnFlight);
93
- const returnFlight = entry?.items.find((item) => item.productType === 7 && item.isReturnFlight);
94
- const otherSegments = entry?.items.filter((item) => item.productType !== 7);
120
+ const numberOfPax = packagingEntry.pax?.length || 1;
121
+ const totalPrice = packagingEntry.price || 0;
122
+ const pricePerPerson = totalPrice / numberOfPax;
95
123
 
96
124
  return (
97
- <>
98
- {/* ---------------- Filters ---------------- */}
99
-
100
- {/* ---------------- Filters desktop ---------------- */}
101
- <div className={`search__filters--modal ${isOpen ? 'is-open' : ''}`}>
102
- <div className="search__filters--background" onClick={() => handleSetIsOpen()}></div>
103
- <button className="search__filters--close" onClick={() => handleSetIsOpen()}>
104
- <Icon name="ui-close" height={24} />
105
- </button>
106
- <div className="search__filters">
107
- <div className="search__filter-row search__filter__header">
108
- <div className="search__filter-row-flex-title">
109
- <p className="search__filter-small-title">{translations.SRP.ITINERARY_TITLE}</p>
110
- </div>
125
+ <div className={`search__filters--modal ${isOpen ? 'is-open' : ''}`}>
126
+ <div className="search__filters--background" onClick={handleSetIsOpen}></div>
127
+
128
+ <button className="search__filters--close" onClick={handleSetIsOpen}>
129
+ <Icon name="ui-close" height={24} />
130
+ </button>
131
+
132
+ <div className="search__filters">
133
+ <div className="search__filter-row search__filter__header">
134
+ <div className="search__filter-row-flex-title">
135
+ <p className="search__filter-small-title">{translations.SRP.ITINERARY_TITLE}</p>
111
136
  </div>
112
- {isLoading ? (
113
- <Spinner />
114
- ) : (
115
- <>
116
- <div className="search__filter-group">
117
- {context?.destinationImage && (
118
- <div className="search__filter__image__wrapper">
119
- <img src={context.destinationImage.url} alt={context.destinationImage.alt} className="search__filter__image" />
120
- {entry?.number && (
121
- <span className="search__filter__image__text">
122
- {translations.SRP.DOSSIER_NUMBER}: {entry?.number}
123
- </span>
124
- )}
125
- <h4 className="search__filter__image__title">{(location || '') + (location && country ? ' - ' : '') + (country || '')}</h4>
126
- </div>
137
+ </div>
138
+
139
+ <>
140
+ <div className="search__filter-group">
141
+ {context?.destinationImage && (
142
+ <div className="search__filter__image__wrapper">
143
+ <img src={context.destinationImage.url} alt={context.destinationImage.alt} className="search__filter__image" />
144
+
145
+ {packagingEntry?.dossierNumber && (
146
+ <span className="search__filter__image__text">
147
+ {translations.SRP.DOSSIER_NUMBER}: {packagingEntry.dossierNumber}
148
+ </span>
127
149
  )}
150
+
151
+ <h4 className="search__filter__image__title">{(location || '') + (location && country ? ' - ' : '') + (country || '')}</h4>
128
152
  </div>
153
+ )}
154
+ </div>
155
+
156
+ <div className="search__filter__prices">
157
+ <div className="search__filter__prices__wrapper">
158
+ <h3 className="search__filter__prices--amount">{formatPrice(pricePerPerson, 'EUR')}</h3>
159
+ <p>{translations.SRP.PACKAGE_PRICE_PER_PERSON}</p>
160
+ <p>
161
+ <strong>
162
+ ({formatPrice(totalPrice, 'EUR')} {translations.SRP.TOTAL})
163
+ </strong>
164
+ </p>
165
+ </div>
166
+ <button className="cta">{translations.QSM.CONFIRM}</button>
167
+ </div>
168
+
169
+ <div className="search__filter__itinerary">
170
+ <p>{translations.SRP.DAY_BY_DAY}</p>
129
171
 
130
- <div className="search__filter__prices">
131
- <div className="search__filter__prices__wrapper">
132
- <h3 className="search__filter__prices--amount">
133
- {formatPrice((entry?.sellingPrice || 0) / (entry?.numberOfPax || 1), entry?.currencyCode || 'EUR')}
134
- </h3>
135
- <p>{translations.SRP.PACKAGE_PRICE_PER_PERSON}</p>
172
+ {firstEntryLine && (
173
+ <div className="search__filter__itinerary__country">
174
+ <div className="search__filter__itinerary__country-icon">
175
+ <Icon name="ui-flag" width={17.5} height={20} />
176
+ </div>
177
+ <div className="search__filter__itinerary__country-content">
136
178
  <p>
137
- <strong>
138
- ({formatPrice(entry?.sellingPrice || 0, entry?.currencyCode || 'EUR')} {translations.SRP.TOTAL})
139
- </strong>
179
+ {format(new Date(firstEntryLine.from), 'EEE. d MMM yyyy')} - <strong>{translations.SRP.START}</strong>
140
180
  </p>
141
181
  </div>
142
- <button className="cta">{translations.QSM.CONFIRM}</button>
143
182
  </div>
183
+ )}
184
+
185
+ {outboundFlight && (
186
+ <div className="search__filter__itinerary__transport">
187
+ <div className="search__filter__itinerary__transport-timeline">
188
+ <div className="search__filter__itinerary__transport-timeline-line"></div>
189
+ </div>
144
190
 
145
- <div className="search__filter__itinerary">
146
- <p>{translations.SRP.DAY_BY_DAY}</p>
147
- <div className="search__filter__itinerary__country">
148
- <div className="search__filter__itinerary__country-icon">
149
- <Icon name="ui-flag" width={17.5} height={20} />
191
+ <div className="search__filter__itinerary__transport-item">
192
+ <div className="search__filter__itinerary__transport-date">
193
+ <p className="search__filter__itinerary__transport-date-date">
194
+ <strong>{format(new Date(outboundFlight.from), 'd')}</strong>
195
+ </p>
196
+ <p>{format(new Date(outboundFlight.from), 'MMM')}</p>
197
+ </div>
198
+
199
+ <div className="search__filter__itinerary__transport-badge">
200
+ <Icon name="ui-plane" height={15} />
150
201
  </div>
151
- <div className="search__filter__itinerary__country-content">
152
- <p>
153
- {format(new Date(firstEntryLine?.startDate || ''), 'EEE. d MMM yyyy')} - <strong>{translations.SRP.START}</strong>
202
+
203
+ <div className="search__filter__itinerary__transport-details">
204
+ <h6>{outboundFlight.productName}</h6>
205
+ <p className="search__filter__itinerary__transport-details-plane">
206
+ <span>
207
+ <Icon name="ui-plane-depart" height={14} /> <strong>{getDepartureTime(outboundFlight)}</strong>
208
+ </span>{' '}
209
+ -{' '}
210
+ <span>
211
+ <Icon name="ui-plane-arrive" height={14} /> <strong>{getArrivalTime(outboundFlight)}</strong>
212
+ </span>
213
+ </p>
214
+ <p className="search__filter__itinerary__transport-details-time">
215
+ <span>
216
+ <Icon name="ui-clock" height={20} /> {getDuration(outboundFlight)}
217
+ </span>
154
218
  </p>
155
219
  </div>
156
220
  </div>
221
+ </div>
222
+ )}
157
223
 
158
- {outboundFlight && (
159
- <div className="search__filter__itinerary__transport">
160
- <div className="search__filter__itinerary__transport-timeline">
161
- <div className="search__filter__itinerary__transport-timeline-line"></div>
224
+ {!isEmpty(otherSegments) && (
225
+ <div className="search__filter__itinerary__segments">
226
+ {otherSegments.map((segment, index) => (
227
+ <div className="search__filter__itinerary__segments__wrapper" key={`segment-${index}`}>
228
+ <div className="search__filter__itinerary__segments-timeline">
229
+ <div className="search__filter__itinerary__segments-timeline-line"></div>
162
230
  </div>
163
- <div className="search__filter__itinerary__transport-item">
164
- <div className="search__filter__itinerary__transport-date">
165
- <p className="search__filter__itinerary__transport-date-date">
166
- <strong>{format(new Date(outboundFlight?.startDate || ''), 'd')}</strong>
167
- </p>
168
- <p>{format(new Date(outboundFlight?.startDate || ''), 'MMM')}</p>
169
- </div>
170
- <div className="search__filter__itinerary__transport-badge">
171
- <Icon name="ui-plane" height={15} />
172
- </div>
173
- <div className="search__filter__itinerary__transport-details">
174
- <h6>{outboundFlight.productName}</h6>
175
- <p className="search__filter__itinerary__transport-details-plane">
176
- <span>
177
- <Icon name="ui-plane-depart" height={14} /> <strong>{getDepartureTime(outboundFlight)}</strong>
178
- </span>{' '}
179
- -{' '}
180
- <span>
181
- <Icon name="ui-plane-arrive" height={14} /> <strong>{getArrivalTime(outboundFlight)}</strong>
182
- </span>
183
- </p>
184
- <p className="search__filter__itinerary__transport-details-time">
185
- <span>
186
- <Icon name="ui-clock" height={20} /> {getDuration(outboundFlight)}
187
- </span>
188
- </p>
231
+
232
+ <div className="search__filter__itinerary__segment">
233
+ <div className="search__filter__itinerary__segment-item search__filter__itinerary__segment-item--start">
234
+ <div className="search__filter__itinerary__transport-date">
235
+ <p className="search__filter__itinerary__transport-date-date">
236
+ <strong>{format(new Date(segment.from), 'd')}</strong>
237
+ </p>
238
+ <p>{format(new Date(segment.from), 'MMM')}</p>
239
+ </div>
240
+
241
+ <div className="search__filter__itinerary__segment-badge">
242
+ <Icon name="ui-location" width={15} height={15} />
243
+ </div>
244
+
245
+ <div className="search__filter__itinerary__segment-details">
246
+ <h6>
247
+ {segment.location?.name || segment.oord?.name || segment.region?.name}
248
+ {(segment.location?.name || segment.oord?.name || segment.region?.name) && segment.country?.name ? ', ' : ''}
249
+ {segment.country?.name}
250
+ </h6>
251
+ <p className="search__filter__itinerary__segment-details-text">
252
+ {format(new Date(segment.from), 'EEE. d MMM yyyy')}
253
+ &gt; {format(new Date(segment.to), 'EEE. d MMM yyyy')}
254
+ </p>
255
+ </div>
189
256
  </div>
190
257
  </div>
191
- </div>
192
- )}
193
- {!isEmpty(otherSegments) && (
194
- <div className="search__filter__itinerary__segments">
195
- {otherSegments?.map((segment, index) => (
196
- <div className="search__filter__itinerary__segments__wrapper" key={`segment-${index}`}>
197
- <div className="search__filter__itinerary__segments-timeline">
198
- <div className="search__filter__itinerary__segments-timeline-line"></div>
199
- </div>
200
- <div className="search__filter__itinerary__segment">
201
- <div className="search__filter__itinerary__segment-item search__filter__itinerary__segment-item--start">
202
- <div className="search__filter__itinerary__transport-date">
203
- <p className="search__filter__itinerary__transport-date-date">
204
- <strong>{format(new Date(segment?.startDate || ''), 'd')}</strong>
205
- </p>
206
- <p>{format(new Date(segment?.startDate || ''), 'MMM')}</p>
207
- </div>
208
- <div className="search__filter__itinerary__segment-badge">
209
- <Icon name="ui-location" width={15} height={15} />
210
- </div>
211
- <div className="search__filter__itinerary__segment-details">
212
- <h6>
213
- {segment?.locationName}, {segment?.countryName}
214
- </h6>
215
- <p className="search__filter__itinerary__segment-details-text">
216
- {format(new Date(segment?.startDate || ''), 'EEE. d MMM yyyy')}
217
- &gt; {format(new Date(segment?.endDate || ''), 'EEE. d MMM yyyy')}
258
+
259
+ <div className="search__filter__itinerary__segment">
260
+ <div className="search__filter__itinerary__segment-item">
261
+ <div className="search__filter__itinerary__segment-date search__filter__itinerary__segment-nights">
262
+ {segment.serviceType === ACCOMMODATION_SERVICE_TYPE && (
263
+ <>
264
+ <p className="search__filter__itinerary__segment-date-date">
265
+ <strong>{numberOfNights(segment)}</strong>
218
266
  </p>
219
- </div>
220
- </div>
267
+ <Icon name="ui-moon" width={16} height={16} />
268
+ </>
269
+ )}
221
270
  </div>
222
- <div className="search__filter__itinerary__segment">
223
- <div className="search__filter__itinerary__segment-item">
224
- {segment.productType === 3 && (
225
- <div className="search__filter__itinerary__segment-date search__filter__itinerary__segment-nights">
226
- <p className="search__filter__itinerary__segment-date-date">
227
- <strong>{numberOfNights(segment)}</strong>
228
- </p>
229
- <Icon name="ui-moon" width={16} height={16} />
230
- </div>
231
- )}
232
- <div className="search__filter__itinerary__segment-badge search__filter__itinerary__segment-badge--secondary">
233
- {segment.productType === 3 && <Icon name="ui-bed" width={15} height={15} />}
234
- {segment.productType === 4 && <Icon name="ui-ticket" width={15} height={15} />}
235
- {(segment.productType === 17 || segment.productType === 22) && <Icon name="ui-car" width={15} height={15} />}
236
- {segment.productType === 11 && <Icon name="ui-ship" width={15} height={15} />}
237
- </div>
238
- <div className="search__filter__itinerary__segment-details">
239
- <h6>{segment?.productName}</h6>
240
- {/* <div className="rating">
241
- <Icon name="ui-star" key={`rating-star-1`} width={14} height={14} />
242
- <Icon name="ui-star" key={`rating-star-2`} width={14} height={14} />
243
- <Icon name="ui-star" key={`rating-star-3`} width={14} height={14} />
244
- <Icon name="ui-star" key={`rating-star-4`} width={14} height={14} />
245
- <Icon name="ui-star" key={`rating-star-5`} width={14} height={14} />
246
- </div> */}
247
- </div>
248
- </div>
271
+
272
+ <div className="search__filter__itinerary__segment-badge search__filter__itinerary__segment-badge--secondary">
273
+ {getSegmentIcon(segment)}
249
274
  </div>
250
- </div>
251
- ))}
252
- </div>
253
- )}
254
275
 
255
- {returnFlight && (
256
- <div className="search__filter__itinerary__transport">
257
- <div className="search__filter__itinerary__transport-timeline">
258
- <div className="search__filter__itinerary__transport-timeline-line"></div>
259
- </div>
260
- <div className="search__filter__itinerary__transport-item">
261
- <div className="search__filter__itinerary__transport-date">
262
- <p className="search__filter__itinerary__transport-date-date">
263
- <strong>{format(new Date(returnFlight?.startDate || ''), 'd')}</strong>
264
- </p>
265
- <p>{format(new Date(returnFlight?.startDate || ''), 'MMM')}</p>
266
- </div>
267
- <div className="search__filter__itinerary__transport-badge">
268
- <Icon name="ui-plane" height={15} />
269
- </div>
270
- <div className="search__filter__itinerary__transport-details">
271
- <h6>{returnFlight?.productName}</h6>
272
- <p className="search__filter__itinerary__transport-details-plane">
273
- <span>
274
- <Icon name="ui-plane-depart" height={14} /> <strong>{getDepartureTime(returnFlight)}</strong>
275
- </span>{' '}
276
- -{' '}
277
- <span>
278
- <Icon name="ui-plane-arrive" height={14} /> <strong>{getArrivalTime(returnFlight)}</strong>
279
- </span>
280
- </p>
281
- <p className="search__filter__itinerary__transport-details-time">
282
- <span>
283
- <Icon name="ui-clock" height={20} /> {getDuration(returnFlight)}
284
- </span>
285
- </p>
276
+ <div className="search__filter__itinerary__segment-details">
277
+ <h6>{getSegmentTitle(segment)}</h6>
278
+ {segment.regimeName && <p>{segment.regimeName}</p>}
279
+ </div>
286
280
  </div>
287
281
  </div>
288
282
  </div>
289
- )}
283
+ ))}
284
+ </div>
285
+ )}
286
+
287
+ {returnFlight && returnFlight !== outboundFlight && (
288
+ <div className="search__filter__itinerary__transport">
289
+ <div className="search__filter__itinerary__transport-timeline">
290
+ <div className="search__filter__itinerary__transport-timeline-line"></div>
291
+ </div>
290
292
 
291
- <div className="search__filter__itinerary__country">
292
- <div className="search__filter__itinerary__country-icon">
293
- <Icon name="ui-flag" width={17.5} height={20} />
293
+ <div className="search__filter__itinerary__transport-item">
294
+ <div className="search__filter__itinerary__transport-date">
295
+ <p className="search__filter__itinerary__transport-date-date">
296
+ <strong>{format(new Date(returnFlight.from), 'd')}</strong>
297
+ </p>
298
+ <p>{format(new Date(returnFlight.from), 'MMM')}</p>
299
+ </div>
300
+
301
+ <div className="search__filter__itinerary__transport-badge">
302
+ <Icon name="ui-plane" height={15} />
294
303
  </div>
295
- <div className="search__filter__itinerary__country-content">
296
- <p>
297
- {format(new Date(lastEntryLine?.startDate || ''), 'EEE. d MMM yyyy')} - <strong>{translations.SRP.END}</strong>
304
+
305
+ <div className="search__filter__itinerary__transport-details">
306
+ <h6>{returnFlight.productName}</h6>
307
+ <p className="search__filter__itinerary__transport-details-plane">
308
+ <span>
309
+ <Icon name="ui-plane-depart" height={14} /> <strong>{getDepartureTime(returnFlight)}</strong>
310
+ </span>{' '}
311
+ -{' '}
312
+ <span>
313
+ <Icon name="ui-plane-arrive" height={14} /> <strong>{getArrivalTime(returnFlight)}</strong>
314
+ </span>
315
+ </p>
316
+ <p className="search__filter__itinerary__transport-details-time">
317
+ <span>
318
+ <Icon name="ui-clock" height={20} /> {getDuration(returnFlight)}
319
+ </span>
298
320
  </p>
299
321
  </div>
300
322
  </div>
301
323
  </div>
302
- </>
303
- )}
304
- </div>
324
+ )}
325
+
326
+ {lastEntryLine && (
327
+ <div className="search__filter__itinerary__country">
328
+ <div className="search__filter__itinerary__country-icon">
329
+ <Icon name="ui-flag" width={17.5} height={20} />
330
+ </div>
331
+ <div className="search__filter__itinerary__country-content">
332
+ <p>
333
+ {format(new Date(lastEntryLine.to), 'EEE. d MMM yyyy')} - <strong>{translations.SRP.END}</strong>
334
+ </p>
335
+ </div>
336
+ </div>
337
+ )}
338
+ </div>
339
+ </>
305
340
  </div>
306
- </>
341
+ </div>
307
342
  );
308
343
  };
309
344
 
@@ -1,4 +1,4 @@
1
- import { BookingPackage, FlightSearchResponseItem, WebsiteConfigurationSearchConfiguration } from '@qite/tide-client';
1
+ import { BookingPackage, FlightSearchResponseItem, PackagingEntry, WebsiteConfigurationSearchConfiguration } from '@qite/tide-client';
2
2
  import { ReactNode } from 'react';
3
3
 
4
4
  export type FlightSelectionMode = 'paired' | 'independent';
@@ -53,6 +53,7 @@ export interface SearchResultsConfiguration {
53
53
 
54
54
  destinationImage?: { url: string; alt: string };
55
55
  onBook?: (result: BookingPackage) => void;
56
+ packagingEntry?: PackagingEntry;
56
57
  }
57
58
 
58
59
  export type FilterType = 'checkbox' | 'toggle' | 'slider' | 'star-rating';
@@ -493,6 +493,7 @@
493
493
  }
494
494
 
495
495
  &-date {
496
+ min-width: 26px;
496
497
  p {
497
498
  margin: 0px;
498
499
  color: var(--tide-booking-search-itinerary-filter-transport-date-month-color);
@@ -670,6 +671,7 @@
670
671
  display: flex;
671
672
  align-items: center;
672
673
  flex-flow: row nowrap;
674
+ min-width: 26px;
673
675
  max-width: 26px;
674
676
 
675
677
  svg {