@qite/tide-components 1.0.6 → 1.0.8

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 (25) hide show
  1. package/build/build-cjs/index.js +1368 -395
  2. package/build/build-cjs/src/search-results/components/itinerary/itinerary-utils.d.ts +12 -0
  3. package/build/build-cjs/src/search-results/components/itinerary/traject-itinerary.d.ts +9 -0
  4. package/build/build-cjs/src/search-results/components/traject/traject-day-activities-flyin.d.ts +6 -0
  5. package/build/build-cjs/src/search-results/components/traject/traject-flights-flyin.d.ts +13 -0
  6. package/build/build-cjs/src/search-results/components/traject/traject-node-card.d.ts +6 -3
  7. package/build/build-cjs/src/search-results/hooks/use-bookable-entry.d.ts +11 -0
  8. package/build/build-cjs/src/search-results/hooks/use-traject-day-activities.d.ts +6 -0
  9. package/build/build-cjs/src/search-results/store/search-results-slice.d.ts +14 -2
  10. package/build/build-cjs/src/search-results/types.d.ts +12 -2
  11. package/build/build-cjs/src/search-results/utils/traject-utils.d.ts +76 -2
  12. package/build/build-esm/index.js +1368 -395
  13. package/build/build-esm/src/search-results/components/itinerary/itinerary-utils.d.ts +12 -0
  14. package/build/build-esm/src/search-results/components/itinerary/traject-itinerary.d.ts +9 -0
  15. package/build/build-esm/src/search-results/components/traject/traject-day-activities-flyin.d.ts +6 -0
  16. package/build/build-esm/src/search-results/components/traject/traject-flights-flyin.d.ts +13 -0
  17. package/build/build-esm/src/search-results/components/traject/traject-node-card.d.ts +6 -3
  18. package/build/build-esm/src/search-results/hooks/use-bookable-entry.d.ts +11 -0
  19. package/build/build-esm/src/search-results/hooks/use-traject-day-activities.d.ts +6 -0
  20. package/build/build-esm/src/search-results/store/search-results-slice.d.ts +14 -2
  21. package/build/build-esm/src/search-results/types.d.ts +12 -2
  22. package/build/build-esm/src/search-results/utils/traject-utils.d.ts +76 -2
  23. package/package.json +2 -2
  24. package/styles/booking-search-results-variables.scss +6 -0
  25. package/styles/components/_search.scss +94 -5
@@ -0,0 +1,12 @@
1
+ import { PackagingEntryLine, PackagingEntryLineFlightLine, PackagingTrajectNode } from '@qite/tide-client';
2
+ export declare const getFlightLines: (flight?: PackagingEntryLine) => PackagingEntryLineFlightLine[];
3
+ export declare const getDepartureTime: (flight?: PackagingEntryLine) => string;
4
+ export declare const getArrivalTime: (flight?: PackagingEntryLine) => string;
5
+ export declare const getDuration: (flight?: PackagingEntryLine) => string;
6
+ export declare const numberOfNights: (segment: PackagingEntryLine) => number;
7
+ /** Icon per service type, so every node on the itinerary reads at a glance. */
8
+ export declare const getServiceTypeIcon: (serviceType?: number) => string;
9
+ export declare const getServiceTypeBadgeModifier: (serviceType?: number) => string;
10
+ export declare const POI_TRAJECT_NODE_TYPE = 2;
11
+ export declare const getTrajectNodeIcon: (node: PackagingTrajectNode) => string;
12
+ export declare const getTrajectNodeBadgeModifier: (node: PackagingTrajectNode) => string;
@@ -0,0 +1,9 @@
1
+ import React from 'react';
2
+ import { PackagingEntry, PackagingTrajectResponse } from '@qite/tide-client';
3
+ interface TrajectItineraryProps {
4
+ trajectEntry: PackagingTrajectResponse;
5
+ packagingEntry: PackagingEntry;
6
+ translations: any;
7
+ }
8
+ declare const TrajectItinerary: React.FC<TrajectItineraryProps>;
9
+ export default TrajectItinerary;
@@ -0,0 +1,6 @@
1
+ import React from 'react';
2
+ interface TrajectDayActivitiesFlyInProps {
3
+ isLoading?: boolean;
4
+ }
5
+ declare const TrajectDayActivitiesFlyIn: React.FC<TrajectDayActivitiesFlyInProps>;
6
+ export default TrajectDayActivitiesFlyIn;
@@ -0,0 +1,13 @@
1
+ import React from 'react';
2
+ interface TrajectFlightsFlyInProps {
3
+ isLoading?: boolean;
4
+ }
5
+ /**
6
+ * Every flight found for one traject leg, shown in the fly-in.
7
+ *
8
+ * A one-way search can return far more options than belong in the results column, so the column
9
+ * keeps three and hands the rest to this list — the same shape the regular flight results use.
10
+ * Each leg is searched on its own, so the single leg of a result always sits in `outward`.
11
+ */
12
+ declare const TrajectFlightsFlyIn: React.FC<TrajectFlightsFlyInProps>;
13
+ export default TrajectFlightsFlyIn;
@@ -1,8 +1,8 @@
1
1
  import React from 'react';
2
- import { PackagingAccommodationResponse } from '@qite/tide-client';
3
- import { TrajectNodeWithLine } from '../../utils/traject-utils';
2
+ import { PackagingAccommodationResponse, PackagingTrajectNode } from '@qite/tide-client';
4
3
  interface TrajectNodeCardProps {
5
- item: TrajectNodeWithLine;
4
+ /** The traject node this result answers, where there is one. A suggestion has none. */
5
+ node?: PackagingTrajectNode;
6
6
  result: PackagingAccommodationResponse;
7
7
  isSelected: boolean;
8
8
  languageCode?: string;
@@ -10,6 +10,9 @@ interface TrajectNodeCardProps {
10
10
  onSelect: () => void;
11
11
  onEditOptions?: () => void;
12
12
  showNights?: boolean;
13
+ /** Wording for the button. Defaults to select/selected; suggestions say add/remove instead. */
14
+ selectLabel?: string;
15
+ selectedLabel?: string;
13
16
  }
14
17
  declare const TrajectNodeCard: React.FC<TrajectNodeCardProps>;
15
18
  export default TrajectNodeCard;
@@ -0,0 +1,11 @@
1
+ import { PackagingEntry } from '@qite/tide-client';
2
+ /**
3
+ * The entry to send to the backend, as opposed to the one the page works with.
4
+ *
5
+ * They differ only for a traject: the page keeps the line guids the traject was rendered with,
6
+ * because that is what joins its nodes to its lines, while pricing and booking need the guids the
7
+ * searches cached their lines under. Anything else passes through untouched, so this can be used
8
+ * wherever the entry leaves the component without checking which flow is running.
9
+ */
10
+ declare const useBookableEntry: () => PackagingEntry | null;
11
+ export default useBookableEntry;
@@ -0,0 +1,6 @@
1
+ export interface TrajectDay {
2
+ order: number;
3
+ date: string;
4
+ }
5
+ declare const useTrajectDayActivities: () => (day: TrajectDay) => Promise<void>;
6
+ export default useTrajectDayActivities;
@@ -42,7 +42,11 @@ export interface SearchResultsState {
42
42
  trajectNodeAvailability: Record<string, TrajectNodeAvailability>;
43
43
  /** Per-flight-node one-way search results, keyed by the entry line guid. */
44
44
  trajectFlightAvailability: Record<string, TrajectFlightAvailability>;
45
+ trajectDaySuggestions: Record<number, TrajectDaySuggestions>;
45
46
  trajectEditLineGuid: string | null;
47
+ trajectActivitiesDayOrder: number | null;
48
+ trajectResolving: boolean;
49
+ trajectItineraryView: boolean;
46
50
  }
47
51
  export type TrajectNodeStatus = 'idle' | 'loading' | 'resolved' | 'unavailable';
48
52
  export interface TrajectNodeAvailability {
@@ -52,6 +56,11 @@ export interface TrajectNodeAvailability {
52
56
  selectedCode: string | null;
53
57
  preferredUnavailable: boolean;
54
58
  }
59
+ export interface TrajectDaySuggestions {
60
+ dayOrder: number;
61
+ status: TrajectNodeStatus;
62
+ results: PackagingAccommodationResponse[];
63
+ }
55
64
  export interface TrajectFlightAvailability {
56
65
  lineGuid: string;
57
66
  status: TrajectNodeStatus;
@@ -79,14 +88,17 @@ export declare const setResults: import("@reduxjs/toolkit").ActionCreatorWithPay
79
88
  }, "searchResults/setTrajectNodeAvailability">, setTrajectNodeSelection: import("@reduxjs/toolkit").ActionCreatorWithPayload<{
80
89
  lineGuid: string;
81
90
  code: string;
82
- }, "searchResults/setTrajectNodeSelection">, setTrajectFlightLoading: import("@reduxjs/toolkit").ActionCreatorWithPayload<string, "searchResults/setTrajectFlightLoading">, setTrajectFlightAvailability: import("@reduxjs/toolkit").ActionCreatorWithPayload<{
91
+ }, "searchResults/setTrajectNodeSelection">, setTrajectResolving: import("@reduxjs/toolkit").ActionCreatorWithPayload<boolean, "searchResults/setTrajectResolving">, setTrajectItineraryView: import("@reduxjs/toolkit").ActionCreatorWithPayload<boolean, "searchResults/setTrajectItineraryView">, setTrajectFlightLoading: import("@reduxjs/toolkit").ActionCreatorWithPayload<string, "searchResults/setTrajectFlightLoading">, setTrajectFlightAvailability: import("@reduxjs/toolkit").ActionCreatorWithPayload<{
83
92
  lineGuid: string;
84
93
  results: PackagingFlightResponse[];
85
94
  selectedGuid: string | null;
86
95
  }, "searchResults/setTrajectFlightAvailability">, setTrajectFlightSelection: import("@reduxjs/toolkit").ActionCreatorWithPayload<{
87
96
  lineGuid: string;
88
97
  guid: string;
89
- }, "searchResults/setTrajectFlightSelection">, setTrajectEditLineGuid: import("@reduxjs/toolkit").ActionCreatorWithPayload<string | null, "searchResults/setTrajectEditLineGuid">, updateTrajectNodeResult: import("@reduxjs/toolkit").ActionCreatorWithPayload<{
98
+ }, "searchResults/setTrajectFlightSelection">, setTrajectEditLineGuid: import("@reduxjs/toolkit").ActionCreatorWithPayload<string | null, "searchResults/setTrajectEditLineGuid">, setTrajectActivitiesDayOrder: import("@reduxjs/toolkit").ActionCreatorWithPayload<number | null, "searchResults/setTrajectActivitiesDayOrder">, setTrajectDaySuggestionsLoading: import("@reduxjs/toolkit").ActionCreatorWithPayload<number, "searchResults/setTrajectDaySuggestionsLoading">, setTrajectDaySuggestions: import("@reduxjs/toolkit").ActionCreatorWithPayload<{
99
+ dayOrder: number;
100
+ results: PackagingAccommodationResponse[];
101
+ }, "searchResults/setTrajectDaySuggestions">, addEditableEntryLines: import("@reduxjs/toolkit").ActionCreatorWithPayload<PackagingEntryLine[], "searchResults/addEditableEntryLines">, updateTrajectNodeResult: import("@reduxjs/toolkit").ActionCreatorWithPayload<{
90
102
  lineGuid: string;
91
103
  result: PackagingAccommodationResponse;
92
104
  }, "searchResults/updateTrajectNodeResult">, resetTrajectAvailability: import("@reduxjs/toolkit").ActionCreatorWithoutPayload<"searchResults/resetTrajectAvailability">, updateEditableEntryLine: import("@reduxjs/toolkit").ActionCreatorWithPayload<PackagingEntryLine, "searchResults/updateEditableEntryLine">, removeEditableEntryLines: import("@reduxjs/toolkit").ActionCreatorWithPayload<string[], "searchResults/removeEditableEntryLines">;
@@ -39,7 +39,17 @@ export interface SearchResultsConfiguration {
39
39
  onFlightBook?: (result: ExtendedFlightSearchResponseItem) => void;
40
40
  packagingEntry?: PackagingEntry | null;
41
41
  trajectEntry?: PackagingTrajectResponse | null;
42
- showNonPreferredItems?: boolean;
42
+ /**
43
+ * From the website portal configuration. When true a traject node may also offer externally
44
+ * sourced (API/vendor) hotels and excursions; when false only products held internally in Tide
45
+ * are searched and shown.
46
+ */
47
+ showApiItems?: boolean;
48
+ /**
49
+ * From the website portal configuration. Hides the "show more" button that opens a traject
50
+ * node's remaining results in the fly-in.
51
+ */
52
+ hideShowMoreResults?: boolean;
43
53
  generatePaymentUrl?: boolean;
44
54
  entryStatus?: number;
45
55
  customEntryStatusId?: number;
@@ -166,7 +176,7 @@ export type SearchSeed = {
166
176
  destinationAirport?: string | null;
167
177
  rooms: BookingPackageRequestRoom[];
168
178
  };
169
- export type FlyInType = 'flight-outward-results' | 'flight-return-results' | 'flight-details' | 'acco-results' | 'acco-details' | 'excursion-results' | 'excursion-details';
179
+ export type FlyInType = 'flight-outward-results' | 'flight-return-results' | 'flight-details' | 'acco-results' | 'acco-details' | 'excursion-results' | 'excursion-details' | 'traject-flight-results' | 'traject-day-activities';
170
180
  export interface ExcursionSearchParams {
171
181
  date: string;
172
182
  fromDate: string;
@@ -1,4 +1,5 @@
1
- import { FlightSearchRequest, PackagingAccommodationRequest, PackagingAccommodationResponse, PackagingEntry, PackagingEntryLine, PackagingFlightResponse, PackagingRoom, PackagingTrajectAlternative, PackagingTrajectNode, PackagingTrajectResponse } from '@qite/tide-client';
1
+ import { FlightSearchRequest, TideClientConfig, PackagingAccommodationRequest, PackagingAccommodationResponse, PackagingDestination, PackagingEntry, PackagingEntryLine, PackagingFlightResponse, PackagingRoom, PackagingTrajectAlternative, PackagingTrajectNode, PackagingTrajectResponse } from '@qite/tide-client';
2
+ import { SearchResultsConfiguration } from '../types';
2
3
  export declare const REGULAR_TRAJECT_NODE_TYPE = 0;
3
4
  export declare const CONNECTING_TRAJECT_NODE_TYPE = 1;
4
5
  export interface TrajectNodeWithLine {
@@ -9,6 +10,7 @@ export interface TrajectNodeWithLine {
9
10
  export declare const isSearchableTrajectNode: (node: PackagingTrajectNode) => boolean;
10
11
  export declare const isTrajectFlightNode: (node: PackagingTrajectNode) => boolean;
11
12
  export declare const getTrajectNodesWithLines: (trajectEntry: PackagingTrajectResponse) => TrajectNodeWithLine[];
13
+ export declare const hasDestination: (destination: PackagingDestination | null) => boolean;
12
14
  export interface TrajectSearchContext {
13
15
  transactionId: string;
14
16
  officeId: number;
@@ -19,7 +21,52 @@ export interface TrajectSearchContext {
19
21
  language: string;
20
22
  rooms: PackagingAccommodationRequest['rooms'];
21
23
  }
22
- export declare const buildTrajectNodeRequest: ({ node, line }: TrajectNodeWithLine, context: TrajectSearchContext, productCode: string) => PackagingAccommodationRequest;
24
+ export declare const buildTrajectClientConfig: (context: SearchResultsConfiguration) => TideClientConfig;
25
+ export declare const buildTrajectSearchContext: (context: SearchResultsConfiguration, trajectEntry: PackagingTrajectResponse) => TrajectSearchContext;
26
+ export declare const buildTrajectNodeRequest: ({ node, line }: TrajectNodeWithLine, context: TrajectSearchContext, productCode: string, destination?: PackagingDestination) => PackagingAccommodationRequest;
27
+ export declare const getDayDestinationItem: (items: TrajectNodeWithLine[], dayOrder: number) => TrajectNodeWithLine | null;
28
+ export declare const getDayDestination: (items: TrajectNodeWithLine[], availability: Record<string, {
29
+ results: PackagingAccommodationResponse[];
30
+ selectedCode: string | null;
31
+ }>, dayOrder: number) => PackagingDestination | null;
32
+ export declare const buildTrajectDayExcursionRequest: (date: string, destination: PackagingDestination, context: TrajectSearchContext) => PackagingAccommodationRequest;
33
+ type ExcursionOption = PackagingAccommodationResponse['rooms'][number]['options'][number];
34
+ export declare const getExcursionOptionGroups: (result: PackagingAccommodationResponse) => ExcursionOption[][];
35
+ export declare const excursionNeedsChoice: (result: PackagingAccommodationResponse) => boolean;
36
+ export declare const buildTrajectExcursionLines: (result: PackagingAccommodationResponse) => PackagingEntryLine[];
37
+ export declare const buildExcursionSearchParams: (result: PackagingAccommodationResponse) => {
38
+ date: string;
39
+ fromDate: string;
40
+ toDate: string;
41
+ countryId: number | null | undefined;
42
+ regionId: number | null | undefined;
43
+ oordId: number | null | undefined;
44
+ locationId: number | null | undefined;
45
+ locationName: string;
46
+ accommodationCode: null;
47
+ accommodationName: null;
48
+ hotelCode: string;
49
+ hotelName: string;
50
+ rooms: import("@qite/tide-client").PackageMainRoom[];
51
+ };
52
+ export interface DayActivityCard {
53
+ result: PackagingAccommodationResponse;
54
+ item?: TrajectNodeWithLine;
55
+ }
56
+ export declare const buildDayActivityCards: (items: TrajectNodeWithLine[], availability: Record<string, {
57
+ results: PackagingAccommodationResponse[];
58
+ selectedCode: string | null;
59
+ }>, suggestions: PackagingAccommodationResponse[]) => DayActivityCard[];
60
+ /**
61
+ * Where to search for a node.
62
+ *
63
+ * Normally the node says so itself, through the product it was configured with. An excursion slot
64
+ * left empty on the traject says nothing at all — no code, no alternatives, and a line with no
65
+ * place on it — so it falls back to wherever the party is staying that day, the same anchor the
66
+ * day's own activity search uses.
67
+ */
68
+ export declare const getNodeSearchDestination: (items: TrajectNodeWithLine[], item: TrajectNodeWithLine) => PackagingDestination;
69
+ export declare const getConfiguredExcursionCodes: (items: TrajectNodeWithLine[], dayOrder: number) => Set<string>;
23
70
  export declare const getNodeCandidates: (node: PackagingTrajectNode) => PackagingTrajectAlternative[];
24
71
  export declare const findCandidateForResult: (node: PackagingTrajectNode, result: PackagingAccommodationResponse) => PackagingTrajectAlternative | null;
25
72
  export declare const matchesCode: (result: PackagingAccommodationResponse, code: string) => boolean;
@@ -28,5 +75,32 @@ export declare const pickCheapest: (results: PackagingAccommodationResponse[]) =
28
75
  export declare const applyResultToLines: (lines: PackagingEntryLine[], result: PackagingAccommodationResponse) => PackagingEntryLine[];
29
76
  export declare const applyResultToLine: (line: PackagingEntryLine, result: PackagingAccommodationResponse, roomIndex?: number) => PackagingEntryLine;
30
77
  export declare const buildTrajectFlightRequest: ({ node, line }: TrajectNodeWithLine, context: TrajectSearchContext, pax: FlightSearchRequest["pax"]) => FlightSearchRequest;
78
+ /**
79
+ * The entry as the backend can price it.
80
+ *
81
+ * A search caches an EntryLine per option and hands back that line's guid on the option. The
82
+ * backend then rebuilds the entry by looking each line up in that cache on its guid, so a line
83
+ * it cannot find is dropped — PackagingEntryBuilder.SyncEntryLines skips it, and an entry whose
84
+ * lines all came off a traject prices as nothing at all.
85
+ *
86
+ * A traject entry is rendered before any search runs, so its lines carry the guids the traject
87
+ * mapper gave them. This swaps in the guid of whatever each line resolved onto, leaving the
88
+ * lines the traveller added themselves alone — those were built from a search result and already
89
+ * carry the right one.
90
+ */
91
+ export declare const withCachedEntryLineGuids: (entry: PackagingEntry, trajectEntry: PackagingTrajectResponse, nodeAvailability: Record<string, {
92
+ results: PackagingAccommodationResponse[];
93
+ selectedCode: string | null;
94
+ }>, flightAvailability: Record<string, {
95
+ selectedGuid: string | null;
96
+ }>) => PackagingEntry;
31
97
  export declare const pickCheapestFlight: (flights: PackagingFlightResponse[]) => PackagingFlightResponse | null;
32
98
  export declare const applyFlightToLine: (line: PackagingEntryLine, flight: PackagingFlightResponse) => PackagingEntryLine;
99
+ /**
100
+ * Externally sourced products carry a vendor configuration; products held internally in Tide have
101
+ * none. `vendorType` is not a reliable signal — the packaging service nulls it out when the search
102
+ * configuration has ExposeProvider off — so the vendor ids are what we go on.
103
+ */
104
+ export declare const isExternalResult: (result: PackagingAccommodationResponse) => boolean;
105
+ export declare const isExternalCandidate: (candidate: PackagingTrajectAlternative) => boolean;
106
+ export {};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@qite/tide-components",
3
- "version": "1.0.6",
3
+ "version": "1.0.8",
4
4
  "description": "React components for Tide (booking, product availability, form, ...)",
5
5
  "main": "build/build-cjs/index.js",
6
6
  "types": "build/build-cjs/src/index.d.ts",
@@ -36,7 +36,7 @@
36
36
  "devDependencies": {
37
37
  "@jsonurl/jsonurl": "^1.1.4",
38
38
  "@popperjs/core": "^2.10.2",
39
- "@qite/tide-client": "^2.0.15",
39
+ "@qite/tide-client": "^2.0.16",
40
40
  "@reduxjs/toolkit": "^2.8.2",
41
41
  "@rollup/plugin-commonjs": "^19.0.1",
42
42
  "@rollup/plugin-json": "^4.1.0",
@@ -545,6 +545,12 @@
545
545
  --tide-booking-search-itinerary-filter-segment-badge--secondary-icon-background-color: orangered;
546
546
  --tide-booking-search-itinerary-filter-segment-badge--secondary-icon-color: var(--tide-booking-white);
547
547
 
548
+ --tide-booking-search-itinerary-service-flight-color: #99a9ff;
549
+ --tide-booking-search-itinerary-service-hotel-color: #3f9bff;
550
+ --tide-booking-search-itinerary-service-excursion-color: #f39c12;
551
+ --tide-booking-search-itinerary-service-poi-color: #3ec758;
552
+ --tide-booking-search-itinerary-service-restaurant-color: #ffcc00;
553
+
548
554
  --tide-booking-search-itinerary-filter-segment-date-day-font-weight: 600;
549
555
  --tide-booking-search-itinerary-filter-segment-date-day-color: var(--tide-booking-black);
550
556
 
@@ -505,6 +505,7 @@
505
505
 
506
506
  &-date {
507
507
  min-width: 26px;
508
+ max-width: 26px;
508
509
 
509
510
  p {
510
511
  margin: 0px;
@@ -535,6 +536,36 @@
535
536
  align-items: center;
536
537
  justify-content: center;
537
538
  color: var(--tide-booking-search-itinerary-filter-transport-badge-icon-color);
539
+
540
+ &--default {
541
+ background-color: var(--tide-booking-search-itinerary-filter-segment-badge-icon-background-color);
542
+ color: var(--tide-booking-search-itinerary-filter-segment-badge-icon-color);
543
+ }
544
+
545
+ &--flight {
546
+ background-color: var(--tide-booking-search-itinerary-service-flight-color);
547
+ color: var(--tide-booking-white);
548
+ }
549
+
550
+ &--hotel {
551
+ background-color: var(--tide-booking-search-itinerary-service-hotel-color);
552
+ color: var(--tide-booking-white);
553
+ }
554
+
555
+ &--excursion {
556
+ background-color: var(--tide-booking-search-itinerary-service-excursion-color);
557
+ color: var(--tide-booking-white);
558
+ }
559
+
560
+ &--poi {
561
+ background-color: var(--tide-booking-search-itinerary-service-poi-color);
562
+ color: var(--tide-booking-white);
563
+ }
564
+
565
+ &--restaurant {
566
+ background-color: var(--tide-booking-search-itinerary-service-restaurant-color);
567
+ color: var(--tide-booking-white);
568
+ }
538
569
  }
539
570
 
540
571
  &-details {
@@ -668,6 +699,26 @@
668
699
  background: var(--tide-booking-search-itinerary-filter-segment-badge--secondary-icon-background-color);
669
700
  color: var(--tide-booking-search-itinerary-filter-segment-badge--secondary-icon-color);
670
701
  }
702
+
703
+ &--flight {
704
+ background: var(--tide-booking-search-itinerary-service-flight-color);
705
+ }
706
+
707
+ &--hotel {
708
+ background: var(--tide-booking-search-itinerary-service-hotel-color);
709
+ }
710
+
711
+ &--excursion {
712
+ background: var(--tide-booking-search-itinerary-service-excursion-color);
713
+ }
714
+
715
+ &--poi {
716
+ background: var(--tide-booking-search-itinerary-service-poi-color);
717
+ }
718
+
719
+ &--restaurant {
720
+ background: var(--tide-booking-search-itinerary-service-restaurant-color);
721
+ }
671
722
  }
672
723
 
673
724
  &-date {
@@ -691,6 +742,10 @@
691
742
  display: flex;
692
743
  align-items: center;
693
744
  flex-flow: row nowrap;
745
+ }
746
+
747
+ &-nights,
748
+ &-date {
694
749
  min-width: 26px;
695
750
  max-width: 26px;
696
751
 
@@ -744,11 +799,7 @@
744
799
  display: flex;
745
800
  flex-direction: column;
746
801
  width: 100%;
747
- grid-column: span 12;
748
-
749
- @include mixins.media-md {
750
- grid-column: auto;
751
- }
802
+ min-width: 0;
752
803
 
753
804
  &__cards {
754
805
  display: grid;
@@ -783,6 +834,43 @@
783
834
  }
784
835
  }
785
836
 
837
+ &__cards--scroll {
838
+ display: flex;
839
+ flex-wrap: nowrap;
840
+ overflow-x: auto;
841
+ overflow-y: hidden;
842
+ scroll-snap-type: x proximity;
843
+ -webkit-overflow-scrolling: touch;
844
+ padding-bottom: 5px;
845
+
846
+ @include mixins.media-sm {
847
+ grid-template-columns: none;
848
+ }
849
+
850
+ @include mixins.media-md {
851
+ grid-template-columns: none;
852
+ }
853
+
854
+ @include mixins.media-lg {
855
+ grid-template-columns: none;
856
+ }
857
+
858
+ @include mixins.media-xgl {
859
+ grid-template-columns: none;
860
+ }
861
+
862
+ > * {
863
+ flex: 0 0 auto;
864
+ scroll-snap-align: start;
865
+ width: 280px;
866
+ max-width: 85vw;
867
+
868
+ @include mixins.media-md {
869
+ width: 320px;
870
+ }
871
+ }
872
+ }
873
+
786
874
  &__wrapper {
787
875
  display: flex;
788
876
  flex-direction: column;
@@ -1124,6 +1212,7 @@
1124
1212
  }
1125
1213
 
1126
1214
  &__header {
1215
+ position: relative;
1127
1216
  display: flex;
1128
1217
  justify-content: space-between;
1129
1218
  gap: 5px;