@qite/tide-components 1.0.8 → 1.0.10
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/build/build-cjs/index.js +585 -319
- package/build/build-cjs/src/booking-product/types.d.ts +10 -0
- package/build/build-cjs/src/search-results/components/itinerary/itinerary-utils.d.ts +12 -0
- package/build/build-cjs/src/search-results/types.d.ts +12 -0
- package/build/build-esm/index.js +586 -320
- package/build/build-esm/src/booking-product/types.d.ts +10 -0
- package/build/build-esm/src/search-results/components/itinerary/itinerary-utils.d.ts +12 -0
- package/build/build-esm/src/search-results/types.d.ts +12 -0
- package/package.json +2 -2
- package/styles/abstracts/_mixins.scss +74 -74
- package/styles/abstracts/_variables.scss +57 -57
- package/styles/base/_fonts.scss +2 -2
- package/styles/base/_normalize.scss +227 -227
- package/styles/base/_typography.scss +35 -35
- package/styles/booking-joker-variables.scss +596 -596
- package/styles/booking-product-variables.scss +330 -330
- package/styles/booking-product.scss +438 -438
- package/styles/booking-qsm-variables.scss +501 -501
- package/styles/booking-qsm.scss +52 -52
- package/styles/booking-search-results-variables.scss +734 -734
- package/styles/booking-search-results.scss +53 -53
- package/styles/booking-wizard-variables.scss +603 -603
- package/styles/booking-wizard.scss +61 -61
- package/styles/components/_accordion.scss +67 -67
- package/styles/components/_animations.scss +39 -39
- package/styles/components/_base.scss +107 -107
- package/styles/components/_booking.scss +906 -906
- package/styles/components/_breadcrumb.scss +92 -92
- package/styles/components/_button.scss +238 -238
- package/styles/components/_checkbox.scss +230 -230
- package/styles/components/_contact.scss +255 -255
- package/styles/components/_content.scss +336 -336
- package/styles/components/_cta.scss +238 -238
- package/styles/components/_date-list.scss +41 -41
- package/styles/components/_date-range-picker.scss +223 -223
- package/styles/components/_decrement-increment.scss +35 -35
- package/styles/components/_dropdown.scss +77 -77
- package/styles/components/_error.scss +50 -50
- package/styles/components/_faq.scss +30 -30
- package/styles/components/_flight-option.scss +1432 -1432
- package/styles/components/_flyin.scss +830 -830
- package/styles/components/_footer.scss +135 -135
- package/styles/components/_form.scss +1693 -1693
- package/styles/components/_gallery.scss +317 -317
- package/styles/components/_header.scss +113 -113
- package/styles/components/_image-with-text.scss +206 -206
- package/styles/components/_img-slider.scss +175 -175
- package/styles/components/_info-message.scss +75 -75
- package/styles/components/_input.scss +35 -35
- package/styles/components/_list.scss +185 -185
- package/styles/components/_loader.scss +152 -152
- package/styles/components/_login.scss +140 -140
- package/styles/components/_map-view.scss +1100 -1100
- package/styles/components/_mixins.scss +579 -579
- package/styles/components/_navbar.scss +765 -765
- package/styles/components/_passenger-picker.scss +306 -306
- package/styles/components/_phone-input.scss +8 -8
- package/styles/components/_placeholders.scss +165 -165
- package/styles/components/_pricing-summary.scss +163 -163
- package/styles/components/_qsm.scss +17 -17
- package/styles/components/_radiobutton.scss +170 -170
- package/styles/components/_search.scss +2197 -2178
- package/styles/components/_select-wrapper.scss +81 -81
- package/styles/components/_slider.scss +128 -128
- package/styles/components/_spinner.scss +29 -29
- package/styles/components/_step-indicators.scss +187 -187
- package/styles/components/_table.scss +81 -81
- package/styles/components/_tide-form.scss +578 -578
- package/styles/components/_tree.scss +648 -648
- package/styles/components/_typeahead.scss +275 -275
- package/styles/components/_variables.scss +89 -89
- package/styles/content-blocks-variables.scss +543 -543
- package/styles/content-blocks.scss +66 -66
- package/styles/font.scss +2 -2
- package/styles/qsm/_calendar.scss +274 -274
- package/styles/qsm/_qsm.scss +1097 -1097
- package/styles/search.scss +1200 -1200
- package/styles/tide-form-variables.scss +275 -275
- package/styles/tide-form.scss +56 -56
package/build/build-cjs/index.js
CHANGED
|
@@ -124,7 +124,7 @@ var PRODUCT$f = {
|
|
|
124
124
|
PER_PERSON_PER_NIGHT: "لكل شخص / لكل ليلة",
|
|
125
125
|
BOOK_NOW: "احجز الآن",
|
|
126
126
|
TO_YOUR_OFFER: "إلى عرضك",
|
|
127
|
-
NOT_AVAILABLE: "غير متاح",
|
|
127
|
+
NOT_AVAILABLE: "غير متاح — يرجى اختيار تاريخ آخر",
|
|
128
128
|
NUMBER_OF_ROOMS: "عدد الغرف",
|
|
129
129
|
AGE_BY_DEPARTURE_DATE: "عمر الأطفال عند تاريخ المغادرة",
|
|
130
130
|
YEAR: "سنة/سنوات",
|
|
@@ -417,6 +417,8 @@ var SRP$f = {
|
|
|
417
417
|
DEPARTURE_ASC: "تاريخ المغادرة (الأقرب أولاً)",
|
|
418
418
|
FILTERS: "عوامل التصفية",
|
|
419
419
|
SHOW_ITINERARY: "عرض خط سير الرحلة",
|
|
420
|
+
VIEW_FULL_ITINERARY: "عرض خط السير الكامل",
|
|
421
|
+
SHOW_SERVICES: "عرض الخدمات",
|
|
420
422
|
VIEW_BOOKING: "عرض الحجز",
|
|
421
423
|
ITINERARY_TITLE: "ملخص رحلتك",
|
|
422
424
|
DOSSIER_NUMBER: "رقم الملف",
|
|
@@ -466,7 +468,7 @@ var SRP$f = {
|
|
|
466
468
|
};
|
|
467
469
|
var ITINERARY$f = {
|
|
468
470
|
DAY: "اليوم",
|
|
469
|
-
NO_ITEMS: "
|
|
471
|
+
NO_ITEMS: "لم يتم اختيار أنشطة لهذا اليوم."
|
|
470
472
|
};
|
|
471
473
|
var FORM$f = {
|
|
472
474
|
LOADING: "جاري تحميل النموذج...",
|
|
@@ -569,7 +571,7 @@ var PRODUCT$e = {
|
|
|
569
571
|
PER_PERSON_PER_NIGHT: "Per person / per nat",
|
|
570
572
|
BOOK_NOW: "Book nu",
|
|
571
573
|
TO_YOUR_OFFER: "Til dit tilbud",
|
|
572
|
-
NOT_AVAILABLE: "Ikke tilgængelig",
|
|
574
|
+
NOT_AVAILABLE: "Ikke tilgængelig — vælg venligst en anden dato",
|
|
573
575
|
NUMBER_OF_ROOMS: "Antal værelser",
|
|
574
576
|
AGE_BY_DEPARTURE_DATE: "Børns alder på afrejsedato",
|
|
575
577
|
YEAR: "år",
|
|
@@ -862,6 +864,8 @@ var SRP$e = {
|
|
|
862
864
|
DEPARTURE_ASC: "Afrejsedato (snarest først)",
|
|
863
865
|
FILTERS: "Filtre",
|
|
864
866
|
SHOW_ITINERARY: "Vis rejseplan",
|
|
867
|
+
VIEW_FULL_ITINERARY: "Se hele rejseplanen",
|
|
868
|
+
SHOW_SERVICES: "Vis ydelser",
|
|
865
869
|
VIEW_BOOKING: "Se booking",
|
|
866
870
|
ITINERARY_TITLE: "Din rejseoversigt",
|
|
867
871
|
DOSSIER_NUMBER: "Sagsnummer",
|
|
@@ -911,7 +915,7 @@ var SRP$e = {
|
|
|
911
915
|
};
|
|
912
916
|
var ITINERARY$e = {
|
|
913
917
|
DAY: "Dag",
|
|
914
|
-
NO_ITEMS: "Ingen
|
|
918
|
+
NO_ITEMS: "Ingen aktiviteter valgt for denne dag."
|
|
915
919
|
};
|
|
916
920
|
var FORM$e = {
|
|
917
921
|
LOADING: "Indlæser formular...",
|
|
@@ -1014,7 +1018,7 @@ var PRODUCT$d = {
|
|
|
1014
1018
|
PER_PERSON_PER_NIGHT: "Pro Person / pro Nacht",
|
|
1015
1019
|
BOOK_NOW: "Jetzt buchen",
|
|
1016
1020
|
TO_YOUR_OFFER: "Zu Ihrem Angebot",
|
|
1017
|
-
NOT_AVAILABLE: "Nicht verfügbar",
|
|
1021
|
+
NOT_AVAILABLE: "Nicht verfügbar — bitte wählen Sie ein anderes Datum",
|
|
1018
1022
|
NUMBER_OF_ROOMS: "Anzahl der Zimmer",
|
|
1019
1023
|
AGE_BY_DEPARTURE_DATE: "Alter der Kinder am Abreisedatum",
|
|
1020
1024
|
YEAR: "Jahr(e)",
|
|
@@ -1311,6 +1315,8 @@ var SRP$d = {
|
|
|
1311
1315
|
DEPARTURE_ASC: "Abreisedatum (früheste zuerst)",
|
|
1312
1316
|
FILTERS: "Filter",
|
|
1313
1317
|
SHOW_ITINERARY: "Reiseverlauf anzeigen",
|
|
1318
|
+
VIEW_FULL_ITINERARY: "Vollständigen Reiseverlauf ansehen",
|
|
1319
|
+
SHOW_SERVICES: "Leistungen anzeigen",
|
|
1314
1320
|
VIEW_BOOKING: "Buchung anzeigen",
|
|
1315
1321
|
ITINERARY_TITLE: "Ihre Reiseübersicht",
|
|
1316
1322
|
DOSSIER_NUMBER: "Vorgangsnummer",
|
|
@@ -1356,7 +1362,7 @@ var SRP$d = {
|
|
|
1356
1362
|
};
|
|
1357
1363
|
var ITINERARY$d = {
|
|
1358
1364
|
DAY: "Tag",
|
|
1359
|
-
NO_ITEMS: "Keine
|
|
1365
|
+
NO_ITEMS: "Keine Aktivitäten für diesen Tag ausgewählt."
|
|
1360
1366
|
};
|
|
1361
1367
|
var FORM$d = {
|
|
1362
1368
|
LOADING: "Formular wird geladen...",
|
|
@@ -1459,7 +1465,7 @@ var PRODUCT$c = {
|
|
|
1459
1465
|
PER_PERSON_PER_NIGHT: "Per person / per night",
|
|
1460
1466
|
BOOK_NOW: "Book now",
|
|
1461
1467
|
TO_YOUR_OFFER: "To your quote",
|
|
1462
|
-
NOT_AVAILABLE: "Not available",
|
|
1468
|
+
NOT_AVAILABLE: "Not available — please select a different date",
|
|
1463
1469
|
NUMBER_OF_ROOMS: "Number of rooms",
|
|
1464
1470
|
AGE_BY_DEPARTURE_DATE: "Age of children on departure date",
|
|
1465
1471
|
YEAR: "Year(s)",
|
|
@@ -1760,6 +1766,8 @@ var SRP$c = {
|
|
|
1760
1766
|
DEPARTURE_ASC: "Departure date (soonest first)",
|
|
1761
1767
|
FILTERS: "Filters",
|
|
1762
1768
|
SHOW_ITINERARY: "Show itinerary",
|
|
1769
|
+
VIEW_FULL_ITINERARY: "View full itinerary",
|
|
1770
|
+
SHOW_SERVICES: "Show services",
|
|
1763
1771
|
VIEW_BOOKING: "View booking",
|
|
1764
1772
|
ITINERARY_TITLE: "Your trip summary",
|
|
1765
1773
|
DOSSIER_NUMBER: "File number",
|
|
@@ -1805,7 +1813,7 @@ var SRP$c = {
|
|
|
1805
1813
|
};
|
|
1806
1814
|
var ITINERARY$c = {
|
|
1807
1815
|
DAY: "Day",
|
|
1808
|
-
NO_ITEMS: "No
|
|
1816
|
+
NO_ITEMS: "No activities selected for this day."
|
|
1809
1817
|
};
|
|
1810
1818
|
var FORM$c = {
|
|
1811
1819
|
LOADING: "Loading form...",
|
|
@@ -1908,7 +1916,7 @@ var PRODUCT$b = {
|
|
|
1908
1916
|
PER_PERSON_PER_NIGHT: "Por persona / por noche",
|
|
1909
1917
|
BOOK_NOW: "Reservar ahora",
|
|
1910
1918
|
TO_YOUR_OFFER: "A su presupuesto",
|
|
1911
|
-
NOT_AVAILABLE: "No disponible",
|
|
1919
|
+
NOT_AVAILABLE: "No disponible — seleccione otra fecha",
|
|
1912
1920
|
NUMBER_OF_ROOMS: "Número de habitaciones",
|
|
1913
1921
|
AGE_BY_DEPARTURE_DATE: "Edad de los niños en la fecha de salida",
|
|
1914
1922
|
YEAR: "Año(s)",
|
|
@@ -2205,6 +2213,8 @@ var SRP$b = {
|
|
|
2205
2213
|
DEPARTURE_ASC: "Fecha de salida (más próxima primero)",
|
|
2206
2214
|
FILTERS: "Filtros",
|
|
2207
2215
|
SHOW_ITINERARY: "Mostrar itinerario",
|
|
2216
|
+
VIEW_FULL_ITINERARY: "Ver itinerario completo",
|
|
2217
|
+
SHOW_SERVICES: "Ver servicios",
|
|
2208
2218
|
VIEW_BOOKING: "Ver reserva",
|
|
2209
2219
|
ITINERARY_TITLE: "Resumen de tu viaje",
|
|
2210
2220
|
DOSSIER_NUMBER: "Número de expediente",
|
|
@@ -2250,7 +2260,7 @@ var SRP$b = {
|
|
|
2250
2260
|
};
|
|
2251
2261
|
var ITINERARY$b = {
|
|
2252
2262
|
DAY: "Día",
|
|
2253
|
-
NO_ITEMS: "No hay
|
|
2263
|
+
NO_ITEMS: "No hay actividades seleccionadas para este día."
|
|
2254
2264
|
};
|
|
2255
2265
|
var FORM$b = {
|
|
2256
2266
|
LOADING: "Cargando formulario...",
|
|
@@ -2353,7 +2363,7 @@ var PRODUCT$a = {
|
|
|
2353
2363
|
PER_PERSON_PER_NIGHT: "Par personne / par nuit",
|
|
2354
2364
|
BOOK_NOW: "Réserver maintenant",
|
|
2355
2365
|
TO_YOUR_OFFER: "Vers votre devis",
|
|
2356
|
-
NOT_AVAILABLE: "Non disponible",
|
|
2366
|
+
NOT_AVAILABLE: "Non disponible — veuillez sélectionner une autre date",
|
|
2357
2367
|
NUMBER_OF_ROOMS: "Nombre de chambres",
|
|
2358
2368
|
AGE_BY_DEPARTURE_DATE: "Âge des enfants à la date de départ",
|
|
2359
2369
|
YEAR: "An(s)",
|
|
@@ -2654,6 +2664,8 @@ var SRP$a = {
|
|
|
2654
2664
|
DEPARTURE_ASC: "Date de départ (la plus proche d’abord)",
|
|
2655
2665
|
FILTERS: "Filtres",
|
|
2656
2666
|
SHOW_ITINERARY: "Afficher l’itinéraire",
|
|
2667
|
+
VIEW_FULL_ITINERARY: "Voir l'itinéraire complet",
|
|
2668
|
+
SHOW_SERVICES: "Voir les services",
|
|
2657
2669
|
VIEW_BOOKING: "Voir la réservation",
|
|
2658
2670
|
ITINERARY_TITLE: "Résumé de votre voyage",
|
|
2659
2671
|
DOSSIER_NUMBER: "Numéro de dossier",
|
|
@@ -2699,7 +2711,7 @@ var SRP$a = {
|
|
|
2699
2711
|
};
|
|
2700
2712
|
var ITINERARY$a = {
|
|
2701
2713
|
DAY: "Jour",
|
|
2702
|
-
NO_ITEMS: "
|
|
2714
|
+
NO_ITEMS: "Aucune activité sélectionnée pour ce jour."
|
|
2703
2715
|
};
|
|
2704
2716
|
var FORM$a = {
|
|
2705
2717
|
LOADING: "Chargement du formulaire...",
|
|
@@ -2802,7 +2814,7 @@ var PRODUCT$9 = {
|
|
|
2802
2814
|
PER_PERSON_PER_NIGHT: "Par personne / par nuit",
|
|
2803
2815
|
BOOK_NOW: "Réservez maintenant",
|
|
2804
2816
|
TO_YOUR_OFFER: "Vers votre devis",
|
|
2805
|
-
NOT_AVAILABLE: "Indisponible",
|
|
2817
|
+
NOT_AVAILABLE: "Indisponible — veuillez sélectionner une autre date",
|
|
2806
2818
|
NUMBER_OF_ROOMS: "Nombre de chambres",
|
|
2807
2819
|
AGE_BY_DEPARTURE_DATE: "Âge des enfants à la date de départ",
|
|
2808
2820
|
YEAR: "An(s)",
|
|
@@ -3099,6 +3111,8 @@ var SRP$9 = {
|
|
|
3099
3111
|
DEPARTURE_ASC: "Date de départ (la plus proche d’abord)",
|
|
3100
3112
|
FILTERS: "Filtres",
|
|
3101
3113
|
SHOW_ITINERARY: "Afficher l’itinéraire",
|
|
3114
|
+
VIEW_FULL_ITINERARY: "Voir l'itinéraire complet",
|
|
3115
|
+
SHOW_SERVICES: "Voir les services",
|
|
3102
3116
|
VIEW_BOOKING: "Voir la réservation",
|
|
3103
3117
|
ITINERARY_TITLE: "Résumé de votre voyage",
|
|
3104
3118
|
DOSSIER_NUMBER: "Numéro de dossier",
|
|
@@ -3144,7 +3158,7 @@ var SRP$9 = {
|
|
|
3144
3158
|
};
|
|
3145
3159
|
var ITINERARY$9 = {
|
|
3146
3160
|
DAY: "Jour",
|
|
3147
|
-
NO_ITEMS: "
|
|
3161
|
+
NO_ITEMS: "Aucune activité sélectionnée pour ce jour."
|
|
3148
3162
|
};
|
|
3149
3163
|
var FORM$9 = {
|
|
3150
3164
|
LOADING: "Chargement du formulaire...",
|
|
@@ -3247,7 +3261,7 @@ var PRODUCT$8 = {
|
|
|
3247
3261
|
PER_PERSON_PER_NIGHT: "Á mann / á nótt",
|
|
3248
3262
|
BOOK_NOW: "Panta núna",
|
|
3249
3263
|
TO_YOUR_OFFER: "Til tilboðsins þíns",
|
|
3250
|
-
NOT_AVAILABLE: "Ekki í boði",
|
|
3264
|
+
NOT_AVAILABLE: "Ekki í boði — vinsamlegast veldu aðra dagsetningu",
|
|
3251
3265
|
NUMBER_OF_ROOMS: "Fjöldi herbergja",
|
|
3252
3266
|
AGE_BY_DEPARTURE_DATE: "Aldur barna á brottfarardegi",
|
|
3253
3267
|
YEAR: "ár",
|
|
@@ -3544,6 +3558,8 @@ var SRP$8 = {
|
|
|
3544
3558
|
DEPARTURE_ASC: "Brottfarardagur (nærst fyrst)",
|
|
3545
3559
|
FILTERS: "Síur",
|
|
3546
3560
|
SHOW_ITINERARY: "Sýna ferðaráætlun",
|
|
3561
|
+
VIEW_FULL_ITINERARY: "Skoða alla ferðaáætlunina",
|
|
3562
|
+
SHOW_SERVICES: "Sýna þjónustu",
|
|
3547
3563
|
VIEW_BOOKING: "Skoða bókun",
|
|
3548
3564
|
ITINERARY_TITLE: "Yfirlit ferðarinnar",
|
|
3549
3565
|
DOSSIER_NUMBER: "Skrárnúmer",
|
|
@@ -3589,7 +3605,7 @@ var SRP$8 = {
|
|
|
3589
3605
|
};
|
|
3590
3606
|
var ITINERARY$8 = {
|
|
3591
3607
|
DAY: "Dagur",
|
|
3592
|
-
NO_ITEMS: "
|
|
3608
|
+
NO_ITEMS: "Engin afþreying valin fyrir þennan dag."
|
|
3593
3609
|
};
|
|
3594
3610
|
var FORM$8 = {
|
|
3595
3611
|
LOADING: "Hleður eyðublað...",
|
|
@@ -3692,7 +3708,7 @@ var PRODUCT$7 = {
|
|
|
3692
3708
|
PER_PERSON_PER_NIGHT: "A persona / a notte",
|
|
3693
3709
|
BOOK_NOW: "Prenota ora",
|
|
3694
3710
|
TO_YOUR_OFFER: "Vai al preventivo",
|
|
3695
|
-
NOT_AVAILABLE: "Non disponibile",
|
|
3711
|
+
NOT_AVAILABLE: "Non disponibile — seleziona un'altra data",
|
|
3696
3712
|
NUMBER_OF_ROOMS: "Numero di camere",
|
|
3697
3713
|
AGE_BY_DEPARTURE_DATE: "Età dei bambini alla data di partenza",
|
|
3698
3714
|
YEAR: "Anno/i",
|
|
@@ -3989,6 +4005,8 @@ var SRP$7 = {
|
|
|
3989
4005
|
DEPARTURE_ASC: "Data di partenza (prima la più vicina)",
|
|
3990
4006
|
FILTERS: "Filtri",
|
|
3991
4007
|
SHOW_ITINERARY: "Mostra itinerario",
|
|
4008
|
+
VIEW_FULL_ITINERARY: "Vedi l'itinerario completo",
|
|
4009
|
+
SHOW_SERVICES: "Mostra i servizi",
|
|
3992
4010
|
VIEW_BOOKING: "Visualizza prenotazione",
|
|
3993
4011
|
ITINERARY_TITLE: "Riepilogo del tuo viaggio",
|
|
3994
4012
|
DOSSIER_NUMBER: "Numero di pratica",
|
|
@@ -4034,7 +4052,7 @@ var SRP$7 = {
|
|
|
4034
4052
|
};
|
|
4035
4053
|
var ITINERARY$7 = {
|
|
4036
4054
|
DAY: "Giorno",
|
|
4037
|
-
NO_ITEMS: "
|
|
4055
|
+
NO_ITEMS: "Nessuna attività selezionata per questo giorno."
|
|
4038
4056
|
};
|
|
4039
4057
|
var FORM$7 = {
|
|
4040
4058
|
LOADING: "Caricamento modulo...",
|
|
@@ -4137,7 +4155,7 @@ var PRODUCT$6 = {
|
|
|
4137
4155
|
PER_PERSON_PER_NIGHT: "Per persoon / per nacht",
|
|
4138
4156
|
BOOK_NOW: "Boek nu",
|
|
4139
4157
|
TO_YOUR_OFFER: "Naar uw offerte",
|
|
4140
|
-
NOT_AVAILABLE: "Niet beschikbaar",
|
|
4158
|
+
NOT_AVAILABLE: "Niet beschikbaar — kies een andere datum",
|
|
4141
4159
|
NUMBER_OF_ROOMS: "Aantal kamers",
|
|
4142
4160
|
AGE_BY_DEPARTURE_DATE: "Leeftijd kinderen op vertrekdatum",
|
|
4143
4161
|
YEAR: "Jaar",
|
|
@@ -4438,6 +4456,8 @@ var SRP$6 = {
|
|
|
4438
4456
|
DEPARTURE_ASC: "Vertrekdatum (dichtstbij eerst)",
|
|
4439
4457
|
FILTERS: "Filters",
|
|
4440
4458
|
SHOW_ITINERARY: "Toon reisplan",
|
|
4459
|
+
VIEW_FULL_ITINERARY: "Bekijk volledige reisroute",
|
|
4460
|
+
SHOW_SERVICES: "Toon diensten",
|
|
4441
4461
|
VIEW_BOOKING: "Bekijk boeking",
|
|
4442
4462
|
ITINERARY_TITLE: "Overzicht van je reis",
|
|
4443
4463
|
DOSSIER_NUMBER: "Dossiernummer",
|
|
@@ -4483,7 +4503,7 @@ var SRP$6 = {
|
|
|
4483
4503
|
};
|
|
4484
4504
|
var ITINERARY$6 = {
|
|
4485
4505
|
DAY: "Dag",
|
|
4486
|
-
NO_ITEMS: "Geen
|
|
4506
|
+
NO_ITEMS: "Geen activiteiten geselecteerd voor deze dag."
|
|
4487
4507
|
};
|
|
4488
4508
|
var FORM$6 = {
|
|
4489
4509
|
LOADING: "Formulier laden...",
|
|
@@ -4586,7 +4606,7 @@ var PRODUCT$5 = {
|
|
|
4586
4606
|
PER_PERSON_PER_NIGHT: "Per persoon / per nacht",
|
|
4587
4607
|
BOOK_NOW: "Nu boeken",
|
|
4588
4608
|
TO_YOUR_OFFER: "Naar uw offerte",
|
|
4589
|
-
NOT_AVAILABLE: "Niet beschikbaar",
|
|
4609
|
+
NOT_AVAILABLE: "Niet beschikbaar — kies een andere datum",
|
|
4590
4610
|
NUMBER_OF_ROOMS: "Aantal kamers",
|
|
4591
4611
|
AGE_BY_DEPARTURE_DATE: "Leeftijd van kinderen op vertrekdatum",
|
|
4592
4612
|
YEAR: "Jaar",
|
|
@@ -4883,6 +4903,8 @@ var SRP$5 = {
|
|
|
4883
4903
|
DEPARTURE_ASC: "Vertrekdatum (dichtstbij eerst)",
|
|
4884
4904
|
FILTERS: "Filters",
|
|
4885
4905
|
SHOW_ITINERARY: "Toon reisplan",
|
|
4906
|
+
VIEW_FULL_ITINERARY: "Bekijk volledige reisroute",
|
|
4907
|
+
SHOW_SERVICES: "Toon diensten",
|
|
4886
4908
|
VIEW_BOOKING: "Bekijk boeking",
|
|
4887
4909
|
ITINERARY_TITLE: "Overzicht van je reis",
|
|
4888
4910
|
DOSSIER_NUMBER: "Dossiernummer",
|
|
@@ -4928,7 +4950,7 @@ var SRP$5 = {
|
|
|
4928
4950
|
};
|
|
4929
4951
|
var ITINERARY$5 = {
|
|
4930
4952
|
DAY: "Dag",
|
|
4931
|
-
NO_ITEMS: "Geen
|
|
4953
|
+
NO_ITEMS: "Geen activiteiten geselecteerd voor deze dag."
|
|
4932
4954
|
};
|
|
4933
4955
|
var FORM$5 = {
|
|
4934
4956
|
LOADING: "Formulier laden...",
|
|
@@ -5031,7 +5053,7 @@ var PRODUCT$4 = {
|
|
|
5031
5053
|
PER_PERSON_PER_NIGHT: "Per person / per natt",
|
|
5032
5054
|
BOOK_NOW: "Bestill nå",
|
|
5033
5055
|
TO_YOUR_OFFER: "Til ditt tilbud",
|
|
5034
|
-
NOT_AVAILABLE: "Ikke tilgjengelig",
|
|
5056
|
+
NOT_AVAILABLE: "Ikke tilgjengelig — velg en annen dato",
|
|
5035
5057
|
NUMBER_OF_ROOMS: "Antall rom",
|
|
5036
5058
|
AGE_BY_DEPARTURE_DATE: "Barnas alder på avreisedato",
|
|
5037
5059
|
YEAR: "År",
|
|
@@ -5328,6 +5350,8 @@ var SRP$4 = {
|
|
|
5328
5350
|
DEPARTURE_ASC: "Avreisedato (nærmeste først)",
|
|
5329
5351
|
FILTERS: "Filtre",
|
|
5330
5352
|
SHOW_ITINERARY: "Vis reiserute",
|
|
5353
|
+
VIEW_FULL_ITINERARY: "Se hele reiseruten",
|
|
5354
|
+
SHOW_SERVICES: "Vis tjenester",
|
|
5331
5355
|
VIEW_BOOKING: "Se bestilling",
|
|
5332
5356
|
ITINERARY_TITLE: "Din reisemåloversikt",
|
|
5333
5357
|
DOSSIER_NUMBER: "Saksnummer",
|
|
@@ -5373,7 +5397,7 @@ var SRP$4 = {
|
|
|
5373
5397
|
};
|
|
5374
5398
|
var ITINERARY$4 = {
|
|
5375
5399
|
DAY: "Dag",
|
|
5376
|
-
NO_ITEMS: "Ingen
|
|
5400
|
+
NO_ITEMS: "Ingen aktiviteter valgt for denne dagen."
|
|
5377
5401
|
};
|
|
5378
5402
|
var FORM$4 = {
|
|
5379
5403
|
LOADING: "Laster inn skjema...",
|
|
@@ -5476,7 +5500,7 @@ var PRODUCT$3 = {
|
|
|
5476
5500
|
PER_PERSON_PER_NIGHT: "Za osobę / za noc",
|
|
5477
5501
|
BOOK_NOW: "Zarezerwuj teraz",
|
|
5478
5502
|
TO_YOUR_OFFER: "Do oferty",
|
|
5479
|
-
NOT_AVAILABLE: "Niedostępne",
|
|
5503
|
+
NOT_AVAILABLE: "Niedostępne — wybierz inną datę",
|
|
5480
5504
|
NUMBER_OF_ROOMS: "Liczba pokoi",
|
|
5481
5505
|
AGE_BY_DEPARTURE_DATE: "Wiek dzieci w dniu wyjazdu",
|
|
5482
5506
|
YEAR: "Rok(lata)",
|
|
@@ -5773,6 +5797,8 @@ var SRP$3 = {
|
|
|
5773
5797
|
DEPARTURE_ASC: "Data wyjazdu (najbliższa najpierw)",
|
|
5774
5798
|
FILTERS: "Filtry",
|
|
5775
5799
|
SHOW_ITINERARY: "Pokaż plan podróży",
|
|
5800
|
+
VIEW_FULL_ITINERARY: "Zobacz pełny plan podróży",
|
|
5801
|
+
SHOW_SERVICES: "Pokaż usługi",
|
|
5776
5802
|
VIEW_BOOKING: "Zobacz rezerwację",
|
|
5777
5803
|
ITINERARY_TITLE: "Podsumowanie Twojej podróży",
|
|
5778
5804
|
DOSSIER_NUMBER: "Numer pliku",
|
|
@@ -5818,7 +5844,7 @@ var SRP$3 = {
|
|
|
5818
5844
|
};
|
|
5819
5845
|
var ITINERARY$3 = {
|
|
5820
5846
|
DAY: "Dzień",
|
|
5821
|
-
NO_ITEMS: "
|
|
5847
|
+
NO_ITEMS: "Nie wybrano atrakcji na ten dzień."
|
|
5822
5848
|
};
|
|
5823
5849
|
var FORM$3 = {
|
|
5824
5850
|
LOADING: "Ładowanie formularza...",
|
|
@@ -5921,7 +5947,7 @@ var PRODUCT$2 = {
|
|
|
5921
5947
|
PER_PERSON_PER_NIGHT: "Por pessoa / por noite",
|
|
5922
5948
|
BOOK_NOW: "Reservar agora",
|
|
5923
5949
|
TO_YOUR_OFFER: "Ir para o orçamento",
|
|
5924
|
-
NOT_AVAILABLE: "Indisponível",
|
|
5950
|
+
NOT_AVAILABLE: "Indisponível — selecione outra data",
|
|
5925
5951
|
NUMBER_OF_ROOMS: "Número de quartos",
|
|
5926
5952
|
AGE_BY_DEPARTURE_DATE: "Idade das crianças à data de partida",
|
|
5927
5953
|
YEAR: "Ano(s)",
|
|
@@ -6218,6 +6244,8 @@ var SRP$2 = {
|
|
|
6218
6244
|
DEPARTURE_ASC: "Data de partida (mais próxima primeiro)",
|
|
6219
6245
|
FILTERS: "Filtros",
|
|
6220
6246
|
SHOW_ITINERARY: "Mostrar itinerário",
|
|
6247
|
+
VIEW_FULL_ITINERARY: "Ver itinerário completo",
|
|
6248
|
+
SHOW_SERVICES: "Ver serviços",
|
|
6221
6249
|
VIEW_BOOKING: "Ver reserva",
|
|
6222
6250
|
ITINERARY_TITLE: "Resumo da sua viagem",
|
|
6223
6251
|
DOSSIER_NUMBER: "Número do processo",
|
|
@@ -6263,7 +6291,7 @@ var SRP$2 = {
|
|
|
6263
6291
|
};
|
|
6264
6292
|
var ITINERARY$2 = {
|
|
6265
6293
|
DAY: "Dia",
|
|
6266
|
-
NO_ITEMS: "
|
|
6294
|
+
NO_ITEMS: "Nenhuma atividade selecionada para este dia."
|
|
6267
6295
|
};
|
|
6268
6296
|
var FORM$2 = {
|
|
6269
6297
|
LOADING: "A carregar formulário...",
|
|
@@ -6366,7 +6394,7 @@ var PRODUCT$1 = {
|
|
|
6366
6394
|
PER_PERSON_PER_NIGHT: "Per person / per natt",
|
|
6367
6395
|
BOOK_NOW: "Boka nu",
|
|
6368
6396
|
TO_YOUR_OFFER: "Till din offert",
|
|
6369
|
-
NOT_AVAILABLE: "Ej tillgänglig",
|
|
6397
|
+
NOT_AVAILABLE: "Ej tillgänglig — välj ett annat datum",
|
|
6370
6398
|
NUMBER_OF_ROOMS: "Antal rum",
|
|
6371
6399
|
AGE_BY_DEPARTURE_DATE: "Barnens ålder vid avresedatum",
|
|
6372
6400
|
YEAR: "År",
|
|
@@ -6663,6 +6691,8 @@ var SRP$1 = {
|
|
|
6663
6691
|
DEPARTURE_ASC: "Avresedatum (närmast först)",
|
|
6664
6692
|
FILTERS: "Filter",
|
|
6665
6693
|
SHOW_ITINERARY: "Visa resplan",
|
|
6694
|
+
VIEW_FULL_ITINERARY: "Visa hela resplanen",
|
|
6695
|
+
SHOW_SERVICES: "Visa tjänster",
|
|
6666
6696
|
VIEW_BOOKING: "Visa bokning",
|
|
6667
6697
|
ITINERARY_TITLE: "Din resesammanfattning",
|
|
6668
6698
|
DOSSIER_NUMBER: "Filnummer",
|
|
@@ -6708,7 +6738,7 @@ var SRP$1 = {
|
|
|
6708
6738
|
};
|
|
6709
6739
|
var ITINERARY$1 = {
|
|
6710
6740
|
DAY: "Dag",
|
|
6711
|
-
NO_ITEMS: "Inga
|
|
6741
|
+
NO_ITEMS: "Inga aktiviteter valda för denna dag."
|
|
6712
6742
|
};
|
|
6713
6743
|
var FORM$1 = {
|
|
6714
6744
|
LOADING: "Laddar formulär...",
|
|
@@ -6811,7 +6841,7 @@ var PRODUCT = {
|
|
|
6811
6841
|
PER_PERSON_PER_NIGHT: "1名・1泊あたり",
|
|
6812
6842
|
BOOK_NOW: "今すぐ予約",
|
|
6813
6843
|
TO_YOUR_OFFER: "見積もりへ",
|
|
6814
|
-
NOT_AVAILABLE: "利用不可",
|
|
6844
|
+
NOT_AVAILABLE: "利用不可 — 別の日付をお選びください",
|
|
6815
6845
|
NUMBER_OF_ROOMS: "客室数",
|
|
6816
6846
|
AGE_BY_DEPARTURE_DATE: "出発日時点での子供の年齢",
|
|
6817
6847
|
YEAR: "歳",
|
|
@@ -7108,6 +7138,8 @@ var SRP = {
|
|
|
7108
7138
|
DEPARTURE_ASC: "出発日(早い順)",
|
|
7109
7139
|
FILTERS: "フィルター",
|
|
7110
7140
|
SHOW_ITINERARY: "旅程を表示",
|
|
7141
|
+
VIEW_FULL_ITINERARY: "旅程の詳細を見る",
|
|
7142
|
+
SHOW_SERVICES: "サービスを表示",
|
|
7111
7143
|
VIEW_BOOKING: "予約を見る",
|
|
7112
7144
|
ITINERARY_TITLE: "あなたの旅行概要",
|
|
7113
7145
|
DOSSIER_NUMBER: "ファイル番号",
|
|
@@ -7153,7 +7185,7 @@ var SRP = {
|
|
|
7153
7185
|
};
|
|
7154
7186
|
var ITINERARY = {
|
|
7155
7187
|
DAY: "日",
|
|
7156
|
-
NO_ITEMS: "
|
|
7188
|
+
NO_ITEMS: "この日に選択されたアクティビティはありません。"
|
|
7157
7189
|
};
|
|
7158
7190
|
var FORM = {
|
|
7159
7191
|
LOADING: "フォームを読み込んでいます...",
|
|
@@ -7817,6 +7849,33 @@ var TrajectNodeType = {
|
|
|
7817
7849
|
subroute: 3,
|
|
7818
7850
|
};
|
|
7819
7851
|
|
|
7852
|
+
var DurationType = {
|
|
7853
|
+
hours: 0,
|
|
7854
|
+
days: 1,
|
|
7855
|
+
nights: 2,
|
|
7856
|
+
minutes: 3,
|
|
7857
|
+
};
|
|
7858
|
+
|
|
7859
|
+
var RouteTransportType = {
|
|
7860
|
+
none: 0,
|
|
7861
|
+
privateTransport: 1,
|
|
7862
|
+
publicTransport: 2,
|
|
7863
|
+
rentalCar: 3,
|
|
7864
|
+
bus: 4,
|
|
7865
|
+
camper: 5,
|
|
7866
|
+
car: 6,
|
|
7867
|
+
charter: 7,
|
|
7868
|
+
cruise: 8,
|
|
7869
|
+
ferry: 9,
|
|
7870
|
+
flight: 10,
|
|
7871
|
+
taxi: 11,
|
|
7872
|
+
train: 12,
|
|
7873
|
+
transfer: 13,
|
|
7874
|
+
rocket: 14,
|
|
7875
|
+
walking: 15,
|
|
7876
|
+
cycling: 16,
|
|
7877
|
+
};
|
|
7878
|
+
|
|
7820
7879
|
/******************************************************************************
|
|
7821
7880
|
Copyright (c) Microsoft Corporation.
|
|
7822
7881
|
|
|
@@ -15168,6 +15227,7 @@ var submitForm = function (config, id, request, signal) {
|
|
|
15168
15227
|
exports.AllotmentType = AllotmentType;
|
|
15169
15228
|
exports.DataType = DataType;
|
|
15170
15229
|
exports.DossierType = DossierType;
|
|
15230
|
+
exports.DurationType = DurationType;
|
|
15171
15231
|
exports.EntryLineFlag = EntryLineFlag;
|
|
15172
15232
|
exports.EntryLineStatus = EntryLineStatus;
|
|
15173
15233
|
exports.ExportStatus = ExportStatus;
|
|
@@ -15180,6 +15240,7 @@ exports.PaymentType = PaymentType;
|
|
|
15180
15240
|
exports.PriceChartType = PriceChartType;
|
|
15181
15241
|
exports.RequirementType = RequirementType;
|
|
15182
15242
|
exports.RoomType = RoomType;
|
|
15243
|
+
exports.RouteTransportType = RouteTransportType;
|
|
15183
15244
|
exports.SaleType = SaleType;
|
|
15184
15245
|
exports.ServiceTokenError = ServiceTokenError;
|
|
15185
15246
|
exports.ServiceType = ServiceType;
|
|
@@ -16657,6 +16718,16 @@ const Icon = ({ name, className, title, width, height, fill }) => {
|
|
|
16657
16718
|
React__default["default"].createElement(HTMLComment, { text: "!Font Awesome Free 6.7.2 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free Copyright 2025 Fonticons, Inc." }),
|
|
16658
16719
|
title && React__default["default"].createElement("title", null, title),
|
|
16659
16720
|
React__default["default"].createElement("path", { d: "M135.2 117.4l-26.1 74.6 293.8 0-26.1-74.6C372.3 104.6 360.2 96 346.6 96L165.4 96c-13.6 0-25.7 8.6-30.2 21.4zM39.6 196.8L74.8 96.3C88.3 57.8 124.6 32 165.4 32l181.2 0c40.8 0 77.1 25.8 90.6 64.3l35.2 100.5c23.2 9.6 39.6 32.5 39.6 59.2l0 192c0 17.7-14.3 32-32 32l-32 0c-17.7 0-32-14.3-32-32l0-32-320 0 0 32c0 17.7-14.3 32-32 32l-32 0c-17.7 0-32-14.3-32-32L0 256c0-26.7 16.4-49.6 39.6-59.2zM128 304a32 32 0 1 0 -64 0 32 32 0 1 0 64 0zm288 32a32 32 0 1 0 0-64 32 32 0 1 0 0 64z", fill: "currentColor" })));
|
|
16721
|
+
case 'ui-cycling':
|
|
16722
|
+
return (React__default["default"].createElement("svg", { className: ['icon', `icon--${name}`, className].filter((className) => !lodash.isEmpty(className)).join(' '), width: width, height: height, viewBox: "0 0 640 512", fill: fill ?? 'currentColor' },
|
|
16723
|
+
React__default["default"].createElement(HTMLComment, { text: "!Font Awesome Free v5.15.4 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free Copyright 2026 Fonticons, Inc." }),
|
|
16724
|
+
title && React__default["default"].createElement("title", null, title),
|
|
16725
|
+
React__default["default"].createElement("path", { d: "M512.509 192.001c-16.373-.064-32.03 2.955-46.436 8.495l-77.68-125.153A24 24 0 0 0 368.001 64h-64c-8.837 0-16 7.163-16 16v16c0 8.837 7.163 16 16 16h50.649l14.896 24H256.002v-16c0-8.837-7.163-16-16-16h-87.459c-13.441 0-24.777 10.999-24.536 24.437.232 13.044 10.876 23.563 23.995 23.563h48.726l-29.417 47.52c-13.433-4.83-27.904-7.483-42.992-7.52C58.094 191.83.412 249.012.002 319.236-.413 390.279 57.055 448 128.002 448c59.642 0 109.758-40.793 123.967-96h52.033a24 24 0 0 0 20.406-11.367L410.37 201.77l14.938 24.067c-25.455 23.448-41.385 57.081-41.307 94.437.145 68.833 57.899 127.051 126.729 127.719 70.606.685 128.181-55.803 129.255-125.996 1.086-70.941-56.526-129.72-127.476-129.996zM186.75 265.772c9.727 10.529 16.673 23.661 19.642 38.228h-43.306l23.664-38.228zM128.002 400c-44.112 0-80-35.888-80-80s35.888-80 80-80c5.869 0 11.586.653 17.099 1.859l-45.505 73.509C89.715 331.327 101.213 352 120.002 352h81.3c-12.37 28.225-40.562 48-73.3 48zm162.63-96h-35.624c-3.96-31.756-19.556-59.894-42.383-80.026L237.371 184h127.547l-74.286 120zm217.057 95.886c-41.036-2.165-74.049-35.692-75.627-76.755-.812-21.121 6.633-40.518 19.335-55.263l44.433 71.586c4.66 7.508 14.524 9.816 22.032 5.156l13.594-8.437c7.508-4.66 9.817-14.524 5.156-22.032l-44.468-71.643a79.901 79.901 0 0 1 19.858-2.497c44.112 0 80 35.888 80 80-.001 45.54-38.252 82.316-84.313 79.885z", fill: "currentColor" })));
|
|
16726
|
+
case 'ui-walking':
|
|
16727
|
+
return (React__default["default"].createElement("svg", { className: ['icon', `icon--${name}`, className].filter((className) => !lodash.isEmpty(className)).join(' '), width: width, height: height, viewBox: "0 0 320 512", fill: fill ?? 'currentColor' },
|
|
16728
|
+
React__default["default"].createElement(HTMLComment, { text: "!Font Awesome Free v5.15.4 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free Copyright 2026 Fonticons, Inc." }),
|
|
16729
|
+
title && React__default["default"].createElement("title", null, title),
|
|
16730
|
+
React__default["default"].createElement("path", { d: "M208 96c26.5 0 48-21.5 48-48S234.5 0 208 0s-48 21.5-48 48 21.5 48 48 48zm94.5 149.1l-23.3-11.8-9.7-29.4c-14.7-44.6-55.7-75.8-102.2-75.9-36-.1-55.9 10.1-93.3 25.2-21.6 8.7-39.3 25.2-49.7 46.2L17.6 213c-7.8 15.8-1.5 35 14.2 42.9 15.6 7.9 34.6 1.5 42.5-14.3L81 228c3.5-7 9.3-12.5 16.5-15.4l26.8-10.8-15.2 60.7c-5.2 20.8.4 42.9 14.9 58.8l59.9 65.4c7.2 7.9 12.3 17.4 14.9 27.7l18.3 73.3c4.3 17.1 21.7 27.6 38.8 23.3 17.1-4.3 27.6-21.7 23.3-38.8l-22.2-89c-2.6-10.3-7.7-19.9-14.9-27.7l-45.5-49.7 17.2-68.7 5.5 16.5c5.3 16.1 16.7 29.4 31.7 37l23.3 11.8c15.6 7.9 34.6 1.5 42.5-14.3 7.7-15.7 1.4-35.1-14.3-43zM73.6 385.8c-3.2 8.1-8 15.4-14.2 21.5l-50 50.1c-12.5 12.5-12.5 32.8 0 45.3s32.7 12.5 45.2 0l59.4-59.4c6.1-6.1 10.9-13.4 14.2-21.5l13.5-33.8c-55.3-60.3-38.7-41.8-47.4-53.7l-20.7 51.5z", fill: "currentColor" })));
|
|
16660
16731
|
case 'ui-bus':
|
|
16661
16732
|
return (React__default["default"].createElement("svg", { className: ['icon', `icon--${name}`, className].filter((className) => !lodash.isEmpty(className)).join(' '), width: width, height: height, viewBox: "0 0 512 512", fill: fill ?? 'currentColor' },
|
|
16662
16733
|
title && React__default["default"].createElement("title", null, title),
|
|
@@ -16970,10 +17041,10 @@ const DateRangePicker$1 = (props) => {
|
|
|
16970
17041
|
month: dateFns.getMonth(new Date())
|
|
16971
17042
|
});
|
|
16972
17043
|
const [isWaitingForToDate, setWaitingForToDate] = React.useState(false);
|
|
16973
|
-
const { searchType = 0 } = React.useContext(SettingsContext$1);
|
|
17044
|
+
const { searchType = 0, allowSingleDayDateSelect = false } = React.useContext(SettingsContext$1);
|
|
16974
17045
|
const handleDayClick = (day) => {
|
|
16975
17046
|
const { onSelectionChange } = props;
|
|
16976
|
-
if (isWaitingForToDate && !lodash.isNil(fromDate) && dateFns.isAfter(day, fromDate)) {
|
|
17047
|
+
if (isWaitingForToDate && !lodash.isNil(fromDate) && (dateFns.isAfter(day, fromDate) || (allowSingleDayDateSelect && dateFns.isSameDay(day, fromDate)))) {
|
|
16977
17048
|
if (searchType === 1) {
|
|
16978
17049
|
// Only allow selecting the exact toDate
|
|
16979
17050
|
const expectedToDate = props.toDateByFromDate?.(fromDate);
|
|
@@ -17014,7 +17085,7 @@ const DateRangePicker$1 = (props) => {
|
|
|
17014
17085
|
}
|
|
17015
17086
|
};
|
|
17016
17087
|
const handleDayMouseOver = (day) => {
|
|
17017
|
-
if (isWaitingForToDate && (lodash.isNil(fromDate) || dateFns.
|
|
17088
|
+
if (isWaitingForToDate && (lodash.isNil(fromDate) || dateFns.isSameDay(day, fromDate) || dateFns.isAfter(day, fromDate))) {
|
|
17018
17089
|
setToDate(day);
|
|
17019
17090
|
}
|
|
17020
17091
|
};
|
|
@@ -21782,6 +21853,7 @@ const OptionRoom = ({ packageRoom, pax, optionPax, onRoomChange, includedService
|
|
|
21782
21853
|
|
|
21783
21854
|
function useOfferPrinter({ bookingPackage, getPax, tagIds = [], printActionId = null, onPrinted }) {
|
|
21784
21855
|
const settings = React.useContext(SettingsContext);
|
|
21856
|
+
const apiSettings = reactRedux.useSelector(selectApiSettings);
|
|
21785
21857
|
if (!settings)
|
|
21786
21858
|
throw new Error('useOfferPrinter must be used inside <BookingWizard>');
|
|
21787
21859
|
const { language, officeId } = settings;
|
|
@@ -21810,9 +21882,9 @@ function useOfferPrinter({ bookingPackage, getPax, tagIds = [], printActionId =
|
|
|
21810
21882
|
customerRequests: []
|
|
21811
21883
|
}
|
|
21812
21884
|
};
|
|
21813
|
-
const cfg = buildTideClientConfig();
|
|
21885
|
+
const cfg = buildTideClientConfig(apiSettings);
|
|
21814
21886
|
return build.book(cfg, request, undefined, language);
|
|
21815
|
-
}, [agentId, bookingPackage, getPax, language, officeId, tagIds]);
|
|
21887
|
+
}, [agentId, apiSettings, bookingPackage, getPax, language, officeId, tagIds]);
|
|
21816
21888
|
const languageData = [
|
|
21817
21889
|
{ code: 'nl-BE', tideId: 1 },
|
|
21818
21890
|
{ code: 'fr-BE', tideId: 2 },
|
|
@@ -21822,7 +21894,7 @@ function useOfferPrinter({ bookingPackage, getPax, tagIds = [], printActionId =
|
|
|
21822
21894
|
return languageData.find((l) => l.code === code)?.tideId || 1;
|
|
21823
21895
|
}
|
|
21824
21896
|
const printOffer = React.useCallback(async (offer) => {
|
|
21825
|
-
const cfg = buildTideClientConfig();
|
|
21897
|
+
const cfg = buildTideClientConfig(apiSettings);
|
|
21826
21898
|
const req = {
|
|
21827
21899
|
id: printActionId ?? 0,
|
|
21828
21900
|
dossierNumber: offer.dossierNumber ?? offer.number,
|
|
@@ -21833,7 +21905,7 @@ function useOfferPrinter({ bookingPackage, getPax, tagIds = [], printActionId =
|
|
|
21833
21905
|
const url = URL.createObjectURL(new Blob([buf], { type: 'application/pdf' }));
|
|
21834
21906
|
onPrinted?.(url);
|
|
21835
21907
|
window.open(url);
|
|
21836
|
-
}, [language, onPrinted]);
|
|
21908
|
+
}, [apiSettings, language, onPrinted, printActionId]);
|
|
21837
21909
|
const handlePrint = React.useCallback(async () => {
|
|
21838
21910
|
try {
|
|
21839
21911
|
setStage('creating');
|
|
@@ -28033,8 +28105,97 @@ const getServiceTypeBadgeModifier = (serviceType) => {
|
|
|
28033
28105
|
return '';
|
|
28034
28106
|
}
|
|
28035
28107
|
};
|
|
28108
|
+
// DurationType, as the SDK numbers it.
|
|
28109
|
+
const DURATION_HOURS = 0;
|
|
28110
|
+
const DURATION_DAYS = 1;
|
|
28111
|
+
const DURATION_NIGHTS = 2;
|
|
28112
|
+
const DURATION_MINUTES = 3;
|
|
28113
|
+
/**
|
|
28114
|
+
* How long a node takes, in the same shape the flight legs are written in — an hour count only
|
|
28115
|
+
* once there is one, so a short drive reads as plain minutes.
|
|
28116
|
+
*/
|
|
28117
|
+
const getTrajectNodeDuration = (node) => {
|
|
28118
|
+
const minutes = toMinutes(node);
|
|
28119
|
+
if (!minutes)
|
|
28120
|
+
return '';
|
|
28121
|
+
const hours = Math.floor(minutes / 60);
|
|
28122
|
+
const rest = minutes % 60;
|
|
28123
|
+
return hours ? `${hours}h ${rest.toString().padStart(2, '0')}m` : `${rest} min`;
|
|
28124
|
+
};
|
|
28125
|
+
const toMinutes = (node) => {
|
|
28126
|
+
const duration = node.duration ?? 0;
|
|
28127
|
+
if (duration <= 0)
|
|
28128
|
+
return 0;
|
|
28129
|
+
switch (node.durationType) {
|
|
28130
|
+
case DURATION_MINUTES:
|
|
28131
|
+
return duration;
|
|
28132
|
+
case DURATION_HOURS:
|
|
28133
|
+
return duration * 60;
|
|
28134
|
+
case DURATION_DAYS:
|
|
28135
|
+
case DURATION_NIGHTS:
|
|
28136
|
+
return duration * 24 * 60;
|
|
28137
|
+
default:
|
|
28138
|
+
return 0;
|
|
28139
|
+
}
|
|
28140
|
+
};
|
|
28141
|
+
// RouteTransportType, as the SDK numbers it. It says how a leg is travelled, which is not the
|
|
28142
|
+
// same question as what was sold: cycling and walking have no service type of their own.
|
|
28143
|
+
const TRANSPORT_PRIVATE = 1;
|
|
28144
|
+
const TRANSPORT_PUBLIC = 2;
|
|
28145
|
+
const TRANSPORT_RENTAL_CAR = 3;
|
|
28146
|
+
const TRANSPORT_BUS = 4;
|
|
28147
|
+
const TRANSPORT_CAMPER = 5;
|
|
28148
|
+
const TRANSPORT_CAR = 6;
|
|
28149
|
+
const TRANSPORT_CHARTER = 7;
|
|
28150
|
+
const TRANSPORT_CRUISE = 8;
|
|
28151
|
+
const TRANSPORT_FERRY = 9;
|
|
28152
|
+
const TRANSPORT_FLIGHT = 10;
|
|
28153
|
+
const TRANSPORT_TAXI = 11;
|
|
28154
|
+
const TRANSPORT_TRAIN = 12;
|
|
28155
|
+
const TRANSPORT_TRANSFER = 13;
|
|
28156
|
+
const TRANSPORT_WALKING = 15;
|
|
28157
|
+
const TRANSPORT_CYCLING = 16;
|
|
28158
|
+
/** Icon per way of travelling, where the route records one. */
|
|
28159
|
+
const getTransportTypeIcon = (transportType) => {
|
|
28160
|
+
switch (transportType) {
|
|
28161
|
+
case TRANSPORT_WALKING:
|
|
28162
|
+
return 'ui-walking';
|
|
28163
|
+
case TRANSPORT_CYCLING:
|
|
28164
|
+
return 'ui-cycling';
|
|
28165
|
+
case TRANSPORT_PRIVATE:
|
|
28166
|
+
case TRANSPORT_RENTAL_CAR:
|
|
28167
|
+
case TRANSPORT_CAMPER:
|
|
28168
|
+
case TRANSPORT_CAR:
|
|
28169
|
+
return 'ui-car';
|
|
28170
|
+
case TRANSPORT_TAXI:
|
|
28171
|
+
case TRANSPORT_TRANSFER:
|
|
28172
|
+
return 'ui-transfer';
|
|
28173
|
+
case TRANSPORT_PUBLIC:
|
|
28174
|
+
case TRANSPORT_BUS:
|
|
28175
|
+
return 'ui-bus';
|
|
28176
|
+
case TRANSPORT_TRAIN:
|
|
28177
|
+
return 'ui-train';
|
|
28178
|
+
case TRANSPORT_CRUISE:
|
|
28179
|
+
case TRANSPORT_FERRY:
|
|
28180
|
+
return 'ui-ship';
|
|
28181
|
+
case TRANSPORT_FLIGHT:
|
|
28182
|
+
case TRANSPORT_CHARTER:
|
|
28183
|
+
return 'ui-plane';
|
|
28184
|
+
default:
|
|
28185
|
+
return null;
|
|
28186
|
+
}
|
|
28187
|
+
};
|
|
28036
28188
|
const POI_TRAJECT_NODE_TYPE = 2;
|
|
28037
|
-
|
|
28189
|
+
/**
|
|
28190
|
+
* A point of interest is a place on the map rather than a service, so it gets a marker. Anything
|
|
28191
|
+
* else goes by how it is travelled where the route says so — a leg on foot or by bike is sold as
|
|
28192
|
+
* nothing, and its service type falls back to a transfer — and by what it is where it does not.
|
|
28193
|
+
*/
|
|
28194
|
+
const getTrajectNodeIcon = (node) => {
|
|
28195
|
+
if (node.trajectNodeType === POI_TRAJECT_NODE_TYPE)
|
|
28196
|
+
return 'ui-location';
|
|
28197
|
+
return getTransportTypeIcon(node.transportType) ?? getServiceTypeIcon(node.serviceType);
|
|
28198
|
+
};
|
|
28038
28199
|
const getTrajectNodeBadgeModifier = (node) => node.trajectNodeType === POI_TRAJECT_NODE_TYPE ? 'poi' : getServiceTypeBadgeModifier(node.serviceType);
|
|
28039
28200
|
|
|
28040
28201
|
const REGULAR_TRAJECT_NODE_TYPE = 0;
|
|
@@ -28101,8 +28262,6 @@ const buildTrajectNodeRequest = ({ node, line }, context, productCode, destinati
|
|
|
28101
28262
|
language: context.language,
|
|
28102
28263
|
serviceType: node.serviceType,
|
|
28103
28264
|
fromDate: toDateOnlyString(line.from),
|
|
28104
|
-
// An excursion happens on a day rather than over a span. The traject gives its line an end a day
|
|
28105
|
-
// out, the way a night is counted, which asks the search for a window it does not have.
|
|
28106
28265
|
toDate: toDateOnlyString(node.serviceType === EXCURSION_SERVICE_TYPE ? line.from : line.to),
|
|
28107
28266
|
destination: destination ?? buildDestination(line, node),
|
|
28108
28267
|
productCode,
|
|
@@ -28473,6 +28632,8 @@ const TrajectItinerary = ({ trajectEntry, packagingEntry, translations }) => {
|
|
|
28473
28632
|
trajectNodeType: REGULAR_TRAJECT_NODE_TYPE,
|
|
28474
28633
|
requirementType: 0,
|
|
28475
28634
|
contentSource: 0,
|
|
28635
|
+
duration: 0,
|
|
28636
|
+
durationType: 0,
|
|
28476
28637
|
alternatives: [],
|
|
28477
28638
|
from: line.from,
|
|
28478
28639
|
to: line.to
|
|
@@ -28506,6 +28667,8 @@ const TrajectItinerary = ({ trajectEntry, packagingEntry, translations }) => {
|
|
|
28506
28667
|
React__default["default"].createElement("p", null, dateFns.format(new Date(value), 'MMM'))));
|
|
28507
28668
|
const renderConnectingNode = ({ node }) => {
|
|
28508
28669
|
const distance = node.distanceInKm ? `${Math.round(node.distanceInKm)} km` : '';
|
|
28670
|
+
// How long the hop takes and how far it is, the way the traject editor puts them.
|
|
28671
|
+
const journey = [getTrajectNodeDuration(node), distance].filter(Boolean).join(' · ');
|
|
28509
28672
|
return (React__default["default"].createElement("div", { className: "search__filter__itinerary__transport", key: `connect-${node.nodeId}` },
|
|
28510
28673
|
React__default["default"].createElement("div", { className: "search__filter__itinerary__transport-timeline" },
|
|
28511
28674
|
React__default["default"].createElement("div", { className: "search__filter__itinerary__transport-timeline-line" })),
|
|
@@ -28514,8 +28677,8 @@ const TrajectItinerary = ({ trajectEntry, packagingEntry, translations }) => {
|
|
|
28514
28677
|
React__default["default"].createElement("div", { className: badgeClass('transport', getTrajectNodeBadgeModifier(node)) },
|
|
28515
28678
|
React__default["default"].createElement(Icon, { name: getTrajectNodeIcon(node), height: 15 })),
|
|
28516
28679
|
React__default["default"].createElement("div", { className: "search__filter__itinerary__transport-details" },
|
|
28517
|
-
React__default["default"].createElement("h6", null, node.name ||
|
|
28518
|
-
!!node.name && !!
|
|
28680
|
+
React__default["default"].createElement("h6", null, node.name || journey),
|
|
28681
|
+
!!node.name && !!journey && React__default["default"].createElement("p", { className: "search__filter__itinerary__transport-details-time" }, journey)))));
|
|
28519
28682
|
};
|
|
28520
28683
|
const renderOvernight = (item, index) => {
|
|
28521
28684
|
const { dayOrder } = item.node;
|
|
@@ -28659,7 +28822,7 @@ const getServiceTypePriority = (serviceType) => {
|
|
|
28659
28822
|
const Itinerary = ({ isOpen, handleSetIsOpen, isLoading, onEditAccommodation }) => {
|
|
28660
28823
|
const context = React.useContext(SearchResultsConfigurationContext);
|
|
28661
28824
|
const translations = getTranslations(context?.languageCode ?? 'en-GB');
|
|
28662
|
-
const { editablePackagingEntry, priceDetails } = reactRedux.useSelector((state) => state.searchResults);
|
|
28825
|
+
const { editablePackagingEntry, priceDetails, trajectItineraryView } = reactRedux.useSelector((state) => state.searchResults);
|
|
28663
28826
|
const dispatch = reactRedux.useDispatch();
|
|
28664
28827
|
const packagingEntry = editablePackagingEntry ?? context?.packagingEntry;
|
|
28665
28828
|
const sortedLines = React.useMemo(() => {
|
|
@@ -28702,6 +28865,11 @@ const Itinerary = ({ isOpen, handleSetIsOpen, isLoading, onEditAccommodation })
|
|
|
28702
28865
|
const handleConfirm = () => {
|
|
28703
28866
|
dispatch(setBookPackagingEntry(true));
|
|
28704
28867
|
};
|
|
28868
|
+
const handleTrajectView = (itinerary) => {
|
|
28869
|
+
dispatch(setTrajectItineraryView(itinerary));
|
|
28870
|
+
if (typeof window !== 'undefined')
|
|
28871
|
+
window.scrollTo(0, 0);
|
|
28872
|
+
};
|
|
28705
28873
|
return (React__default["default"].createElement("div", { className: `search__filters--modal ${isOpen ? 'is-open' : ''}` },
|
|
28706
28874
|
React__default["default"].createElement("div", { className: "search__filters--background", onClick: handleSetIsOpen }),
|
|
28707
28875
|
React__default["default"].createElement("button", { className: "search__filters--close", onClick: handleSetIsOpen },
|
|
@@ -28729,7 +28897,8 @@ const Itinerary = ({ isOpen, handleSetIsOpen, isLoading, onEditAccommodation })
|
|
|
28729
28897
|
" ",
|
|
28730
28898
|
translations.SRP.TOTAL,
|
|
28731
28899
|
")"))),
|
|
28732
|
-
React__default["default"].createElement("button", { className: "cta", onClick: handleConfirm }, translations.QSM.CONFIRM)
|
|
28900
|
+
React__default["default"].createElement("button", { className: "cta", onClick: handleConfirm }, translations.QSM.CONFIRM),
|
|
28901
|
+
!!context?.trajectEntry && (React__default["default"].createElement("button", { type: "button", className: "cta cta--secondary", onClick: () => handleTrajectView(!trajectItineraryView) }, trajectItineraryView ? translations.SRP.SHOW_SERVICES : translations.SRP.VIEW_FULL_ITINERARY))))),
|
|
28733
28902
|
React__default["default"].createElement("div", { className: "search__filter__itinerary" },
|
|
28734
28903
|
React__default["default"].createElement("p", null, translations.SRP.DAY_BY_DAY),
|
|
28735
28904
|
firstEntryLine && (React__default["default"].createElement("div", { className: "search__filter__itinerary__country" },
|
|
@@ -31012,7 +31181,7 @@ const Filters = ({ initialFilters, filters, isOpen, handleSetIsOpen, isLoading,
|
|
|
31012
31181
|
const max = filter.max ?? 100;
|
|
31013
31182
|
const selectedMin = filter.selectedMin ?? min;
|
|
31014
31183
|
const selectedMax = filter.selectedMax ?? max;
|
|
31015
|
-
return (React__default["default"].createElement(MultiRangeFilter, { min: min, max: max, selectedMin: selectedMin, selectedMax: selectedMax, valueFormatter: (value) => `${value}
|
|
31184
|
+
return (React__default["default"].createElement(MultiRangeFilter, { min: min, max: max, selectedMin: selectedMin, selectedMax: selectedMax, valueFormatter: (value) => (filter.property === 'price' ? value.toFixed(2).replace('.', ',') : `${value}`), onChange: (newMin, newMax) => {
|
|
31016
31185
|
handleSliderChange(filter, newMin, newMax);
|
|
31017
31186
|
} }));
|
|
31018
31187
|
})(),
|
|
@@ -31715,7 +31884,7 @@ const FlyIn = ({ srpType, isOpen, setIsOpen, className = '', onPanelRef, details
|
|
|
31715
31884
|
dispatch(setBookPackagingEntry(true));
|
|
31716
31885
|
}
|
|
31717
31886
|
};
|
|
31718
|
-
return (React__default["default"].createElement("div", { className: `flyin ${isOpen ? 'flyin--active' : ''} ${className} ${isPackageEditFlow || flyInType === 'acco-results' || flyInType === 'traject-day-activities' ? 'flyin--large' : ''} ${flyInType === 'excursion-results' || flyInType === 'excursion-details' ? 'flyin--medium' : ''}
|
|
31887
|
+
return (React__default["default"].createElement("div", { className: `flyin ${isOpen ? 'flyin--active' : ''} ${className} ${isPackageEditFlow || flyInType === 'acco-results' || flyInType === 'traject-day-activities' ? 'flyin--large' : ''} ${flyInType === 'excursion-results' || flyInType === 'excursion-details' ? 'flyin--medium' : ''}
|
|
31719
31888
|
${flyInType === 'flight-outward-results' || flyInType === 'flight-return-results' || flyInType === 'traject-flight-results' ? 'flyin--flight' : ''}` },
|
|
31720
31889
|
React__default["default"].createElement("div", { className: `flyin__panel ${isOpen ? 'flyin__panel--active' : ''}`, ref: panelRef },
|
|
31721
31890
|
React__default["default"].createElement("div", { className: "flyin__content" },
|
|
@@ -32504,7 +32673,7 @@ const FlightFilters = ({ isOpen, handleSetIsOpen, isLoading }) => {
|
|
|
32504
32673
|
!lodash.isEmpty(priceRangeValues) &&
|
|
32505
32674
|
(() => {
|
|
32506
32675
|
return (React__default["default"].createElement("div", { className: "search__filter-rows" },
|
|
32507
|
-
React__default["default"].createElement(MultiRangeFilter, { min: minPrice, max: maxPrice, selectedMin: lodash.first(priceRangeValues) ?? minPrice, selectedMax: lodash.last(priceRangeValues) ?? maxPrice, valueFormatter: (value) => `€${value}`, onChange: (newMin, newMax) => {
|
|
32676
|
+
React__default["default"].createElement(MultiRangeFilter, { min: minPrice, max: maxPrice, selectedMin: lodash.first(priceRangeValues) ?? minPrice, selectedMax: lodash.last(priceRangeValues) ?? maxPrice, valueFormatter: (value) => `€${value.toFixed(2).replace('.', ',')}`, onChange: (newMin, newMax) => {
|
|
32508
32677
|
handlePriceSliderChange([newMin, newMax]);
|
|
32509
32678
|
} })));
|
|
32510
32679
|
})()))))));
|
|
@@ -33182,6 +33351,27 @@ const getRequestRoomsFromPackagingSegments = (entry, segments) => {
|
|
|
33182
33351
|
}));
|
|
33183
33352
|
};
|
|
33184
33353
|
|
|
33354
|
+
/**
|
|
33355
|
+
* The entry to send to the backend, as opposed to the one the page works with.
|
|
33356
|
+
*
|
|
33357
|
+
* They differ only for a traject: the page keeps the line guids the traject was rendered with,
|
|
33358
|
+
* because that is what joins its nodes to its lines, while pricing and booking need the guids the
|
|
33359
|
+
* searches cached their lines under. Anything else passes through untouched, so this can be used
|
|
33360
|
+
* wherever the entry leaves the component without checking which flow is running.
|
|
33361
|
+
*/
|
|
33362
|
+
const useBookableEntry = () => {
|
|
33363
|
+
const context = React.useContext(SearchResultsConfigurationContext);
|
|
33364
|
+
const { editablePackagingEntry, trajectNodeAvailability, trajectFlightAvailability } = reactRedux.useSelector((state) => state.searchResults);
|
|
33365
|
+
const trajectEntry = context?.trajectEntry;
|
|
33366
|
+
return React.useMemo(() => {
|
|
33367
|
+
if (!editablePackagingEntry)
|
|
33368
|
+
return null;
|
|
33369
|
+
if (!trajectEntry)
|
|
33370
|
+
return editablePackagingEntry;
|
|
33371
|
+
return withCachedEntryLineGuids(editablePackagingEntry, trajectEntry, trajectNodeAvailability, trajectFlightAvailability);
|
|
33372
|
+
}, [editablePackagingEntry, trajectEntry, trajectNodeAvailability, trajectFlightAvailability]);
|
|
33373
|
+
};
|
|
33374
|
+
|
|
33185
33375
|
const escapeHtml = (value) => {
|
|
33186
33376
|
if (!value)
|
|
33187
33377
|
return '';
|
|
@@ -33240,12 +33430,62 @@ const findAccommodationForDay = (nodes, currentDay) => {
|
|
|
33240
33430
|
}
|
|
33241
33431
|
return null;
|
|
33242
33432
|
};
|
|
33243
|
-
const
|
|
33433
|
+
const formatTime = (time) => (time ? time.slice(0, 5) : '');
|
|
33434
|
+
/**
|
|
33435
|
+
* Whether generated content actually shows something.
|
|
33436
|
+
*
|
|
33437
|
+
* A content view whose data is missing still returns its wrapper markup, or the whitespace left by
|
|
33438
|
+
* a guard around its body — markup that renders as a blank gap. Only text or an image counts as
|
|
33439
|
+
* something the traveller can read.
|
|
33440
|
+
*/
|
|
33441
|
+
const hasVisibleContent = (contents) => {
|
|
33442
|
+
if (!contents)
|
|
33443
|
+
return false;
|
|
33444
|
+
if (/<(img|svg|picture|video|iframe)\b/i.test(contents))
|
|
33445
|
+
return true;
|
|
33446
|
+
return (contents
|
|
33447
|
+
.replace(/<[^>]*>/g, ' ')
|
|
33448
|
+
.replace(/ /gi, ' ')
|
|
33449
|
+
.trim().length > 0);
|
|
33450
|
+
};
|
|
33451
|
+
/** The legs of a flight, as the entry line records them. */
|
|
33452
|
+
const buildFlightHtml = (line) => {
|
|
33453
|
+
const flightLines = line.flightInformation?.flightLines ?? [];
|
|
33454
|
+
if (!flightLines.length)
|
|
33455
|
+
return '';
|
|
33456
|
+
const legs = flightLines
|
|
33457
|
+
.map((leg) => {
|
|
33458
|
+
const from = escapeHtml(leg.departureAirportDescription || leg.departureAirportCode);
|
|
33459
|
+
const to = escapeHtml(leg.arrivalAirportDescription || leg.arrivalAirportCode);
|
|
33460
|
+
const carrier = escapeHtml([leg.airlineDescription, leg.flightNumber].filter(Boolean).join(' '));
|
|
33461
|
+
return `<li>${from} ${formatTime(leg.departureTime)} → ${to} ${formatTime(leg.arrivalTime)}${carrier ? ` · ${carrier}` : ''}</li>`;
|
|
33462
|
+
})
|
|
33463
|
+
.join('');
|
|
33464
|
+
return `<ul class="itinerary-item__legs">${legs}</ul>`;
|
|
33465
|
+
};
|
|
33466
|
+
/**
|
|
33467
|
+
* What to show for an item the generator returned no content for.
|
|
33468
|
+
*
|
|
33469
|
+
* An item comes back with a title and a template but an empty body whenever its template has no
|
|
33470
|
+
* content view of its own — flights, today. Rendering that empty body leaves a blank where a
|
|
33471
|
+
* service should be, so what the entry already knows about the line is drawn instead.
|
|
33472
|
+
*/
|
|
33473
|
+
const buildFallbackHtml = (item, line) => {
|
|
33474
|
+
const details = [line?.accommodationName, line?.regimeName].filter(Boolean).join(' — ');
|
|
33475
|
+
return `
|
|
33476
|
+
<div class="itinerary-item__fallback">
|
|
33477
|
+
<h3 class="itinerary-item__fallback-title">${escapeHtml(item.title)}</h3>
|
|
33478
|
+
${line ? buildFlightHtml(line) : ''}
|
|
33479
|
+
${details ? `<p class="itinerary-item__fallback-details">${escapeHtml(details)}</p>` : ''}
|
|
33480
|
+
</div>
|
|
33481
|
+
`;
|
|
33482
|
+
};
|
|
33483
|
+
const buildItineraryHtml = (itinerary, translations, lines) => {
|
|
33244
33484
|
if (!itinerary) {
|
|
33245
|
-
return `
|
|
33246
|
-
<div class="itinerary-shell">
|
|
33247
|
-
<div class="itinerary-empty">Geen reisroute beschikbaar.</div>
|
|
33248
|
-
</div>
|
|
33485
|
+
return `
|
|
33486
|
+
<div class="itinerary-shell">
|
|
33487
|
+
<div class="itinerary-empty">Geen reisroute beschikbaar.</div>
|
|
33488
|
+
</div>
|
|
33249
33489
|
`;
|
|
33250
33490
|
}
|
|
33251
33491
|
const allNodes = itinerary.nodes ?? [];
|
|
@@ -33259,75 +33499,81 @@ const buildItineraryHtml = (itinerary, translations) => {
|
|
|
33259
33499
|
const hasAccommodationInCurrentNode = uniqueItems.some(isAccommodationItem);
|
|
33260
33500
|
const activeAccommodation = findAccommodationForDay(allNodes, startDay);
|
|
33261
33501
|
const accommodationBanner = !hasAccommodationInCurrentNode && activeAccommodation
|
|
33262
|
-
? `
|
|
33263
|
-
<div class="itinerary-node__accommodation-banner">
|
|
33264
|
-
Accommodatie voor deze dag: <strong>${escapeHtml(getAccommodationName(activeAccommodation))}</strong>
|
|
33265
|
-
</div>
|
|
33502
|
+
? `
|
|
33503
|
+
<div class="itinerary-node__accommodation-banner">
|
|
33504
|
+
Accommodatie voor deze dag: <strong>${escapeHtml(getAccommodationName(activeAccommodation))}</strong>
|
|
33505
|
+
</div>
|
|
33266
33506
|
`
|
|
33267
33507
|
: '';
|
|
33268
33508
|
const itemsHtml = hasItems
|
|
33269
33509
|
? uniqueItems
|
|
33270
|
-
.map((item) => `
|
|
33271
|
-
<article class="itinerary-item" data-template="${escapeHtml(item.templateName)}">
|
|
33272
|
-
${item.contents
|
|
33273
|
-
|
|
33510
|
+
.map((item) => `
|
|
33511
|
+
<article class="itinerary-item" data-template="${escapeHtml(item.templateName)}">
|
|
33512
|
+
${hasVisibleContent(item.contents)
|
|
33513
|
+
? item.contents
|
|
33514
|
+
: buildFallbackHtml(item, lines.find((line) => line.guid === item.itemGuid))}
|
|
33515
|
+
</article>
|
|
33274
33516
|
`)
|
|
33275
33517
|
.join('')
|
|
33276
33518
|
: `<div class="itinerary-node__empty">${translations.ITINERARY.NO_ITEMS}</div>`;
|
|
33277
|
-
return `
|
|
33278
|
-
<section class="itinerary-node">
|
|
33279
|
-
<header class="itinerary-node__header">
|
|
33280
|
-
|
|
33281
|
-
<div class="itinerary-node__day">
|
|
33282
|
-
<p class="itinerary-node__day-day">${day}</p>
|
|
33283
|
-
<p class="itinerary-node__day-month">${month}</p>
|
|
33284
|
-
</div>
|
|
33285
|
-
|
|
33286
|
-
<div>
|
|
33287
|
-
<h2 class="itinerary-node__title">${escapeHtml(node.title)}</h2>
|
|
33288
|
-
</div>
|
|
33289
|
-
</header>
|
|
33290
|
-
|
|
33291
|
-
<div class="itinerary-node__content">
|
|
33292
|
-
${accommodationBanner}
|
|
33293
|
-
${itemsHtml}
|
|
33294
|
-
</div>
|
|
33295
|
-
</section>
|
|
33519
|
+
return `
|
|
33520
|
+
<section class="itinerary-node">
|
|
33521
|
+
<header class="itinerary-node__header">
|
|
33522
|
+
|
|
33523
|
+
<div class="itinerary-node__day">
|
|
33524
|
+
<p class="itinerary-node__day-day">${day}</p>
|
|
33525
|
+
<p class="itinerary-node__day-month">${month}</p>
|
|
33526
|
+
</div>
|
|
33527
|
+
|
|
33528
|
+
<div>
|
|
33529
|
+
<h2 class="itinerary-node__title">${escapeHtml(node.title)}</h2>
|
|
33530
|
+
</div>
|
|
33531
|
+
</header>
|
|
33532
|
+
|
|
33533
|
+
<div class="itinerary-node__content">
|
|
33534
|
+
${accommodationBanner}
|
|
33535
|
+
${itemsHtml}
|
|
33536
|
+
</div>
|
|
33537
|
+
</section>
|
|
33296
33538
|
`;
|
|
33297
33539
|
})
|
|
33298
33540
|
.join('');
|
|
33299
33541
|
const defaultItemsHtml = itinerary.defaultItems && itinerary.defaultItems.length > 0
|
|
33300
|
-
? `
|
|
33301
|
-
<section class="itinerary-default-items">
|
|
33302
|
-
<h2 class="itinerary-default-items__title">Algemene info</h2>
|
|
33542
|
+
? `
|
|
33543
|
+
<section class="itinerary-default-items">
|
|
33544
|
+
<h2 class="itinerary-default-items__title">Algemene info</h2>
|
|
33303
33545
|
${getUniqueItems(itinerary.defaultItems)
|
|
33304
|
-
.map((item) => `
|
|
33305
|
-
<article class="itinerary-item" data-template="${escapeHtml(item.templateName)}">
|
|
33306
|
-
${item.contents
|
|
33307
|
-
|
|
33546
|
+
.map((item) => `
|
|
33547
|
+
<article class="itinerary-item" data-template="${escapeHtml(item.templateName)}">
|
|
33548
|
+
${hasVisibleContent(item.contents)
|
|
33549
|
+
? item.contents
|
|
33550
|
+
: buildFallbackHtml(item, lines.find((line) => line.guid === item.itemGuid))}
|
|
33551
|
+
</article>
|
|
33308
33552
|
`)
|
|
33309
|
-
.join('')}
|
|
33310
|
-
</section>
|
|
33553
|
+
.join('')}
|
|
33554
|
+
</section>
|
|
33311
33555
|
`
|
|
33312
33556
|
: '';
|
|
33313
|
-
return `
|
|
33314
|
-
<div class="itinerary-shell">
|
|
33315
|
-
${itinerary.title ? `<header class="itinerary-shell__header"><h1 class="itinerary-shell__title">${escapeHtml(itinerary.title)}</h1></header>` : ''}
|
|
33316
|
-
|
|
33317
|
-
<div class="itinerary-shell__content">
|
|
33318
|
-
${nodesHtml}
|
|
33319
|
-
${defaultItemsHtml}
|
|
33320
|
-
</div>
|
|
33321
|
-
</div>
|
|
33557
|
+
return `
|
|
33558
|
+
<div class="itinerary-shell">
|
|
33559
|
+
${itinerary.title ? `<header class="itinerary-shell__header"><h1 class="itinerary-shell__title">${escapeHtml(itinerary.title)}</h1></header>` : ''}
|
|
33560
|
+
|
|
33561
|
+
<div class="itinerary-shell__content">
|
|
33562
|
+
${nodesHtml}
|
|
33563
|
+
${defaultItemsHtml}
|
|
33564
|
+
</div>
|
|
33565
|
+
</div>
|
|
33322
33566
|
`;
|
|
33323
33567
|
};
|
|
33324
33568
|
const FullItinerary = ({ isLoading }) => {
|
|
33325
33569
|
const { itinerary } = reactRedux.useSelector((state) => state.searchResults);
|
|
33326
33570
|
const context = React.useContext(SearchResultsConfigurationContext);
|
|
33571
|
+
// The entry as it was sent: its line guids are the ones the itinerary items carry back.
|
|
33572
|
+
const bookableEntry = useBookableEntry();
|
|
33327
33573
|
const translations = getTranslations(context?.languageCode ?? 'en-GB');
|
|
33328
33574
|
const hostRef = React.useRef(null);
|
|
33329
33575
|
const shadowRootRef = React.useRef(null);
|
|
33330
|
-
const html = React.useMemo(() => buildItineraryHtml(itinerary, translations), [itinerary, translations]);
|
|
33576
|
+
const html = React.useMemo(() => buildItineraryHtml(itinerary, translations, bookableEntry?.lines ?? []), [itinerary, translations, bookableEntry]);
|
|
33331
33577
|
React.useEffect(() => {
|
|
33332
33578
|
if (isLoading) {
|
|
33333
33579
|
return;
|
|
@@ -33338,141 +33584,170 @@ const FullItinerary = ({ isLoading }) => {
|
|
|
33338
33584
|
}
|
|
33339
33585
|
const shadowRoot = host.shadowRoot ?? host.attachShadow({ mode: 'open' });
|
|
33340
33586
|
shadowRootRef.current = shadowRoot;
|
|
33341
|
-
shadowRoot.innerHTML = `
|
|
33342
|
-
<style>
|
|
33343
|
-
:host {
|
|
33344
|
-
all: initial;
|
|
33345
|
-
display: block;
|
|
33346
|
-
width: 100%;
|
|
33347
|
-
}
|
|
33348
|
-
|
|
33349
|
-
*,
|
|
33350
|
-
*::before,
|
|
33351
|
-
*::after {
|
|
33352
|
-
box-sizing: border-box;
|
|
33353
|
-
}
|
|
33354
|
-
|
|
33355
|
-
.itinerary-shell {
|
|
33356
|
-
width: 100%;
|
|
33357
|
-
margin: 0 auto;
|
|
33358
|
-
font-family: 'Outfit', sans-serif;
|
|
33359
|
-
color: #222;
|
|
33360
|
-
}
|
|
33361
|
-
|
|
33362
|
-
.itinerary-shell__header {
|
|
33363
|
-
margin-bottom: 24px;
|
|
33364
|
-
}
|
|
33365
|
-
|
|
33366
|
-
.itinerary-shell__title {
|
|
33367
|
-
margin: 0;
|
|
33368
|
-
font-size: 32px;
|
|
33369
|
-
line-height: 1.2;
|
|
33370
|
-
}
|
|
33371
|
-
|
|
33372
|
-
.itinerary-shell__content {
|
|
33373
|
-
display: grid;
|
|
33374
|
-
gap: 24px;
|
|
33375
|
-
}
|
|
33376
|
-
|
|
33377
|
-
.itinerary-node {
|
|
33378
|
-
border: 1px solid #e5e7eb;
|
|
33379
|
-
border-radius: 16px;
|
|
33380
|
-
overflow: hidden;
|
|
33381
|
-
background: #fff;
|
|
33382
|
-
box-shadow: 0 2px 10px rgba(0, 0, 0, 0.04);
|
|
33383
|
-
}
|
|
33384
|
-
|
|
33385
|
-
.itinerary-node__header {
|
|
33386
|
-
display: flex;
|
|
33387
|
-
gap: 16px;
|
|
33388
|
-
align-items: center;
|
|
33389
|
-
border-bottom: 1px solid #eef0f2;
|
|
33390
|
-
background: #fafafa;
|
|
33391
|
-
}
|
|
33392
|
-
|
|
33393
|
-
.itinerary-node__day {
|
|
33394
|
-
flex: 50px 0 0;
|
|
33395
|
-
display: flex;
|
|
33396
|
-
flex-flow: column;
|
|
33397
|
-
align-items: center;
|
|
33398
|
-
justify-content: center;
|
|
33399
|
-
background: #1f9470;
|
|
33400
|
-
color: white;
|
|
33401
|
-
border: 1.5px solid var(--tide-booking-color-secondary);
|
|
33402
|
-
}
|
|
33403
|
-
|
|
33404
|
-
.itinerary-node__day-month {
|
|
33405
|
-
margin: 0px;
|
|
33406
|
-
}
|
|
33407
|
-
|
|
33408
|
-
.itinerary-node__day-day {
|
|
33409
|
-
margin: 0px;
|
|
33410
|
-
font-weight: var(--tide-booking-search-results-label-date-month-font-weight);
|
|
33411
|
-
color: var(--tide-booking-search-results-label-date-month-color);
|
|
33412
|
-
font-size: 24px;
|
|
33413
|
-
}
|
|
33414
|
-
|
|
33415
|
-
.itinerary-node__title {
|
|
33416
|
-
margin: 0;
|
|
33417
|
-
font-size: 22px;
|
|
33418
|
-
line-height: 1.25;
|
|
33419
|
-
}
|
|
33420
|
-
|
|
33421
|
-
.itinerary-node__content {
|
|
33422
|
-
display: grid;
|
|
33423
|
-
gap: 20px;
|
|
33424
|
-
padding: 20px;
|
|
33425
|
-
}
|
|
33426
|
-
|
|
33427
|
-
.itinerary-node__accommodation-banner {
|
|
33428
|
-
padding: 12px 16px;
|
|
33429
|
-
border: 1px solid #dbeafe;
|
|
33430
|
-
border-radius: 12px;
|
|
33431
|
-
background: #eff6ff;
|
|
33432
|
-
color: #1e3a8a;
|
|
33433
|
-
font-size: 14px;
|
|
33434
|
-
line-height: 1.4;
|
|
33435
|
-
}
|
|
33436
|
-
|
|
33437
|
-
.itinerary-item {
|
|
33438
|
-
display: block;
|
|
33439
|
-
border-radius: 12px;
|
|
33440
|
-
overflow: hidden;
|
|
33441
|
-
background: #fff;
|
|
33442
|
-
}
|
|
33443
|
-
|
|
33444
|
-
.
|
|
33445
|
-
.itinerary-
|
|
33446
|
-
padding: 20px;
|
|
33447
|
-
border: 1px
|
|
33448
|
-
border-radius: 12px;
|
|
33449
|
-
|
|
33450
|
-
|
|
33451
|
-
|
|
33452
|
-
|
|
33453
|
-
|
|
33454
|
-
|
|
33455
|
-
|
|
33456
|
-
|
|
33457
|
-
|
|
33458
|
-
|
|
33459
|
-
|
|
33460
|
-
|
|
33461
|
-
|
|
33462
|
-
|
|
33463
|
-
|
|
33464
|
-
|
|
33465
|
-
|
|
33466
|
-
|
|
33467
|
-
|
|
33468
|
-
|
|
33469
|
-
|
|
33470
|
-
|
|
33471
|
-
|
|
33472
|
-
|
|
33473
|
-
|
|
33474
|
-
|
|
33475
|
-
|
|
33587
|
+
shadowRoot.innerHTML = `
|
|
33588
|
+
<style>
|
|
33589
|
+
:host {
|
|
33590
|
+
all: initial;
|
|
33591
|
+
display: block;
|
|
33592
|
+
width: 100%;
|
|
33593
|
+
}
|
|
33594
|
+
|
|
33595
|
+
*,
|
|
33596
|
+
*::before,
|
|
33597
|
+
*::after {
|
|
33598
|
+
box-sizing: border-box;
|
|
33599
|
+
}
|
|
33600
|
+
|
|
33601
|
+
.itinerary-shell {
|
|
33602
|
+
width: 100%;
|
|
33603
|
+
margin: 0 auto;
|
|
33604
|
+
font-family: 'Outfit', sans-serif;
|
|
33605
|
+
color: #222;
|
|
33606
|
+
}
|
|
33607
|
+
|
|
33608
|
+
.itinerary-shell__header {
|
|
33609
|
+
margin-bottom: 24px;
|
|
33610
|
+
}
|
|
33611
|
+
|
|
33612
|
+
.itinerary-shell__title {
|
|
33613
|
+
margin: 0;
|
|
33614
|
+
font-size: 32px;
|
|
33615
|
+
line-height: 1.2;
|
|
33616
|
+
}
|
|
33617
|
+
|
|
33618
|
+
.itinerary-shell__content {
|
|
33619
|
+
display: grid;
|
|
33620
|
+
gap: 24px;
|
|
33621
|
+
}
|
|
33622
|
+
|
|
33623
|
+
.itinerary-node {
|
|
33624
|
+
border: 1px solid #e5e7eb;
|
|
33625
|
+
border-radius: 16px;
|
|
33626
|
+
overflow: hidden;
|
|
33627
|
+
background: #fff;
|
|
33628
|
+
box-shadow: 0 2px 10px rgba(0, 0, 0, 0.04);
|
|
33629
|
+
}
|
|
33630
|
+
|
|
33631
|
+
.itinerary-node__header {
|
|
33632
|
+
display: flex;
|
|
33633
|
+
gap: 16px;
|
|
33634
|
+
align-items: center;
|
|
33635
|
+
border-bottom: 1px solid #eef0f2;
|
|
33636
|
+
background: #fafafa;
|
|
33637
|
+
}
|
|
33638
|
+
|
|
33639
|
+
.itinerary-node__day {
|
|
33640
|
+
flex: 50px 0 0;
|
|
33641
|
+
display: flex;
|
|
33642
|
+
flex-flow: column;
|
|
33643
|
+
align-items: center;
|
|
33644
|
+
justify-content: center;
|
|
33645
|
+
background: #1f9470;
|
|
33646
|
+
color: white;
|
|
33647
|
+
border: 1.5px solid var(--tide-booking-color-secondary);
|
|
33648
|
+
}
|
|
33649
|
+
|
|
33650
|
+
.itinerary-node__day-month {
|
|
33651
|
+
margin: 0px;
|
|
33652
|
+
}
|
|
33653
|
+
|
|
33654
|
+
.itinerary-node__day-day {
|
|
33655
|
+
margin: 0px;
|
|
33656
|
+
font-weight: var(--tide-booking-search-results-label-date-month-font-weight);
|
|
33657
|
+
color: var(--tide-booking-search-results-label-date-month-color);
|
|
33658
|
+
font-size: 24px;
|
|
33659
|
+
}
|
|
33660
|
+
|
|
33661
|
+
.itinerary-node__title {
|
|
33662
|
+
margin: 0;
|
|
33663
|
+
font-size: 22px;
|
|
33664
|
+
line-height: 1.25;
|
|
33665
|
+
}
|
|
33666
|
+
|
|
33667
|
+
.itinerary-node__content {
|
|
33668
|
+
display: grid;
|
|
33669
|
+
gap: 20px;
|
|
33670
|
+
padding: 20px;
|
|
33671
|
+
}
|
|
33672
|
+
|
|
33673
|
+
.itinerary-node__accommodation-banner {
|
|
33674
|
+
padding: 12px 16px;
|
|
33675
|
+
border: 1px solid #dbeafe;
|
|
33676
|
+
border-radius: 12px;
|
|
33677
|
+
background: #eff6ff;
|
|
33678
|
+
color: #1e3a8a;
|
|
33679
|
+
font-size: 14px;
|
|
33680
|
+
line-height: 1.4;
|
|
33681
|
+
}
|
|
33682
|
+
|
|
33683
|
+
.itinerary-item {
|
|
33684
|
+
display: block;
|
|
33685
|
+
border-radius: 12px;
|
|
33686
|
+
overflow: hidden;
|
|
33687
|
+
background: #fff;
|
|
33688
|
+
}
|
|
33689
|
+
|
|
33690
|
+
/* An item whose template has no content view of its own still has to read as a service. */
|
|
33691
|
+
.itinerary-item__fallback {
|
|
33692
|
+
padding: 16px 20px;
|
|
33693
|
+
border: 1px solid #e5e7eb;
|
|
33694
|
+
border-radius: 12px;
|
|
33695
|
+
}
|
|
33696
|
+
|
|
33697
|
+
.itinerary-item__fallback-title {
|
|
33698
|
+
margin: 0;
|
|
33699
|
+
font-size: 16px;
|
|
33700
|
+
font-weight: 600;
|
|
33701
|
+
color: #111827;
|
|
33702
|
+
}
|
|
33703
|
+
|
|
33704
|
+
.itinerary-item__legs {
|
|
33705
|
+
margin: 8px 0 0;
|
|
33706
|
+
padding-left: 18px;
|
|
33707
|
+
color: #374151;
|
|
33708
|
+
}
|
|
33709
|
+
|
|
33710
|
+
.itinerary-item__legs li + li {
|
|
33711
|
+
margin-top: 4px;
|
|
33712
|
+
}
|
|
33713
|
+
|
|
33714
|
+
.itinerary-item__fallback-details {
|
|
33715
|
+
margin: 8px 0 0;
|
|
33716
|
+
color: #6b7280;
|
|
33717
|
+
}
|
|
33718
|
+
|
|
33719
|
+
.itinerary-node__empty,
|
|
33720
|
+
.itinerary-empty {
|
|
33721
|
+
padding: 20px;
|
|
33722
|
+
border: 1px dashed #d1d5db;
|
|
33723
|
+
border-radius: 12px;
|
|
33724
|
+
color: #6b7280;
|
|
33725
|
+
background: #fafafa;
|
|
33726
|
+
}
|
|
33727
|
+
|
|
33728
|
+
.itinerary-default-items {
|
|
33729
|
+
border: 1px solid #e5e7eb;
|
|
33730
|
+
border-radius: 16px;
|
|
33731
|
+
padding: 20px;
|
|
33732
|
+
background: #fff;
|
|
33733
|
+
box-shadow: 0 2px 10px rgba(0, 0, 0, 0.04);
|
|
33734
|
+
}
|
|
33735
|
+
|
|
33736
|
+
.itinerary-default-items__title {
|
|
33737
|
+
margin: 0 0 16px;
|
|
33738
|
+
font-size: 22px;
|
|
33739
|
+
}
|
|
33740
|
+
|
|
33741
|
+
@media (max-width: 768px) {
|
|
33742
|
+
.itinerary-shell {
|
|
33743
|
+
padding: 16px;
|
|
33744
|
+
}
|
|
33745
|
+
}
|
|
33746
|
+
|
|
33747
|
+
${itinerary?.styleSheetBody ?? ''}
|
|
33748
|
+
</style>
|
|
33749
|
+
|
|
33750
|
+
${html}
|
|
33476
33751
|
`;
|
|
33477
33752
|
}, [html, itinerary?.styleSheetBody, isLoading]);
|
|
33478
33753
|
return (React__default["default"].createElement(React__default["default"].Fragment, null,
|
|
@@ -33576,27 +33851,6 @@ const DayByDayExcursions = () => {
|
|
|
33576
33851
|
})));
|
|
33577
33852
|
};
|
|
33578
33853
|
|
|
33579
|
-
/**
|
|
33580
|
-
* The entry to send to the backend, as opposed to the one the page works with.
|
|
33581
|
-
*
|
|
33582
|
-
* They differ only for a traject: the page keeps the line guids the traject was rendered with,
|
|
33583
|
-
* because that is what joins its nodes to its lines, while pricing and booking need the guids the
|
|
33584
|
-
* searches cached their lines under. Anything else passes through untouched, so this can be used
|
|
33585
|
-
* wherever the entry leaves the component without checking which flow is running.
|
|
33586
|
-
*/
|
|
33587
|
-
const useBookableEntry = () => {
|
|
33588
|
-
const context = React.useContext(SearchResultsConfigurationContext);
|
|
33589
|
-
const { editablePackagingEntry, trajectNodeAvailability, trajectFlightAvailability } = reactRedux.useSelector((state) => state.searchResults);
|
|
33590
|
-
const trajectEntry = context?.trajectEntry;
|
|
33591
|
-
return React.useMemo(() => {
|
|
33592
|
-
if (!editablePackagingEntry)
|
|
33593
|
-
return null;
|
|
33594
|
-
if (!trajectEntry)
|
|
33595
|
-
return editablePackagingEntry;
|
|
33596
|
-
return withCachedEntryLineGuids(editablePackagingEntry, trajectEntry, trajectNodeAvailability, trajectFlightAvailability);
|
|
33597
|
-
}, [editablePackagingEntry, trajectEntry, trajectNodeAvailability, trajectFlightAvailability]);
|
|
33598
|
-
};
|
|
33599
|
-
|
|
33600
33854
|
const renderEditablePackagingEntrySummaryOptions = (editablePackagingEntry, priceDetails, translations, currencyCode) => {
|
|
33601
33855
|
const priceDetailsByProduct = lodash.groupBy(priceDetails?.details ?? [], (detail) => `${detail.productCode}|${detail.accommodationCode}`);
|
|
33602
33856
|
return (editablePackagingEntry?.lines ?? []).map((line) => {
|
|
@@ -34087,15 +34341,18 @@ const getNodeIcon = (node) => {
|
|
|
34087
34341
|
const isRenderableNode = (node) => node.trajectNodeType === REGULAR_TRAJECT_NODE_TYPE &&
|
|
34088
34342
|
(node.serviceType === ACCOMMODATION_SERVICE_TYPE || node.serviceType === EXCURSION_SERVICE_TYPE || node.serviceType === FLIGHT_SERVICE_TYPE);
|
|
34089
34343
|
const MAX_DAY_ACTIVITIES = 6;
|
|
34344
|
+
const MAX_HOTEL_RESULTS = 6;
|
|
34090
34345
|
const TrajectResults = ({ isLoading }) => {
|
|
34091
34346
|
const context = React.useContext(SearchResultsConfigurationContext);
|
|
34092
34347
|
const dispatch = reactRedux.useDispatch();
|
|
34093
34348
|
const loadDay = useTrajectDayActivities();
|
|
34094
34349
|
const translations = getTranslations(context?.languageCode ?? 'en-GB');
|
|
34095
34350
|
const locale = getLocale(context?.languageCode ?? 'en-GB');
|
|
34096
|
-
const { trajectNodeAvailability, trajectFlightAvailability, trajectDaySuggestions, editablePackagingEntry
|
|
34351
|
+
const { trajectNodeAvailability, trajectFlightAvailability, trajectDaySuggestions, editablePackagingEntry } = reactRedux.useSelector((state) => state.searchResults);
|
|
34097
34352
|
const trajectEntry = context?.trajectEntry;
|
|
34098
34353
|
const hideShowMoreResults = !!context?.hideShowMoreResults;
|
|
34354
|
+
const loadDayActivitiesOnDemand = !!context?.loadDayActivitiesOnDemand;
|
|
34355
|
+
const showNonPreferredHotels = !!context?.showNonPreferredHotels;
|
|
34099
34356
|
const nodesWithLines = React.useMemo(() => (trajectEntry ? getTrajectNodesWithLines(trajectEntry) : []), [trajectEntry]);
|
|
34100
34357
|
const lineByNodeId = React.useMemo(() => new Map(nodesWithLines.map((x) => [x.node.nodeId, x])), [nodesWithLines]);
|
|
34101
34358
|
const nodesByDay = React.useMemo(() => {
|
|
@@ -34123,6 +34380,24 @@ const TrajectResults = ({ isLoading }) => {
|
|
|
34123
34380
|
});
|
|
34124
34381
|
return { stayByDay: byDay, stayStartByNodeId: byNodeId };
|
|
34125
34382
|
}, [nodesWithLines]);
|
|
34383
|
+
/** Whether every node of the trip has an answer, one way or the other. */
|
|
34384
|
+
const tripResolved = React.useMemo(() => nodesWithLines
|
|
34385
|
+
.filter((x) => isSearchableTrajectNode(x.node) || isTrajectFlightNode(x.node))
|
|
34386
|
+
.every((x) => {
|
|
34387
|
+
const status = isTrajectFlightNode(x.node) ? trajectFlightAvailability[x.line.guid]?.status : trajectNodeAvailability[x.line.guid]?.status;
|
|
34388
|
+
return !!status && status !== 'loading';
|
|
34389
|
+
}), [nodesWithLines, trajectNodeAvailability, trajectFlightAvailability]);
|
|
34390
|
+
/**
|
|
34391
|
+
* Each day's activities are one more search, and a traject has as many as it has days. They go
|
|
34392
|
+
* out together, but only once the trip itself has resolved — sharing the connections with the
|
|
34393
|
+
* searches the trip cannot do without would only make those slower. A portal can turn the
|
|
34394
|
+
* automatic load off, and then each day waits for its own "show activities" click instead.
|
|
34395
|
+
*/
|
|
34396
|
+
React.useEffect(() => {
|
|
34397
|
+
if (!trajectEntry || !tripResolved || loadDayActivitiesOnDemand)
|
|
34398
|
+
return;
|
|
34399
|
+
(trajectEntry.traject.days ?? []).filter((day) => stayByDay.has(day.order)).forEach((day) => loadDay(day));
|
|
34400
|
+
}, [trajectEntry, tripResolved, stayByDay, loadDayActivitiesOnDemand]);
|
|
34126
34401
|
if (!context || !trajectEntry)
|
|
34127
34402
|
return null;
|
|
34128
34403
|
const handleSelect = (item, code) => {
|
|
@@ -34196,6 +34471,10 @@ const TrajectResults = ({ isLoading }) => {
|
|
|
34196
34471
|
const selected = results.find((x) => x.code === availability?.selectedCode) ?? null;
|
|
34197
34472
|
const configured = results.filter((x) => x.code !== selected?.code && !!findCandidateForResult(node, x));
|
|
34198
34473
|
const others = results.filter((x) => x.code !== selected?.code && !findCandidateForResult(node, x));
|
|
34474
|
+
// A hotel row holds the hotels configured on the node; a portal can also let it fill up with
|
|
34475
|
+
// non-preferred hotels found in the area, the rest staying behind "show more".
|
|
34476
|
+
const fill = showNonPreferredHotels && node.serviceType === ACCOMMODATION_SERVICE_TYPE ? others.slice(0, Math.max(MAX_HOTEL_RESULTS - 1 - configured.length, 0)) : [];
|
|
34477
|
+
const remaining = others.length - fill.length;
|
|
34199
34478
|
// No entry yet means the node's search has been queued but not dispatched — still loading.
|
|
34200
34479
|
const status = availability?.status ?? 'loading';
|
|
34201
34480
|
return (React__default["default"].createElement(React__default["default"].Fragment, { key: line.guid },
|
|
@@ -34215,12 +34494,12 @@ const TrajectResults = ({ isLoading }) => {
|
|
|
34215
34494
|
node.preferredAccommodationName,
|
|
34216
34495
|
" \u2014 ",
|
|
34217
34496
|
translations.SRP.NO_RESULTS))),
|
|
34218
|
-
React__default["default"].createElement("div", { className: "search__results__cards search__results__cards--scroll" }, [selected, ...configured].map((result) => (React__default["default"].createElement(TrajectNodeCard, { key: result.code, node: node, result: result, isSelected: result.code === selected.code, languageCode: context.languageCode, translations: translations, onSelect: () => handleSelect(item, result.code), onEditOptions: node.serviceType === ACCOMMODATION_SERVICE_TYPE ? () => handleEditOptions(item) : undefined, showNights: node.serviceType === ACCOMMODATION_SERVICE_TYPE })))),
|
|
34219
|
-
|
|
34497
|
+
React__default["default"].createElement("div", { className: "search__results__cards search__results__cards--scroll" }, [selected, ...configured, ...fill].map((result) => (React__default["default"].createElement(TrajectNodeCard, { key: result.code, node: node, result: result, isSelected: result.code === selected.code, languageCode: context.languageCode, translations: translations, onSelect: () => handleSelect(item, result.code), onEditOptions: node.serviceType === ACCOMMODATION_SERVICE_TYPE ? () => handleEditOptions(item) : undefined, showNights: node.serviceType === ACCOMMODATION_SERVICE_TYPE })))),
|
|
34498
|
+
remaining > 0 && !hideShowMoreResults && (React__default["default"].createElement("div", { className: "search__results__cards__actions" },
|
|
34220
34499
|
React__default["default"].createElement("button", { type: "button", className: "cta cta--secondary", onClick: () => handleShowMore(item) },
|
|
34221
34500
|
translations.SRP.SHOW_MORE,
|
|
34222
34501
|
" (",
|
|
34223
|
-
|
|
34502
|
+
remaining,
|
|
34224
34503
|
")")))))));
|
|
34225
34504
|
};
|
|
34226
34505
|
const handleSelectFlight = (item, flight) => {
|
|
@@ -34279,11 +34558,6 @@ const TrajectResults = ({ isLoading }) => {
|
|
|
34279
34558
|
if (lines.length)
|
|
34280
34559
|
dispatch(addEditableEntryLines(lines));
|
|
34281
34560
|
};
|
|
34282
|
-
const handleShowItinerary = () => {
|
|
34283
|
-
dispatch(setTrajectItineraryView(true));
|
|
34284
|
-
if (typeof window !== 'undefined')
|
|
34285
|
-
window.scrollTo(0, 0);
|
|
34286
|
-
};
|
|
34287
34561
|
const handleShowMoreActivities = (dayOrder) => {
|
|
34288
34562
|
dispatch(setTrajectActivitiesDayOrder(dayOrder));
|
|
34289
34563
|
dispatch(setFlyInType('traject-day-activities'));
|
|
@@ -34308,16 +34582,17 @@ const TrajectResults = ({ isLoading }) => {
|
|
|
34308
34582
|
const cards = buildDayActivityCards(items, trajectNodeAvailability, suggestions?.results ?? []);
|
|
34309
34583
|
const nodesResolving = items.some((item) => (trajectNodeAvailability[item.line.guid]?.status ?? 'loading') === 'loading');
|
|
34310
34584
|
const isSearching = suggestions?.status === 'loading';
|
|
34311
|
-
|
|
34585
|
+
// A day is worth filling only if the party is staying somewhere that night. The day they fly
|
|
34586
|
+
// home is covered by no stay — the last night was the night before — and nobody is looking for
|
|
34587
|
+
// something to do on it.
|
|
34588
|
+
const canSearch = stayByDay.has(day.order) && !!getDayDestination(nodesWithLines, trajectNodeAvailability, day.order);
|
|
34312
34589
|
if (!items.length && !canSearch)
|
|
34313
34590
|
return null;
|
|
34314
34591
|
const visible = cards.slice(0, MAX_DAY_ACTIVITIES);
|
|
34315
34592
|
const hidden = cards.length - visible.length;
|
|
34593
|
+
const awaitsRequest = loadDayActivitiesOnDemand && !suggestions && canSearch && !nodesResolving && hidden === 0;
|
|
34316
34594
|
return (React__default["default"].createElement(React__default["default"].Fragment, { key: `activities-${day.order}` },
|
|
34317
|
-
React__default["default"].createElement("div", { className: "search__results__label search__results__label--
|
|
34318
|
-
React__default["default"].createElement("div", { className: "search__results__label__date" },
|
|
34319
|
-
React__default["default"].createElement("p", { className: "search__results__label__date-date" }, dateFns.format(new Date(day.date), 'd', { locale })),
|
|
34320
|
-
React__default["default"].createElement("p", null, dateFns.format(new Date(day.date), 'MMM', { locale }))),
|
|
34595
|
+
React__default["default"].createElement("div", { className: "search__results__label search__results__label--sub" },
|
|
34321
34596
|
React__default["default"].createElement("div", { className: "search__results__label__text" },
|
|
34322
34597
|
React__default["default"].createElement(Icon, { name: "ui-excursion", height: 16 }),
|
|
34323
34598
|
React__default["default"].createElement("h3", null,
|
|
@@ -34326,7 +34601,7 @@ const TrajectResults = ({ isLoading }) => {
|
|
|
34326
34601
|
!!cards.length && React__default["default"].createElement("div", { className: "search__results__cards search__results__cards--scroll" }, visible.map(renderActivityCard)),
|
|
34327
34602
|
!nodesResolving && !isSearching && !cards.length && (!!items.length || !!suggestions) && (React__default["default"].createElement("div", { className: "no-results" }, translations.SRP.NO_RESULTS)),
|
|
34328
34603
|
React__default["default"].createElement("div", { className: "search__results__cards__actions" },
|
|
34329
|
-
|
|
34604
|
+
awaitsRequest && (React__default["default"].createElement("button", { type: "button", className: "cta cta--secondary", onClick: () => loadDay(day) }, translations.SRP.SHOW_ACTIVITIES)),
|
|
34330
34605
|
hidden > 0 && !hideShowMoreResults && (React__default["default"].createElement("button", { type: "button", className: "cta cta--secondary", onClick: () => handleShowMoreActivities(day.order) },
|
|
34331
34606
|
translations.SRP.SHOW_MORE,
|
|
34332
34607
|
" (",
|
|
@@ -34343,35 +34618,32 @@ const TrajectResults = ({ isLoading }) => {
|
|
|
34343
34618
|
};
|
|
34344
34619
|
if (isLoading)
|
|
34345
34620
|
return React__default["default"].createElement(Spinner, { label: translations.SRP.LOADING_ITINERARY });
|
|
34346
|
-
return (React__default["default"].createElement(React__default["default"].Fragment, null,
|
|
34347
|
-
|
|
34348
|
-
|
|
34349
|
-
|
|
34350
|
-
|
|
34351
|
-
|
|
34352
|
-
|
|
34353
|
-
|
|
34354
|
-
|
|
34355
|
-
|
|
34356
|
-
|
|
34357
|
-
|
|
34358
|
-
|
|
34359
|
-
|
|
34360
|
-
|
|
34361
|
-
|
|
34362
|
-
|
|
34363
|
-
|
|
34364
|
-
|
|
34365
|
-
|
|
34366
|
-
|
|
34367
|
-
|
|
34368
|
-
|
|
34369
|
-
|
|
34370
|
-
|
|
34371
|
-
|
|
34372
|
-
}),
|
|
34373
|
-
React__default["default"].createElement("div", { className: "search__results__cards__actions" },
|
|
34374
|
-
React__default["default"].createElement("button", { type: "button", className: "cta", disabled: trajectResolving, onClick: handleShowItinerary }, translations.STEPS.NEXT))));
|
|
34621
|
+
return (React__default["default"].createElement(React__default["default"].Fragment, null, trajectEntry.traject.days.map((day) => {
|
|
34622
|
+
const stay = stayByDay.get(day.order);
|
|
34623
|
+
const dayNodes = (nodesByDay.get(day.order) ?? []).filter((node) => isRenderableNode(node) && lineByNodeId.has(node.nodeId));
|
|
34624
|
+
const stayLeadsDay = !!stay && (stay.night > 0 || dayNodes[0]?.nodeId === stay.item.node.nodeId);
|
|
34625
|
+
// Where the day's activities belong in the order: with the first excursion it carries.
|
|
34626
|
+
const firstExcursionNodeId = dayNodes.find((node) => node.serviceType === EXCURSION_SERVICE_TYPE)?.nodeId;
|
|
34627
|
+
const showDayHeader = stayLeadsDay || !!day.name?.trim();
|
|
34628
|
+
return (React__default["default"].createElement(React__default["default"].Fragment, { key: `day-${day.order}` },
|
|
34629
|
+
showDayHeader && renderDayHeader(day, stayLeadsDay ? stay : undefined),
|
|
34630
|
+
dayNodes.map((node) => {
|
|
34631
|
+
const item = lineByNodeId.get(node.nodeId);
|
|
34632
|
+
if (node.serviceType === ACCOMMODATION_SERVICE_TYPE) {
|
|
34633
|
+
const stayStart = stayStartByNodeId.get(node.nodeId);
|
|
34634
|
+
const titledByDayHeader = stayLeadsDay && stay.item.node.nodeId === node.nodeId;
|
|
34635
|
+
return renderServiceNode(item, !titledByDayHeader, stayStart && getStayTitle(stayStart));
|
|
34636
|
+
}
|
|
34637
|
+
// Every excursion the day holds is drawn once, in one block, where the first of
|
|
34638
|
+
// them falls in the order — so the activities still sit between the stay and the
|
|
34639
|
+
// flight that follow them.
|
|
34640
|
+
if (node.serviceType === EXCURSION_SERVICE_TYPE) {
|
|
34641
|
+
return node.nodeId === firstExcursionNodeId ? renderDayActivities(day) : null;
|
|
34642
|
+
}
|
|
34643
|
+
return renderFlightNode(item);
|
|
34644
|
+
}),
|
|
34645
|
+
firstExcursionNodeId === undefined && renderDayActivities(day)));
|
|
34646
|
+
})));
|
|
34375
34647
|
};
|
|
34376
34648
|
|
|
34377
34649
|
const useTrajectAvailability = () => {
|
|
@@ -35318,6 +35590,9 @@ const SearchResultsContainer = ({ onBookingStarted }) => {
|
|
|
35318
35590
|
setPricesAreLoading(false);
|
|
35319
35591
|
}
|
|
35320
35592
|
};
|
|
35593
|
+
fetchPriceDetails();
|
|
35594
|
+
}, [editablePackagingEntry, bookableEntry, trajectResolving]);
|
|
35595
|
+
React.useEffect(() => {
|
|
35321
35596
|
const fetchItinerary = async () => {
|
|
35322
35597
|
if (!context || !context.packagingEntry || !editablePackagingEntry || lodash.isEmpty(editablePackagingEntry.lines))
|
|
35323
35598
|
return;
|
|
@@ -35347,7 +35622,6 @@ const SearchResultsContainer = ({ onBookingStarted }) => {
|
|
|
35347
35622
|
setItineraryIsLoading(false);
|
|
35348
35623
|
}
|
|
35349
35624
|
};
|
|
35350
|
-
fetchPriceDetails();
|
|
35351
35625
|
fetchItinerary();
|
|
35352
35626
|
}, [editablePackagingEntry, bookableEntry, trajectResolving, trajectItineraryView]);
|
|
35353
35627
|
// Flight selection
|
|
@@ -35698,11 +35972,6 @@ const SearchResultsContainer = ({ onBookingStarted }) => {
|
|
|
35698
35972
|
address: {}
|
|
35699
35973
|
};
|
|
35700
35974
|
};
|
|
35701
|
-
const handleComposeTraject = () => {
|
|
35702
|
-
dispatch(setTrajectItineraryView(false));
|
|
35703
|
-
if (typeof window !== 'undefined')
|
|
35704
|
-
window.scrollTo(0, 0);
|
|
35705
|
-
};
|
|
35706
35975
|
const handleShowMoreFlights = (flyInType) => {
|
|
35707
35976
|
dispatch(setFlyInType(flyInType));
|
|
35708
35977
|
dispatch(setFlyInIsOpen(true));
|
|
@@ -35793,10 +36062,7 @@ const SearchResultsContainer = ({ onBookingStarted }) => {
|
|
|
35793
36062
|
selectedReturnKey && selectedReturn && (React__default["default"].createElement(IndependentFlightOption, { key: `flight-${selectedReturnKey}`, item: selectedReturn.return, guid: selectedReturn.outwardGuid, selectedGuid: selectedReturn.outwardGuid, isOutward: false, showSelectedState: true, price: selectedReturn.price })),
|
|
35794
36063
|
uniqueReturnFlights.map((result) => (React__default["default"].createElement(IndependentFlightOption, { key: `flight-${result.outwardGuid}`, item: result.return, onSelect: () => dispatch(setSelectedReturnKey(getFlightKey(result.return.segments))), guid: result.outwardGuid, isOutward: false, currentSelectedPrice: selectedReturn?.price, price: result.price })))))),
|
|
35795
36064
|
context.searchConfiguration.qsmType === build.PortalQsmType.AccommodationAndFlight && context.trajectEntry && !trajectItineraryView && (React__default["default"].createElement(TrajectResults, { isLoading: isLoading })),
|
|
35796
|
-
context.searchConfiguration.qsmType === build.PortalQsmType.AccommodationAndFlight && context.trajectEntry && trajectItineraryView && (React__default["default"].createElement(
|
|
35797
|
-
React__default["default"].createElement("div", { className: "search__results__cards__actions" },
|
|
35798
|
-
React__default["default"].createElement("button", { type: "button", className: "cta cta--secondary", onClick: handleComposeTraject }, translations.STEPS.PREVIOUS)),
|
|
35799
|
-
React__default["default"].createElement(FullItinerary, { isLoading: itineraryIsLoading }))),
|
|
36065
|
+
context.searchConfiguration.qsmType === build.PortalQsmType.AccommodationAndFlight && context.trajectEntry && trajectItineraryView && (React__default["default"].createElement(FullItinerary, { isLoading: itineraryIsLoading })),
|
|
35800
36066
|
context.searchConfiguration.qsmType === build.PortalQsmType.AccommodationAndFlight && context.packagingEntry && !context.trajectEntry && (React__default["default"].createElement(FullItinerary, { isLoading: itineraryIsLoading })))),
|
|
35801
36067
|
React__default["default"].createElement(FlyIn, { srpType: context.searchConfiguration.qsmType, isOpen: flyInIsOpen, setIsOpen: handleFlyInToggle, handleConfirm: () => handleConfirmHotelSwap(), onPanelRef: (el) => (panelRef.current = el), detailsLoading: detailsIsLoading, flyInType: flyInType, isPackageEditFlow: !!context.packagingEntry, sortByTypes: sortByTypes, activeSearchSeed: activeSearchSeed, toggleFilters: () => setFiltersOpen(!filtersOpen), filtersOpen: filtersOpen })))))))));
|
|
35802
36068
|
};
|
|
@@ -38705,20 +38971,20 @@ function ItineraryMapView({ destinations: propDestinations, adults = 2, dateFrom
|
|
|
38705
38971
|
const isStartEnd = dest.isStart || dest.isEnd;
|
|
38706
38972
|
let iconHtml;
|
|
38707
38973
|
if (isStartEnd) {
|
|
38708
|
-
iconHtml = `
|
|
38709
|
-
<div class="map-view__marker map-view__marker--plane">
|
|
38710
|
-
<svg viewBox="0 0 576 512" fill="currentColor" width="16" height="16" xmlns="http://www.w3.org/2000/svg">
|
|
38711
|
-
<path d="M482.3 192c34.2 0 93.7 29 93.7 64c0 36-59.5 64-93.7 64l-116.6 0L265.2 495.9c-5.7 10.1-16.3 16.1-27.8 16.1l-56.2 0c-10.6 0-18.3-10.3-15.8-20.6l49-196.3L112 288 68.8 377.6c-3 6.1-9.2 10.4-16 10.4l-2.8 0c-9.2 0-16-8.8-13.3-17.6L80 256L36.7 141.6C34 132.8 40.8 124 50 124l2.8 0c6.8 0 13 4.3 16 10.4L112 224l102.9 0-49-196.3C163.5 17.3 171.2 7 181.8 7l56.2 0c11.5 0 22.1 6 27.8 16.1L365.7 192l116.6 0z"/>
|
|
38712
|
-
</svg>
|
|
38974
|
+
iconHtml = `
|
|
38975
|
+
<div class="map-view__marker map-view__marker--plane">
|
|
38976
|
+
<svg viewBox="0 0 576 512" fill="currentColor" width="16" height="16" xmlns="http://www.w3.org/2000/svg">
|
|
38977
|
+
<path d="M482.3 192c34.2 0 93.7 29 93.7 64c0 36-59.5 64-93.7 64l-116.6 0L265.2 495.9c-5.7 10.1-16.3 16.1-27.8 16.1l-56.2 0c-10.6 0-18.3-10.3-15.8-20.6l49-196.3L112 288 68.8 377.6c-3 6.1-9.2 10.4-16 10.4l-2.8 0c-9.2 0-16-8.8-13.3-17.6L80 256L36.7 141.6C34 132.8 40.8 124 50 124l2.8 0c6.8 0 13 4.3 16 10.4L112 224l102.9 0-49-196.3C163.5 17.3 171.2 7 181.8 7l56.2 0c11.5 0 22.1 6 27.8 16.1L365.7 192l116.6 0z"/>
|
|
38978
|
+
</svg>
|
|
38713
38979
|
</div>`;
|
|
38714
38980
|
}
|
|
38715
38981
|
else {
|
|
38716
38982
|
stopIndex++;
|
|
38717
38983
|
const imgStyle = dest.imageUrl ? `style="background-image:url('${dest.imageUrl}')"` : '';
|
|
38718
|
-
iconHtml = `
|
|
38719
|
-
<div class="map-view__marker map-view__marker--stop" ${imgStyle}>
|
|
38720
|
-
${!dest.imageUrl ? `<span class="map-view__marker-number">${stopIndex}</span>` : ''}
|
|
38721
|
-
<span class="map-view__marker-badge">${stopIndex}</span>
|
|
38984
|
+
iconHtml = `
|
|
38985
|
+
<div class="map-view__marker map-view__marker--stop" ${imgStyle}>
|
|
38986
|
+
${!dest.imageUrl ? `<span class="map-view__marker-number">${stopIndex}</span>` : ''}
|
|
38987
|
+
<span class="map-view__marker-badge">${stopIndex}</span>
|
|
38722
38988
|
</div>`;
|
|
38723
38989
|
}
|
|
38724
38990
|
const icon = L.divIcon({
|