From b2935114e32976a7c2ff814c29d48fb35a5f325a Mon Sep 17 00:00:00 2001 From: Christel Westerberg Date: Mon, 13 Jan 2025 14:26:38 +0100 Subject: [PATCH] refactor: url management in hotel reservation flow --- .../(standard)/page.module.css | 3 +- .../(standard)/select-hotel/map/page.tsx | 11 +- .../(standard)/select-hotel/page.tsx | 6 +- .../(standard)/select-rate/page.tsx | 13 +- .../hotelreservation/(standard)/step/page.tsx | 16 +- .../hotelreservation/(standard)/utils.ts | 51 +++--- .../[contentType]/[uid]/page.tsx | 17 +- .../@bookingwidget/hotelreservation/page.tsx | 7 +- app/[lang]/(live)/@bookingwidget/page.tsx | 5 +- app/[lang]/(live-current)/layout.tsx | 1 - components/BookingWidget/Client.tsx | 25 ++- .../MobileToggleButton/index.tsx | 4 +- components/BookingWidget/index.tsx | 4 +- .../Forms/BookingWidget/form.module.css | 4 + components/Forms/BookingWidget/index.tsx | 27 +-- components/Forms/BookingWidget/schema.ts | 6 +- .../ChildSelector/ChildInfoSelector.tsx | 10 +- .../GuestsRoomsPicker/ChildSelector/index.tsx | 4 +- components/GuestsRoomsPicker/Form.tsx | 2 +- .../GuestsRoomsPicker/GuestsRoom/index.tsx | 6 +- components/GuestsRoomsPicker/index.tsx | 7 +- .../BookingConfirmation/index.tsx | 2 +- .../Payment/PaymentCallback/index.tsx | 8 +- .../EnterDetails/Payment/PaymentClient.tsx | 20 +-- .../SelectHotelMapContainer.tsx | 16 +- .../HotelReservation/SelectHotel/index.tsx | 24 +-- .../SelectRate/HotelInfoCard/NoRoomsAlert.tsx | 2 +- .../SelectRate/RoomFilter/index.tsx | 3 +- .../RoomSelection/RoomCard/index.tsx | 2 +- .../SelectRate/RoomSelection/index.tsx | 39 ++-- .../SelectRate/RoomSelection/utils.ts | 113 ------------ .../SelectRate/Rooms/RoomsContainer.tsx | 2 +- .../HotelReservation/SelectRate/utils.ts | 19 -- components/HotelReservation/utils.ts | 47 +++++ middlewares/dateFormat.ts | 14 +- next.config.js | 16 +- stores/enter-details/helpers.ts | 9 +- .../useEnterDetailsStore.test.tsx | 2 +- .../bookingWidget/guestsRoomsPicker.ts | 12 +- types/components/bookingWidget/index.ts | 9 +- .../enterDetails/bookingData.ts | 17 -- .../hotelReservation/selectHotel/map.ts | 4 +- .../selectHotel/selectHotel.ts | 3 +- .../selectHotel/selectHotelSearchParams.ts | 14 +- .../hotelReservation/selectRate/selectRate.ts | 19 +- types/providers/enter-details.ts | 5 +- types/stores/enter-details.ts | 6 +- utils/url.ts | 169 +++++++++++++++--- 48 files changed, 407 insertions(+), 418 deletions(-) delete mode 100644 components/HotelReservation/SelectRate/RoomSelection/utils.ts delete mode 100644 components/HotelReservation/SelectRate/utils.ts create mode 100644 components/HotelReservation/utils.ts delete mode 100644 types/components/hotelReservation/enterDetails/bookingData.ts diff --git a/app/[lang]/(live)/(public)/hotelreservation/(standard)/page.module.css b/app/[lang]/(live)/(public)/hotelreservation/(standard)/page.module.css index 3446c2a84..fe7743861 100644 --- a/app/[lang]/(live)/(public)/hotelreservation/(standard)/page.module.css +++ b/app/[lang]/(live)/(public)/hotelreservation/(standard)/page.module.css @@ -1,7 +1,8 @@ .page { background-color: var(--Base-Background-Primary-Normal); min-height: 50dvh; - max-width: var(--max-width); + max-width: var(--max-width-page); + margin: 0 auto; display: flex; align-items: center; justify-content: center; diff --git a/app/[lang]/(live)/(public)/hotelreservation/(standard)/select-hotel/map/page.tsx b/app/[lang]/(live)/(public)/hotelreservation/(standard)/select-hotel/map/page.tsx index 236acc354..9a9c357bb 100644 --- a/app/[lang]/(live)/(public)/hotelreservation/(standard)/select-hotel/map/page.tsx +++ b/app/[lang]/(live)/(public)/hotelreservation/(standard)/select-hotel/map/page.tsx @@ -20,8 +20,13 @@ export default async function SelectHotelMapPage({ setLang(params.lang) const searchDetails = await getHotelSearchDetails({ searchParams }) if (!searchDetails) return notFound() - const { city, adultsInRoom, childrenInRoom, childrenInRoomArray } = - searchDetails + const { + city, + adultsInRoom, + childrenInRoom, + childrenInRoomArray, + selectHotelParams, + } = searchDetails if (!city) return notFound() @@ -34,7 +39,7 @@ export default async function SelectHotelMapPage({ > (searchParams) const { - hotel: hotelId, + hotelId, rooms: [ { adults, children, roomTypeCode, rateCode, packages: packageCodes }, ], // TODO: Handle multiple rooms @@ -153,8 +151,8 @@ export default async function StepPage({ } : undefined - const arrivalDate = new Date(searchParams.fromDate) - const departureDate = new Date(searchParams.toDate) + const arrivalDate = new Date(fromDate) + const departureDate = new Date(toDate) const hotelAttributes = hotelData?.data.attributes const initialPageTrackingData: TrackingSDKPageData = { diff --git a/app/[lang]/(live)/(public)/hotelreservation/(standard)/utils.ts b/app/[lang]/(live)/(public)/hotelreservation/(standard)/utils.ts index 2a0ae8d42..1b296d273 100644 --- a/app/[lang]/(live)/(public)/hotelreservation/(standard)/utils.ts +++ b/app/[lang]/(live)/(public)/hotelreservation/(standard)/utils.ts @@ -2,10 +2,8 @@ import { notFound } from "next/navigation" import { getLocations } from "@/lib/trpc/memoizedRequests" -import { - generateChildrenString, - getHotelReservationQueryParams, -} from "@/components/HotelReservation/SelectRate/RoomSelection/utils" +import { generateChildrenString } from "@/components/HotelReservation/utils" +import { convertSearchParamsToObj } from "@/utils/url" import type { SelectHotelSearchParams } from "@/types/components/hotelReservation/selectHotel/selectHotelSearchParams" import type { @@ -14,62 +12,59 @@ import type { } from "@/types/components/hotelReservation/selectRate/selectRate" import type { Location } from "@/types/trpc/routers/hotel/locations" -interface HotelSearchDetails { +interface HotelSearchDetails { city: Location | null hotel: Location | null - urlSearchParams?: URLSearchParams + selectHotelParams: T adultsInRoom: number childrenInRoom?: string childrenInRoomArray?: Child[] } -export async function getHotelSearchDetails({ +export async function getHotelSearchDetails< + T extends SelectHotelSearchParams | SelectRateSearchParams, +>({ searchParams, }: { - searchParams: - | (SelectHotelSearchParams & { - [key: string]: string - }) - | (SelectRateSearchParams & { - [key: string]: string - }) -}): Promise { + searchParams: T & { + [key: string]: string + } +}): Promise | null> { + const selectHotelParams = convertSearchParamsToObj(searchParams) + const locations = await getLocations() if (!locations || "error" in locations) return null const city = locations.data.find( (location) => - location.name.toLowerCase() === searchParams.city?.toLowerCase() + location.name.toLowerCase() === selectHotelParams.city?.toLowerCase() ) const hotel = locations.data.find( (location) => - "operaId" in location && location.operaId == searchParams.hotel + "operaId" in location && location.operaId == selectHotelParams.hotelId ) if (!city && !hotel) return notFound() - const urlSearchParams = new URLSearchParams(searchParams) - const searchParamsObject = getHotelReservationQueryParams(urlSearchParams) - let adultsInRoom = 1 let childrenInRoom: string | undefined = undefined let childrenInRoomArray: Child[] | undefined = undefined - if (searchParamsObject.room && searchParamsObject.room.length > 0) { - adultsInRoom = searchParamsObject.room[0].adults // TODO: Handle multiple rooms - childrenInRoom = searchParamsObject.room[0].child - ? generateChildrenString(searchParamsObject.room[0].child) - : undefined // TODO: Handle multiple rooms - childrenInRoomArray = searchParamsObject.room[0].child - ? searchParamsObject.room[0].child + const { rooms } = selectHotelParams + + if (rooms && rooms.length > 0) { + adultsInRoom = rooms[0].adults // TODO: Handle multiple rooms + childrenInRoom = rooms[0].children + ? generateChildrenString(rooms[0].children) : undefined // TODO: Handle multiple rooms + childrenInRoomArray = rooms[0].children ? rooms[0].children : undefined // TODO: Handle multiple rooms } return { city: city ?? null, hotel: hotel ?? null, - urlSearchParams, + selectHotelParams, adultsInRoom, childrenInRoom, childrenInRoomArray, diff --git a/app/[lang]/(live)/@bookingwidget/[contentType]/[uid]/page.tsx b/app/[lang]/(live)/@bookingwidget/[contentType]/[uid]/page.tsx index 2f3916668..e840242a4 100644 --- a/app/[lang]/(live)/@bookingwidget/[contentType]/[uid]/page.tsx +++ b/app/[lang]/(live)/@bookingwidget/[contentType]/[uid]/page.tsx @@ -4,21 +4,20 @@ import { getHotelData, getHotelPage } from "@/lib/trpc/memoizedRequests" import BookingWidget, { preload } from "@/components/BookingWidget" import { getLang } from "@/i18n/serverContext" +import type { BookingWidgetSearchData } from "@/types/components/bookingWidget" import type { ContentTypeParams, PageArgs } from "@/types/params" import { PageContentTypeEnum } from "@/types/requests/contentType" export default async function BookingWidgetPage({ params, searchParams, -}: PageArgs) { +}: PageArgs) { if (!env.ENABLE_BOOKING_WIDGET) { return null } preload() - const urlParams = new URLSearchParams() - if (params.contentType === PageContentTypeEnum.hotelPage) { const hotelPageData = await getHotelPage() @@ -26,10 +25,14 @@ export default async function BookingWidgetPage({ hotelId: hotelPageData?.hotel_page_id || "", language: getLang(), }) - urlParams.set("hotel", hotelData?.data?.id || "") - urlParams.set("city", hotelData?.data?.attributes?.cityName || "") - return + const hotelPageParams = { + hotel: hotelData?.data?.id || "", + city: hotelData?.data?.attributes?.cityName || "", + } + + return } - return + + return } diff --git a/app/[lang]/(live)/@bookingwidget/hotelreservation/page.tsx b/app/[lang]/(live)/@bookingwidget/hotelreservation/page.tsx index a6d940572..4e4b9d496 100644 --- a/app/[lang]/(live)/@bookingwidget/hotelreservation/page.tsx +++ b/app/[lang]/(live)/@bookingwidget/hotelreservation/page.tsx @@ -2,16 +2,17 @@ import { env } from "@/env/server" import BookingWidget, { preload } from "@/components/BookingWidget" -import type { PageArgs } from "@/types/params" +import type { BookingWidgetSearchData } from "@/types/components/bookingWidget" +import type { LangParams, PageArgs } from "@/types/params" export default async function BookingWidgetPage({ searchParams, -}: PageArgs<{}, URLSearchParams>) { +}: PageArgs) { if (!env.ENABLE_BOOKING_WIDGET_HOTELRESERVATION_PATH) { return null } preload() - return + return } diff --git a/app/[lang]/(live)/@bookingwidget/page.tsx b/app/[lang]/(live)/@bookingwidget/page.tsx index 93e81d617..224ffe7d0 100644 --- a/app/[lang]/(live)/@bookingwidget/page.tsx +++ b/app/[lang]/(live)/@bookingwidget/page.tsx @@ -3,11 +3,12 @@ import { serverClient } from "@/lib/trpc/server" import BookingWidget, { preload } from "@/components/BookingWidget" +import type { BookingWidgetSearchData } from "@/types/components/bookingWidget" import type { PageArgs } from "@/types/params" export default async function BookingWidgetPage({ searchParams, -}: PageArgs<{}, URLSearchParams>) { +}: PageArgs<{}, BookingWidgetSearchData>) { if (!env.ENABLE_BOOKING_WIDGET) { return null } @@ -22,5 +23,5 @@ export default async function BookingWidgetPage({ return null } - return + return } diff --git a/app/[lang]/(live-current)/layout.tsx b/app/[lang]/(live-current)/layout.tsx index 3867b76d1..ef9477a87 100644 --- a/app/[lang]/(live-current)/layout.tsx +++ b/app/[lang]/(live-current)/layout.tsx @@ -4,7 +4,6 @@ import "@scandic-hotels/design-system/style.css" import Script from "next/script" import TokenRefresher from "@/components/Auth/TokenRefresher" -import BookingWidget from "@/components/BookingWidget" import CookieBotConsent from "@/components/CookieBot" import AdobeScript from "@/components/Current/AdobeScript" import Footer from "@/components/Current/Footer" diff --git a/components/BookingWidget/Client.tsx b/components/BookingWidget/Client.tsx index 017d9c76a..9901b0439 100644 --- a/components/BookingWidget/Client.tsx +++ b/components/BookingWidget/Client.tsx @@ -14,7 +14,7 @@ import { CloseLargeIcon } from "@/components/Icons" import useStickyPosition from "@/hooks/useStickyPosition" import { debounce } from "@/utils/debounce" import isValidJson from "@/utils/isValidJson" -import { getFormattedUrlQueryParams } from "@/utils/url" +import { convertSearchParamsToObj } from "@/utils/url" import MobileToggleButton, { MobileToggleButtonSkeleton, @@ -25,14 +25,14 @@ import styles from "./bookingWidget.module.css" import type { BookingWidgetClientProps, BookingWidgetSchema, - BookingWidgetSearchParams, + BookingWidgetSearchData, } from "@/types/components/bookingWidget" import type { Location } from "@/types/trpc/routers/hotel/locations" export default function BookingWidgetClient({ locations, type, - searchParams, + bookingWidgetSearchParams, }: BookingWidgetClientProps) { const [isOpen, setIsOpen] = useState(false) const bookingWidgetRef = useRef(null) @@ -41,14 +41,11 @@ export default function BookingWidgetClient({ name: StickyElementNameEnum.BOOKING_WIDGET, }) - const bookingWidgetSearchData: BookingWidgetSearchParams | undefined = - searchParams - ? getFormattedUrlQueryParams(new URLSearchParams(searchParams), { - adults: "number", - age: "number", - bed: "number", - }) - : undefined + const bookingWidgetSearchData = bookingWidgetSearchParams + ? convertSearchParamsToObj( + bookingWidgetSearchParams + ) + : undefined const getLocationObj = (destination: string): Location | undefined => { if (destination) { @@ -85,13 +82,13 @@ export default function BookingWidgetClient({ ) : undefined - const defaultRoomsData = bookingWidgetSearchData?.room?.map((room) => ({ + const defaultRoomsData = bookingWidgetSearchData?.rooms?.map((room) => ({ adults: room.adults, - child: room.child ?? [], + children: room.children ?? [], })) ?? [ { adults: 1, - child: [], + children: [], }, ] diff --git a/components/BookingWidget/MobileToggleButton/index.tsx b/components/BookingWidget/MobileToggleButton/index.tsx index f7229ae02..54239d936 100644 --- a/components/BookingWidget/MobileToggleButton/index.tsx +++ b/components/BookingWidget/MobileToggleButton/index.tsx @@ -49,8 +49,8 @@ export default function MobileToggleButton({ return acc }, 0) const totalChildren = rooms.reduce((acc, room) => { - if (room.child) { - acc = acc + room.child.length + if (room.children) { + acc = acc + room.children.length } return acc }, 0) diff --git a/components/BookingWidget/index.tsx b/components/BookingWidget/index.tsx index ecff629c6..456ff9777 100644 --- a/components/BookingWidget/index.tsx +++ b/components/BookingWidget/index.tsx @@ -10,7 +10,7 @@ export function preload() { export default async function BookingWidget({ type, - searchParams, + bookingWidgetSearchParams, }: BookingWidgetProps) { const locations = await getLocations() const siteConfig = await getSiteConfig() @@ -23,7 +23,7 @@ export default async function BookingWidget({ ) } diff --git a/components/Forms/BookingWidget/form.module.css b/components/Forms/BookingWidget/form.module.css index baa541be1..d8c0cb4e2 100644 --- a/components/Forms/BookingWidget/form.module.css +++ b/components/Forms/BookingWidget/form.module.css @@ -10,6 +10,10 @@ } @media screen and (max-width: 767px) { + .section { + max-width: var(--max-width-page); + } + .form { align-self: flex-start; } diff --git a/components/Forms/BookingWidget/index.tsx b/components/Forms/BookingWidget/index.tsx index 3d0a67b20..011029e6d 100644 --- a/components/Forms/BookingWidget/index.tsx +++ b/components/Forms/BookingWidget/index.tsx @@ -6,6 +6,7 @@ import { useFormContext } from "react-hook-form" import { selectHotel, selectRate } from "@/constants/routes/hotelReservation" import useLang from "@/hooks/useLang" +import { convertObjToSearchParams } from "@/utils/url" import FormContent, { BookingWidgetFormContentSkeleton } from "./FormContent" import { bookingWidgetVariants } from "./variants" @@ -37,26 +38,14 @@ export default function Form({ const bookingFlowPage = locationData.type == "cities" ? selectHotel(lang) : selectRate(lang) - const bookingWidgetParams = new URLSearchParams(data.date) - - if (locationData.type == "cities") - bookingWidgetParams.set("city", locationData.name) - else bookingWidgetParams.set("hotel", locationData.operaId || "") - - data.rooms.forEach((room, index) => { - bookingWidgetParams.set(`room[${index}].adults`, room.adults.toString()) - - room.child.forEach((child, childIndex) => { - bookingWidgetParams.set( - `room[${index}].child[${childIndex}].age`, - child.age.toString() - ) - bookingWidgetParams.set( - `room[${index}].child[${childIndex}].bed`, - child.bed.toString() - ) - }) + const bookingWidgetParams = convertObjToSearchParams({ + rooms: data.rooms, + ...data.date, + ...(locationData.type == "cities" + ? { city: locationData.name } + : { hotel: locationData.operaId || "" }), }) + onClose() router.push(`${bookingFlowPage}?${bookingWidgetParams.toString()}`) } diff --git a/components/Forms/BookingWidget/schema.ts b/components/Forms/BookingWidget/schema.ts index c8beb98d5..f6bafd2d5 100644 --- a/components/Forms/BookingWidget/schema.ts +++ b/components/Forms/BookingWidget/schema.ts @@ -6,7 +6,7 @@ import type { Location } from "@/types/trpc/routers/hotel/locations" export const guestRoomSchema = z .object({ adults: z.number().default(1), - child: z + children: z .array( z.object({ age: z.number().min(0, "Age is required"), @@ -16,11 +16,11 @@ export const guestRoomSchema = z .default([]), }) .superRefine((value, ctx) => { - const childrenInAdultsBed = value.child.filter( + const childrenInAdultsBed = value.children.filter( (c) => c.bed === ChildBedMapEnum.IN_ADULTS_BED ) if (value.adults < childrenInAdultsBed.length) { - const lastAdultBedIndex = value.child + const lastAdultBedIndex = value.children .map((c) => c.bed) .lastIndexOf(ChildBedMapEnum.IN_ADULTS_BED) diff --git a/components/GuestsRoomsPicker/ChildSelector/ChildInfoSelector.tsx b/components/GuestsRoomsPicker/ChildSelector/ChildInfoSelector.tsx index 67ebf4aa7..6f4f845f3 100644 --- a/components/GuestsRoomsPicker/ChildSelector/ChildInfoSelector.tsx +++ b/components/GuestsRoomsPicker/ChildSelector/ChildInfoSelector.tsx @@ -29,8 +29,8 @@ export default function ChildInfoSelector({ index = 0, roomIndex = 0, }: ChildInfoSelectorProps) { - const ageFieldName = `rooms.${roomIndex}.child.${index}.age` - const bedFieldName = `rooms.${roomIndex}.child.${index}.bed` + const ageFieldName = `rooms.${roomIndex}.children.${index}.age` + const bedFieldName = `rooms.${roomIndex}.children.${index}.bed` const intl = useIntl() const ageLabel = intl.formatMessage({ id: "Age" }) const bedLabel = intl.formatMessage({ id: "Bed" }) @@ -38,11 +38,11 @@ export default function ChildInfoSelector({ const { setValue, formState } = useFormContext() function updateSelectedBed(bed: number) { - setValue(`rooms.${roomIndex}.child.${index}.bed`, bed) + setValue(`rooms.${roomIndex}.children.${index}.bed`, bed) } function updateSelectedAge(age: number) { - setValue(`rooms.${roomIndex}.child.${index}.age`, age) + setValue(`rooms.${roomIndex}.children.${index}.age`, age) const availableBedTypes = getAvailableBeds(age) updateSelectedBed(availableBedTypes[0].value) } @@ -77,7 +77,7 @@ export default function ChildInfoSelector({ } //@ts-expect-error: formState is typed with FormValues - const roomErrors = formState.errors.rooms?.[roomIndex]?.child?.[index] + const roomErrors = formState.errors.rooms?.[roomIndex]?.children?.[index] const ageError = roomErrors?.age const bedError = roomErrors?.bed diff --git a/components/GuestsRoomsPicker/ChildSelector/index.tsx b/components/GuestsRoomsPicker/ChildSelector/index.tsx index b76517528..b164b0ded 100644 --- a/components/GuestsRoomsPicker/ChildSelector/index.tsx +++ b/components/GuestsRoomsPicker/ChildSelector/index.tsx @@ -24,7 +24,7 @@ export default function ChildSelector({ function increaseChildrenCount(roomIndex: number) { if (currentChildren.length < 5) { - setValue(`rooms.${roomIndex}.child.${currentChildren.length}`, { + setValue(`rooms.${roomIndex}.children.${currentChildren.length}`, { age: undefined, bed: undefined, }) @@ -33,7 +33,7 @@ export default function ChildSelector({ function decreaseChildrenCount(roomIndex: number) { if (currentChildren.length > 0) { currentChildren.pop() - setValue(`rooms.${roomIndex}.child`, currentChildren) + setValue(`rooms.${roomIndex}.children`, currentChildren) } } diff --git a/components/GuestsRoomsPicker/Form.tsx b/components/GuestsRoomsPicker/Form.tsx index f1175ef99..da31282b5 100644 --- a/components/GuestsRoomsPicker/Form.tsx +++ b/components/GuestsRoomsPicker/Form.tsx @@ -48,7 +48,7 @@ export default function GuestsRoomsPickerDialog({ }, [trigger, onClose]) const handleAddRoom = useCallback(() => { - setValue("rooms", [...roomsValue, { adults: 1, child: [] }], { + setValue("rooms", [...roomsValue, { adults: 1, children: [] }], { shouldValidate: true, }) }, [roomsValue, setValue]) diff --git a/components/GuestsRoomsPicker/GuestsRoom/index.tsx b/components/GuestsRoomsPicker/GuestsRoom/index.tsx index 7122a0a31..038db6093 100644 --- a/components/GuestsRoomsPicker/GuestsRoom/index.tsx +++ b/components/GuestsRoomsPicker/GuestsRoom/index.tsx @@ -25,7 +25,7 @@ export function GuestsRoom({ const intl = useIntl() const roomLabel = intl.formatMessage({ id: "Room" }) - const childrenInAdultsBed = room.child.filter( + const childrenInAdultsBed = room.children.filter( (child) => child.bed === ChildBedMapEnum.IN_ADULTS_BED ).length @@ -38,13 +38,13 @@ export function GuestsRoom({ {index !== 0 && ( diff --git a/components/GuestsRoomsPicker/index.tsx b/components/GuestsRoomsPicker/index.tsx index 262b256d9..7edad97d8 100644 --- a/components/GuestsRoomsPicker/index.tsx +++ b/components/GuestsRoomsPicker/index.tsx @@ -28,7 +28,8 @@ export default function GuestsRoomsPickerForm() { const [isDesktop, setIsDesktop] = useState(true) const [isOpen, setIsOpen] = useState(false) const [containerHeight, setContainerHeight] = useState(0) - const childCount = rooms[0] ? rooms[0].child.length : 0 // ToDo Update for multiroom later + const childCount = + rooms[0] && rooms[0].children ? rooms[0].children.length : 0 // ToDo Update for multiroom later const htmlElement = typeof window !== "undefined" ? document.querySelector("body") : null @@ -153,7 +154,7 @@ function Trigger({ ) ) - if (rooms.some((room) => room.child.length > 0)) { + if (rooms.some((room) => room.children.length > 0)) { parts.push( intl.formatMessage( { @@ -161,7 +162,7 @@ function Trigger({ }, { totalChildren: rooms.reduce( - (acc, room) => acc + room.child.length, + (acc, room) => acc + room.children.length, 0 ), } diff --git a/components/HotelReservation/BookingConfirmation/index.tsx b/components/HotelReservation/BookingConfirmation/index.tsx index 333537b69..fbd1f5093 100644 --- a/components/HotelReservation/BookingConfirmation/index.tsx +++ b/components/HotelReservation/BookingConfirmation/index.tsx @@ -6,7 +6,7 @@ import { getBookingConfirmation } from "@/lib/trpc/memoizedRequests" import TrackingSDK from "@/components/TrackingSDK" import { getLang } from "@/i18n/serverContext" -import { invertedBedTypeMap } from "../SelectRate/RoomSelection/utils" +import { invertedBedTypeMap } from "../utils" import Confirmation from "./Confirmation" import type { BookingConfirmationProps } from "@/types/components/hotelReservation/bookingConfirmation/bookingConfirmation" diff --git a/components/HotelReservation/EnterDetails/Payment/PaymentCallback/index.tsx b/components/HotelReservation/EnterDetails/Payment/PaymentCallback/index.tsx index 88d2e2581..22b8a5d40 100644 --- a/components/HotelReservation/EnterDetails/Payment/PaymentCallback/index.tsx +++ b/components/HotelReservation/EnterDetails/Payment/PaymentCallback/index.tsx @@ -5,9 +5,9 @@ import { useEffect } from "react" import { detailsStorageName } from "@/stores/enter-details" -import { createQueryParamsForEnterDetails } from "@/components/HotelReservation/SelectRate/RoomSelection/utils" import LoadingSpinner from "@/components/LoadingSpinner" import { trackPaymentEvent } from "@/utils/tracking" +import { convertObjToSearchParams } from "@/utils/url" import type { PersistedState } from "@/types/stores/enter-details" @@ -29,7 +29,7 @@ export default function PaymentCallback({ if (bookingData) { const detailsStorage: PersistedState = JSON.parse(bookingData) - const searchParams = createQueryParamsForEnterDetails( + const searchParams = convertObjToSearchParams( detailsStorage.booking, searchObject ) @@ -37,13 +37,13 @@ export default function PaymentCallback({ if (status === "cancel") { trackPaymentEvent({ event: "paymentCancel", - hotelId: detailsStorage.booking.hotel, + hotelId: detailsStorage.booking.hotelId, }) } if (status === "error") { trackPaymentEvent({ event: "paymentFail", - hotelId: detailsStorage.booking.hotel, + hotelId: detailsStorage.booking.hotelId, errorMessage, }) } diff --git a/components/HotelReservation/EnterDetails/Payment/PaymentClient.tsx b/components/HotelReservation/EnterDetails/Payment/PaymentClient.tsx index 412ab3814..67a3d7f59 100644 --- a/components/HotelReservation/EnterDetails/Payment/PaymentClient.tsx +++ b/components/HotelReservation/EnterDetails/Payment/PaymentClient.tsx @@ -33,7 +33,7 @@ import { usePaymentFailedToast } from "@/hooks/booking/usePaymentFailedToast" import useLang from "@/hooks/useLang" import { trackPaymentEvent } from "@/utils/tracking" -import { bedTypeMap } from "../../SelectRate/RoomSelection/utils" +import { bedTypeMap } from "../../utils" import PriceChangeDialog from "../PriceChangeDialog" import GuaranteeDetails from "./GuaranteeDetails" import PaymentOption from "./PaymentOption" @@ -87,7 +87,7 @@ export default function PaymentClient({ newPrice: number } | null>() - const { toDate, fromDate, rooms, hotel } = booking + const { toDate, fromDate, rooms, hotelId } = booking usePaymentFailedToast() @@ -171,14 +171,14 @@ export default function PaymentClient({ trackPaymentEvent({ event: "paymentFail", - hotelId: hotel, + hotelId, method: currentPaymentMethod, isSavedCreditCard, smsEnable, errorMessage, }) }, - [intl, methods, savedCreditCards, hotel] + [intl, methods, savedCreditCards, hotelId] ) useEffect(() => { @@ -226,7 +226,7 @@ export default function PaymentClient({ trackPaymentEvent({ event: "paymentAttemptStart", - hotelId: hotel, + hotelId, method: paymentMethod, isSavedCreditCard: !!savedCreditCard, smsEnable: data.smsConfirmation, @@ -234,7 +234,7 @@ export default function PaymentClient({ initiateBooking.mutate({ language: lang, - hotelId: hotel, + hotelId, checkInDate: fromDate, checkOutDate: toDate, rooms: rooms.map((room) => ({ @@ -294,7 +294,7 @@ export default function PaymentClient({ savedCreditCards, lang, initiateBooking, - hotel, + hotelId, fromDate, toDate, rooms, @@ -347,7 +347,7 @@ export default function PaymentClient({ ] } cardNumber={savedCreditCard.truncatedNumber} - hotelId={hotel} + hotelId={hotelId} /> ))} @@ -364,7 +364,7 @@ export default function PaymentClient({ name="paymentMethod" value={PaymentMethodEnum.card} label={intl.formatMessage({ id: "Credit card" })} - hotelId={hotel} + hotelId={hotelId} /> {availablePaymentOptions.map((paymentMethod) => ( ))} diff --git a/components/HotelReservation/SelectHotel/SelectHotelMap/SelectHotelMapContainer.tsx b/components/HotelReservation/SelectHotel/SelectHotelMap/SelectHotelMapContainer.tsx index e58119e33..d7877094b 100644 --- a/components/HotelReservation/SelectHotel/SelectHotelMap/SelectHotelMapContainer.tsx +++ b/components/HotelReservation/SelectHotel/SelectHotelMap/SelectHotelMapContainer.tsx @@ -9,6 +9,7 @@ import { getFiltersFromHotels, } from "@/app/[lang]/(live)/(public)/hotelreservation/(standard)/select-hotel/utils" import TrackingSDK from "@/components/TrackingSDK" +import { getLang } from "@/i18n/serverContext" import { safeTry } from "@/utils/safeTry" import { getHotelPins } from "../../HotelCardDialogListing/utils" @@ -33,19 +34,20 @@ function isValidHotelData(hotel: NullableHotelData): hotel is HotelData { export async function SelectHotelMapContainer({ city, - searchParams, + selectHotelParams, adultsInRoom, childrenInRoom, child, }: SelectHotelMapContainerProps) { + const lang = getLang() const googleMapId = env.GOOGLE_DYNAMIC_MAP_ID const googleMapsApiKey = env.GOOGLE_STATIC_MAP_KEY const fetchAvailableHotelsPromise = safeTry( fetchAvailableHotels({ cityId: city.id, - roomStayStartDate: searchParams.fromDate, - roomStayEndDate: searchParams.toDate, + roomStayStartDate: selectHotelParams.fromDate, + roomStayEndDate: selectHotelParams.toDate, adults: adultsInRoom, children: childrenInRoom, }) @@ -62,12 +64,12 @@ export async function SelectHotelMapContainer({ hotel: { address: hotels?.[0]?.hotelData?.address.streetAddress }, }) - const arrivalDate = new Date(searchParams.fromDate) - const departureDate = new Date(searchParams.toDate) + const arrivalDate = new Date(selectHotelParams.fromDate) + const departureDate = new Date(selectHotelParams.toDate) const pageTrackingData: TrackingSDKPageData = { pageId: "select-hotel", - domainLanguage: searchParams.lang as Lang, + domainLanguage: lang, channel: TrackingChannelEnum["hotelreservation"], pageName: "hotelreservation|select-hotel|mapview", siteSections: "hotelreservation|select-hotel|mapview", @@ -77,7 +79,7 @@ export async function SelectHotelMapContainer({ const hotelsTrackingData: TrackingSDKHotelInfo = { availableResults: validHotels.length, - searchTerm: searchParams.city, + searchTerm: selectHotelParams.city, arrivalDate: format(arrivalDate, "yyyy-MM-dd"), departureDate: format(departureDate, "yyyy-MM-dd"), noOfAdults: adultsInRoom, diff --git a/components/HotelReservation/SelectHotel/index.tsx b/components/HotelReservation/SelectHotel/index.tsx index cfc37179b..85ac0b47a 100644 --- a/components/HotelReservation/SelectHotel/index.tsx +++ b/components/HotelReservation/SelectHotel/index.tsx @@ -20,6 +20,7 @@ import Subtitle from "@/components/TempDesignSystem/Text/Subtitle" import TrackingSDK from "@/components/TrackingSDK" import { getIntl } from "@/i18n" import { safeTry } from "@/utils/safeTry" +import { convertObjToSearchParams } from "@/utils/url" import HotelCardListing from "../HotelCardListing" import HotelCount from "./HotelCount" @@ -46,7 +47,6 @@ export default async function SelectHotel({ }: SelectHotelProps) { const { selectHotelParams, - searchParams, adultsInRoom, childrenInRoom, childrenInRoomArray, @@ -57,8 +57,8 @@ export default async function SelectHotel({ const hotelsPromise = safeTry( fetchAvailableHotels({ cityId: city.id, - roomStayStartDate: searchParams.fromDate, - roomStayEndDate: searchParams.toDate, + roomStayStartDate: selectHotelParams.fromDate, + roomStayEndDate: selectHotelParams.toDate, adults: adultsInRoom, children: childrenInRoom, }) @@ -66,8 +66,8 @@ export default async function SelectHotel({ const [hotels] = await hotelsPromise - const arrivalDate = new Date(searchParams.fromDate) - const departureDate = new Date(searchParams.toDate) + const arrivalDate = new Date(selectHotelParams.fromDate) + const departureDate = new Date(selectHotelParams.toDate) const isCityWithCountry = (city: any): city is { country: string } => "country" in city @@ -76,6 +76,8 @@ export default async function SelectHotel({ hotels?.filter((hotel): hotel is HotelData => hotel !== null) || [] const filterList = getFiltersFromHotels(validHotels) + + const searchParams = convertObjToSearchParams(selectHotelParams) const breadcrumbs = [ { title: intl.formatMessage({ id: "Home" }), @@ -89,7 +91,7 @@ export default async function SelectHotel({ }, { title: intl.formatMessage({ id: "Select hotel" }), - href: `${selectHotel(params.lang)}/?${selectHotelParams}`, + href: `${selectHotel(params.lang)}/?${searchParams.toString()}`, uid: "select-hotel", }, { @@ -112,7 +114,7 @@ export default async function SelectHotel({ const hotelsTrackingData: TrackingSDKHotelInfo = { availableResults: validHotels.length, - searchTerm: searchParams.city, + searchTerm: selectHotelParams.city, arrivalDate: format(arrivalDate, "yyyy-MM-dd"), departureDate: format(departureDate, "yyyy-MM-dd"), noOfAdults: adultsInRoom, @@ -158,13 +160,13 @@ export default async function SelectHotel({ >