@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
@@ -0,0 +1,100 @@
1
+ import {
2
+ BookingOptionGroup,
3
+ BookingOptionUnit,
4
+ PerUnitPackageOption,
5
+ } from "@qite/tide-client/build/types";
6
+ import React, { useEffect, useState } from "react";
7
+ import { buildClassName } from "../../utils/class-util";
8
+ import translations from "../../translations/translations.json";
9
+ import OptionUnitGroup from "./option-unit-group";
10
+
11
+ interface OptionUnitsCardProps {
12
+ units: BookingOptionUnit[];
13
+ parentIndex?: number;
14
+ onUnitsChange?: (units: BookingOptionUnit[], index?: number) => void;
15
+ }
16
+
17
+ const OptionUnitsCard: React.FC<OptionUnitsCardProps> = ({
18
+ units,
19
+ parentIndex,
20
+ onUnitsChange,
21
+ }) => {
22
+ const [toggleStates, setToggleStates] = useState<boolean[]>();
23
+
24
+ useEffect(() => {
25
+ if (!toggleStates || toggleStates.length !== units.length) {
26
+ setToggleStates(units.map(() => true));
27
+ }
28
+ }, [units, toggleStates, setToggleStates]);
29
+
30
+ const getUnitPaxLabel = (unitIndex: number) => {
31
+ return "";
32
+ };
33
+
34
+ const onGroupChange = (
35
+ group: BookingOptionGroup<PerUnitPackageOption>,
36
+ unitIndex: number
37
+ ) => {
38
+ const updatedUnits = units.map((u) => {
39
+ return u.index !== unitIndex
40
+ ? u
41
+ : {
42
+ ...u,
43
+ groups: u.groups.map((ug) => {
44
+ return ug.name !== group.name ? ug : group;
45
+ }),
46
+ };
47
+ });
48
+
49
+ if (onUnitsChange) onUnitsChange(updatedUnits, parentIndex);
50
+ };
51
+
52
+ return (
53
+ <>
54
+ {units.map((u, i) => (
55
+ <div
56
+ className={buildClassName([
57
+ "booking-card__group",
58
+ toggleStates && toggleStates[i] && "booking-card__group--active",
59
+ ])}
60
+ >
61
+ <div className="booking-card__group-header">
62
+ <h3 className="booking-card__body-heading">
63
+ {translations.OPTIONS_FORM.UNIT_TITLE} {u.index + 1}
64
+ </h3>
65
+ <p>{getUnitPaxLabel(u.index)}</p>
66
+ <div className="booking-card__actions">
67
+ <button
68
+ type="button"
69
+ className="booking-card__toggle"
70
+ onClick={() => {
71
+ setToggleStates(
72
+ toggleStates?.map((s, si) => (si == i ? !s : s))
73
+ );
74
+ }}
75
+ ></button>
76
+ </div>
77
+ </div>
78
+ {toggleStates &&
79
+ toggleStates[i] &&
80
+ u.groups.map(
81
+ (ug) =>
82
+ ug && (
83
+ <OptionUnitGroup
84
+ key={ug.name}
85
+ unitIndex={u.index}
86
+ group={ug}
87
+ firstClassName={"booking-card__group-body"}
88
+ secondClassName={"booking-card__group-heading"}
89
+ parentId={`${u.index}_${ug.name}`}
90
+ onGroupChange={onGroupChange}
91
+ />
92
+ )
93
+ )}
94
+ </div>
95
+ ))}
96
+ </>
97
+ );
98
+ };
99
+
100
+ export default OptionUnitsCard;
@@ -1,76 +1,254 @@
1
1
  import React, { useContext } from "react";
2
2
 
3
3
  import SettingsContext from "../../settings-context";
4
- import TreeLevel from "./tree-level";
5
- import { compact } from "lodash";
4
+ import { isEmpty } from "lodash";
6
5
  import { navigate, Link } from "@reach/router";
7
- import { selectBookingQueryString } from "../booking/booking-slice";
8
- import { selectOptions } from "./product-options-slice";
6
+ import {
7
+ setPackageGroups,
8
+ setPackageOptionPax,
9
+ setPackageOptionUnits,
10
+ setPackageRooms,
11
+ } from "../booking/booking-slice";
12
+ import {
13
+ selectBookingPackagePax,
14
+ selectBookingQueryString,
15
+ selectIsFetchingProductOptions,
16
+ selectPackageGroups,
17
+ selectPackageOptionPax,
18
+ selectPackageOptionUnits,
19
+ selectPackageRooms,
20
+ selectRequestRooms,
21
+ } from "../booking/selectors";
9
22
  import { selectTravelersFormValues } from "../travelers-form/travelers-form-slice";
10
23
  import translations from "../../translations/translations.json";
11
24
  import { useSelector } from "react-redux";
25
+ import { buildClassName } from "../../utils/class-util";
26
+ import NoOptions from "./no-options";
27
+ import { useAppDispatch } from "../../store";
28
+ import OptionRoom from "./option-room";
29
+ import { fetchPriceDetails } from "../price-details/price-details-slice";
30
+ import OptionPaxCard from "./option-pax-card";
31
+ import {
32
+ BookingOptionGroup,
33
+ BookingOptionPax,
34
+ BookingOptionUnit,
35
+ PerBookingPackageOption,
36
+ } from "@qite/tide-client/build/types";
37
+ import OptionUnitsCard from "./option-units-card";
38
+ import OptionBookingGroup from "./option-booking-group";
12
39
 
13
40
  interface OptionsFormProps {}
14
41
 
15
42
  const OptionsForm: React.FC<OptionsFormProps> = () => {
16
- const settings = useContext(SettingsContext);
43
+ const { basePath, summary, loaderComponent } = useContext(SettingsContext);
17
44
 
45
+ const dispatch = useAppDispatch();
18
46
  const travelerFormValues = useSelector(selectTravelersFormValues);
19
- const productOptions = useSelector(selectOptions);
47
+ console.log("travelerFormValues", travelerFormValues);
48
+ const requestRooms = useSelector(selectRequestRooms);
49
+ const pax = useSelector(selectBookingPackagePax);
50
+ const packageRooms = useSelector(selectPackageRooms);
20
51
  const bookingQueryString = useSelector(selectBookingQueryString);
52
+ const isLoading = useSelector(selectIsFetchingProductOptions);
21
53
 
22
- if (!travelerFormValues) {
23
- navigate(settings.basePath);
54
+ const groups = useSelector(selectPackageGroups);
55
+ const optionUnits = useSelector(selectPackageOptionUnits);
56
+ const optionPax = useSelector(selectPackageOptionPax);
57
+
58
+ if (!packageRooms) {
59
+ navigate(`${basePath}?${bookingQueryString}`);
24
60
  }
25
61
 
26
- const topLevelProductOptions = compact(
27
- Object.values(productOptions).filter(
28
- (productOption) => productOption?.parentCode === undefined
29
- )
30
- );
62
+ const getRoomPax = (index: number) => {
63
+ var room = requestRooms?.find((x) => x.index == index);
64
+ return pax.filter((x) => room?.pax.some((y) => y.id == x.id));
65
+ };
31
66
 
32
67
  const handleSubmit: React.FormEventHandler<HTMLFormElement> = (e) => {
33
- navigate(
34
- `${settings.basePath}${settings.summaryPathSuffix}?${bookingQueryString}`
35
- );
36
-
68
+ navigate(`${basePath}${summary.pathSuffix}?${bookingQueryString}`);
37
69
  e.preventDefault();
38
70
  };
39
71
 
72
+ const handleOnRoomChange = (
73
+ index: number,
74
+ accommodationCode: string,
75
+ regimeCode: string
76
+ ) => {
77
+ if (!packageRooms) return;
78
+
79
+ const updatedPackageRooms = packageRooms.map((room) => {
80
+ if (room.index !== index) return room;
81
+
82
+ return {
83
+ ...room,
84
+ options: room.options.map((option) => {
85
+ return {
86
+ ...option,
87
+ isSelected:
88
+ option.accommodationCode === accommodationCode &&
89
+ option.regimeCode === regimeCode,
90
+ };
91
+ }),
92
+ };
93
+ });
94
+
95
+ dispatch(setPackageRooms(updatedPackageRooms));
96
+ dispatch(fetchPriceDetails());
97
+ };
98
+
99
+ const handleOnPaxChange = (pax: BookingOptionPax[]) => {
100
+ dispatch(setPackageOptionPax(pax));
101
+ dispatch(fetchPriceDetails());
102
+ };
103
+
104
+ const handleOnUnitsChange = (units: BookingOptionUnit[]) => {
105
+ dispatch(setPackageOptionUnits(units));
106
+ dispatch(fetchPriceDetails());
107
+ };
108
+
109
+ const handleOnGroupChange = (
110
+ group: BookingOptionGroup<PerBookingPackageOption>
111
+ ) => {
112
+ if (groups) {
113
+ const updatedGroups = groups?.map((g) =>
114
+ g.name === group.name ? group : g
115
+ );
116
+
117
+ dispatch(setPackageGroups(updatedGroups));
118
+ dispatch(fetchPriceDetails());
119
+ }
120
+ };
121
+
40
122
  return (
41
- <form className="form" noValidate onSubmit={handleSubmit}>
42
- <div className="form__region">
43
- <div className="form__row">
44
- {topLevelProductOptions.map((productOption) => (
45
- <div className="form__group" key={productOption?.code}>
46
- <table className="table table--striped">
47
- <tbody>
48
- <tr>
49
- <td>
50
- <div className="tree">
51
- <TreeLevel productOption={productOption} />
52
- </div>
53
- </td>
54
- </tr>
55
- </tbody>
56
- </table>
123
+ <>
124
+ <form
125
+ className="form"
126
+ name="booking--step2"
127
+ id="booking--step2"
128
+ noValidate
129
+ onSubmit={handleSubmit}
130
+ >
131
+ {isLoading && loaderComponent}
132
+ {!isLoading && (
133
+ <div className="form__region">
134
+ <div className="form__group">
135
+ <div className="booking-card">
136
+ <div className="booking-card__body">
137
+ <div
138
+ className={buildClassName([
139
+ "booking-card__group",
140
+ "booking-card__group--package",
141
+ ])}
142
+ >
143
+ <span className="booking-card__tag">
144
+ {translations.OPTIONS_FORM.PACKAGE}
145
+ </span>
146
+ <div className="booking-card__group-body">
147
+ <table className="table table--striped">
148
+ <tbody>
149
+ {packageRooms &&
150
+ packageRooms.map((room) => (
151
+ <OptionRoom
152
+ key={room.index}
153
+ packageRoom={room}
154
+ pax={getRoomPax(room.index)}
155
+ onRoomChange={handleOnRoomChange}
156
+ />
157
+ ))}
158
+ </tbody>
159
+ </table>
160
+ </div>
161
+ </div>
162
+ </div>
163
+ </div>
57
164
  </div>
58
- ))}
165
+
166
+ {optionUnits && !isEmpty(optionUnits) && (
167
+ <div className="form__group">
168
+ <div className="booking-card">
169
+ <div className="booking-card__header">
170
+ <h2 className="booking-card__header-heading">
171
+ {translations.OPTIONS_FORM.PER_UNIT_TITLE}
172
+ </h2>
173
+ </div>
174
+ <div className="booking-card__body">
175
+ <OptionUnitsCard
176
+ units={optionUnits}
177
+ onUnitsChange={handleOnUnitsChange}
178
+ />
179
+ </div>
180
+ </div>
181
+ </div>
182
+ )}
183
+
184
+ {optionPax && !isEmpty(optionPax) && (
185
+ <div className="form__group">
186
+ <div className="booking-card">
187
+ <div className="booking-card__header">
188
+ <h2 className="booking-card__header-heading">
189
+ {translations.OPTIONS_FORM.PER_PAX_TITLE}
190
+ </h2>
191
+ </div>
192
+ <div className="booking-card__body">
193
+ <OptionPaxCard
194
+ pax={optionPax}
195
+ onPaxChange={handleOnPaxChange}
196
+ />
197
+ </div>
198
+ </div>
199
+ </div>
200
+ )}
201
+
202
+ {groups && !isEmpty(groups) && (
203
+ <div className="form__group">
204
+ <div className="booking-card">
205
+ <div className="booking-card__header">
206
+ <h2 className="booking-card__header-heading">
207
+ {translations.OPTIONS_FORM.PER_BOOKING_TITLE}
208
+ </h2>
209
+ </div>
210
+ <div className="booking-card__body">
211
+ <div className="tree__body">
212
+ {groups.map((group, i) => (
213
+ <OptionBookingGroup
214
+ key={`${group.name}_${i}`}
215
+ group={group}
216
+ firstClassName={"tree__level"}
217
+ secondClassName={"tree__level-heading"}
218
+ parentId={`booking_${group.name}`}
219
+ onGroupChange={handleOnGroupChange}
220
+ />
221
+ ))}
222
+ </div>
223
+ </div>
224
+ </div>
225
+ </div>
226
+ )}
227
+
228
+ {isEmpty(groups) && isEmpty(optionUnits) && isEmpty(optionPax) && (
229
+ <NoOptions />
230
+ )}
231
+ </div>
232
+ )}
233
+ <div className="booking__navigator">
234
+ <Link
235
+ to={`${basePath}?${bookingQueryString}`}
236
+ title={translations.STEPS.PREVIOUS}
237
+ className="cta cta--secondary"
238
+ >
239
+ {translations.STEPS.PREVIOUS}
240
+ </Link>
241
+ <button
242
+ type="submit"
243
+ title={translations.STEPS.NEXT}
244
+ disabled={isLoading}
245
+ className={buildClassName(["cta", isLoading && "cta--disabled"])}
246
+ >
247
+ {translations.STEPS.NEXT}
248
+ </button>
59
249
  </div>
60
- </div>
61
- <div className="booking__navigator">
62
- <Link
63
- to={`${settings.basePath}?${bookingQueryString}`}
64
- title={translations.STEPS.PREVIOUS}
65
- className="cta cta--secondary"
66
- >
67
- {translations.STEPS.PREVIOUS}
68
- </Link>
69
- <button type="submit" title={translations.STEPS.NEXT} className="cta">
70
- {translations.STEPS.NEXT}
71
- </button>
72
- </div>
73
- </form>
250
+ </form>
251
+ </>
74
252
  );
75
253
  };
76
254
 
@@ -1,14 +1,19 @@
1
1
  import {
2
2
  selectDepartureFlight,
3
+ selectIsFetchingProductOptions,
4
+ selectIsOnRequest,
5
+ selectPackageRooms,
3
6
  selectReturnFlight,
4
- } from "../product-options/product-options-slice";
5
- import { getDateText, getFlightText, getTravelersText } from "./sidebar-util";
7
+ } from "../booking/selectors";
8
+ import { getDateText, getTravelersText } from "./sidebar-util";
6
9
  import {
7
- selectAdultCount,
8
- selectChildCount,
10
+ selectAdultIds,
11
+ selectChildIds,
9
12
  } from "../travelers-form/travelers-form-slice";
10
13
  import {
11
14
  selectBasePrice,
15
+ selectDeposit,
16
+ selectIsFetchingPriceDetails,
12
17
  selectSeparateExtraPriceDetails,
13
18
  selectSeparatePackagePriceDetails,
14
19
  selectTotalPrice,
@@ -18,38 +23,56 @@ import { useSelector } from "react-redux";
18
23
  import React from "react";
19
24
  import SettingsContext from "../../settings-context";
20
25
  import Sidebar from "./sidebar";
21
- import { selectBookingAttributes } from "../booking/booking-slice";
26
+ import { selectBookingAttributes } from "../booking/selectors";
22
27
  import { useContext } from "react";
23
28
 
24
- const SidebarContainer: React.FC = () => {
25
- const {
26
- showSidebarAccommodationInfo,
27
- showSidebarDeposit,
28
- sidebarHeaderComponent,
29
- sidebarFooterComponent,
30
- } = useContext(SettingsContext);
29
+ interface SidebarProps {
30
+ productName: string;
31
+ thumbnailUrl?: string;
32
+ }
33
+
34
+ const SidebarContainer: React.FC<SidebarProps> = ({
35
+ productName,
36
+ thumbnailUrl,
37
+ }) => {
38
+ const { sidebarHeaderComponent, sidebarFooterComponent, loaderComponent } =
39
+ useContext(SettingsContext);
31
40
  const bookingAttributes = useSelector(selectBookingAttributes);
32
- const adultCount = useSelector(selectAdultCount);
33
- const childCount = useSelector(selectChildCount);
34
- const travelersText = getTravelersText(adultCount, childCount);
41
+ const adultIds = useSelector(selectAdultIds);
42
+ const childIds = useSelector(selectChildIds);
43
+ const travelersText = getTravelersText(adultIds, childIds);
35
44
  const departureFlight = useSelector(selectDepartureFlight);
36
45
  const returnFlight = useSelector(selectReturnFlight);
46
+ const isFetchingProductOptions = useSelector(selectIsFetchingProductOptions);
47
+ const isFetchingPriceDetails = useSelector(selectIsFetchingPriceDetails);
48
+ const accommodations = useSelector(selectPackageRooms);
49
+
50
+ const isLoading = isFetchingProductOptions || isFetchingPriceDetails;
37
51
 
38
52
  return (
39
53
  <Sidebar
54
+ productName={productName}
55
+ thumbnailUrl={thumbnailUrl}
56
+ isLoading={isLoading}
40
57
  startDateText={getDateText(bookingAttributes?.startDate)}
41
- endDateText={getDateText(bookingAttributes?.endDate)}
58
+ endDateText={
59
+ bookingAttributes?.startDate !== bookingAttributes?.endDate
60
+ ? getDateText(bookingAttributes?.endDate)
61
+ : undefined
62
+ }
42
63
  travelersText={travelersText}
43
- departureFlightText={getFlightText(departureFlight)}
44
- returnFlightText={getFlightText(returnFlight)}
64
+ departureFlight={departureFlight}
65
+ returnFlight={returnFlight}
45
66
  basePrice={useSelector(selectBasePrice)}
46
67
  totalPrice={useSelector(selectTotalPrice)}
47
68
  includedCosts={useSelector(selectSeparatePackagePriceDetails)}
48
69
  extraCosts={useSelector(selectSeparateExtraPriceDetails)}
49
- showAccommodationInfo={showSidebarAccommodationInfo}
50
- showDeposit={showSidebarDeposit}
70
+ accommodations={accommodations}
71
+ deposit={useSelector(selectDeposit)}
72
+ isOnRequest={useSelector(selectIsOnRequest)}
51
73
  headerComponent={sidebarHeaderComponent ?? undefined}
52
74
  footerComponent={sidebarFooterComponent ?? undefined}
75
+ loaderComponent={loaderComponent ?? undefined}
53
76
  />
54
77
  );
55
78
  };
@@ -0,0 +1,66 @@
1
+ import { BookingPackageFlight } from "@qite/tide-client/build/types";
2
+ import { first, last } from "lodash";
3
+ import React from "react";
4
+ import { getAirlines, getDateText, parseFlightLines } from "./sidebar-util";
5
+ import translations from "../../translations/translations.json";
6
+
7
+ interface SidebarFlightProps {
8
+ title: string;
9
+ flight: BookingPackageFlight;
10
+ }
11
+
12
+ const SidebarFlight: React.FC<SidebarFlightProps> = ({ title, flight }) => {
13
+ const flightLines = parseFlightLines(flight.flightMetaData);
14
+ const firstFlight = first(flightLines);
15
+ const lastFlight = last(flightLines);
16
+
17
+ return (
18
+ <div className="pricing-summary__group">
19
+ <h6 className="pricing-summary__title">{title}</h6>
20
+ <div className="pricing-summary__row">
21
+ <div className="pricing-summary__property">
22
+ {translations.SIDEBAR.FLIGHT_DEPARTURE}
23
+ </div>
24
+ <div className="pricing-summary__value">
25
+ {firstFlight?.departureAirportDescription} (
26
+ {firstFlight?.departureAirportIata})<br />
27
+ {getDateText(firstFlight?.departureDate)} {firstFlight?.departureTime}
28
+ </div>
29
+ </div>
30
+
31
+ <div className="pricing-summary__row">
32
+ <div className="pricing-summary__property">
33
+ {translations.SIDEBAR.FLIGHT_ARRIVAL}
34
+ </div>
35
+ <div className="pricing-summary__value">
36
+ {lastFlight?.arrivalAirportDescription} (
37
+ {lastFlight?.arrivalAirportIata})<br />
38
+ {getDateText(lastFlight?.arrivalDate)} {lastFlight?.arrivalTime}
39
+ </div>
40
+ </div>
41
+
42
+ <div className="pricing-summary__row">
43
+ <div className="pricing-summary__property">
44
+ {flight.flightMetaData.flightLines.length > 1 && (
45
+ <i>
46
+ {flight.flightMetaData.flightLines.length - 1}
47
+ {"x "}
48
+ {translations.SIDEBAR.CHANGES}
49
+ </i>
50
+ )}
51
+ </div>
52
+ <div className="pricing-summary__value">{getAirlines(flightLines)}</div>
53
+ </div>
54
+ {flight.flightMetaData.luggageIncluded && (
55
+ <div className="pricing-summary__row">
56
+ <div className="pricing-summary__property"></div>
57
+ <div className="pricing-summary__value">
58
+ {translations.SIDEBAR.LUGGAGE_INCLUDED}
59
+ </div>
60
+ </div>
61
+ )}
62
+ </div>
63
+ );
64
+ };
65
+
66
+ export default SidebarFlight;