@qite/tide-booking-component 0.0.2-preview.9 → 1.0.0-preview

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 (143) hide show
  1. package/README.md +1 -0
  2. package/build/build-cjs/booking-wizard/components/message.d.ts +1 -0
  3. package/build/build-cjs/booking-wizard/components/product-card.d.ts +1 -2
  4. package/build/build-cjs/booking-wizard/features/booking/api.d.ts +21 -0
  5. package/build/build-cjs/booking-wizard/features/booking/booking-slice.d.ts +95 -19
  6. package/build/build-cjs/booking-wizard/features/booking/booking.d.ts +1 -2
  7. package/build/build-cjs/booking-wizard/features/booking/selectors.d.ts +208 -0
  8. package/build/build-cjs/booking-wizard/features/price-details/price-details-api.d.ts +8 -6
  9. package/build/build-cjs/booking-wizard/features/price-details/price-details-slice.d.ts +98 -30
  10. package/build/build-cjs/booking-wizard/features/price-details/util.d.ts +5 -0
  11. package/build/build-cjs/booking-wizard/features/product-options/no-options.d.ts +2 -0
  12. package/build/build-cjs/booking-wizard/features/product-options/none-option.d.ts +17 -0
  13. package/build/build-cjs/booking-wizard/features/product-options/option-booking-group.d.ts +18 -0
  14. package/build/build-cjs/booking-wizard/features/product-options/option-item.d.ts +11 -0
  15. package/build/build-cjs/booking-wizard/features/product-options/option-pax-card.d.ts +9 -0
  16. package/build/build-cjs/booking-wizard/features/product-options/option-pax-group.d.ts +20 -0
  17. package/build/build-cjs/booking-wizard/features/product-options/option-room.d.ts +16 -0
  18. package/build/build-cjs/booking-wizard/features/product-options/option-unit-group.d.ts +20 -0
  19. package/build/build-cjs/booking-wizard/features/product-options/option-units-card.d.ts +9 -0
  20. package/build/build-cjs/booking-wizard/features/sidebar/index.d.ts +5 -1
  21. package/build/build-cjs/booking-wizard/features/sidebar/sidebar-flight.d.ts +8 -0
  22. package/build/build-cjs/booking-wizard/features/sidebar/sidebar-util.d.ts +22 -5
  23. package/build/build-cjs/booking-wizard/features/sidebar/sidebar.d.ts +16 -8
  24. package/build/build-cjs/booking-wizard/features/summary/summary-booking-option-pax.d.ts +7 -0
  25. package/build/build-cjs/booking-wizard/features/summary/summary-booking-option-unit.d.ts +7 -0
  26. package/build/build-cjs/booking-wizard/features/summary/summary-flight.d.ts +8 -0
  27. package/build/build-cjs/booking-wizard/features/summary/summary-per-booking-option-group.d.ts +10 -0
  28. package/build/build-cjs/booking-wizard/features/summary/summary-per-pax-option-group.d.ts +10 -0
  29. package/build/build-cjs/booking-wizard/features/summary/summary-per-unit-option-group.d.ts +10 -0
  30. package/build/build-cjs/booking-wizard/features/summary/summary-slice.d.ts +0 -28
  31. package/build/build-cjs/booking-wizard/features/travelers-form/travelers-form-slice.d.ts +82 -88
  32. package/build/build-cjs/booking-wizard/features/travelers-form/type-ahead-input.d.ts +1 -0
  33. package/build/build-cjs/booking-wizard/features/travelers-form/validate-form.d.ts +2 -1
  34. package/build/build-cjs/booking-wizard/index.d.ts +3 -2
  35. package/build/build-cjs/booking-wizard/store.d.ts +23 -45
  36. package/build/build-cjs/booking-wizard/types.d.ts +63 -11
  37. package/build/build-cjs/booking-wizard/utils/query-string-util.d.ts +13 -0
  38. package/build/build-cjs/index.js +12065 -2381
  39. package/build/build-esm/booking-wizard/components/message.d.ts +1 -0
  40. package/build/build-esm/booking-wizard/components/product-card.d.ts +1 -2
  41. package/build/build-esm/booking-wizard/features/booking/api.d.ts +21 -0
  42. package/build/build-esm/booking-wizard/features/booking/booking-slice.d.ts +95 -19
  43. package/build/build-esm/booking-wizard/features/booking/booking.d.ts +1 -2
  44. package/build/build-esm/booking-wizard/features/booking/selectors.d.ts +208 -0
  45. package/build/build-esm/booking-wizard/features/price-details/price-details-api.d.ts +8 -6
  46. package/build/build-esm/booking-wizard/features/price-details/price-details-slice.d.ts +98 -30
  47. package/build/build-esm/booking-wizard/features/price-details/util.d.ts +5 -0
  48. package/build/build-esm/booking-wizard/features/product-options/no-options.d.ts +2 -0
  49. package/build/build-esm/booking-wizard/features/product-options/none-option.d.ts +17 -0
  50. package/build/build-esm/booking-wizard/features/product-options/option-booking-group.d.ts +18 -0
  51. package/build/build-esm/booking-wizard/features/product-options/option-item.d.ts +11 -0
  52. package/build/build-esm/booking-wizard/features/product-options/option-pax-card.d.ts +9 -0
  53. package/build/build-esm/booking-wizard/features/product-options/option-pax-group.d.ts +20 -0
  54. package/build/build-esm/booking-wizard/features/product-options/option-room.d.ts +16 -0
  55. package/build/build-esm/booking-wizard/features/product-options/option-unit-group.d.ts +20 -0
  56. package/build/build-esm/booking-wizard/features/product-options/option-units-card.d.ts +9 -0
  57. package/build/build-esm/booking-wizard/features/sidebar/index.d.ts +5 -1
  58. package/build/build-esm/booking-wizard/features/sidebar/sidebar-flight.d.ts +8 -0
  59. package/build/build-esm/booking-wizard/features/sidebar/sidebar-util.d.ts +22 -5
  60. package/build/build-esm/booking-wizard/features/sidebar/sidebar.d.ts +16 -8
  61. package/build/build-esm/booking-wizard/features/summary/summary-booking-option-pax.d.ts +7 -0
  62. package/build/build-esm/booking-wizard/features/summary/summary-booking-option-unit.d.ts +7 -0
  63. package/build/build-esm/booking-wizard/features/summary/summary-flight.d.ts +8 -0
  64. package/build/build-esm/booking-wizard/features/summary/summary-per-booking-option-group.d.ts +10 -0
  65. package/build/build-esm/booking-wizard/features/summary/summary-per-pax-option-group.d.ts +10 -0
  66. package/build/build-esm/booking-wizard/features/summary/summary-per-unit-option-group.d.ts +10 -0
  67. package/build/build-esm/booking-wizard/features/summary/summary-slice.d.ts +0 -28
  68. package/build/build-esm/booking-wizard/features/travelers-form/travelers-form-slice.d.ts +82 -88
  69. package/build/build-esm/booking-wizard/features/travelers-form/type-ahead-input.d.ts +1 -0
  70. package/build/build-esm/booking-wizard/features/travelers-form/validate-form.d.ts +2 -1
  71. package/build/build-esm/booking-wizard/index.d.ts +3 -2
  72. package/build/build-esm/booking-wizard/store.d.ts +23 -45
  73. package/build/build-esm/booking-wizard/types.d.ts +63 -11
  74. package/build/build-esm/booking-wizard/utils/query-string-util.d.ts +13 -0
  75. package/build/build-esm/index.js +11888 -2330
  76. package/package.json +8 -4
  77. package/rollup.config.js +1 -6
  78. package/src/booking-wizard/components/message.tsx +14 -8
  79. package/src/booking-wizard/components/product-card.tsx +10 -39
  80. package/src/booking-wizard/components/step-indicator.tsx +1 -1
  81. package/src/booking-wizard/components/step-route.tsx +1 -1
  82. package/src/booking-wizard/features/booking/api.ts +44 -0
  83. package/src/booking-wizard/features/booking/booking-slice.ts +274 -40
  84. package/src/booking-wizard/features/booking/booking.tsx +193 -57
  85. package/src/booking-wizard/features/booking/selectors.ts +328 -0
  86. package/src/booking-wizard/features/confirmation/confirmation.tsx +22 -11
  87. package/src/booking-wizard/features/error/error.tsx +15 -2
  88. package/src/booking-wizard/features/price-details/price-details-api.ts +12 -6
  89. package/src/booking-wizard/features/price-details/price-details-slice.ts +80 -50
  90. package/src/booking-wizard/features/price-details/util.ts +135 -0
  91. package/src/booking-wizard/features/product-options/no-options.tsx +18 -0
  92. package/src/booking-wizard/features/product-options/none-option.tsx +118 -0
  93. package/src/booking-wizard/features/product-options/option-booking-group.tsx +210 -0
  94. package/src/booking-wizard/features/product-options/option-item.tsx +321 -0
  95. package/src/booking-wizard/features/product-options/option-pax-card.tsx +102 -0
  96. package/src/booking-wizard/features/product-options/option-pax-group.tsx +169 -0
  97. package/src/booking-wizard/features/product-options/option-room.tsx +300 -0
  98. package/src/booking-wizard/features/product-options/option-unit-group.tsx +192 -0
  99. package/src/booking-wizard/features/product-options/option-units-card.tsx +100 -0
  100. package/src/booking-wizard/features/product-options/options-form.tsx +226 -48
  101. package/src/booking-wizard/features/sidebar/index.tsx +43 -20
  102. package/src/booking-wizard/features/sidebar/sidebar-flight.tsx +66 -0
  103. package/src/booking-wizard/features/sidebar/sidebar-util.ts +81 -39
  104. package/src/booking-wizard/features/sidebar/sidebar.tsx +150 -100
  105. package/src/booking-wizard/features/summary/summary-booking-option-pax.tsx +25 -0
  106. package/src/booking-wizard/features/summary/summary-booking-option-unit.tsx +25 -0
  107. package/src/booking-wizard/features/summary/summary-flight.tsx +35 -0
  108. package/src/booking-wizard/features/summary/summary-per-booking-option-group.tsx +57 -0
  109. package/src/booking-wizard/features/summary/summary-per-pax-option-group.tsx +51 -0
  110. package/src/booking-wizard/features/summary/summary-per-unit-option-group.tsx +54 -0
  111. package/src/booking-wizard/features/summary/summary-slice.ts +1 -134
  112. package/src/booking-wizard/features/summary/summary.tsx +521 -134
  113. package/src/booking-wizard/features/travelers-form/travelers-form-slice.ts +54 -55
  114. package/src/booking-wizard/features/travelers-form/travelers-form.tsx +202 -94
  115. package/src/booking-wizard/features/travelers-form/type-ahead-input.tsx +23 -3
  116. package/src/booking-wizard/features/travelers-form/validate-form.ts +40 -3
  117. package/src/booking-wizard/index.tsx +5 -6
  118. package/src/booking-wizard/settings-context.ts +33 -5
  119. package/src/booking-wizard/store.ts +5 -4
  120. package/src/booking-wizard/translations/translations.json +95 -61
  121. package/src/booking-wizard/types.ts +67 -10
  122. package/src/booking-wizard/utils/query-string-util.ts +42 -0
  123. package/build/build-cjs/booking-wizard/features/product-options/checkbox.d.ts +0 -11
  124. package/build/build-cjs/booking-wizard/features/product-options/option-details.d.ts +0 -11
  125. package/build/build-cjs/booking-wizard/features/product-options/product-options-api.d.ts +0 -29
  126. package/build/build-cjs/booking-wizard/features/product-options/product-options-slice.d.ts +0 -75
  127. package/build/build-cjs/booking-wizard/features/product-options/radio-button.d.ts +0 -10
  128. package/build/build-cjs/booking-wizard/features/product-options/rooms-slice.d.ts +0 -23
  129. package/build/build-cjs/booking-wizard/features/product-options/tree-level.d.ts +0 -7
  130. package/build/build-esm/booking-wizard/features/product-options/checkbox.d.ts +0 -11
  131. package/build/build-esm/booking-wizard/features/product-options/option-details.d.ts +0 -11
  132. package/build/build-esm/booking-wizard/features/product-options/product-options-api.d.ts +0 -29
  133. package/build/build-esm/booking-wizard/features/product-options/product-options-slice.d.ts +0 -75
  134. package/build/build-esm/booking-wizard/features/product-options/radio-button.d.ts +0 -10
  135. package/build/build-esm/booking-wizard/features/product-options/rooms-slice.d.ts +0 -23
  136. package/build/build-esm/booking-wizard/features/product-options/tree-level.d.ts +0 -7
  137. package/src/booking-wizard/features/product-options/checkbox.tsx +0 -38
  138. package/src/booking-wizard/features/product-options/option-details.tsx +0 -65
  139. package/src/booking-wizard/features/product-options/product-options-api.ts +0 -148
  140. package/src/booking-wizard/features/product-options/product-options-slice.ts +0 -149
  141. package/src/booking-wizard/features/product-options/radio-button.tsx +0 -35
  142. package/src/booking-wizard/features/product-options/rooms-slice.ts +0 -28
  143. package/src/booking-wizard/features/product-options/tree-level.tsx +0 -118
@@ -1,20 +1,21 @@
1
- import { ServiceType } from "@qite/tide-client";
2
- import { EntryLineMetaData } from "@qite/tide-client/build/types";
3
- import { MetaDataType } from "@qite/tide-client";
4
- import { format, parseISO } from "date-fns";
5
- import { compact, first, isEmpty, last, orderBy, uniq } from "lodash";
1
+ import { BookingPackageFlightMetaData } from "@qite/tide-client/build/types";
2
+ import { differenceInCalendarDays, format, parseISO } from "date-fns";
3
+ import { compact, isEmpty, orderBy, uniq } from "lodash";
6
4
  import translations from "../../translations/translations.json";
7
- import { ProductOption } from "../product-options/product-options-api";
8
5
  import { FlightLine } from "../../types";
9
6
 
10
7
  export const getTravelersText = (
11
- adultCount: number,
12
- childCount: number
8
+ adultIds: number[],
9
+ childIds: number[]
13
10
  ): string | undefined => {
14
11
  const travelersText = compact([
15
- adultCount && `${adultCount} ${translations.SIDEBAR.TRAVELERS_ADULTS}`,
16
- adultCount && childCount && ", ",
17
- childCount && `${childCount} ${translations.SIDEBAR.TRAVELERS_CHILDREN}`,
12
+ adultIds.length,
13
+ adultIds.length === 1 && ` ${translations.SIDEBAR.TRAVELERS_ADULT}`,
14
+ adultIds.length > 1 && ` ${translations.SIDEBAR.TRAVELERS_ADULTS}`,
15
+ adultIds && adultIds.length && childIds && childIds.length && ", ",
16
+ childIds.length,
17
+ childIds.length === 1 && ` ${translations.SIDEBAR.TRAVELERS_CHILD}`,
18
+ childIds.length > 1 && ` ${translations.SIDEBAR.TRAVELERS_CHILDREN}`,
18
19
  ]).join("");
19
20
 
20
21
  return !isEmpty(travelersText) ? travelersText : undefined;
@@ -34,46 +35,85 @@ export const getDateText = (date: string | undefined): string | undefined => {
34
35
  }
35
36
  };
36
37
 
37
- export const getFlightText = (
38
- productOption?: ProductOption
39
- ): string | undefined => {
40
- if (productOption?.productType !== ServiceType.flight) {
41
- // Option isn't a flight
38
+ export const getDatePeriodText = (
39
+ from?: string,
40
+ to?: string,
41
+ nightsOnly?: boolean
42
+ ) => {
43
+ if (!from || !to) {
42
44
  return undefined;
43
45
  }
44
46
 
45
- const flightLines = parseFlightLines(productOption.metaDatas);
46
- const firstFlight = first(flightLines);
47
- const lastFlight = last(flightLines);
47
+ try {
48
+ const fromDate = parseISO(from);
49
+ const toDate = parseISO(to);
50
+
51
+ const dayDifference = differenceInCalendarDays(toDate, fromDate);
52
+ const daysLabel =
53
+ dayDifference == 0
54
+ ? `1 ${translations.OPTIONS_FORM.DAY}`
55
+ : `${dayDifference + 1} ${translations.OPTIONS_FORM.DAYS}`;
48
56
 
49
- const airlines = uniq(
50
- flightLines?.map((flightLine) => flightLine.airlineDescription)
51
- ).join(", ");
57
+ if (!dayDifference) return daysLabel;
58
+
59
+ const nightsLabel =
60
+ dayDifference == 1
61
+ ? `1 ${translations.OPTIONS_FORM.NIGHT}`
62
+ : `${dayDifference} ${translations.OPTIONS_FORM.NIGHTS}`;
63
+
64
+ return nightsOnly ? nightsLabel : `${daysLabel}, ${nightsLabel}`;
65
+ } catch {
66
+ return undefined;
67
+ }
68
+ };
52
69
 
70
+ export const getFlightText = (
71
+ firstFlight: FlightLine | undefined,
72
+ lastFlight: FlightLine | undefined
73
+ ): string => {
53
74
  return compact([
54
75
  firstFlight?.departureAirportDescription,
76
+ ` (${firstFlight?.departureAirportIata})`,
55
77
  firstFlight?.departureAirportDescription &&
56
78
  lastFlight?.arrivalAirportDescription &&
57
79
  " > ",
58
80
  lastFlight?.arrivalAirportDescription,
59
- airlines && ` (${airlines})`,
81
+ ` (${lastFlight?.arrivalAirportIata})`,
60
82
  ]).join("");
61
83
  };
62
84
 
63
- const parseFlightLines = (
64
- metaDatas: EntryLineMetaData[]
65
- ): FlightLine[] | undefined => {
66
- const flightLineMetaData = metaDatas?.find(
67
- (metaData) => metaData.metaDataType === MetaDataType.flight
68
- );
85
+ export const getAirlines = (flightLines: FlightLine[] | undefined) => {
86
+ return uniq(
87
+ flightLines
88
+ ?.filter((x) => x.airlineDescription)
89
+ ?.map((flightLine) => flightLine.airlineDescription)
90
+ ).join(", ");
91
+ };
69
92
 
70
- if (!flightLineMetaData) {
93
+ export const getFlightHours = (
94
+ firstFlight: FlightLine | undefined,
95
+ lastFlight: FlightLine | undefined
96
+ ): string => {
97
+ return compact([
98
+ getDateText(firstFlight?.departureDate),
99
+ " ",
100
+ firstFlight?.departureTime,
101
+ " > ",
102
+ getDateText(lastFlight?.arrivalDate),
103
+ " ",
104
+ lastFlight?.arrivalTime,
105
+ ]).join("");
106
+ };
107
+
108
+ export const parseFlightLines = (
109
+ metaDatas: BookingPackageFlightMetaData
110
+ ): FlightLine[] | undefined => {
111
+ if (!metaDatas.flightLines) {
71
112
  return undefined;
72
113
  }
73
114
 
74
- const flightLines = JSON.parse(flightLineMetaData.configuration).flightLines;
75
- const parsedFlightLines: FlightLine[] = flightLines.map(
76
- (parsedFlightLine: any) => {
115
+ const parsedFlightLines: FlightLine[] = metaDatas.flightLines.map(
116
+ (parsedFlightLine) => {
77
117
  const departureDate = parseFlightLineDateTime(
78
118
  parsedFlightLine.departureDate,
79
119
  parsedFlightLine.departureTime
@@ -88,36 +128,38 @@ const parseFlightLines = (
88
128
  departureAirportDescription:
89
129
  parsedFlightLine.departureAirportDescription,
90
130
  departureDate: departureDate,
131
+ departureTime: parsedFlightLine.departureTime,
91
132
  arrivalAirportIata: parsedFlightLine.arrivalAirport,
92
133
  arrivalAirportDescription: parsedFlightLine.arrivalAirportDescription,
93
134
  arrivalDate: arrivalDate,
135
+ arrivalTime: parsedFlightLine.arrivalTime,
94
136
  airlineIata: parsedFlightLine.airline,
95
- airlineDescription: parsedFlightLine.airlineDescription,
137
+ airlineDescription: parsedFlightLine.operatingAirlineDescription,
96
138
  airlineNumber: parsedFlightLine.number,
97
139
  };
98
140
  }
99
141
  );
100
142
 
101
- return orderBy(parsedFlightLines, ["departureDate"], ["asc"]);
143
+ return orderBy(parsedFlightLines, "departureDate", "asc");
102
144
  };
103
145
 
104
146
  const parseFlightLineDateTime = (
105
- date: string,
147
+ date: Date,
106
148
  time: string
107
149
  ): string | undefined => {
108
150
  try {
109
151
  // Parse date
110
- const parsedDate = parseISO(date);
152
+ const parsedDate = new Date(date);
111
153
 
112
154
  // Parse time
113
155
  const parsedTimeHours = parseInt(time.substring(0, 2));
114
156
  const parsedTimeMinutes = parseInt(time.substring(3, 5));
115
157
 
116
- if (parsedTimeHours && parsedTimeMinutes) {
158
+ if (!Number.isNaN(parsedTimeHours) && !Number.isNaN(parsedTimeMinutes)) {
117
159
  parsedDate.setUTCHours(parsedTimeHours, parsedTimeMinutes);
118
160
  }
119
161
 
120
- return parsedDate.toISOString();
162
+ return parsedDate.toISOString().slice(0, -1);
121
163
  } catch {
122
164
  // Parsing failed
123
165
  return undefined;
@@ -1,75 +1,88 @@
1
- import { PriceDetail } from "@qite/tide-client";
2
- import React from "react";
1
+ import React, { useState } from "react";
3
2
  import { formatPrice } from "../../utils/localization-util";
4
3
  import translations from "../../translations/translations.json";
5
- import { isEmpty } from "lodash";
4
+ import { compact, isEmpty } from "lodash";
5
+ import { buildClassName } from "../../utils/class-util";
6
+ import ProductCard from "../../components/product-card";
7
+ import {
8
+ BookingPackageFlight,
9
+ BookingPackageRoom,
10
+ BookingPriceDetail,
11
+ } from "@qite/tide-client/build/types";
12
+ import SidebarFlight from "./sidebar-flight";
13
+ import { getDatePeriodText } from "./sidebar-util";
6
14
 
7
15
  interface SidebarProps {
8
- depositText?: string;
16
+ productName: string;
17
+ thumbnailUrl?: string;
18
+ isLoading: boolean;
9
19
  travelersText?: string;
10
20
  startDateText?: string;
11
21
  endDateText?: string;
12
- departureFlightText?: string;
13
- returnFlightText?: string;
22
+ departureFlight?: BookingPackageFlight;
23
+ returnFlight?: BookingPackageFlight;
14
24
  basePrice?: number;
15
25
  totalPrice?: number;
16
26
  remainingAmountText?: string;
17
- includedCosts?: PriceDetail[];
18
- extraCosts?: PriceDetail[];
19
- showDeposit: boolean;
20
- showAccommodationInfo: boolean;
27
+ includedCosts?: BookingPriceDetail[];
28
+ extraCosts?: BookingPriceDetail[];
29
+ deposit?: number;
30
+ accommodations?: BookingPackageRoom[];
31
+ isOnRequest?: boolean;
21
32
  headerComponent?: JSX.Element;
22
33
  footerComponent?: JSX.Element;
34
+ loaderComponent?: JSX.Element;
23
35
  }
24
36
 
25
37
  const Sidebar: React.FC<SidebarProps> = ({
26
- depositText,
38
+ productName,
39
+ thumbnailUrl,
40
+ isLoading,
27
41
  travelersText,
28
42
  startDateText,
29
43
  endDateText,
30
- departureFlightText,
31
- returnFlightText,
44
+ departureFlight,
45
+ returnFlight,
32
46
  basePrice,
33
47
  totalPrice,
34
- remainingAmountText,
35
48
  includedCosts,
36
49
  extraCosts,
37
- showDeposit,
38
- showAccommodationInfo,
50
+ deposit,
51
+ accommodations,
52
+ isOnRequest,
39
53
  headerComponent,
40
54
  footerComponent,
55
+ loaderComponent,
41
56
  }) => {
57
+ const [active, setActive] = useState<boolean>(false);
58
+
42
59
  const canShowPriceBreakdownSection =
43
60
  Boolean(basePrice && basePrice > 0) ||
44
61
  !isEmpty(includedCosts) ||
45
62
  !isEmpty(extraCosts);
46
63
  const canShowTotalPriceSection = Boolean(totalPrice && totalPrice > 0);
47
64
 
65
+ const remainingAmount = (totalPrice ?? 0) - (deposit ?? 0);
66
+
67
+ const handleToggleClick = () => {
68
+ setActive(!active);
69
+ };
70
+
48
71
  return (
49
- <div className="booking__sidebar">
72
+ <div
73
+ className={buildClassName([
74
+ "booking__sidebar",
75
+ active && "booking__sidebar--active",
76
+ ])}
77
+ >
50
78
  {headerComponent}
51
79
 
52
80
  <div className="booking__sidebar-frame">
53
- <div className="booking__sidebar-heading" id="booking-sidebar__toggle">
54
- {showDeposit && (
55
- <h5 className="booking__sidebar-title">
56
- {translations.SIDEBAR.SLIDE_DEPOSIT}
57
- {depositText}
58
- </h5>
59
- )}
60
-
61
- {!showDeposit && totalPrice !== undefined && totalPrice > 0 && (
62
- <h5 className="booking__sidebar-title">
63
- {translations.SIDEBAR.SLIDE_TOTAL_PRICE}
64
- {formatPrice(totalPrice)}
65
- </h5>
66
- )}
67
-
68
- <h5 className="booking__sidebar-title-withoutprice">
69
- {translations.SIDEBAR.OVERVIEW}
70
- </h5>
71
- </div>
72
-
81
+ <ProductCard
82
+ productName={productName}
83
+ thumbnailUrl={thumbnailUrl}
84
+ handleToggleClick={handleToggleClick}
85
+ />
73
86
  <div className="pricing-summary">
74
87
  <div className="pricing-summary__region">
75
88
  <div className="pricing-summary__group">
@@ -89,7 +102,9 @@ const Sidebar: React.FC<SidebarProps> = ({
89
102
  {startDateText && (
90
103
  <div className="pricing-summary__row">
91
104
  <div className="pricing-summary__property">
92
- {translations.SIDEBAR.DEPARTURE}
105
+ {startDateText && endDateText
106
+ ? translations.SIDEBAR.DEPARTURE
107
+ : translations.SIDEBAR.DEPARTURE_SINGLE}
93
108
  </div>
94
109
  <div className="pricing-summary__value">{startDateText}</div>
95
110
  </div>
@@ -105,74 +120,92 @@ const Sidebar: React.FC<SidebarProps> = ({
105
120
  )}
106
121
  </div>
107
122
 
108
- {departureFlightText && returnFlightText && (
109
- <div className="pricing-summary__group">
110
- <h6 className="pricing-summary__title">
111
- {translations.SIDEBAR.FLIGHT}
112
- </h6>
113
- <div className="pricing-summary__row">
114
- <div className="pricing-summary__property">
115
- {translations.SIDEBAR.DEPARTURE}
116
- </div>
117
- <div className="pricing-summary__value">
118
- {departureFlightText}
119
- </div>
120
- </div>
121
- <div className="pricing-summary__row">
122
- <div className="pricing-summary__property">
123
- {translations.SIDEBAR.ARRIVAL}
124
- </div>
125
- <div className="pricing-summary__value">
126
- {returnFlightText}
127
- </div>
128
- </div>
129
- </div>
123
+ {isLoading && loaderComponent}
124
+ {!isLoading && departureFlight && returnFlight && (
125
+ <>
126
+ <SidebarFlight
127
+ title={translations.SIDEBAR.DEPARTURE_FLIGHT}
128
+ flight={departureFlight}
129
+ />
130
+ <SidebarFlight
131
+ title={translations.SIDEBAR.ARRIVAL_FLIGHT}
132
+ flight={returnFlight}
133
+ />
134
+ </>
130
135
  )}
131
136
 
132
- {showAccommodationInfo && (
137
+ {accommodations && (
133
138
  <div className="pricing-summary__group">
134
139
  <h6 className="pricing-summary__title">
135
140
  {translations.SIDEBAR.ACCOMMODATION}
136
141
  </h6>
137
- <div className="pricing-summary__row">
138
- <div className="pricing-summary__property">
139
- 1x Family kamer
140
- </div>
141
-
142
- <div className="pricing-summary__value">&euro; 850</div>
143
- </div>
144
- <div className="pricing-summary__row">
145
- <div className="pricing-summary__property">
146
- 2x Deluxe kamer
147
- </div>
148
-
149
- <div className="pricing-summary__value">&euro; 650</div>
150
- </div>
142
+ {accommodations.map((accommodation) => {
143
+ let option = accommodation.options.find((x) => x.isSelected);
144
+ return (
145
+ <div key={accommodation.index}>
146
+ <div className="pricing-summary__row">
147
+ <div className="pricing-summary__property">
148
+ {option?.accommodationName}
149
+ {isOnRequest
150
+ ? ` (${translations.SIDEBAR.ON_REQUEST})`
151
+ : ""}
152
+ {option?.isOnRequest
153
+ ? ` (${translations.SIDEBAR.ON_REQUEST})`
154
+ : ""}
155
+ </div>
156
+ <div className="pricing-summary__value">
157
+ {option?.price && formatPrice(option?.price)}
158
+ </div>
159
+ </div>
160
+ <div className="pricing-summary__row">
161
+ <div className="price-summarty__property">
162
+ {option?.regimeName}
163
+ </div>
164
+ <div className="price-summary__value">
165
+ {getDatePeriodText(option?.from, option?.to, true)}
166
+ </div>
167
+ </div>
168
+ </div>
169
+ );
170
+ })}
151
171
  </div>
152
172
  )}
153
173
  </div>
154
174
 
155
- {canShowPriceBreakdownSection && (
175
+ {!isLoading && canShowPriceBreakdownSection && (
156
176
  <div className="pricing-summary__region">
157
177
  {!isEmpty(includedCosts) && (
158
178
  <div className="pricing-summary__group">
159
179
  <h6 className="pricing-summary__title">
160
180
  {translations.SIDEBAR.INCLUDED_COSTS}
161
181
  </h6>
162
- {includedCosts?.map((priceDetail) => (
163
- <div
164
- className="pricing-summary__row"
165
- key={`${priceDetail.productCode}_${priceDetail.priceDescription}`}
182
+ {includedCosts?.map((priceDetail, index) => (
183
+ <React.Fragment
184
+ key={compact([
185
+ priceDetail.productCode,
186
+ priceDetail.accommodationCode,
187
+ index,
188
+ ]).join("_")}
166
189
  >
167
- <div className="pricing-summary__property">
168
- {priceDetail.productName} {priceDetail.priceDescription}
190
+ <div className="pricing-summary__row">
191
+ <div className="pricing-summary__property">
192
+ {priceDetail.productName}
193
+ </div>
194
+ {priceDetail.showPrice && (
195
+ <div className="pricing-summary__value">
196
+ {formatPrice(
197
+ priceDetail.price * priceDetail.amount
198
+ )}
199
+ </div>
200
+ )}
169
201
  </div>
170
- {priceDetail.showPrice && (
171
- <div className="pricing-summary__value">
172
- {formatPrice(priceDetail.price * priceDetail.amount)}
202
+ <div className="pricing-summary__row">
203
+ <div className="price-summary__property">
204
+ {priceDetail.accommodationName ??
205
+ priceDetail.accommodationCode}
173
206
  </div>
174
- )}
175
- </div>
207
+ </div>
208
+ </React.Fragment>
176
209
  ))}
177
210
  </div>
178
211
  )}
@@ -195,27 +228,42 @@ const Sidebar: React.FC<SidebarProps> = ({
195
228
  <h6 className="pricing-summary__title">
196
229
  {translations.SIDEBAR.EXTRA_COSTS}
197
230
  </h6>
198
- {extraCosts?.map((priceDetail) => (
199
- <div
200
- className="pricing-summary__row"
201
- key={`${priceDetail.productCode}_${priceDetail.priceDescription}`}
231
+ {extraCosts?.map((priceDetail, index) => (
232
+ <React.Fragment
233
+ key={compact([
234
+ priceDetail.productCode,
235
+ priceDetail.accommodationCode,
236
+ index,
237
+ ]).join("_")}
202
238
  >
203
- <div className="pricing-summary__property">
204
- {priceDetail.productName} {priceDetail.priceDescription}
239
+ <div className="pricing-summary__row">
240
+ <div className="pricing-summary__property">
241
+ {priceDetail.productName}
242
+ </div>
243
+ {priceDetail.showPrice && (
244
+ <div className="pricing-summary__value">
245
+ {formatPrice(
246
+ priceDetail.price * priceDetail.amount
247
+ )}
248
+ </div>
249
+ )}
205
250
  </div>
206
- <div className="pricing-summary__value">
207
- {formatPrice(priceDetail.price * priceDetail.amount)}
251
+ <div className="pricing-summary__row">
252
+ <div className="price-summary__property">
253
+ {priceDetail.accommodationName ??
254
+ priceDetail.accommodationCode}
255
+ </div>
208
256
  </div>
209
- </div>
257
+ </React.Fragment>
210
258
  ))}
211
259
  </div>
212
260
  )}
213
261
  </div>
214
262
  )}
215
263
 
216
- {canShowTotalPriceSection && (
264
+ {!isLoading && canShowTotalPriceSection && (
217
265
  <div className="pricing-summary__region pricing-summary__region--pricing">
218
- {showDeposit ? (
266
+ {deposit ? (
219
267
  <div className="pricing-summary__group">
220
268
  {totalPrice !== undefined && totalPrice > 0 && (
221
269
  <div className="pricing-summary__row pricing-summary__row--total-price">
@@ -242,7 +290,9 @@ const Sidebar: React.FC<SidebarProps> = ({
242
290
 
243
291
  <div className="pricing-summary__value">
244
292
  <div className="pricing">
245
- <div className="pricing__price">{depositText}</div>
293
+ <div className="pricing__price">
294
+ {formatPrice(deposit)}
295
+ </div>
246
296
  </div>
247
297
  </div>
248
298
  </div>
@@ -252,7 +302,7 @@ const Sidebar: React.FC<SidebarProps> = ({
252
302
  {translations.SIDEBAR.DEPOSIT_TEXT1}
253
303
  <strong>{translations.SIDEBAR.DEPOSIT_TEXT2}</strong>
254
304
  {translations.SIDEBAR.DEPOSIT_TEXT3}
255
- {remainingAmountText}
305
+ {formatPrice(remainingAmount)}
256
306
  {translations.SIDEBAR.DEPOSIT_TEXT4}
257
307
  <strong>{translations.SIDEBAR.DEPOSIT_TEXT5}</strong>
258
308
  {translations.SIDEBAR.DEPOSIT_TEXT6}
@@ -0,0 +1,25 @@
1
+ import { BookingOptionPax } from "@qite/tide-client/build/types";
2
+ import { isEmpty } from "lodash";
3
+ import React from "react";
4
+ import SummaryPerPaxOptionGroup from "./summary-per-pax-option-group";
5
+
6
+ interface SummaryBookingOptionPaxProps {
7
+ pax: BookingOptionPax;
8
+ }
9
+
10
+ const SummaryBookingOptionPax: React.FC<SummaryBookingOptionPaxProps> = ({
11
+ pax,
12
+ }) => {
13
+ return (
14
+ <>
15
+ {pax.groups.map((y) => {
16
+ const paxOptions = y.options.filter((y) => y.isSelected);
17
+ if (isEmpty(paxOptions)) return;
18
+
19
+ return <SummaryPerPaxOptionGroup group={y} />;
20
+ })}
21
+ </>
22
+ );
23
+ };
24
+
25
+ export default SummaryBookingOptionPax;
@@ -0,0 +1,25 @@
1
+ import { BookingOptionUnit } from "@qite/tide-client/build/types";
2
+ import { isEmpty } from "lodash";
3
+ import React from "react";
4
+ import SummaryPerUnitOptionGroup from "./summary-per-unit-option-group";
5
+
6
+ interface SummaryBookingOptionUnitProps {
7
+ unit: BookingOptionUnit;
8
+ }
9
+
10
+ const SummaryBookingOptionUnit: React.FC<SummaryBookingOptionUnitProps> = ({
11
+ unit,
12
+ }) => {
13
+ return (
14
+ <>
15
+ {unit.groups.map((y) => {
16
+ const unitOptions = y.options.filter((y) => y.isSelected);
17
+ if (isEmpty(unitOptions)) return;
18
+
19
+ return <SummaryPerUnitOptionGroup group={y} />;
20
+ })}
21
+ </>
22
+ );
23
+ };
24
+
25
+ export default SummaryBookingOptionUnit;
@@ -0,0 +1,35 @@
1
+ import { BookingPackageFlight } from "@qite/tide-client/build/types";
2
+ import React from "react";
3
+ import translations from "../../translations/translations.json";
4
+ import { getDateText, parseFlightLines } from "../sidebar/sidebar-util";
5
+
6
+ interface SummaryFlightProps {
7
+ flight: BookingPackageFlight;
8
+ header: string;
9
+ }
10
+
11
+ const SummaryFlight: React.FC<SummaryFlightProps> = ({ flight, header }) => {
12
+ return (
13
+ <li>
14
+ <h6>{header}</h6>
15
+ {parseFlightLines(flight.flightMetaData)?.map((flightLine) => (
16
+ <p key={flightLine.departureAirportIata}>
17
+ {flightLine.departureAirportDescription} (
18
+ {flightLine.departureAirportIata}) &gt;{" "}
19
+ {flightLine.arrivalAirportDescription} (
20
+ {flightLine.arrivalAirportIata})
21
+ <br />
22
+ {getDateText(flightLine.departureDate)} {flightLine.departureTime}{" "}
23
+ &gt; {getDateText(flightLine.arrivalDate)} {flightLine.arrivalTime}
24
+ <br />
25
+ {flightLine.airlineDescription}
26
+ </p>
27
+ ))}
28
+ {flight.flightMetaData.luggageIncluded && (
29
+ <p>{translations.SIDEBAR.LUGGAGE_INCLUDED}</p>
30
+ )}
31
+ </li>
32
+ );
33
+ };
34
+
35
+ export default SummaryFlight;