@qite/tide-booking-component 1.4.34 → 1.4.36

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 (64) hide show
  1. package/build/build-cjs/index.js +1628 -376
  2. package/build/build-cjs/qsm/types.d.ts +0 -1
  3. package/build/build-cjs/search-results/components/filters/filters.d.ts +2 -2
  4. package/build/build-cjs/search-results/components/flight/flight-results.d.ts +2 -0
  5. package/build/build-cjs/search-results/components/hotel/hotel-card.d.ts +1 -0
  6. package/build/build-cjs/search-results/components/itinerary/index.d.ts +2 -2
  7. package/build/build-cjs/search-results/store/search-results-slice.d.ts +11 -2
  8. package/build/build-cjs/search-results/types.d.ts +4 -14
  9. package/build/build-esm/index.js +1628 -376
  10. package/build/build-esm/qsm/types.d.ts +0 -1
  11. package/build/build-esm/search-results/components/filters/filters.d.ts +2 -2
  12. package/build/build-esm/search-results/components/flight/flight-results.d.ts +2 -0
  13. package/build/build-esm/search-results/components/hotel/hotel-card.d.ts +1 -0
  14. package/build/build-esm/search-results/components/itinerary/index.d.ts +2 -2
  15. package/build/build-esm/search-results/store/search-results-slice.d.ts +11 -2
  16. package/build/build-esm/search-results/types.d.ts +4 -14
  17. package/package.json +2 -2
  18. package/src/booking-wizard/features/booking/booking-self-contained.tsx +0 -1
  19. package/src/booking-wizard/features/travelers-form/controls/gender-control.tsx +5 -5
  20. package/src/booking-wizard/features/travelers-form/travelers-form.tsx +10 -10
  21. package/src/content/components/icon.tsx +1 -1
  22. package/src/content/features/content-page/content-page-self-contained.tsx +0 -1
  23. package/src/qsm/components/QSMContainer/qsm-container.tsx +15 -13
  24. package/src/qsm/components/mobile-filter-modal/index.tsx +12 -10
  25. package/src/qsm/components/travel-class-picker/index.tsx +5 -3
  26. package/src/qsm/components/travel-input/index.tsx +15 -12
  27. package/src/qsm/components/travel-input-group/index.tsx +14 -3
  28. package/src/qsm/components/travel-nationality-picker/index.tsx +5 -3
  29. package/src/qsm/components/travel-type-picker/index.tsx +5 -3
  30. package/src/qsm/qsm-configuration-context.ts +0 -1
  31. package/src/qsm/types.ts +0 -1
  32. package/src/search-results/components/filters/filters.tsx +15 -16
  33. package/src/search-results/components/flight/flight-results.tsx +168 -1099
  34. package/src/search-results/components/hotel/hotel-accommodation-results.tsx +21 -24
  35. package/src/search-results/components/hotel/hotel-card.tsx +4 -3
  36. package/src/search-results/components/icon.tsx +1 -1
  37. package/src/search-results/components/itinerary/index.tsx +233 -131
  38. package/src/search-results/components/round-trip/round-trip-results.tsx +1 -1
  39. package/src/search-results/components/search-results-container/search-results-container.tsx +45 -33
  40. package/src/search-results/components/spinner/spinner.tsx +3 -1
  41. package/src/search-results/components/tab-views/index.tsx +13 -7
  42. package/src/search-results/features/flights/flight-search-results-self-contained.tsx +4 -13
  43. package/src/search-results/features/hotels/hotel-flight-search-results-self-contained.tsx +5 -1
  44. package/src/search-results/features/hotels/hotel-search-results-self-contained.tsx +4 -13
  45. package/src/search-results/features/roundtrips/roundtrip-search-results-self-contained.tsx +5 -1
  46. package/src/search-results/store/search-results-slice.ts +37 -3
  47. package/src/search-results/types.ts +2 -15
  48. package/src/shared/translations/ar-SA.json +70 -0
  49. package/src/shared/translations/da-DK.json +70 -0
  50. package/src/shared/translations/de-DE.json +70 -0
  51. package/src/shared/translations/en-GB.json +71 -1
  52. package/src/shared/translations/es-ES.json +70 -0
  53. package/src/shared/translations/fr-BE.json +71 -1
  54. package/src/shared/translations/fr-FR.json +70 -0
  55. package/src/shared/translations/is-IS.json +72 -2
  56. package/src/shared/translations/it-IT.json +70 -0
  57. package/src/shared/translations/ja-JP.json +72 -2
  58. package/src/shared/translations/nl-BE.json +70 -0
  59. package/src/shared/translations/nl-NL.json +70 -0
  60. package/src/shared/translations/no-NO.json +72 -2
  61. package/src/shared/translations/pl-PL.json +70 -0
  62. package/src/shared/translations/pt-PT.json +70 -0
  63. package/src/shared/translations/sv-SE.json +72 -2
  64. package/styles/components/_search.scss +7 -1
@@ -6,16 +6,23 @@ import { useSelector } from 'react-redux';
6
6
  import { SearchResultsRootState } from '../../store/search-results-store';
7
7
  import { BookingPackageItem } from '@qite/tide-client/build/types';
8
8
  import { format, parseISO } from 'date-fns';
9
+ import { formatPrice, getTranslations } from '../../../shared/utils/localization-util';
9
10
 
10
11
  interface HotelAccommodationResultsProps {
11
12
  isLoading: boolean;
12
13
  context: SearchResultsConfiguration;
13
14
  }
14
15
 
15
- const renderResults = (results: BookingPackageItem[], context: SearchResultsConfiguration, cmsMap: Map<any, any>, activeTab: string | null) => {
16
+ const renderResults = (
17
+ results: BookingPackageItem[],
18
+ context: SearchResultsConfiguration,
19
+ cmsMap: Map<any, any>,
20
+ activeTab: string | null,
21
+ translations: any
22
+ ) => {
16
23
  const renderedResults = results.map((result, index) => {
17
24
  const cmsItem = cmsMap.get(result.productId);
18
- const mappedResult: HotelResult = mapSearchResult(result, cmsItem, context.languageCode);
25
+ const mappedResult: HotelResult = mapSearchResult(result, cmsItem, context.languageCode, translations);
19
26
  if (context?.showCustomCards && context?.customCardRenderer) {
20
27
  return (
21
28
  <div key={`${mappedResult.id}-${index}`} className="search__result-card">
@@ -23,13 +30,13 @@ const renderResults = (results: BookingPackageItem[], context: SearchResultsConf
23
30
  </div>
24
31
  );
25
32
  }
26
- return <HotelCard key={`${mappedResult.id}-${index}`} result={mappedResult} />;
33
+ return <HotelCard key={`${mappedResult.id}-${index}`} result={mappedResult} translations={translations} />;
27
34
  });
28
35
 
29
36
  return <div className={`search__results__cards ${activeTab ? `search__results__cards--${activeTab}` : ''}`}>{renderedResults}</div>;
30
37
  };
31
38
 
32
- const mapSearchResult = (searchResult: BookingPackageItem, cmsItem: any, languageCode?: string): HotelResult => {
39
+ const mapSearchResult = (searchResult: BookingPackageItem, cmsItem: any, languageCode?: string, translations?: any): HotelResult => {
33
40
  return {
34
41
  type: 'hotel',
35
42
  id: searchResult.productId,
@@ -38,36 +45,26 @@ const mapSearchResult = (searchResult: BookingPackageItem, cmsItem: any, languag
38
45
  description: cmsItem?.content?.descriptions?.introductionTitle || '',
39
46
  location:
40
47
  searchResult.locationName && searchResult.countryName ? `${searchResult.locationName}, ${searchResult.countryName}` : cmsItem?.parentItem?.name || '',
41
- price: formatPrice(searchResult.currencyCode, searchResult.price, languageCode),
42
- ctaText: 'View details',
43
- days: calculateNights(searchResult.stayFromDate, searchResult.stayToDate),
48
+ price: formatPrice(searchResult.price, searchResult.currencyCode, languageCode),
49
+ ctaText: translations?.SRP.VIEW_DETAILS,
50
+ days: calculateNights(searchResult.stayFromDate, searchResult.stayToDate, translations),
44
51
  accommodation: searchResult.accommodationName,
45
52
  regime: searchResult.regimeName,
46
53
  stars: cmsItem?.content?.general?.stars || searchResult.hotelStars
47
54
  };
48
55
  };
49
56
 
50
- const formatPrice = (currencyCode: string, price: number, languageCode?: string) => {
51
- if (!price) {
52
- return 'Price unavailable';
53
- }
54
-
55
- return new Intl.NumberFormat(languageCode ?? 'en-GB', {
56
- style: 'currency',
57
- currency: currencyCode,
58
- currencyDisplay: 'symbol'
59
- }).format(price);
60
- };
61
-
62
- const calculateNights = (fromDate: Date, toDate: Date): string => {
57
+ const calculateNights = (fromDate: Date, toDate: Date, translations?: any): string => {
63
58
  const from = new Date(fromDate).getTime(); // returns a number
64
59
  const to = new Date(toDate).getTime(); // returns a number
65
60
  const diffTime = Math.abs(to - from);
66
61
  const diffDays = Math.ceil(diffTime / (1000 * 60 * 60 * 24));
67
- return `${diffDays} nights`;
62
+ return `${diffDays} ${translations?.SRP.NIGHTS}`;
68
63
  };
69
64
 
70
65
  const HotelAccommodationResults: React.FC<HotelAccommodationResultsProps> = ({ isLoading, context }) => {
66
+ const translations = getTranslations(context?.languageCode ?? 'en-GB');
67
+
71
68
  if (isLoading) {
72
69
  return <>{context?.customSpinner ?? <Spinner />}</>;
73
70
  }
@@ -75,7 +72,7 @@ const HotelAccommodationResults: React.FC<HotelAccommodationResultsProps> = ({ i
75
72
  const { results, activeTab } = useSelector((state: SearchResultsRootState) => state.searchResults);
76
73
 
77
74
  if (!results.length) {
78
- return <div className="no-results">{context.noResultsLabel || 'No results found.'}</div>;
75
+ return <div className="no-results">{translations.SRP.NO_RESULTS}</div>;
79
76
  }
80
77
 
81
78
  const cmsMap = React.useMemo(() => {
@@ -102,11 +99,11 @@ const HotelAccommodationResults: React.FC<HotelAccommodationResultsProps> = ({ i
102
99
  </div>
103
100
  <div className="search__results__label__text">
104
101
  <h3>
105
- Select <strong>Accommodation</strong>
102
+ {translations.SRP.SELECT} <strong>{translations.SRP.ACCOMMODATION}</strong>
106
103
  </h3>
107
104
  </div>
108
105
  </div>
109
- {renderResults(results, context, cmsMap, activeTab)}
106
+ {renderResults(results, context, cmsMap, activeTab, translations)}
110
107
  </>
111
108
  );
112
109
  };
@@ -7,9 +7,10 @@ import { setSelectedHotel } from '../../store/search-results-slice';
7
7
 
8
8
  interface HotelCardProps {
9
9
  result: HotelResult;
10
+ translations?: any;
10
11
  }
11
12
 
12
- const HotelCard: React.FC<HotelCardProps> = ({ result }) => {
13
+ const HotelCard: React.FC<HotelCardProps> = ({ result, translations }) => {
13
14
  const dispatch = useDispatch();
14
15
  const { selectedHotelId } = useSelector((state: SearchResultsRootState) => state.searchResults);
15
16
 
@@ -27,7 +28,7 @@ const HotelCard: React.FC<HotelCardProps> = ({ result }) => {
27
28
  <div className="search__result-card__img-wrapper">
28
29
  <img src={result.image} alt={result.title} className="search__result-card__img" />
29
30
  <div className="search__result-card__price__wrapper">
30
- <span className="search__result-card__price__label">Total price</span>
31
+ <span className="search__result-card__price__label">{translations?.SHARED.TOTAL_PRICE}</span>
31
32
  <span className="search__result-card__price">{result.price}</span>
32
33
  </div>
33
34
  </div>
@@ -75,7 +76,7 @@ const HotelCard: React.FC<HotelCardProps> = ({ result }) => {
75
76
  {selectedHotelId === result.id ? 'Selected' : 'Select'}
76
77
  </button>
77
78
  <button type="button" className="cta cta--select" onClick={() => console.log('Clicked on customCard with id:', result.id)}>
78
- View details
79
+ {translations?.SRP.VIEW_DETAILS}
79
80
  </button>
80
81
  </div>
81
82
  </div>
@@ -537,7 +537,7 @@ const Icon: React.FC<IconProps> = ({ name, className, title, width, height }) =>
537
537
  </svg>
538
538
  );
539
539
 
540
- case 'ui-comparator':
540
+ case 'ui-list':
541
541
  return (
542
542
  <svg
543
543
  className={['icon', `icon--${name}`, className].filter((className) => !isEmpty(className)).join(' ')}
@@ -1,31 +1,112 @@
1
- import React from 'react';
1
+ import React, { useContext } from 'react';
2
2
  import Icon from '../icon';
3
3
  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
+ import SearchResultsConfigurationContext from '../../search-results-configuration-context';
4
11
 
5
12
  interface ItineraryProps {
6
- isMobileFiltersOpen: boolean;
7
- handleSetIsMobileFiltersOpen: () => void;
13
+ isOpen: boolean;
14
+ handleSetIsOpen: () => void;
8
15
  isLoading?: boolean;
9
16
  }
10
17
 
11
- const Itinerary: React.FC<ItineraryProps> = ({ isMobileFiltersOpen, handleSetIsMobileFiltersOpen, isLoading }) => {
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);
27
+
28
+ return (line as any)?.DepartureTime ?? '';
29
+ } catch {
30
+ return '';
31
+ }
32
+ };
33
+
34
+ const getArrivalTime = (flight?: EntryLineLight): string => {
35
+ if (isEmpty(flight?.metaDatas)) return '';
36
+
37
+ try {
38
+ const config = first(flight?.metaDatas)?.configuration;
39
+ if (!config) return '';
40
+
41
+ const parsed = JSON.parse(config);
42
+ const line = last(parsed?.FlightLines);
43
+
44
+ return (line as any)?.ArrivalTime ?? '';
45
+ } catch {
46
+ return '';
47
+ }
48
+ };
49
+
50
+ const getDuration = (flight?: EntryLineLight): string => {
51
+ if (isEmpty(flight?.metaDatas)) return '';
52
+
53
+ try {
54
+ const config = first(flight?.metaDatas)?.configuration;
55
+ if (!config) return '';
56
+
57
+ const parsed = JSON.parse(config);
58
+ const ticks = parsed?.DurationInTicks;
59
+
60
+ if (!ticks) return '';
61
+
62
+ const seconds = ticks / 10_000_000;
63
+ const hours = Math.floor(seconds / 3600);
64
+ const minutes = Math.floor((seconds % 3600) / 60);
65
+
66
+ return `${hours}h ${minutes.toString().padStart(2, '0')}m`;
67
+ } catch {
68
+ return '';
69
+ }
70
+ };
71
+
72
+ const numberOfNights = (segment: EntryLineLight) => {
73
+ return differenceInCalendarDays(new Date(segment.endDate), new Date(segment.startDate));
74
+ };
75
+
76
+ const Itinerary: React.FC<ItineraryProps> = ({ isOpen, handleSetIsOpen, isLoading }) => {
77
+ const context = useContext(SearchResultsConfigurationContext);
78
+ const translations = getTranslations(context?.languageCode ?? 'en-GB');
79
+
80
+ const { entry } = useSelector((state: SearchResultsRootState) => state.searchResults);
81
+
82
+ if (isLoading || !entry) {
83
+ return null;
84
+ }
85
+
86
+ const firstEntryLine = first(entry?.items);
87
+ const lastEntryLine = last(entry?.items);
88
+
89
+ const country = firstEntryLine?.countryName;
90
+ const location = firstEntryLine?.locationName;
91
+
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);
95
+
12
96
  return (
13
97
  <>
14
98
  {/* ---------------- Filters ---------------- */}
15
99
 
16
100
  {/* ---------------- Filters desktop ---------------- */}
17
- <div className={`search__filters--modal ${isMobileFiltersOpen ? 'is-open' : ''}`}>
18
- <div className="search__filters--background" onClick={() => handleSetIsMobileFiltersOpen()}></div>
19
- <button className="search__filters--close" onClick={() => handleSetIsMobileFiltersOpen()}>
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()}>
20
104
  <Icon name="ui-close" height={24} />
21
105
  </button>
22
106
  <div className="search__filters">
23
107
  <div className="search__filter-row search__filter__header">
24
108
  <div className="search__filter-row-flex-title">
25
- <p className="search__filter-small-title">
26
- {/* */}
27
- Your trip summary
28
- </p>
109
+ <p className="search__filter-small-title">{translations.SRP.ITINERARY_TITLE}</p>
29
110
  </div>
30
111
  </div>
31
112
  {isLoading ? (
@@ -33,166 +114,187 @@ const Itinerary: React.FC<ItineraryProps> = ({ isMobileFiltersOpen, handleSetIsM
33
114
  ) : (
34
115
  <>
35
116
  <div className="search__filter-group">
36
- <div className="search__filter__image__wrapper">
37
- <img
38
- src="https://images.unsplash.com/photo-1534292425621-6fbc5c09219a?fm=jpg&q=60&w=3000&ixlib=rb-4.1.0&ixid=M3wxMjA3fDB8MHxzZWFyY2h8M3x8dGVuZXJpZmV8ZW58MHx8MHx8fDA%3D"
39
- alt="filter-img"
40
- className="search__filter__image"
41
- />
42
- <span className="search__filter__image__text">Transport + hotel to</span>
43
- <h4 className="search__filter__image__title">Costa del Silencio - Tenerife Sur</h4>
44
- </div>
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>
127
+ )}
45
128
  </div>
46
129
 
47
130
  <div className="search__filter__prices">
48
131
  <div className="search__filter__prices__wrapper">
49
- <h3 className="search__filter__prices--amount">€256</h3>
50
- <p>package price per person</p>
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>
51
136
  <p>
52
- <strong>(1.974 € Total)</strong>
137
+ <strong>
138
+ ({formatPrice(entry?.sellingPrice || 0, entry?.currencyCode || 'EUR')} {translations.SRP.TOTAL})
139
+ </strong>
53
140
  </p>
54
141
  </div>
55
- <button className="cta">Comfirm</button>
142
+ <button className="cta">{translations.QSM.CONFIRM}</button>
56
143
  </div>
57
144
 
58
145
  <div className="search__filter__itinerary">
59
- <p>Your trip day by day</p>
146
+ <p>{translations.SRP.DAY_BY_DAY}</p>
60
147
  <div className="search__filter__itinerary__country">
61
148
  <div className="search__filter__itinerary__country-icon">
62
149
  <Icon name="ui-flag" width={17.5} height={20} />
63
150
  </div>
64
151
  <div className="search__filter__itinerary__country-content">
65
- <h4>Brussels, Belgium</h4>
66
152
  <p>
67
- Mon. 19 Jan 2026 - <strong>Start</strong>
153
+ {format(new Date(firstEntryLine?.startDate || ''), 'EEE. d MMM yyyy')} - <strong>{translations.SRP.START}</strong>
68
154
  </p>
69
155
  </div>
70
156
  </div>
71
157
 
72
- <div className="search__filter__itinerary__transport">
73
- <div className="search__filter__itinerary__transport-timeline">
74
- <div className="search__filter__itinerary__transport-timeline-line"></div>
75
- </div>
76
- <div className="search__filter__itinerary__transport-item">
77
- <div className="search__filter__itinerary__transport-date">
78
- <p className="search__filter__itinerary__transport-date-date">
79
- <strong>19</strong>
80
- </p>
81
- <p>Jan</p>
82
- </div>
83
- <div className="search__filter__itinerary__transport-badge">
84
- <Icon name="ui-plane" height={15} />
85
- </div>
86
- <div className="search__filter__itinerary__transport-details">
87
- <h6>Brussels Airport (BRU) - Tenerife South Airport (TFS)</h6>
88
- <p className="search__filter__itinerary__transport-details-plane">
89
- <span>
90
- <Icon name="ui-plane-depart" height={14} /> <strong>08:00</strong>
91
- </span>{' '}
92
- -{' '}
93
- <span>
94
- <Icon name="ui-plane-arrive" height={14} /> <strong>12:30</strong>
95
- </span>
96
- </p>
97
- <p className="search__filter__itinerary__transport-details-time">
98
- <span>
99
- <Icon name="ui-clock" height={20} /> 4h30m
100
- </span>
101
- </p>
102
- </div>
103
- </div>
104
- </div>
105
-
106
- <div className="search__filter__itinerary__segments">
107
- <div className="search__filter__itinerary__segments__wrapper">
108
- <div className="search__filter__itinerary__segments-timeline">
109
- <div className="search__filter__itinerary__segments-timeline-line"></div>
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>
110
162
  </div>
111
- <div className="search__filter__itinerary__segment">
112
- <div className="search__filter__itinerary__segment-item search__filter__itinerary__segment-item--start">
113
- <div className="search__filter__itinerary__segment-date">
114
- <p className="search__filter__itinerary__segment-date-date">
115
- <strong>19</strong>
116
- </p>
117
- <p>Jan</p>
118
- </div>
119
- <div className="search__filter__itinerary__segment-badge">
120
- <Icon name="ui-location" width={15} height={15} />
121
- </div>
122
- <div className="search__filter__itinerary__segment-details">
123
- <h6>Costa del Silencio - Tenerife Sur</h6>
124
- <p className="search__filter__itinerary__segment-details-text">Mon. 19 Jan 2026 &gt; Sat. 31 Jan 2026</p>
125
- </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>
126
189
  </div>
127
190
  </div>
128
- <div className="search__filter__itinerary__segment">
129
- <div className="search__filter__itinerary__segment-item">
130
- <div className="search__filter__itinerary__segment-date search__filter__itinerary__segment-nights">
131
- <p className="search__filter__itinerary__segment-date-date">
132
- <strong>12</strong>
133
- </p>
134
- <Icon name="ui-moon" width={16} height={16} />
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>
135
199
  </div>
136
- <div className="search__filter__itinerary__segment-badge search__filter__itinerary__segment-badge--secondary">
137
- <Icon name="ui-bed" width={15} height={15} />
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')}
218
+ </p>
219
+ </div>
220
+ </div>
138
221
  </div>
139
- <div className="search__filter__itinerary__segment-details">
140
- <h6>Grand Muthu Golf Plaza Hotel</h6>
141
- <div className="rating">
142
- <Icon name="ui-star" key={`rating-star-1`} width={14} height={14} />
143
- <Icon name="ui-star" key={`rating-star-2`} width={14} height={14} />
144
- <Icon name="ui-star" key={`rating-star-3`} width={14} height={14} />
145
- <Icon name="ui-star" key={`rating-star-4`} width={14} height={14} />
146
- <Icon name="ui-star" key={`rating-star-5`} width={14} height={14} />
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>
147
248
  </div>
148
249
  </div>
149
250
  </div>
150
- </div>
251
+ ))}
151
252
  </div>
152
- </div>
253
+ )}
153
254
 
154
- <div className="search__filter__itinerary__transport">
155
- <div className="search__filter__itinerary__transport-timeline">
156
- <div className="search__filter__itinerary__transport-timeline-line"></div>
157
- </div>
158
- <div className="search__filter__itinerary__transport-item">
159
- <div className="search__filter__itinerary__transport-date">
160
- <p className="search__filter__itinerary__transport-date-date">
161
- <strong>30</strong>
162
- </p>
163
- <p>Jan</p>
164
- </div>
165
- <div className="search__filter__itinerary__transport-badge">
166
- <Icon name="ui-plane" height={15} />
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>
167
259
  </div>
168
- <div className="search__filter__itinerary__transport-details">
169
- <h6>Tenerife South Airport (TFS) - Brussels Airport (BRU)</h6>
170
- <p className="search__filter__itinerary__transport-details-plane">
171
- <span>
172
- <Icon name="ui-plane-depart" height={14} /> <strong>12:55</strong>
173
- </span>{' '}
174
- -{' '}
175
- <span>
176
- <Icon name="ui-plane-arrive" height={14} /> <strong>18:25</strong>
177
- </span>
178
- </p>
179
- <p className="search__filter__itinerary__transport-details-time">
180
- <span>
181
- <Icon name="ui-clock" height={20} /> 4h30m
182
- </span>
183
- </p>
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>
286
+ </div>
184
287
  </div>
185
288
  </div>
186
- </div>
289
+ )}
187
290
 
188
291
  <div className="search__filter__itinerary__country">
189
292
  <div className="search__filter__itinerary__country-icon">
190
293
  <Icon name="ui-flag" width={17.5} height={20} />
191
294
  </div>
192
295
  <div className="search__filter__itinerary__country-content">
193
- <h4>Brussels, Belgium</h4>
194
296
  <p>
195
- Mon. 19 Jan 2026 - <strong>End</strong>
297
+ {format(new Date(lastEntryLine?.startDate || ''), 'EEE. d MMM yyyy')} - <strong>{translations.SRP.END}</strong>
196
298
  </p>
197
299
  </div>
198
300
  </div>
@@ -5,7 +5,7 @@ interface RoundTripResultsProps {}
5
5
 
6
6
  const RoundTripResults: React.FC<RoundTripResultsProps> = () => {
7
7
  return (
8
- <div className="search__results__cards search__results__cards--comparator">
8
+ <div className="search__results__cards search__results__cards--list">
9
9
  <div className="search__result-card">
10
10
  <div className="search__result-card__allotment">
11
11
  <div className="search__result-card__allotment__title__wrapper">