import React, { useContext } from 'react'; import { useSelector } from 'react-redux'; import { getDateFromParams, getFlightsFromParams, getNumberFromParams, getNumbersFromParams, getRoomsFromParams, getStringFromParams } from '../../../shared/utils/query-string-util'; import { fetchPackage, setAccommodationViewId, setAgentAdressId, setBookingAttributes, setBookingNumber, setBookingOptions, setBookingType, setCalculateDeposit, setCurrentStep, setGeneratePaymentUrl, setLanguageCode, setOfficeId, setProductAttributes, setShowCommission, setSkipPayment, setTagIds, setTranslations } from './booking-slice'; import { isNil } from 'lodash'; import { useEffect } from 'react'; import Loader from '../../../shared/components/loader'; import { setApiKey, setApiUrl } from '../../api-settings-slice'; import StepRoute from '../../components/step-route'; import SettingsContext from '../../settings-context'; import { useAppDispatch } from '../../store'; import Confirmation from '../confirmation/confirmation'; import Error from '../error/error'; import FlightOptionsForm from '../flight-options'; import OptionsForm from '../product-options/options-form'; import RoomOptionsForm from '../room-options'; import Sidebar from '../sidebar'; import Summary from '../summary/summary'; import TravelersForm from '../travelers-form/travelers-form'; import { CONFIRMATION_STEP, ERROR_STEP, FLIGHT_OPTIONS_FORM_STEP, OPTIONS_FORM_STEP, ROOM_OPTIONS_FORM_STEP, SUMMARY_STEP, TRAVELERS_FORM_STEP } from './constants'; import { selectApiSettings, selectBookingAttributes, selectBookingNumber, selectBookingRooms, selectCurrentStep, selectIsUnavailable, selectPackageDetails, selectProductAttributes, selectTranslations } from './selectors'; interface BookingProps { productCode: string; productName: string; thumbnailUrl?: string; } const BookingSelfContained: React.FC = ({ productCode, productName, thumbnailUrl }) => { const { officeId, bookingOptions, showSidebarDeposit, showCommission, includeFlights, skipPaymentWithAgent, generatePaymentUrl, tagIds, agentAdressId, language, apiUrl, apiKey, translationFiles, roomOptions, flightOptions, accommodationViewId, isOffer, allowOption, travellers } = useContext(SettingsContext); const dispatch = useAppDispatch(); const productAttributes = useSelector(selectProductAttributes); const bookingAttributes = useSelector(selectBookingAttributes); const rooms = useSelector(selectBookingRooms); const bookingNumber = useSelector(selectBookingNumber); const packageDetails = useSelector(selectPackageDetails); const isUnvailable = useSelector(selectIsUnavailable); const currentStep = useSelector(selectCurrentStep); const apiSettings = useSelector(selectApiSettings); const translations = useSelector(selectTranslations); useEffect(() => { dispatch(setSkipPayment(skipPaymentWithAgent ?? false)); dispatch(setGeneratePaymentUrl(generatePaymentUrl ?? false)); }, [skipPaymentWithAgent, generatePaymentUrl]); useEffect(() => { if (!isNil(apiUrl) && !isNil(apiKey)) { dispatch(setApiUrl(apiUrl)); dispatch(setApiKey(apiKey)); } }, [apiUrl, apiKey]); useEffect(() => { const params = new URLSearchParams(location.search); const startDate = getDateFromParams(params, 'startDate'); const endDate = getDateFromParams(params, 'endDate'); const catalogueId = getNumberFromParams(params, 'catalogueId') ?? getNumberFromParams(params, 'catalog'); const rooms = getRoomsFromParams(params, 'rooms'); const flight = getFlightsFromParams(params, 'flight'); const flightRouteId = getStringFromParams(params, 'flightRouteId'); const vendorConfigurationId = getNumberFromParams(params, 'vendorConfigurationId'); const allotmentName = getStringFromParams(params, 'allotmentName'); const allotmentIds = getNumbersFromParams(params, 'allotmentId'); const tourCode = getStringFromParams(params, 'tourCode'); const bookingNumber = params.get('bookingNr') ?? undefined; if (typeof window !== 'undefined') { window.scrollTo(0, 0); } if (!isNil(bookingNumber)) { dispatch(setBookingNumber(bookingNumber)); dispatch(setCurrentStep(CONFIRMATION_STEP)); } else if (travellers.travelersFirstStep) { dispatch(setCurrentStep(TRAVELERS_FORM_STEP)); } else if (!flightOptions.isHidden) { dispatch(setCurrentStep(FLIGHT_OPTIONS_FORM_STEP)); } else if (!roomOptions.isHidden) { dispatch(setCurrentStep(ROOM_OPTIONS_FORM_STEP)); } if (!isNil(startDate) && !isNil(endDate) && !isNil(catalogueId) && !isNil(rooms)) { dispatch( setBookingAttributes({ startDate, endDate, catalogueId, rooms, flight, includeFlights, allotmentName, allotmentIds, tourCode, flightRouteId, vendorConfigurationId }) ); } else { console.error('Failure when setting booking attributes', startDate, endDate, catalogueId, rooms); } }, [location.search, setBookingAttributes, setBookingNumber, includeFlights]); useEffect(() => { if (!isNil(productCode) && !isNil(productName)) { dispatch( setProductAttributes({ productCode, productName }) ); } else { console.error('Failure when setting product attributes', productCode, productName); } }, [productCode, productName, setProductAttributes]); const getTranslations = async () => { const translations = translationFiles?.map((x) => fetch(x.path) .then((y) => y.json()) .then((z) => ({ language: x.language, value: z })) ); return translations && (await Promise.all(translations)); }; useEffect(() => { const loadTranslations = async () => { const translations = await getTranslations(); dispatch(setTranslations(translations)); // Now dispatch the resolved value }; loadTranslations(); dispatch(setOfficeId(officeId)); dispatch(setLanguageCode(language)); dispatch(setBookingOptions(bookingOptions)); dispatch(setCalculateDeposit(showSidebarDeposit)); dispatch(setShowCommission(showCommission)); if (tagIds && tagIds.length > 0) { dispatch(setTagIds(tagIds ?? undefined)); } dispatch(setAgentAdressId(agentAdressId ?? undefined)); if (agentAdressId && agentAdressId != 0) { dispatch(setBookingType('b2b')); } if (accommodationViewId && accommodationViewId != 0) { dispatch(setAccommodationViewId(accommodationViewId)); } }, [ officeId, language, bookingOptions, showSidebarDeposit, showCommission, setOfficeId, setLanguageCode, setCalculateDeposit, tagIds, agentAdressId, accommodationViewId ]); useEffect(() => { if (!productAttributes || !bookingAttributes || !rooms?.length || !isNil(bookingNumber) || !isNil(packageDetails)) { return; } // Fetch data const promise = dispatch(fetchPackage()); return () => { promise.abort(); }; }, [productAttributes, bookingAttributes, rooms, bookingNumber, packageDetails, apiSettings.apiUrl, apiSettings.apiKey]); const renderStep = () => { switch (currentStep) { case FLIGHT_OPTIONS_FORM_STEP: return } />; case ROOM_OPTIONS_FORM_STEP: return } />; case OPTIONS_FORM_STEP: return ( } /> ); case TRAVELERS_FORM_STEP: return ( } /> ); case SUMMARY_STEP: return ( } /> ); case CONFIRMATION_STEP: return ( } /> ); case ERROR_STEP: return ( } /> ); } }; return ( <> {((productAttributes && bookingAttributes && packageDetails) || bookingNumber) && (
{renderStep()}
{packageDetails && }
)} {!packageDetails && !bookingNumber && !isUnvailable && (

{allowOption ? translations.MAIN.PREPARING_DOSSIER : isOffer ? translations.MAIN.PREPARING_OFFER : translations.MAIN.PREPARING_BOOKING}

)} {isUnvailable && (

{translations.MAIN.PRODUCT_UNAVAILABLE}

)} ); }; export default BookingSelfContained;