import React, { useContext, useEffect, useMemo, useState } from 'react'; import { getTranslations } from '../../../shared/utils/localization-util'; import { SearchResultsRootState } from '../../store/search-results-store'; import { useDispatch, useSelector } from 'react-redux'; import SearchResultsConfigurationContext from '../../search-results-configuration-context'; import BookingPanel from '../../../shared/booking/booking-panel'; import StepIndicators from '../../../shared/booking/step-indicators'; import WLSidebar from './wl-sidebar'; import { SearchSeed } from '../../types'; import SharedTravelersForm, { applyTravelersFormValuesToEditablePackagingEntry, createInitialValuesFromEditablePackagingEntry, SharedTravelersSettings } from '../../../shared/booking/travelers-form'; import { useFormik } from 'formik'; import { TravelersFormValues } from '../../../booking-wizard/types'; import { setBookingNumber, setCurrentStep, setEditablePackagingEntry } from '../../store/search-results-slice'; import validateForm from '../../../booking-wizard/features/travelers-form/validate-form'; import { bookPackagingEntry, CountryItem, getCountries, PackagingAccommodationResponse, PackagingEntry, PackagingRequestBase, TideClientConfig } from '@qite/tide-client'; import SharedSummary from '../../../shared/booking/summary'; import { renderEditablePackagingEntrySummaryOptions } from '../../../shared/utils/booking-summary'; import SharedConfirmation from '../../../shared/booking/shared-confirmation'; import Spinner from '../spinner/spinner'; interface BookPackagingEntryProps { activeSearchSeed: SearchSeed | null; isLoading: boolean; isConfirmationPage?: boolean; } const travelerFormFields = [{ type: 'gender' }, { type: 'firstName' }, { type: 'lastName' }, { type: 'birthDate' }]; const mainBookerFormFields = [ { type: 'street' }, { type: 'houseNumber' }, { type: 'box' }, { type: 'zipCode' }, { type: 'place' }, { type: 'country' }, { type: 'phone' }, { type: 'email' } ]; const travellersSettings: SharedTravelersSettings = { countries: [ { iso2: 'BE', name: 'Belgium', phonePrefix: '+32' }, { iso2: 'NL', name: 'Netherlands', phonePrefix: '+31' }, { iso2: 'FR', name: 'France', phonePrefix: '+33' } ], formFields: travelerFormFields, mainBookerFormFields }; const BookPackagingEntry: React.FC = ({ activeSearchSeed, isLoading, isConfirmationPage }) => { const context = useContext(SearchResultsConfigurationContext); const dispatch = useDispatch(); const { editablePackagingEntry, priceDetails, currentStep, bookingNumber, selectedPackagingAccoResultCode, packagingAccoResults } = useSelector( (state: SearchResultsRootState) => state.searchResults ); const [countries, setCountries] = useState([]); const [userValidated, setUserValidated] = useState(true); const [remarks, setRemarks] = useState(''); const [isSubmitting, setIsSubmitting] = useState(false); const [selectedPackagingAccoResult, setSelectedPackagingAccoResult] = useState(null); const translations = useMemo(() => getTranslations(context?.languageCode ?? 'en-GB'), [context?.languageCode]); const stepLabels = [translations.STEPS.PERSONAL_DETAILS, translations.STEPS.SUMMARY, translations.STEPS.CONFIRMATION]; const config: TideClientConfig | null = useMemo(() => { if (!context) return null; return { host: context.tideConnection.host, apiKey: context.tideConnection.apiKey }; }, [context]); const initialValues = useMemo(() => { if (!editablePackagingEntry) { return {} as TravelersFormValues; } return createInitialValuesFromEditablePackagingEntry(editablePackagingEntry); }, [editablePackagingEntry?.transactionId]); const formik = useFormik({ initialValues, enableReinitialize: true, validate: (values) => validateForm(values, false, 'b2c', translations, travellersSettings.formFields, travellersSettings.mainBookerFormFields), onSubmit: (values) => { if (!editablePackagingEntry) return; dispatch(setEditablePackagingEntry(applyTravelersFormValuesToEditablePackagingEntry(editablePackagingEntry, values))); dispatch(setCurrentStep(1)); } }); useEffect(() => { if (!context || !config) return; const controller = new AbortController(); (async () => { try { const result = await getCountries(config, controller.signal); setCountries(result.items); } catch { // optionally handle error } })(); return () => controller.abort(); }, [context, config]); useEffect(() => { if (isConfirmationPage) { dispatch(setCurrentStep(2)); } }, [isConfirmationPage, dispatch]); useEffect(() => { const selectedPackagingAccoResult = packagingAccoResults?.find((result) => result.code === selectedPackagingAccoResultCode); if (selectedPackagingAccoResult) { setSelectedPackagingAccoResult(selectedPackagingAccoResult); } }, [selectedPackagingAccoResultCode, packagingAccoResults]); if (!context || !editablePackagingEntry || !priceDetails || !config) return ; const handleSummarySubmit: React.FormEventHandler = async (e) => { e.preventDefault(); setIsSubmitting(true); if (typeof window !== 'undefined') { window.scrollTo(0, 0); } let updatedEditablePackagingEntry: PackagingEntry = { ...editablePackagingEntry, remarks }; if (context.generatePaymentUrl && typeof window !== 'undefined') { const redirectUrl = new URL(window.location.href); redirectUrl.searchParams.set('bookingConfirmation', 'true'); redirectUrl.searchParams.set('link', ''); updatedEditablePackagingEntry = { ...updatedEditablePackagingEntry, redirectUrl: redirectUrl.toString(), returnPaymentUrl: true }; } dispatch(setEditablePackagingEntry(updatedEditablePackagingEntry)); try { const request = { language: context.languageCode ?? 'en-GB', officeId: context.tideConnection.officeId, catalogueId: context.searchConfiguration.defaultCatalogueId ?? 0, agentId: context.agentId, payload: updatedEditablePackagingEntry } as PackagingRequestBase; const bookingResponse = await bookPackagingEntry(config, request); dispatch(setBookingNumber(bookingResponse.number)); if (bookingResponse.paymentUrl) { window.location.href = bookingResponse.paymentUrl; } else { dispatch(setCurrentStep(2)); setIsSubmitting(false); } } catch (error) { dispatch(setCurrentStep(3)); } }; return (
( <> {step + 1}. {stepLabels[step]} )}> {isConfirmationPage && isLoading && } {currentStep === 0 && ( )} {currentStep === 1 && ( renderEditablePackagingEntrySummaryOptions(editablePackagingEntry, priceDetails, translations)} renderPreviousButton={() => ( )} /> )} {currentStep === 2 && ( )} {currentStep === 3 &&
{/* error */}
}
); }; export default BookPackagingEntry;