@qite/tide-booking-component 1.4.77 → 1.4.79

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.
@@ -24412,7 +24412,7 @@ var aggregatePricePerPaxType = function (priceDetails, requestRooms) {
24412
24412
  room.pax.forEach(function (pax) {
24413
24413
  var paxType = 'ADULT';
24414
24414
  if (typeof pax.age === 'number') {
24415
- if (pax.age <= 11) {
24415
+ if (pax.age <= 11 && pax.age > 2) {
24416
24416
  paxType = 'CHILD';
24417
24417
  } else if (pax.age <= 2) {
24418
24418
  paxType = 'INFANT';
@@ -30413,6 +30413,7 @@ var Footer = function (_a) {
30413
30413
 
30414
30414
  var QSMConfigurationContext = React__default['default'].createContext({
30415
30415
  type: exports.PortalQsmType.Accommodation,
30416
+ searchConfigurations: [],
30416
30417
  askTravelers: false,
30417
30418
  askNationality: false,
30418
30419
  askTravelClass: false,
@@ -33042,6 +33043,7 @@ var TravelNationalityPicker = function () {
33042
33043
  };
33043
33044
 
33044
33045
  var QSMContainer = function () {
33046
+ var _a;
33045
33047
  var dispatch = reactRedux.useDispatch();
33046
33048
  var isMobile = useMediaQuery('(max-width: 768px)');
33047
33049
  var qsmState = reactRedux.useSelector(function (state) {
@@ -33052,23 +33054,24 @@ var QSMContainer = function () {
33052
33054
  fromDate = qsmState.fromDate,
33053
33055
  toDate = qsmState.toDate,
33054
33056
  tripType = qsmState.tripType;
33055
- var _a = React.useContext(QSMConfigurationContext),
33056
- askTravelers = _a.askTravelers,
33057
- askRooms = _a.askRooms,
33058
- askNationality = _a.askNationality,
33059
- askTravelClass = _a.askTravelClass,
33060
- askTravelType = _a.askTravelType,
33061
- submitIcon = _a.submitIcon,
33062
- onSubmit = _a.onSubmit,
33063
- travelTypes = _a.travelTypes,
33064
- languageCode = _a.languageCode,
33065
- departureAirport = _a.departureAirport,
33066
- destinationAirport = _a.destinationAirport,
33067
- returnAirport = _a.returnAirport,
33068
- destination = _a.destination,
33069
- allowOneWay = _a.allowOneWay,
33070
- allowRoundtrip = _a.allowRoundtrip,
33071
- allowOpenJaw = _a.allowOpenJaw;
33057
+ var _b = React.useContext(QSMConfigurationContext),
33058
+ askTravelers = _b.askTravelers,
33059
+ askRooms = _b.askRooms,
33060
+ askNationality = _b.askNationality,
33061
+ askTravelClass = _b.askTravelClass,
33062
+ askTravelType = _b.askTravelType,
33063
+ submitIcon = _b.submitIcon,
33064
+ onSubmit = _b.onSubmit,
33065
+ travelTypes = _b.travelTypes,
33066
+ languageCode = _b.languageCode,
33067
+ departureAirport = _b.departureAirport,
33068
+ destinationAirport = _b.destinationAirport,
33069
+ returnAirport = _b.returnAirport,
33070
+ destination = _b.destination,
33071
+ allowOneWay = _b.allowOneWay,
33072
+ allowRoundtrip = _b.allowRoundtrip,
33073
+ allowOpenJaw = _b.allowOpenJaw,
33074
+ searchConfigurations = _b.searchConfigurations;
33072
33075
  var translations = getTranslations(languageCode !== null && languageCode !== void 0 ? languageCode : 'en-GB');
33073
33076
  React.useEffect(
33074
33077
  function () {
@@ -33103,12 +33106,36 @@ var QSMContainer = function () {
33103
33106
  };
33104
33107
  var handleQsmTypeChange = function (value) {
33105
33108
  dispatch(setSelectedQsmType(value));
33106
- var startDate = dateFns.addMonths(new Date(), 1);
33109
+ var now = new Date();
33110
+ // Default fallback
33111
+ var startDate = dateFns.addMonths(now, 1);
33107
33112
  var endDate = dateFns.addDays(startDate, 7);
33108
33113
  if (value === exports.PortalQsmType.GroupTour) {
33109
- startDate = new Date();
33114
+ startDate = now;
33110
33115
  endDate = dateFns.addYears(startDate, 1);
33111
33116
  }
33117
+ var searchConfig = searchConfigurations.find(function (config) {
33118
+ return config.qsmType === value;
33119
+ });
33120
+ if (searchConfig) {
33121
+ var applyAmount = function (baseDate, type, amount) {
33122
+ if (!amount || type == null) return baseDate;
33123
+ switch (type) {
33124
+ case build.DateAmountType.days:
33125
+ return dateFns.addDays(baseDate, amount);
33126
+ case build.DateAmountType.months:
33127
+ return dateFns.addMonths(baseDate, amount);
33128
+ default:
33129
+ return baseDate;
33130
+ }
33131
+ };
33132
+ if (searchConfig.fromDateAmount) {
33133
+ startDate = applyAmount(now, searchConfig.fromDateAmountType, searchConfig.fromDateAmount);
33134
+ }
33135
+ if (searchConfig.toDateAmount) {
33136
+ endDate = applyAmount(startDate, searchConfig.toDateAmountType, searchConfig.toDateAmount);
33137
+ }
33138
+ }
33112
33139
  handleDateChange({
33113
33140
  fromDate: startDate,
33114
33141
  toDate: endDate
@@ -33207,6 +33234,53 @@ var QSMContainer = function () {
33207
33234
  },
33208
33235
  [fromDate, toDate, departureAirport, returnAirport, allowOpenJaw]
33209
33236
  );
33237
+ var qsmTypeMeta =
33238
+ ((_a = {}),
33239
+ (_a[exports.PortalQsmType.Multidestination] = {
33240
+ icon: 'ui-location',
33241
+ label: translations.QSM.MULTIDESTINATION
33242
+ }),
33243
+ (_a[exports.PortalQsmType.Package] = {
33244
+ icon: 'ui-suitcase',
33245
+ label: translations.QSM.PACKAGES
33246
+ }),
33247
+ (_a[exports.PortalQsmType.AccommodationAndFlight] = {
33248
+ icon: ['ui-backforward', 'ui-bed'],
33249
+ label: translations.QSM.TRANSPORT_HOTEL
33250
+ }),
33251
+ (_a[exports.PortalQsmType.Accommodation] = {
33252
+ icon: 'ui-bed',
33253
+ label: translations.QSM.ACCOMMODATION
33254
+ }),
33255
+ (_a[exports.PortalQsmType.Flight] = {
33256
+ icon: 'ui-flight',
33257
+ label: translations.QSM.TRANSPORTS
33258
+ }),
33259
+ (_a[exports.PortalQsmType.GroupTour] = {
33260
+ icon: 'ui-group',
33261
+ label: translations.QSM.GROUP_TOUR
33262
+ }),
33263
+ (_a[exports.PortalQsmType.RoundTrip] = {
33264
+ icon: 'ui-group',
33265
+ label: translations.QSM.ROUNDTRIP
33266
+ }),
33267
+ (_a[exports.PortalQsmType.Ticket] = {
33268
+ icon: 'ui-ticket',
33269
+ label: translations.QSM.TICKET_ONLY
33270
+ }),
33271
+ (_a[exports.PortalQsmType.Car] = {
33272
+ icon: 'ui-car',
33273
+ label: translations.QSM.RENT_A_CAR
33274
+ }),
33275
+ (_a[exports.PortalQsmType.Transfer] = {
33276
+ icon: 'ui-backforward',
33277
+ label: translations.QSM.TRANSFERS
33278
+ }),
33279
+ (_a[exports.PortalQsmType.Cruise] = {
33280
+ icon: 'ui-ship',
33281
+ label: translations.QSM.CRUISES
33282
+ }),
33283
+ _a);
33210
33284
  return React__default['default'].createElement(
33211
33285
  'div',
33212
33286
  { className: 'qsm' },
@@ -33216,168 +33290,31 @@ var QSMContainer = function () {
33216
33290
  React__default['default'].createElement(
33217
33291
  'div',
33218
33292
  { className: 'qsm__tabs' },
33219
- React__default['default'].createElement(
33220
- 'button',
33221
- {
33222
- type: 'button',
33223
- className: 'qsm__tab '.concat(qsmType == exports.PortalQsmType.Multidestination ? 'qsm__tab--active' : ''),
33224
- onClick: function () {
33225
- return handleQsmTypeChange(exports.PortalQsmType.Multidestination);
33226
- }
33227
- },
33228
- React__default['default'].createElement(
33229
- 'span',
33230
- { className: 'qsm__tab__icons' },
33231
- React__default['default'].createElement(Icon$2, { name: 'ui-location', height: 16 })
33232
- ),
33233
- translations.QSM.MULTIDESTINATION
33234
- ),
33235
- React__default['default'].createElement(
33236
- 'button',
33237
- {
33238
- type: 'button',
33239
- className: 'qsm__tab '.concat(qsmType == exports.PortalQsmType.Package ? 'qsm__tab--active' : ''),
33240
- onClick: function () {
33241
- return handleQsmTypeChange(exports.PortalQsmType.Package);
33242
- }
33243
- },
33244
- React__default['default'].createElement(
33245
- 'span',
33246
- { className: 'qsm__tab__icons' },
33247
- React__default['default'].createElement(Icon$2, { name: 'ui-suitcase', height: 16 })
33248
- ),
33249
- translations.QSM.PACKAGES
33250
- ),
33251
- React__default['default'].createElement(
33252
- 'button',
33253
- {
33254
- type: 'button',
33255
- className: 'qsm__tab '.concat(qsmType == exports.PortalQsmType.AccommodationAndFlight ? 'qsm__tab--active' : ''),
33256
- onClick: function () {
33257
- return handleQsmTypeChange(exports.PortalQsmType.AccommodationAndFlight);
33258
- }
33259
- },
33260
- React__default['default'].createElement(
33261
- 'span',
33262
- { className: 'qsm__tab__icons' },
33263
- React__default['default'].createElement(Icon$2, { name: 'ui-backforward', height: 14 }),
33264
- '+',
33265
- React__default['default'].createElement(Icon$2, { name: 'ui-bed', height: 14 })
33266
- ),
33267
- translations.QSM.TRANSPORT_HOTEL
33268
- ),
33269
- React__default['default'].createElement(
33270
- 'button',
33271
- {
33272
- type: 'button',
33273
- className: 'qsm__tab '.concat(qsmType == exports.PortalQsmType.Accommodation ? 'qsm__tab--active' : ''),
33274
- onClick: function () {
33275
- return handleQsmTypeChange(exports.PortalQsmType.Accommodation);
33276
- }
33277
- },
33278
- React__default['default'].createElement(
33279
- 'span',
33280
- { className: 'qsm__tab__icons' },
33281
- React__default['default'].createElement(Icon$2, { name: 'ui-bed', height: 16 })
33282
- ),
33283
- translations.QSM.ACCOMMODATION
33284
- ),
33285
- React__default['default'].createElement(
33286
- 'button',
33287
- {
33288
- type: 'button',
33289
- className: 'qsm__tab '.concat(qsmType == exports.PortalQsmType.Flight ? 'qsm__tab--active' : ''),
33290
- onClick: function () {
33291
- return handleQsmTypeChange(exports.PortalQsmType.Flight);
33292
- }
33293
- },
33294
- React__default['default'].createElement(
33295
- 'span',
33296
- { className: 'qsm__tab__icons' },
33297
- React__default['default'].createElement(Icon$2, { name: 'ui-flight', height: 16 })
33298
- ),
33299
- translations.QSM.TRANSPORTS
33300
- ),
33301
- React__default['default'].createElement(
33302
- 'button',
33303
- {
33304
- type: 'button',
33305
- className: 'qsm__tab '.concat(qsmType == exports.PortalQsmType.GroupTour ? 'qsm__tab--active' : ''),
33306
- onClick: function () {
33307
- return handleQsmTypeChange(exports.PortalQsmType.GroupTour);
33308
- }
33309
- },
33310
- React__default['default'].createElement(
33311
- 'span',
33312
- { className: 'qsm__tab__icons' },
33313
- React__default['default'].createElement(Icon$2, { name: 'ui-group', height: 16 })
33314
- ),
33315
- translations.QSM.GROUP_TOUR
33316
- ),
33317
- React__default['default'].createElement(
33318
- 'button',
33319
- {
33320
- type: 'button',
33321
- className: 'qsm__tab '.concat(qsmType == exports.PortalQsmType.Ticket ? 'qsm__tab--active' : ''),
33322
- onClick: function () {
33323
- return handleQsmTypeChange(exports.PortalQsmType.Ticket);
33324
- }
33325
- },
33326
- React__default['default'].createElement(
33327
- 'span',
33328
- { className: 'qsm__tab__icons' },
33329
- React__default['default'].createElement(Icon$2, { name: 'ui-ticket', height: 16 })
33330
- ),
33331
- translations.QSM.TICKET_ONLY
33332
- ),
33333
- React__default['default'].createElement(
33334
- 'button',
33335
- {
33336
- type: 'button',
33337
- className: 'qsm__tab '.concat(qsmType == exports.PortalQsmType.Car ? 'qsm__tab--active' : ''),
33338
- onClick: function () {
33339
- return handleQsmTypeChange(exports.PortalQsmType.Car);
33340
- }
33341
- },
33342
- React__default['default'].createElement(
33343
- 'span',
33344
- { className: 'qsm__tab__icons' },
33345
- React__default['default'].createElement(Icon$2, { name: 'ui-car', height: 16 })
33346
- ),
33347
- translations.QSM.RENT_A_CAR
33348
- ),
33349
- React__default['default'].createElement(
33350
- 'button',
33351
- {
33352
- type: 'button',
33353
- className: 'qsm__tab '.concat(qsmType == exports.PortalQsmType.Transfer ? 'qsm__tab--active' : ''),
33354
- onClick: function () {
33355
- return handleQsmTypeChange(exports.PortalQsmType.Transfer);
33356
- }
33357
- },
33358
- React__default['default'].createElement(
33359
- 'span',
33360
- { className: 'qsm__tab__icons' },
33361
- React__default['default'].createElement(Icon$2, { name: 'ui-backforward', height: 16 })
33362
- ),
33363
- translations.QSM.TRANSFERS
33364
- ),
33365
- React__default['default'].createElement(
33366
- 'button',
33367
- {
33368
- type: 'button',
33369
- className: 'qsm__tab '.concat(qsmType == exports.PortalQsmType.Cruise ? 'qsm__tab--active' : ''),
33370
- onClick: function () {
33371
- return handleQsmTypeChange(exports.PortalQsmType.Cruise);
33372
- }
33373
- },
33374
- React__default['default'].createElement(
33375
- 'span',
33376
- { className: 'qsm__tab__icons' },
33377
- React__default['default'].createElement(Icon$2, { name: 'ui-ship', height: 16 })
33378
- ),
33379
- translations.QSM.CRUISES
33380
- )
33293
+ searchConfigurations.map(function (searchConfig, index) {
33294
+ var meta = qsmTypeMeta[searchConfig.qsmType];
33295
+ if (!meta) return null; // safety guard
33296
+ return React__default['default'].createElement(
33297
+ 'button',
33298
+ {
33299
+ key: 'qsm-type-'.concat(index),
33300
+ type: 'button',
33301
+ className: 'qsm__tab '.concat(qsmType === searchConfig.qsmType ? 'qsm__tab--active' : ''),
33302
+ onClick: function () {
33303
+ return handleQsmTypeChange(searchConfig.qsmType);
33304
+ }
33305
+ },
33306
+ React__default['default'].createElement(
33307
+ 'span',
33308
+ { className: 'qsm__tab__icons' },
33309
+ Array.isArray(meta.icon)
33310
+ ? meta.icon.map(function (icon, i) {
33311
+ return React__default['default'].createElement(Icon$2, { key: i, name: icon, height: 14 });
33312
+ })
33313
+ : React__default['default'].createElement(Icon$2, { name: meta.icon, height: 16 })
33314
+ ),
33315
+ meta.label
33316
+ );
33317
+ })
33381
33318
  ),
33382
33319
  React__default['default'].createElement(
33383
33320
  'div',
@@ -1,7 +1,9 @@
1
1
  import { ReactNode } from 'react';
2
2
  import { PortalQsmType, TravelClass, TravelType } from '../shared/types';
3
+ import { WebsiteConfigurationSearchConfiguration } from '@qite/tide-client';
3
4
  export interface QSMConfiguration {
4
5
  type?: PortalQsmType;
6
+ searchConfigurations: WebsiteConfigurationSearchConfiguration[];
5
7
  askRooms?: boolean;
6
8
  askTravelType?: boolean;
7
9
  allowOneWay?: boolean;
@@ -24364,7 +24364,7 @@ var aggregatePricePerPaxType = function (priceDetails, requestRooms) {
24364
24364
  room.pax.forEach(function (pax) {
24365
24365
  var paxType = 'ADULT';
24366
24366
  if (typeof pax.age === 'number') {
24367
- if (pax.age <= 11) {
24367
+ if (pax.age <= 11 && pax.age > 2) {
24368
24368
  paxType = 'CHILD';
24369
24369
  } else if (pax.age <= 2) {
24370
24370
  paxType = 'INFANT';
@@ -30300,6 +30300,7 @@ var Footer = function (_a) {
30300
30300
 
30301
30301
  var QSMConfigurationContext = React__default.createContext({
30302
30302
  type: PortalQsmType.Accommodation,
30303
+ searchConfigurations: [],
30303
30304
  askTravelers: false,
30304
30305
  askNationality: false,
30305
30306
  askTravelClass: false,
@@ -32907,6 +32908,7 @@ var TravelNationalityPicker = function () {
32907
32908
  };
32908
32909
 
32909
32910
  var QSMContainer = function () {
32911
+ var _a;
32910
32912
  var dispatch = useDispatch();
32911
32913
  var isMobile = useMediaQuery('(max-width: 768px)');
32912
32914
  var qsmState = useSelector(function (state) {
@@ -32917,23 +32919,24 @@ var QSMContainer = function () {
32917
32919
  fromDate = qsmState.fromDate,
32918
32920
  toDate = qsmState.toDate,
32919
32921
  tripType = qsmState.tripType;
32920
- var _a = useContext(QSMConfigurationContext),
32921
- askTravelers = _a.askTravelers,
32922
- askRooms = _a.askRooms,
32923
- askNationality = _a.askNationality,
32924
- askTravelClass = _a.askTravelClass,
32925
- askTravelType = _a.askTravelType,
32926
- submitIcon = _a.submitIcon,
32927
- onSubmit = _a.onSubmit,
32928
- travelTypes = _a.travelTypes,
32929
- languageCode = _a.languageCode,
32930
- departureAirport = _a.departureAirport,
32931
- destinationAirport = _a.destinationAirport,
32932
- returnAirport = _a.returnAirport,
32933
- destination = _a.destination,
32934
- allowOneWay = _a.allowOneWay,
32935
- allowRoundtrip = _a.allowRoundtrip,
32936
- allowOpenJaw = _a.allowOpenJaw;
32922
+ var _b = useContext(QSMConfigurationContext),
32923
+ askTravelers = _b.askTravelers,
32924
+ askRooms = _b.askRooms,
32925
+ askNationality = _b.askNationality,
32926
+ askTravelClass = _b.askTravelClass,
32927
+ askTravelType = _b.askTravelType,
32928
+ submitIcon = _b.submitIcon,
32929
+ onSubmit = _b.onSubmit,
32930
+ travelTypes = _b.travelTypes,
32931
+ languageCode = _b.languageCode,
32932
+ departureAirport = _b.departureAirport,
32933
+ destinationAirport = _b.destinationAirport,
32934
+ returnAirport = _b.returnAirport,
32935
+ destination = _b.destination,
32936
+ allowOneWay = _b.allowOneWay,
32937
+ allowRoundtrip = _b.allowRoundtrip,
32938
+ allowOpenJaw = _b.allowOpenJaw,
32939
+ searchConfigurations = _b.searchConfigurations;
32937
32940
  var translations = getTranslations(languageCode !== null && languageCode !== void 0 ? languageCode : 'en-GB');
32938
32941
  useEffect(
32939
32942
  function () {
@@ -32968,12 +32971,36 @@ var QSMContainer = function () {
32968
32971
  };
32969
32972
  var handleQsmTypeChange = function (value) {
32970
32973
  dispatch(setSelectedQsmType(value));
32971
- var startDate = addMonths(new Date(), 1);
32974
+ var now = new Date();
32975
+ // Default fallback
32976
+ var startDate = addMonths(now, 1);
32972
32977
  var endDate = addDays(startDate, 7);
32973
32978
  if (value === PortalQsmType.GroupTour) {
32974
- startDate = new Date();
32979
+ startDate = now;
32975
32980
  endDate = addYears(startDate, 1);
32976
32981
  }
32982
+ var searchConfig = searchConfigurations.find(function (config) {
32983
+ return config.qsmType === value;
32984
+ });
32985
+ if (searchConfig) {
32986
+ var applyAmount = function (baseDate, type, amount) {
32987
+ if (!amount || type == null) return baseDate;
32988
+ switch (type) {
32989
+ case build.DateAmountType.days:
32990
+ return addDays(baseDate, amount);
32991
+ case build.DateAmountType.months:
32992
+ return addMonths(baseDate, amount);
32993
+ default:
32994
+ return baseDate;
32995
+ }
32996
+ };
32997
+ if (searchConfig.fromDateAmount) {
32998
+ startDate = applyAmount(now, searchConfig.fromDateAmountType, searchConfig.fromDateAmount);
32999
+ }
33000
+ if (searchConfig.toDateAmount) {
33001
+ endDate = applyAmount(startDate, searchConfig.toDateAmountType, searchConfig.toDateAmount);
33002
+ }
33003
+ }
32977
33004
  handleDateChange({
32978
33005
  fromDate: startDate,
32979
33006
  toDate: endDate
@@ -33072,6 +33099,53 @@ var QSMContainer = function () {
33072
33099
  },
33073
33100
  [fromDate, toDate, departureAirport, returnAirport, allowOpenJaw]
33074
33101
  );
33102
+ var qsmTypeMeta =
33103
+ ((_a = {}),
33104
+ (_a[PortalQsmType.Multidestination] = {
33105
+ icon: 'ui-location',
33106
+ label: translations.QSM.MULTIDESTINATION
33107
+ }),
33108
+ (_a[PortalQsmType.Package] = {
33109
+ icon: 'ui-suitcase',
33110
+ label: translations.QSM.PACKAGES
33111
+ }),
33112
+ (_a[PortalQsmType.AccommodationAndFlight] = {
33113
+ icon: ['ui-backforward', 'ui-bed'],
33114
+ label: translations.QSM.TRANSPORT_HOTEL
33115
+ }),
33116
+ (_a[PortalQsmType.Accommodation] = {
33117
+ icon: 'ui-bed',
33118
+ label: translations.QSM.ACCOMMODATION
33119
+ }),
33120
+ (_a[PortalQsmType.Flight] = {
33121
+ icon: 'ui-flight',
33122
+ label: translations.QSM.TRANSPORTS
33123
+ }),
33124
+ (_a[PortalQsmType.GroupTour] = {
33125
+ icon: 'ui-group',
33126
+ label: translations.QSM.GROUP_TOUR
33127
+ }),
33128
+ (_a[PortalQsmType.RoundTrip] = {
33129
+ icon: 'ui-group',
33130
+ label: translations.QSM.ROUNDTRIP
33131
+ }),
33132
+ (_a[PortalQsmType.Ticket] = {
33133
+ icon: 'ui-ticket',
33134
+ label: translations.QSM.TICKET_ONLY
33135
+ }),
33136
+ (_a[PortalQsmType.Car] = {
33137
+ icon: 'ui-car',
33138
+ label: translations.QSM.RENT_A_CAR
33139
+ }),
33140
+ (_a[PortalQsmType.Transfer] = {
33141
+ icon: 'ui-backforward',
33142
+ label: translations.QSM.TRANSFERS
33143
+ }),
33144
+ (_a[PortalQsmType.Cruise] = {
33145
+ icon: 'ui-ship',
33146
+ label: translations.QSM.CRUISES
33147
+ }),
33148
+ _a);
33075
33149
  return React__default.createElement(
33076
33150
  'div',
33077
33151
  { className: 'qsm' },
@@ -33081,132 +33155,31 @@ var QSMContainer = function () {
33081
33155
  React__default.createElement(
33082
33156
  'div',
33083
33157
  { className: 'qsm__tabs' },
33084
- React__default.createElement(
33085
- 'button',
33086
- {
33087
- type: 'button',
33088
- className: 'qsm__tab '.concat(qsmType == PortalQsmType.Multidestination ? 'qsm__tab--active' : ''),
33089
- onClick: function () {
33090
- return handleQsmTypeChange(PortalQsmType.Multidestination);
33091
- }
33092
- },
33093
- React__default.createElement('span', { className: 'qsm__tab__icons' }, React__default.createElement(Icon$2, { name: 'ui-location', height: 16 })),
33094
- translations.QSM.MULTIDESTINATION
33095
- ),
33096
- React__default.createElement(
33097
- 'button',
33098
- {
33099
- type: 'button',
33100
- className: 'qsm__tab '.concat(qsmType == PortalQsmType.Package ? 'qsm__tab--active' : ''),
33101
- onClick: function () {
33102
- return handleQsmTypeChange(PortalQsmType.Package);
33103
- }
33104
- },
33105
- React__default.createElement('span', { className: 'qsm__tab__icons' }, React__default.createElement(Icon$2, { name: 'ui-suitcase', height: 16 })),
33106
- translations.QSM.PACKAGES
33107
- ),
33108
- React__default.createElement(
33109
- 'button',
33110
- {
33111
- type: 'button',
33112
- className: 'qsm__tab '.concat(qsmType == PortalQsmType.AccommodationAndFlight ? 'qsm__tab--active' : ''),
33113
- onClick: function () {
33114
- return handleQsmTypeChange(PortalQsmType.AccommodationAndFlight);
33115
- }
33116
- },
33117
- React__default.createElement(
33118
- 'span',
33119
- { className: 'qsm__tab__icons' },
33120
- React__default.createElement(Icon$2, { name: 'ui-backforward', height: 14 }),
33121
- '+',
33122
- React__default.createElement(Icon$2, { name: 'ui-bed', height: 14 })
33123
- ),
33124
- translations.QSM.TRANSPORT_HOTEL
33125
- ),
33126
- React__default.createElement(
33127
- 'button',
33128
- {
33129
- type: 'button',
33130
- className: 'qsm__tab '.concat(qsmType == PortalQsmType.Accommodation ? 'qsm__tab--active' : ''),
33131
- onClick: function () {
33132
- return handleQsmTypeChange(PortalQsmType.Accommodation);
33133
- }
33134
- },
33135
- React__default.createElement('span', { className: 'qsm__tab__icons' }, React__default.createElement(Icon$2, { name: 'ui-bed', height: 16 })),
33136
- translations.QSM.ACCOMMODATION
33137
- ),
33138
- React__default.createElement(
33139
- 'button',
33140
- {
33141
- type: 'button',
33142
- className: 'qsm__tab '.concat(qsmType == PortalQsmType.Flight ? 'qsm__tab--active' : ''),
33143
- onClick: function () {
33144
- return handleQsmTypeChange(PortalQsmType.Flight);
33145
- }
33146
- },
33147
- React__default.createElement('span', { className: 'qsm__tab__icons' }, React__default.createElement(Icon$2, { name: 'ui-flight', height: 16 })),
33148
- translations.QSM.TRANSPORTS
33149
- ),
33150
- React__default.createElement(
33151
- 'button',
33152
- {
33153
- type: 'button',
33154
- className: 'qsm__tab '.concat(qsmType == PortalQsmType.GroupTour ? 'qsm__tab--active' : ''),
33155
- onClick: function () {
33156
- return handleQsmTypeChange(PortalQsmType.GroupTour);
33157
- }
33158
- },
33159
- React__default.createElement('span', { className: 'qsm__tab__icons' }, React__default.createElement(Icon$2, { name: 'ui-group', height: 16 })),
33160
- translations.QSM.GROUP_TOUR
33161
- ),
33162
- React__default.createElement(
33163
- 'button',
33164
- {
33165
- type: 'button',
33166
- className: 'qsm__tab '.concat(qsmType == PortalQsmType.Ticket ? 'qsm__tab--active' : ''),
33167
- onClick: function () {
33168
- return handleQsmTypeChange(PortalQsmType.Ticket);
33169
- }
33170
- },
33171
- React__default.createElement('span', { className: 'qsm__tab__icons' }, React__default.createElement(Icon$2, { name: 'ui-ticket', height: 16 })),
33172
- translations.QSM.TICKET_ONLY
33173
- ),
33174
- React__default.createElement(
33175
- 'button',
33176
- {
33177
- type: 'button',
33178
- className: 'qsm__tab '.concat(qsmType == PortalQsmType.Car ? 'qsm__tab--active' : ''),
33179
- onClick: function () {
33180
- return handleQsmTypeChange(PortalQsmType.Car);
33181
- }
33182
- },
33183
- React__default.createElement('span', { className: 'qsm__tab__icons' }, React__default.createElement(Icon$2, { name: 'ui-car', height: 16 })),
33184
- translations.QSM.RENT_A_CAR
33185
- ),
33186
- React__default.createElement(
33187
- 'button',
33188
- {
33189
- type: 'button',
33190
- className: 'qsm__tab '.concat(qsmType == PortalQsmType.Transfer ? 'qsm__tab--active' : ''),
33191
- onClick: function () {
33192
- return handleQsmTypeChange(PortalQsmType.Transfer);
33193
- }
33194
- },
33195
- React__default.createElement('span', { className: 'qsm__tab__icons' }, React__default.createElement(Icon$2, { name: 'ui-backforward', height: 16 })),
33196
- translations.QSM.TRANSFERS
33197
- ),
33198
- React__default.createElement(
33199
- 'button',
33200
- {
33201
- type: 'button',
33202
- className: 'qsm__tab '.concat(qsmType == PortalQsmType.Cruise ? 'qsm__tab--active' : ''),
33203
- onClick: function () {
33204
- return handleQsmTypeChange(PortalQsmType.Cruise);
33205
- }
33206
- },
33207
- React__default.createElement('span', { className: 'qsm__tab__icons' }, React__default.createElement(Icon$2, { name: 'ui-ship', height: 16 })),
33208
- translations.QSM.CRUISES
33209
- )
33158
+ searchConfigurations.map(function (searchConfig, index) {
33159
+ var meta = qsmTypeMeta[searchConfig.qsmType];
33160
+ if (!meta) return null; // safety guard
33161
+ return React__default.createElement(
33162
+ 'button',
33163
+ {
33164
+ key: 'qsm-type-'.concat(index),
33165
+ type: 'button',
33166
+ className: 'qsm__tab '.concat(qsmType === searchConfig.qsmType ? 'qsm__tab--active' : ''),
33167
+ onClick: function () {
33168
+ return handleQsmTypeChange(searchConfig.qsmType);
33169
+ }
33170
+ },
33171
+ React__default.createElement(
33172
+ 'span',
33173
+ { className: 'qsm__tab__icons' },
33174
+ Array.isArray(meta.icon)
33175
+ ? meta.icon.map(function (icon, i) {
33176
+ return React__default.createElement(Icon$2, { key: i, name: icon, height: 14 });
33177
+ })
33178
+ : React__default.createElement(Icon$2, { name: meta.icon, height: 16 })
33179
+ ),
33180
+ meta.label
33181
+ );
33182
+ })
33210
33183
  ),
33211
33184
  React__default.createElement(
33212
33185
  'div',
@@ -1,7 +1,9 @@
1
1
  import { ReactNode } from 'react';
2
2
  import { PortalQsmType, TravelClass, TravelType } from '../shared/types';
3
+ import { WebsiteConfigurationSearchConfiguration } from '@qite/tide-client';
3
4
  export interface QSMConfiguration {
4
5
  type?: PortalQsmType;
6
+ searchConfigurations: WebsiteConfigurationSearchConfiguration[];
5
7
  askRooms?: boolean;
6
8
  askTravelType?: boolean;
7
9
  allowOneWay?: boolean;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@qite/tide-booking-component",
3
- "version": "1.4.77",
3
+ "version": "1.4.79",
4
4
  "description": "React Booking wizard & Booking product component for Tide",
5
5
  "main": "build/build-cjs/index.js",
6
6
  "types": "build/build-cjs/src/index.d.ts",
@@ -51,7 +51,7 @@ const aggregatePricePerPaxType = (priceDetails: BookingPriceDetail[], requestRoo
51
51
  room.pax.forEach((pax) => {
52
52
  let paxType = 'ADULT';
53
53
  if (typeof pax.age === 'number') {
54
- if (pax.age <= 11) {
54
+ if (pax.age <= 11 && pax.age > 2) {
55
55
  paxType = 'CHILD';
56
56
  } else if (pax.age <= 2) {
57
57
  paxType = 'INFANT';
@@ -6,6 +6,7 @@ import ContactForm from '../../components/contact';
6
6
  import Slider from '../../components/slider';
7
7
  import { Nationality, QSMConfiguration, TypeaheadOption } from '../../../qsm/types';
8
8
  import QSM from '../../../qsm';
9
+ import { WebsiteConfigurationSearchConfiguration } from '@qite/tide-client';
9
10
 
10
11
  interface ContentPageSelfContainedProps {
11
12
  path: string;
@@ -52,8 +53,93 @@ const travelClasses = [
52
53
  { id: 8, label: 'First Class' }
53
54
  ];
54
55
 
56
+ const searchConfigurations: WebsiteConfigurationSearchConfiguration[] = [
57
+ {
58
+ id: 4,
59
+ name: 'Search Group tour',
60
+ icon: '',
61
+ defaultSearchType: 1,
62
+ serviceTypes: [0],
63
+ defaultCatalogueId: undefined,
64
+ defaultDuration: undefined,
65
+ fromDateAmount: 0,
66
+ fromDateAmountType: 0,
67
+ toDateAmount: 12,
68
+ toDateAmountType: 1,
69
+ enableManualPackaging: false,
70
+ allowFlights: false,
71
+ allowAccommodations: false,
72
+ allowCarRentals: false,
73
+ allowTransfers: false,
74
+ allowExcursions: false,
75
+ qsmType: 5
76
+ },
77
+ {
78
+ id: 5,
79
+ name: 'Search Hotels',
80
+ icon: '',
81
+ defaultSearchType: 0,
82
+ serviceTypes: [3],
83
+ defaultCatalogueId: undefined,
84
+ defaultDuration: undefined,
85
+ fromDateAmount: 1,
86
+ fromDateAmountType: 1,
87
+ toDateAmount: 7,
88
+ toDateAmountType: 0,
89
+ enableManualPackaging: false,
90
+ allowFlights: false,
91
+ allowAccommodations: false,
92
+ allowCarRentals: false,
93
+ allowTransfers: false,
94
+ allowExcursions: false,
95
+ qsmType: 1
96
+ },
97
+ {
98
+ id: 6,
99
+ name: 'Search Flights',
100
+ icon: '',
101
+ defaultSearchType: 3,
102
+ serviceTypes: [7],
103
+ defaultCatalogueId: undefined,
104
+ defaultDuration: undefined,
105
+ fromDateAmount: 1,
106
+ fromDateAmountType: 1,
107
+ toDateAmount: 7,
108
+ toDateAmountType: 0,
109
+ enableManualPackaging: false,
110
+ allowFlights: false,
111
+ allowAccommodations: false,
112
+ allowCarRentals: false,
113
+ allowTransfers: false,
114
+ allowExcursions: false,
115
+ qsmType: 3
116
+ },
117
+ {
118
+ id: 7,
119
+ name: 'Transport + hotel',
120
+ icon: '',
121
+ defaultSearchType: 0,
122
+ serviceTypes: [0],
123
+ defaultCatalogueId: undefined,
124
+ defaultDuration: undefined,
125
+ fromDateAmount: 1,
126
+ fromDateAmountType: 1,
127
+ toDateAmount: 7,
128
+ toDateAmountType: 0,
129
+ enableManualPackaging: true,
130
+ allowFlights: true,
131
+ allowAccommodations: true,
132
+ allowCarRentals: false,
133
+ allowTransfers: false,
134
+ allowExcursions: false,
135
+ qsmType: 2
136
+ }
137
+ ];
138
+
55
139
  let configuration: QSMConfiguration = {
56
140
  type: PortalQsmType.Accommodation,
141
+ searchConfigurations: searchConfigurations,
142
+
57
143
  askTravelers: true,
58
144
  askNationality: true,
59
145
  askTravelClass: true,
@@ -18,6 +18,7 @@ import { QSMState, setFromDate, setSelectedQsmType, setToDate, setTripType } fro
18
18
  import { BaseFieldConfig, DoubleFieldConfig } from '../../types';
19
19
  import { getTranslations } from '../../../shared/utils/localization-util';
20
20
  import { PortalQsmType } from '../../../shared/types';
21
+ import { DateAmountType } from '@qite/tide-client';
21
22
 
22
23
  const QSMContainer: React.FC = () => {
23
24
  const dispatch = useDispatch();
@@ -40,7 +41,8 @@ const QSMContainer: React.FC = () => {
40
41
  destination,
41
42
  allowOneWay,
42
43
  allowRoundtrip,
43
- allowOpenJaw
44
+ allowOpenJaw,
45
+ searchConfigurations
44
46
  } = useContext(QSMConfigurationContext);
45
47
  const translations = getTranslations(languageCode ?? 'en-GB');
46
48
 
@@ -80,14 +82,41 @@ const QSMContainer: React.FC = () => {
80
82
  const handleQsmTypeChange = (value: PortalQsmType) => {
81
83
  dispatch(setSelectedQsmType(value));
82
84
 
83
- let startDate = addMonths(new Date(), 1);
84
- let endDate = addDays(startDate, 7);
85
+ const now = new Date();
85
86
 
87
+ // Default fallback
88
+ let startDate = addMonths(now, 1);
89
+ let endDate = addDays(startDate, 7);
86
90
  if (value === PortalQsmType.GroupTour) {
87
- startDate = new Date();
91
+ startDate = now;
88
92
  endDate = addYears(startDate, 1);
89
93
  }
90
94
 
95
+ const searchConfig = searchConfigurations.find((config) => config.qsmType === value);
96
+
97
+ if (searchConfig) {
98
+ const applyAmount = (baseDate: Date, type: DateAmountType, amount?: number) => {
99
+ if (!amount || type == null) return baseDate;
100
+
101
+ switch (type) {
102
+ case DateAmountType.days:
103
+ return addDays(baseDate, amount);
104
+ case DateAmountType.months:
105
+ return addMonths(baseDate, amount);
106
+ default:
107
+ return baseDate;
108
+ }
109
+ };
110
+
111
+ if (searchConfig.fromDateAmount) {
112
+ startDate = applyAmount(now, searchConfig.fromDateAmountType, searchConfig.fromDateAmount);
113
+ }
114
+
115
+ if (searchConfig.toDateAmount) {
116
+ endDate = applyAmount(startDate, searchConfig.toDateAmountType, searchConfig.toDateAmount);
117
+ }
118
+ }
119
+
91
120
  handleDateChange({
92
121
  fromDate: startDate,
93
122
  toDate: endDate
@@ -180,10 +209,77 @@ const QSMContainer: React.FC = () => {
180
209
  };
181
210
  }, [fromDate, toDate, departureAirport, returnAirport, allowOpenJaw]);
182
211
 
212
+ const qsmTypeMeta: Record<PortalQsmType, { icon: string | string[]; label: string }> = {
213
+ [PortalQsmType.Multidestination]: {
214
+ icon: 'ui-location',
215
+ label: translations.QSM.MULTIDESTINATION
216
+ },
217
+ [PortalQsmType.Package]: {
218
+ icon: 'ui-suitcase',
219
+ label: translations.QSM.PACKAGES
220
+ },
221
+ [PortalQsmType.AccommodationAndFlight]: {
222
+ icon: ['ui-backforward', 'ui-bed'],
223
+ label: translations.QSM.TRANSPORT_HOTEL
224
+ },
225
+ [PortalQsmType.Accommodation]: {
226
+ icon: 'ui-bed',
227
+ label: translations.QSM.ACCOMMODATION
228
+ },
229
+ [PortalQsmType.Flight]: {
230
+ icon: 'ui-flight',
231
+ label: translations.QSM.TRANSPORTS
232
+ },
233
+ [PortalQsmType.GroupTour]: {
234
+ icon: 'ui-group',
235
+ label: translations.QSM.GROUP_TOUR
236
+ },
237
+ [PortalQsmType.RoundTrip]: {
238
+ icon: 'ui-group',
239
+ label: translations.QSM.ROUNDTRIP
240
+ },
241
+ [PortalQsmType.Ticket]: {
242
+ icon: 'ui-ticket',
243
+ label: translations.QSM.TICKET_ONLY
244
+ },
245
+ [PortalQsmType.Car]: {
246
+ icon: 'ui-car',
247
+ label: translations.QSM.RENT_A_CAR
248
+ },
249
+ [PortalQsmType.Transfer]: {
250
+ icon: 'ui-backforward',
251
+ label: translations.QSM.TRANSFERS
252
+ },
253
+ [PortalQsmType.Cruise]: {
254
+ icon: 'ui-ship',
255
+ label: translations.QSM.CRUISES
256
+ }
257
+ };
258
+
183
259
  return (
184
260
  <div className="qsm">
185
261
  <div className="qsm__content">
186
262
  <div className="qsm__tabs">
263
+ {searchConfigurations.map((searchConfig, index) => {
264
+ const meta = qsmTypeMeta[searchConfig.qsmType];
265
+
266
+ if (!meta) return null; // safety guard
267
+
268
+ return (
269
+ <button
270
+ key={`qsm-type-${index}`}
271
+ type="button"
272
+ className={`qsm__tab ${qsmType === searchConfig.qsmType ? 'qsm__tab--active' : ''}`}
273
+ onClick={() => handleQsmTypeChange(searchConfig.qsmType)}>
274
+ <span className="qsm__tab__icons">
275
+ {Array.isArray(meta.icon) ? meta.icon.map((icon, i) => <Icon key={i} name={icon} height={14} />) : <Icon name={meta.icon} height={16} />}
276
+ </span>
277
+
278
+ {meta.label}
279
+ </button>
280
+ );
281
+ })}
282
+ {/*
187
283
  <button
188
284
  type="button"
189
285
  className={`qsm__tab ${qsmType == PortalQsmType.Multidestination ? 'qsm__tab--active' : ''}`}
@@ -275,7 +371,7 @@ const QSMContainer: React.FC = () => {
275
371
  <Icon name="ui-ship" height={16} />
276
372
  </span>
277
373
  {translations.QSM.CRUISES}
278
- </button>
374
+ </button> */}
279
375
  </div>
280
376
  <div className="qsm__filter">
281
377
  {(qsmType === PortalQsmType.Accommodation || qsmType === PortalQsmType.AccommodationAndFlight || qsmType === PortalQsmType.GroupTour) && (
@@ -4,6 +4,7 @@ import { PortalQsmType } from '../shared/types';
4
4
 
5
5
  const QSMConfigurationContext = React.createContext<QSMConfiguration>({
6
6
  type: PortalQsmType.Accommodation,
7
+ searchConfigurations: [],
7
8
  askTravelers: false,
8
9
  askNationality: false,
9
10
  askTravelClass: false,
package/src/qsm/types.ts CHANGED
@@ -1,9 +1,12 @@
1
1
  import { ReactNode } from 'react';
2
2
  import { PortalQsmType, TravelClass, TravelType } from '../shared/types';
3
+ import { WebsiteConfigurationSearchConfiguration } from '@qite/tide-client';
3
4
 
4
5
  export interface QSMConfiguration {
5
6
  type?: PortalQsmType;
6
- // Type specification and dedicated parameters
7
+
8
+ searchConfigurations: WebsiteConfigurationSearchConfiguration[];
9
+
7
10
  askRooms?: boolean; // hotel || roundTrip
8
11
  askTravelType?: boolean; // hotel || roundTrip
9
12
  allowOneWay?: boolean; // flight