@qite/tide-booking-component 1.0.42 → 1.0.44
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.
- package/package.json +1 -1
- package/src/booking-product/components/date-range-picker/calendar.tsx +1 -1
- package/src/booking-product/components/dates.tsx +47 -27
- package/src/booking-product/components/header.tsx +4 -4
- package/src/booking-product/components/icon.tsx +32 -0
- package/src/booking-product/components/product.tsx +9 -7
- package/src/booking-product/components/rooms.tsx +11 -8
- package/src/{shared → booking-wizard}/components/icon.tsx +4 -2
- package/src/booking-wizard/components/message.tsx +1 -1
- package/src/booking-wizard/features/confirmation/confirmation.tsx +1 -1
- package/src/booking-wizard/features/flight-options/flight-option.tsx +1 -1
- package/src/booking-wizard/features/flight-options/index.tsx +3 -3
- package/src/booking-wizard/features/product-options/options-form.tsx +137 -5
- package/src/booking-wizard/features/room-options/index.tsx +44 -83
- package/src/booking-wizard/features/summary/summary.tsx +1 -1
- package/src/booking-wizard/features/travelers-form/type-ahead-input.tsx +1 -1
- package/src/shared/components/rating.tsx +1 -1
- package/src/shared/translations/fr-BE.json +3 -1
- package/src/shared/translations/nl-BE.json +3 -1
package/package.json
CHANGED
|
@@ -14,7 +14,7 @@ import {
|
|
|
14
14
|
} from "date-fns";
|
|
15
15
|
import { chunk, isFunction, range } from "lodash";
|
|
16
16
|
import React, { useContext } from "react";
|
|
17
|
-
import Icon from "../../../
|
|
17
|
+
import Icon from "../../../booking-wizard/components/icon";
|
|
18
18
|
import { buildClassName } from "../../../shared/utils/class-util";
|
|
19
19
|
import { getLocale } from "../../../shared/utils/localization-util";
|
|
20
20
|
import SettingsContext from "../../settings-context";
|
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
import { format, isBefore, startOfDay } from "date-fns";
|
|
2
|
-
import React, { useContext, useState } from "react";
|
|
2
|
+
import React, { useContext, useEffect, useState } from "react";
|
|
3
|
+
import { usePopper } from "react-popper";
|
|
3
4
|
import { buildClassName } from "../../shared/utils/class-util";
|
|
4
5
|
import { getTranslations } from "../../shared/utils/localization-util";
|
|
5
6
|
import SettingsContext from "../settings-context";
|
|
6
|
-
import DateRangePicker from "./date-range-picker";
|
|
7
|
-
import { usePopper } from "react-popper";
|
|
8
7
|
import { DateRange } from "../types";
|
|
8
|
+
import DateRangePicker from "./date-range-picker";
|
|
9
|
+
import Icon from "./icon";
|
|
9
10
|
|
|
10
11
|
interface DatesProps {
|
|
11
12
|
value?: DateRange;
|
|
@@ -56,37 +57,55 @@ const Dates: React.FC<DatesProps> = ({
|
|
|
56
57
|
setPanelActive(false);
|
|
57
58
|
}
|
|
58
59
|
};
|
|
60
|
+
|
|
61
|
+
useEffect(() => {
|
|
62
|
+
document.addEventListener("mousedown", handleDocumentClick);
|
|
63
|
+
return () => {
|
|
64
|
+
document.removeEventListener("mousedown", handleDocumentClick);
|
|
65
|
+
};
|
|
66
|
+
});
|
|
67
|
+
|
|
68
|
+
const handleDocumentClick: EventListener = (event) => {
|
|
69
|
+
if (referenceElement && !referenceElement.contains(event.target as Node)) {
|
|
70
|
+
if (panelActive) setPanelActive(false);
|
|
71
|
+
}
|
|
72
|
+
};
|
|
59
73
|
|
|
60
74
|
return (
|
|
61
75
|
<div className="booking-product__dates" ref={setReferenceElement}>
|
|
62
|
-
<div className="booking-product__dates-
|
|
63
|
-
<
|
|
64
|
-
|
|
65
|
-
type="text"
|
|
66
|
-
readOnly
|
|
67
|
-
value={value?.fromDate ? format(value.fromDate, "dd/MM/yyyy") : ""}
|
|
68
|
-
className="booking-product__dates_input-field"
|
|
69
|
-
placeholder={translations.PRODUCT.DEPARTURE_DATE}
|
|
70
|
-
onClick={handleInputFocus}
|
|
71
|
-
/>
|
|
76
|
+
<div className="booking-product__dates-title">
|
|
77
|
+
<Icon name="ui-calendar" />
|
|
78
|
+
{translations.PRODUCT.TRAVEL_PERIOD}
|
|
72
79
|
</div>
|
|
80
|
+
<div className="form__group form__group--datepicker form__group--icon">
|
|
81
|
+
<div className="form__group-input">
|
|
82
|
+
<label className="form__label">{translations.PRODUCT.DEPARTURE}</label>
|
|
83
|
+
<input
|
|
84
|
+
type="text"
|
|
85
|
+
readOnly
|
|
86
|
+
value={value?.fromDate ? format(value.fromDate, "dd/MM/yyyy") : ""}
|
|
87
|
+
className="form__input"
|
|
88
|
+
placeholder={translations.PRODUCT.DEPARTURE_DATE}
|
|
89
|
+
onClick={handleInputFocus}
|
|
90
|
+
/>
|
|
91
|
+
</div>
|
|
73
92
|
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
93
|
+
<div className="form__group-input">
|
|
94
|
+
<label className="form__label">{translations.PRODUCT.RETURN}</label>
|
|
95
|
+
<input
|
|
96
|
+
type="text"
|
|
97
|
+
readOnly
|
|
98
|
+
value={value?.toDate ? format(value.toDate, "dd/MM/yyyy") : ""}
|
|
99
|
+
className="form__input"
|
|
100
|
+
placeholder={translations.PRODUCT.RETURN_DATE}
|
|
101
|
+
onClick={handleInputFocus}
|
|
102
|
+
/>
|
|
103
|
+
</div>
|
|
104
|
+
<div
|
|
86
105
|
ref={setPopperElement}
|
|
87
106
|
className={buildClassName([
|
|
88
|
-
"
|
|
89
|
-
panelActive && "
|
|
107
|
+
"qsm__panel qsm__panel--bordered qsm__panel--dates-pricing",
|
|
108
|
+
panelActive && "qsm__panel--active",
|
|
90
109
|
])}
|
|
91
110
|
style={mql?.matches ? styles.popper : undefined}
|
|
92
111
|
{...attributes.popper}
|
|
@@ -99,6 +118,7 @@ const Dates: React.FC<DatesProps> = ({
|
|
|
99
118
|
onSelectionChange={handleSelectionChange}
|
|
100
119
|
/>
|
|
101
120
|
</div>
|
|
121
|
+
</div>
|
|
102
122
|
</div>
|
|
103
123
|
);
|
|
104
124
|
}
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import React, { useContext } from "react";
|
|
2
|
-
import Icon from "../../shared/components/icon";
|
|
3
2
|
import Loader from "../../shared/components/loader";
|
|
4
3
|
import Rating from "../../shared/components/rating";
|
|
5
4
|
import { getTranslations } from "../../shared/utils/localization-util";
|
|
6
5
|
import SettingsContext from "../settings-context";
|
|
6
|
+
import Icon from "./icon";
|
|
7
7
|
|
|
8
8
|
interface HeaderProps {
|
|
9
9
|
name: string;
|
|
@@ -29,16 +29,16 @@ const Header: React.FC<HeaderProps> = ({
|
|
|
29
29
|
|
|
30
30
|
return (
|
|
31
31
|
<div className="booking-product__header">
|
|
32
|
-
<div className="booking-
|
|
32
|
+
<div className="booking-product__hotel">
|
|
33
33
|
{rating && <Rating rating={rating} />}
|
|
34
|
-
<div className="booking-
|
|
34
|
+
<div className="booking-product__title">{name}</div>
|
|
35
35
|
</div>
|
|
36
36
|
<div className="booking-product__price">
|
|
37
37
|
{isLoading
|
|
38
38
|
? (<Loader loaderText={translations.PRODUCT.LOADING_PRICE} />)
|
|
39
39
|
: (
|
|
40
40
|
<>
|
|
41
|
-
<div className="
|
|
41
|
+
<div className="pricing__header pricing__price">
|
|
42
42
|
{priceText}
|
|
43
43
|
</div>
|
|
44
44
|
<div className="package-icons">
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { isEmpty } from "lodash";
|
|
2
|
+
import React, { useContext } from "react";
|
|
3
|
+
import SettingsContext from "../settings-context";
|
|
4
|
+
|
|
5
|
+
interface IconProps {
|
|
6
|
+
name: string;
|
|
7
|
+
className?: string;
|
|
8
|
+
title?: string;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
const Icon: React.FC<IconProps> = ({
|
|
12
|
+
name, className, title
|
|
13
|
+
}) => {
|
|
14
|
+
const { icons } = useContext(SettingsContext);
|
|
15
|
+
|
|
16
|
+
if (!icons) {
|
|
17
|
+
return null;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
return (
|
|
21
|
+
<svg
|
|
22
|
+
className={["icon", `icon--${name}`, className]
|
|
23
|
+
.filter((className) => !isEmpty(className))
|
|
24
|
+
.join(" ")}
|
|
25
|
+
>
|
|
26
|
+
{title && <title>{title}</title>}
|
|
27
|
+
<use href={`${icons}#${name}`}></use>
|
|
28
|
+
</svg>
|
|
29
|
+
);
|
|
30
|
+
};
|
|
31
|
+
|
|
32
|
+
export default Icon;
|
|
@@ -242,13 +242,15 @@ const Product: React.FC<ProductProps> = ({
|
|
|
242
242
|
isLoading={isLoading}
|
|
243
243
|
hasFlight={hasFlight}
|
|
244
244
|
hasTransfer={hasTransfer} />
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
245
|
+
<div className="booking-product__body">
|
|
246
|
+
<Rooms
|
|
247
|
+
rooms={rooms}
|
|
248
|
+
onChange={handleRoomChange} />
|
|
249
|
+
<Dates
|
|
250
|
+
value={dateRange}
|
|
251
|
+
duration={duration}
|
|
252
|
+
onChange={handleDateChange} />
|
|
253
|
+
</div>
|
|
252
254
|
<Footer
|
|
253
255
|
priceText={priceText}
|
|
254
256
|
handleBookClick={handleBookClick}
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import { range } from "lodash";
|
|
2
2
|
import React, { useContext, useState } from "react";
|
|
3
|
+
import { buildClassName } from "../../shared/utils/class-util";
|
|
3
4
|
import { getTranslations } from "../../shared/utils/localization-util";
|
|
4
5
|
import SettingsContext from "../settings-context";
|
|
5
6
|
import { ProductRoom } from "../types";
|
|
6
7
|
import AgeSelect from "./age-select";
|
|
7
8
|
import AmountInput from "./amount-input";
|
|
8
|
-
import
|
|
9
|
-
import Icon from "../../shared/components/icon";
|
|
9
|
+
import Icon from "./icon";
|
|
10
10
|
|
|
11
11
|
interface RoomsProps {
|
|
12
12
|
rooms: ProductRoom[];
|
|
@@ -34,9 +34,12 @@ const Rooms: React.FC<RoomsProps> = ({
|
|
|
34
34
|
|
|
35
35
|
return (
|
|
36
36
|
<div className="booking-product__rooms">
|
|
37
|
-
<div className="booking-product__rooms-
|
|
38
|
-
<
|
|
39
|
-
|
|
37
|
+
<div className="booking-product__rooms-title">
|
|
38
|
+
<Icon name="ui-user" />{translations.PRODUCT.WHO_YOU_TRAVELING_WITH}
|
|
39
|
+
</div>
|
|
40
|
+
<div className="booking-product__rooms__header">
|
|
41
|
+
<div className="booking-product__rooms__heading">{translations.SHARED.ROOMS}</div>
|
|
42
|
+
<div className="booking-product__rooms__actions">
|
|
40
43
|
<AmountInput
|
|
41
44
|
label={translations.PRODUCT.NUMBER_OF_ROOMS}
|
|
42
45
|
value={currentRooms.length}
|
|
@@ -55,11 +58,11 @@ const Rooms: React.FC<RoomsProps> = ({
|
|
|
55
58
|
<div className="booking-product__rooms-body">
|
|
56
59
|
{currentRooms.map((room, roomIndex) => (
|
|
57
60
|
<div className="booking-product__room" key={roomIndex}>
|
|
58
|
-
<div className="booking-
|
|
59
|
-
<h3 className="booking-
|
|
61
|
+
<div className="booking-product__room__header">
|
|
62
|
+
<h3 className="booking-product__room__heading">
|
|
60
63
|
{translations.SHARED.ROOM + " " + (roomIndex + 1)}
|
|
61
64
|
</h3>
|
|
62
|
-
<div className="booking-
|
|
65
|
+
<div className="booking-product__room__actions">
|
|
63
66
|
<AmountInput
|
|
64
67
|
label={translations.SHARED.ADULTS}
|
|
65
68
|
value={room.adults}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import React from "react";
|
|
2
2
|
import { isEmpty } from "lodash";
|
|
3
3
|
import { useContext } from "react";
|
|
4
|
-
import SettingsContext from "
|
|
4
|
+
import SettingsContext from "../settings-context";
|
|
5
5
|
|
|
6
6
|
interface IconProps {
|
|
7
7
|
name: string;
|
|
@@ -9,7 +9,9 @@ interface IconProps {
|
|
|
9
9
|
title?: string;
|
|
10
10
|
}
|
|
11
11
|
|
|
12
|
-
const Icon: React.FC<IconProps> = ({
|
|
12
|
+
const Icon: React.FC<IconProps> = ({
|
|
13
|
+
name, className, title
|
|
14
|
+
}) => {
|
|
13
15
|
const { icons } = useContext(SettingsContext);
|
|
14
16
|
|
|
15
17
|
if (!icons) {
|
|
@@ -8,7 +8,7 @@ import Message from "../../components/message";
|
|
|
8
8
|
import SettingsContext from "../../settings-context";
|
|
9
9
|
import { navigate } from "@reach/router";
|
|
10
10
|
import { useSelector } from "react-redux";
|
|
11
|
-
import Icon from "
|
|
11
|
+
import Icon from "../../components/icon";
|
|
12
12
|
import { getTranslations } from "../../../shared/utils/localization-util";
|
|
13
13
|
import { useAppDispatch } from "../../store";
|
|
14
14
|
import { setCurrentStep } from "../booking/booking-slice";
|
|
@@ -6,7 +6,7 @@ import React, { useContext } from "react";
|
|
|
6
6
|
import { buildClassName } from "../../../shared/utils/class-util";
|
|
7
7
|
import { getPriceDifferenceText, getTranslations } from "../../../shared/utils/localization-util";
|
|
8
8
|
import SettingsContext from "../../settings-context";
|
|
9
|
-
import Icon from "
|
|
9
|
+
import Icon from "../../components/icon";
|
|
10
10
|
|
|
11
11
|
interface FlightOptionProps {
|
|
12
12
|
item: BookingPackageFlight;
|
|
@@ -13,7 +13,7 @@ import {
|
|
|
13
13
|
setPackage,
|
|
14
14
|
setReturnFlight
|
|
15
15
|
} from "../booking/booking-slice";
|
|
16
|
-
import { FLIGHT_OPTIONS_FORM_STEP, OPTIONS_FORM_STEP } from "../booking/constants";
|
|
16
|
+
import { FLIGHT_OPTIONS_FORM_STEP, OPTIONS_FORM_STEP, ROOM_OPTIONS_FORM_STEP } from "../booking/constants";
|
|
17
17
|
import {
|
|
18
18
|
selectBookingQueryString,
|
|
19
19
|
selectIsFetchingProductOptions,
|
|
@@ -46,7 +46,7 @@ const FlightOptionsForm: React.FC<FlightOptionsFormProps> = () => {
|
|
|
46
46
|
};
|
|
47
47
|
|
|
48
48
|
const goPrevious = () => {
|
|
49
|
-
dispatch(setCurrentStep(
|
|
49
|
+
dispatch(setCurrentStep(ROOM_OPTIONS_FORM_STEP));
|
|
50
50
|
};
|
|
51
51
|
|
|
52
52
|
const selectedOptionGuid = packageDetails?.options.find(x => x.isSelected)?.id!;
|
|
@@ -187,7 +187,7 @@ const FlightOptionsForm: React.FC<FlightOptionsFormProps> = () => {
|
|
|
187
187
|
</button>
|
|
188
188
|
) : (
|
|
189
189
|
<Link
|
|
190
|
-
to={`${settings.basePath}${settings.
|
|
190
|
+
to={`${settings.basePath}${settings.roomOptions.pathSuffix}?${bookingQueryString}`}
|
|
191
191
|
title={translations.STEPS.PREVIOUS}
|
|
192
192
|
className="cta cta--secondary"
|
|
193
193
|
>
|
|
@@ -25,10 +25,13 @@ import {
|
|
|
25
25
|
setPackageAirportGroups,
|
|
26
26
|
setPackageGroups,
|
|
27
27
|
setPackageOptionPax,
|
|
28
|
-
setPackageOptionUnits
|
|
28
|
+
setPackageOptionUnits,
|
|
29
|
+
setPackageRooms,
|
|
30
|
+
setTagIds
|
|
29
31
|
} from "../booking/booking-slice";
|
|
30
32
|
import { FLIGHT_OPTIONS_FORM_STEP, ROOM_OPTIONS_FORM_STEP, TRAVELERS_FORM_STEP } from "../booking/constants";
|
|
31
33
|
import {
|
|
34
|
+
selectBookingPackagePax,
|
|
32
35
|
selectBookingQueryString,
|
|
33
36
|
selectIsFetchingProductOptions,
|
|
34
37
|
selectPackageAirlineGroups,
|
|
@@ -37,7 +40,10 @@ import {
|
|
|
37
40
|
selectPackageGroups,
|
|
38
41
|
selectPackageOptionPax,
|
|
39
42
|
selectPackageOptionUnits,
|
|
40
|
-
|
|
43
|
+
selectPackageRooms,
|
|
44
|
+
selectPackageTags,
|
|
45
|
+
selectRequestRooms,
|
|
46
|
+
selectTagIds
|
|
41
47
|
} from "../booking/selectors";
|
|
42
48
|
import { fetchPriceDetails } from "../price-details/price-details-slice";
|
|
43
49
|
import NoOptions from "./no-options";
|
|
@@ -45,12 +51,14 @@ import OptionBookingAirlineGroup from "./option-booking-airline-group";
|
|
|
45
51
|
import OptionBookingGroup from "./option-booking-group";
|
|
46
52
|
import OptionPaxCard from "./option-pax-card";
|
|
47
53
|
import OptionUnitsCard from "./option-units-card";
|
|
54
|
+
import OptionRoom from "./option-room";
|
|
48
55
|
|
|
49
56
|
interface OptionsFormProps { }
|
|
50
57
|
|
|
51
58
|
const OptionsForm: React.FC<OptionsFormProps> = () => {
|
|
52
59
|
const settings = useContext(SettingsContext);
|
|
53
60
|
|
|
61
|
+
|
|
54
62
|
const translations = getTranslations(settings.language);
|
|
55
63
|
const dispatch = useAppDispatch();
|
|
56
64
|
const packageDetails = useSelector(selectPackageDetails);
|
|
@@ -64,6 +72,50 @@ const OptionsForm: React.FC<OptionsFormProps> = () => {
|
|
|
64
72
|
const airportGroups = useSelector(selectPackageAirportGroups);
|
|
65
73
|
const optionUnits = useSelector(selectPackageOptionUnits);
|
|
66
74
|
const optionPax = useSelector(selectPackageOptionPax);
|
|
75
|
+
|
|
76
|
+
// ROOMS
|
|
77
|
+
const showRoomOptions = settings.roomOptions.isHidden;
|
|
78
|
+
const packageRooms = useSelector(selectPackageRooms);
|
|
79
|
+
const pax = useSelector(selectBookingPackagePax);
|
|
80
|
+
|
|
81
|
+
const getRoomPax = (index: number) => {
|
|
82
|
+
var room = requestRooms?.find((x) => x.index == index);
|
|
83
|
+
var bookingPackagePax = pax.filter((x) =>
|
|
84
|
+
room?.pax.some((y) => y.id == x.id)
|
|
85
|
+
);
|
|
86
|
+
return bookingPackagePax.length > 0 ? bookingPackagePax : room?.pax ?? [];
|
|
87
|
+
};
|
|
88
|
+
|
|
89
|
+
const handleOnRoomChange = (
|
|
90
|
+
index: number,
|
|
91
|
+
accommodationCode: string,
|
|
92
|
+
regimeCode: string | null
|
|
93
|
+
) => {
|
|
94
|
+
if (!packageRooms) return;
|
|
95
|
+
|
|
96
|
+
const updatedPackageRooms = packageRooms.map((room) => {
|
|
97
|
+
if (room.index !== index) return room;
|
|
98
|
+
|
|
99
|
+
return {
|
|
100
|
+
...room,
|
|
101
|
+
options: room.options.map((option) => {
|
|
102
|
+
return {
|
|
103
|
+
...option,
|
|
104
|
+
isSelected:
|
|
105
|
+
option.accommodationCode === accommodationCode &&
|
|
106
|
+
option.regimeCode === regimeCode,
|
|
107
|
+
};
|
|
108
|
+
}),
|
|
109
|
+
};
|
|
110
|
+
});
|
|
111
|
+
|
|
112
|
+
dispatch(setPackageRooms(updatedPackageRooms));
|
|
113
|
+
dispatch(fetchPriceDetails());
|
|
114
|
+
};
|
|
115
|
+
|
|
116
|
+
// TAGS
|
|
117
|
+
const packageTags = settings.hideTags ? [] : useSelector(selectPackageTags);
|
|
118
|
+
let tagIds = useSelector(selectTagIds) ?? [];
|
|
67
119
|
|
|
68
120
|
const handleSubmit: React.FormEventHandler<HTMLFormElement> = (e) => {
|
|
69
121
|
if (settings.skipRouter) {
|
|
@@ -125,6 +177,20 @@ const OptionsForm: React.FC<OptionsFormProps> = () => {
|
|
|
125
177
|
}
|
|
126
178
|
};
|
|
127
179
|
|
|
180
|
+
const handleOnTagChange = (id: number, checked: boolean) => {
|
|
181
|
+
let updatedTags = [...tagIds];
|
|
182
|
+
if (checked) {
|
|
183
|
+
if (!updatedTags?.includes(id)) {
|
|
184
|
+
updatedTags?.push(id);
|
|
185
|
+
}
|
|
186
|
+
} else {
|
|
187
|
+
updatedTags = updatedTags?.filter((x) => x != id);
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
dispatch(setTagIds(updatedTags));
|
|
191
|
+
dispatch(fetchPriceDetails());
|
|
192
|
+
};
|
|
193
|
+
|
|
128
194
|
useEffect(() => {
|
|
129
195
|
if (packageDetails && settings.roomOptions.isHidden && settings.flightOptions.isHidden) {
|
|
130
196
|
const params = new URLSearchParams(location.search);
|
|
@@ -171,12 +237,12 @@ const OptionsForm: React.FC<OptionsFormProps> = () => {
|
|
|
171
237
|
const goPrevious = () => {
|
|
172
238
|
if (settings.flightOptions.isHidden) {
|
|
173
239
|
dispatch(setCurrentStep(ROOM_OPTIONS_FORM_STEP));
|
|
174
|
-
} else {
|
|
240
|
+
} else {
|
|
175
241
|
dispatch(setCurrentStep(FLIGHT_OPTIONS_FORM_STEP));
|
|
176
242
|
}
|
|
177
243
|
};
|
|
178
244
|
|
|
179
|
-
const previousUrl = settings.flightOptions.isHidden
|
|
245
|
+
const previousUrl = settings.flightOptions.isHidden
|
|
180
246
|
? `${settings.basePath}${settings.roomOptions.pathSuffix}?${bookingQueryString}`
|
|
181
247
|
: `${settings.basePath}${settings.flightOptions.pathSuffix}?${bookingQueryString}`;
|
|
182
248
|
const hasPrevious = !settings.roomOptions.isHidden || !settings.flightOptions.isHidden;
|
|
@@ -193,7 +259,73 @@ const OptionsForm: React.FC<OptionsFormProps> = () => {
|
|
|
193
259
|
{isLoading && settings.loaderComponent}
|
|
194
260
|
{!isLoading && (
|
|
195
261
|
<div className="form__region">
|
|
196
|
-
|
|
262
|
+
{packageTags && (
|
|
263
|
+
<div className="form__group">
|
|
264
|
+
<div className="booking-card">
|
|
265
|
+
<div className="booking-card__body">
|
|
266
|
+
<div
|
|
267
|
+
className={buildClassName([
|
|
268
|
+
"booking-card__group",
|
|
269
|
+
"booking-card__group--package",
|
|
270
|
+
])}
|
|
271
|
+
>
|
|
272
|
+
{showRoomOptions && (
|
|
273
|
+
<span className="booking-card__tag">
|
|
274
|
+
{translations.OPTIONS_FORM.PACKAGE}
|
|
275
|
+
</span>
|
|
276
|
+
)}
|
|
277
|
+
<div className="booking-card__group-body">
|
|
278
|
+
{showRoomOptions && (
|
|
279
|
+
<table className="table table--striped">
|
|
280
|
+
<tbody>
|
|
281
|
+
{packageRooms &&
|
|
282
|
+
packageRooms.map((room) => (
|
|
283
|
+
<OptionRoom
|
|
284
|
+
key={room.index}
|
|
285
|
+
packageRoom={room}
|
|
286
|
+
pax={getRoomPax(room.index)}
|
|
287
|
+
optionPax={optionPax}
|
|
288
|
+
onRoomChange={handleOnRoomChange}
|
|
289
|
+
/>
|
|
290
|
+
))}
|
|
291
|
+
</tbody>
|
|
292
|
+
</table>
|
|
293
|
+
)}
|
|
294
|
+
<div className="booking-card__tag-translations">
|
|
295
|
+
{packageTags.map((tag, index) => (
|
|
296
|
+
<label
|
|
297
|
+
key={index}
|
|
298
|
+
htmlFor={`tag-translation-${index}-${tag.title}`}
|
|
299
|
+
className="checkbox__label tag-translation"
|
|
300
|
+
>
|
|
301
|
+
<div className="tag-translation-input__container">
|
|
302
|
+
<input
|
|
303
|
+
type="checkbox"
|
|
304
|
+
id={`tag-translation-${index}-${tag.title}`}
|
|
305
|
+
name={`tag-translation-${index}-${tag.title}`}
|
|
306
|
+
className="checkbox__input"
|
|
307
|
+
checked={tagIds?.includes(tag.id)}
|
|
308
|
+
onChange={(e) =>
|
|
309
|
+
handleOnTagChange(tag.id, e.target.checked)
|
|
310
|
+
}
|
|
311
|
+
/>
|
|
312
|
+
</div>
|
|
313
|
+
<span className="tag-translation__title">
|
|
314
|
+
{tag.title}
|
|
315
|
+
</span>
|
|
316
|
+
|
|
317
|
+
<span className="tag-translation__description">
|
|
318
|
+
{tag.description}
|
|
319
|
+
</span>
|
|
320
|
+
</label>
|
|
321
|
+
))}
|
|
322
|
+
</div>
|
|
323
|
+
</div>
|
|
324
|
+
</div>
|
|
325
|
+
</div>
|
|
326
|
+
</div>
|
|
327
|
+
</div>
|
|
328
|
+
)}
|
|
197
329
|
{optionUnits && !isEmpty(optionUnits) && (
|
|
198
330
|
<div className="form__group">
|
|
199
331
|
<div className="booking-card">
|
|
@@ -12,8 +12,7 @@ import { useAppDispatch } from "../../store";
|
|
|
12
12
|
import {
|
|
13
13
|
setCurrentStep,
|
|
14
14
|
setPackage,
|
|
15
|
-
setPackageRooms
|
|
16
|
-
setTagIds
|
|
15
|
+
setPackageRooms
|
|
17
16
|
} from "../booking/booking-slice";
|
|
18
17
|
import { FLIGHT_OPTIONS_FORM_STEP, OPTIONS_FORM_STEP } from "../booking/constants";
|
|
19
18
|
import {
|
|
@@ -23,9 +22,7 @@ import {
|
|
|
23
22
|
selectPackageDetails,
|
|
24
23
|
selectPackageOptionPax,
|
|
25
24
|
selectPackageRooms,
|
|
26
|
-
|
|
27
|
-
selectRequestRooms,
|
|
28
|
-
selectTagIds
|
|
25
|
+
selectRequestRooms
|
|
29
26
|
} from "../booking/selectors";
|
|
30
27
|
import { fetchPriceDetails } from "../price-details/price-details-slice";
|
|
31
28
|
import OptionRoom from "../product-options/option-room";
|
|
@@ -39,8 +36,7 @@ const RoomOptionsForm: React.FC<RoomOptionsFormProps> = () => {
|
|
|
39
36
|
options,
|
|
40
37
|
loaderComponent,
|
|
41
38
|
language,
|
|
42
|
-
skipRouter
|
|
43
|
-
hideTags,
|
|
39
|
+
skipRouter
|
|
44
40
|
} = useContext(SettingsContext);
|
|
45
41
|
|
|
46
42
|
const translations = getTranslations(language);
|
|
@@ -53,9 +49,6 @@ const RoomOptionsForm: React.FC<RoomOptionsFormProps> = () => {
|
|
|
53
49
|
const isLoading = useSelector(selectIsFetchingProductOptions);
|
|
54
50
|
const optionPax = useSelector(selectPackageOptionPax);
|
|
55
51
|
|
|
56
|
-
const packageTags = hideTags ? [] : useSelector(selectPackageTags);
|
|
57
|
-
let tagIds = useSelector(selectTagIds) ?? [];
|
|
58
|
-
|
|
59
52
|
const getRoomPax = (index: number) => {
|
|
60
53
|
var room = requestRooms?.find((x) => x.index == index);
|
|
61
54
|
var bookingPackagePax = pax.filter((x) =>
|
|
@@ -109,20 +102,6 @@ const RoomOptionsForm: React.FC<RoomOptionsFormProps> = () => {
|
|
|
109
102
|
dispatch(fetchPriceDetails());
|
|
110
103
|
};
|
|
111
104
|
|
|
112
|
-
const handleOnTagChange = (id: number, checked: boolean) => {
|
|
113
|
-
let updatedTags = [...tagIds];
|
|
114
|
-
if (checked) {
|
|
115
|
-
if (!updatedTags?.includes(id)) {
|
|
116
|
-
updatedTags?.push(id);
|
|
117
|
-
}
|
|
118
|
-
} else {
|
|
119
|
-
updatedTags = updatedTags?.filter((x) => x != id);
|
|
120
|
-
}
|
|
121
|
-
|
|
122
|
-
dispatch(setTagIds(updatedTags));
|
|
123
|
-
dispatch(fetchPriceDetails());
|
|
124
|
-
};
|
|
125
|
-
|
|
126
105
|
useEffect(() => {
|
|
127
106
|
if (packageDetails) {
|
|
128
107
|
const params = new URLSearchParams(location.search);
|
|
@@ -175,73 +154,55 @@ const RoomOptionsForm: React.FC<RoomOptionsFormProps> = () => {
|
|
|
175
154
|
noValidate
|
|
176
155
|
onSubmit={handleSubmit}
|
|
177
156
|
>
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
<div className="
|
|
182
|
-
<div className="
|
|
183
|
-
<div className="booking-
|
|
184
|
-
<div
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
<
|
|
195
|
-
<
|
|
196
|
-
|
|
197
|
-
packageRooms
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
))}
|
|
206
|
-
</tbody>
|
|
207
|
-
</table>
|
|
208
|
-
<div className="booking-card__tag-translations">
|
|
209
|
-
{packageTags &&
|
|
210
|
-
packageTags.map((tag, index) => (
|
|
211
|
-
<label
|
|
212
|
-
key={index}
|
|
213
|
-
htmlFor={`tag-translation-${index}-${tag.title}`}
|
|
214
|
-
className="checkbox__label tag-translation"
|
|
215
|
-
>
|
|
216
|
-
<div className="tag-translation-input__container">
|
|
217
|
-
<input
|
|
218
|
-
type="checkbox"
|
|
219
|
-
id={`tag-translation-${index}-${tag.title}`}
|
|
220
|
-
name={`tag-translation-${index}-${tag.title}`}
|
|
221
|
-
className="checkbox__input"
|
|
222
|
-
checked={tagIds?.includes(tag.id)}
|
|
223
|
-
onChange={(e) =>
|
|
224
|
-
handleOnTagChange(tag.id, e.target.checked)
|
|
225
|
-
}
|
|
157
|
+
<div className="form__wrapper">
|
|
158
|
+
{isLoading && loaderComponent}
|
|
159
|
+
{!isLoading && (
|
|
160
|
+
<div className="form__region">
|
|
161
|
+
<div className="form__group">
|
|
162
|
+
<div className="booking-card">
|
|
163
|
+
<div className="booking-card__body">
|
|
164
|
+
<div
|
|
165
|
+
className={buildClassName([
|
|
166
|
+
"booking-card__group",
|
|
167
|
+
"booking-card__group--package",
|
|
168
|
+
])}
|
|
169
|
+
>
|
|
170
|
+
<span className="booking-card__tag">
|
|
171
|
+
{translations.OPTIONS_FORM.PACKAGE}
|
|
172
|
+
</span>
|
|
173
|
+
<div className="booking-card__group-body">
|
|
174
|
+
<table className="table table--striped">
|
|
175
|
+
<tbody>
|
|
176
|
+
{packageRooms &&
|
|
177
|
+
packageRooms.map((room) => (
|
|
178
|
+
<OptionRoom
|
|
179
|
+
key={room.index}
|
|
180
|
+
packageRoom={room}
|
|
181
|
+
pax={getRoomPax(room.index)}
|
|
182
|
+
optionPax={optionPax}
|
|
183
|
+
onRoomChange={handleOnRoomChange}
|
|
226
184
|
/>
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
</span>
|
|
231
|
-
|
|
232
|
-
<span className="tag-translation__description">
|
|
233
|
-
{tag.description}
|
|
234
|
-
</span>
|
|
235
|
-
</label>
|
|
236
|
-
))}
|
|
185
|
+
))}
|
|
186
|
+
</tbody>
|
|
187
|
+
</table>
|
|
237
188
|
</div>
|
|
238
189
|
</div>
|
|
239
190
|
</div>
|
|
240
191
|
</div>
|
|
241
192
|
</div>
|
|
242
193
|
</div>
|
|
194
|
+
|
|
195
|
+
)}
|
|
196
|
+
|
|
197
|
+
<div className="form__room">
|
|
198
|
+
<div className="form__room__image">
|
|
199
|
+
<img src="https://picsum.photos/1920/1080" alt="" className="form__room__img"/>
|
|
200
|
+
<div className="form__room__favorite">
|
|
201
|
+
<i className="fa fa-heart"></i>
|
|
202
|
+
</div>
|
|
203
|
+
</div>
|
|
243
204
|
</div>
|
|
244
|
-
|
|
205
|
+
</div>
|
|
245
206
|
<div className="booking__navigator">
|
|
246
207
|
<button
|
|
247
208
|
type="submit"
|
|
@@ -7,7 +7,7 @@ import { Link, navigate, useLocation } from "@reach/router";
|
|
|
7
7
|
import { compact, findIndex, isEmpty, isNil, uniqBy } from "lodash";
|
|
8
8
|
import React, { useContext, useEffect, useState } from "react";
|
|
9
9
|
import { useSelector } from "react-redux";
|
|
10
|
-
import Icon from "
|
|
10
|
+
import Icon from "../../components/icon";
|
|
11
11
|
import SettingsContext from "../../settings-context";
|
|
12
12
|
import { useAppDispatch } from "../../store";
|
|
13
13
|
import { SummaryCheckbox } from "../../types";
|
|
@@ -41,7 +41,9 @@
|
|
|
41
41
|
"DEPARTURE": "",
|
|
42
42
|
"DEPARTURE_DATE": "",
|
|
43
43
|
"RETURN": "",
|
|
44
|
-
"RETURN_DATE": ""
|
|
44
|
+
"RETURN_DATE": "",
|
|
45
|
+
"WHO_YOU_TRAVELING_WITH": "",
|
|
46
|
+
"TRAVEL_PERIOD": ""
|
|
45
47
|
},
|
|
46
48
|
"MAIN": {
|
|
47
49
|
"PREPARING_BOOKING": "Veuillez patienter, nous préparons votre réservation",
|
|
@@ -41,7 +41,9 @@
|
|
|
41
41
|
"DEPARTURE": "Vertrek",
|
|
42
42
|
"DEPARTURE_DATE": "Vertrekdatum",
|
|
43
43
|
"RETURN": "Terugkeer",
|
|
44
|
-
"RETURN_DATE": "Terugkeerdatum"
|
|
44
|
+
"RETURN_DATE": "Terugkeerdatum",
|
|
45
|
+
"WHO_YOU_TRAVELING_WITH": "Met wie ga je?",
|
|
46
|
+
"TRAVEL_PERIOD": "Reisperiode"
|
|
45
47
|
},
|
|
46
48
|
"MAIN": {
|
|
47
49
|
"PREPARING_BOOKING": "Even geduld, we bereiden uw boeking voor",
|