Merged in fix/refactor-booking-flow-search-params (pull request #2148)
Fix: refactor booking flow search params * wip: apply codemod and upgrade swc plugin * wip: design-system to react 19, fix issues from async (search)params * Prepare new parse function for booking flow search params * Prepare serialize function for booking flow search params * Improve handling of comma separated arrays * Slightly refactor for readability * Next abstracts URLSearchParams so handle the abstraction instead * Refactor booking widget to use new search params parsing * Rename search param functions * Refactor select-hotel to use new search param parser * Use new search params parser in select-rate and details * Fix hotelId type * Avoid passing down search params into BookingWidget components * More updates to use new types instead of SearchParams<T> * Remove types SelectHotelSearchParams and AlternativeSelectHotelSearchParams * Fix parseBookingWidgetSearchParams return type * Add error handling to booking search param parsers * Fix modifyRateIndex handling in details page * Clean up * Refactor booking widget search param serializing to util function * Move start page booking widget search param parsing to page * Use new search param serializer in HandleErrorCallback * Delete convertSearchParamsToObj & convertObjToSearchParams Approved-by: Michael Zetterberg
This commit is contained in:
@@ -19,7 +19,6 @@ import useLang from "@/hooks/useLang"
|
||||
import useStickyPosition from "@/hooks/useStickyPosition"
|
||||
import { debounce } from "@/utils/debounce"
|
||||
import isValidJson from "@/utils/isValidJson"
|
||||
import { convertSearchParamsToObj } from "@/utils/url"
|
||||
|
||||
import MobileToggleButton, {
|
||||
MobileToggleButtonSkeleton,
|
||||
@@ -35,12 +34,11 @@ import type {
|
||||
BookingCodeSchema,
|
||||
BookingWidgetClientProps,
|
||||
BookingWidgetSchema,
|
||||
BookingWidgetSearchData,
|
||||
} from "@/types/components/bookingWidget"
|
||||
|
||||
export default function BookingWidgetClient({
|
||||
type,
|
||||
bookingWidgetSearchParams,
|
||||
data,
|
||||
pageSettingsBookingCodePromise,
|
||||
}: BookingWidgetClientProps) {
|
||||
const [isOpen, setIsOpen] = useState(false)
|
||||
@@ -50,22 +48,19 @@ export default function BookingWidgetClient({
|
||||
null
|
||||
)
|
||||
|
||||
const params = convertSearchParamsToObj<BookingWidgetSearchData>(
|
||||
bookingWidgetSearchParams
|
||||
)
|
||||
const shouldFetchAutoComplete = !!data.hotelId || !!data.city
|
||||
|
||||
const shouldFetchAutoComplete = !!params.hotelId || !!params.city
|
||||
|
||||
const { data, isPending } = trpc.autocomplete.destinations.useQuery(
|
||||
{
|
||||
lang,
|
||||
query: "",
|
||||
includeTypes: ["hotels", "cities"],
|
||||
selectedHotelId: params.hotelId,
|
||||
selectedCity: params.city,
|
||||
},
|
||||
{ enabled: shouldFetchAutoComplete }
|
||||
)
|
||||
const { data: destinationsData, isPending } =
|
||||
trpc.autocomplete.destinations.useQuery(
|
||||
{
|
||||
lang,
|
||||
query: "",
|
||||
includeTypes: ["hotels", "cities"],
|
||||
selectedHotelId: data.hotelId ? data.hotelId.toString() : undefined,
|
||||
selectedCity: data.city,
|
||||
},
|
||||
{ enabled: shouldFetchAutoComplete }
|
||||
)
|
||||
const shouldShowSkeleton = shouldFetchAutoComplete && isPending
|
||||
|
||||
useStickyPosition({
|
||||
@@ -76,8 +71,8 @@ export default function BookingWidgetClient({
|
||||
const now = dt()
|
||||
// if fromDate or toDate is undefined, dt will return value that represents the same as 'now' above.
|
||||
// this is fine as isDateParamValid will catch this and default the values accordingly.
|
||||
let fromDate = dt(params.fromDate)
|
||||
let toDate = dt(params.toDate)
|
||||
let fromDate = dt(data.fromDate)
|
||||
let toDate = dt(data.toDate)
|
||||
|
||||
const isDateParamValid =
|
||||
fromDate.isValid() &&
|
||||
@@ -91,17 +86,18 @@ export default function BookingWidgetClient({
|
||||
}
|
||||
|
||||
let selectedLocation =
|
||||
data?.currentSelection.hotel ?? data?.currentSelection.city
|
||||
destinationsData?.currentSelection.hotel ??
|
||||
destinationsData?.currentSelection.city
|
||||
|
||||
// if bookingCode is not provided in the search params,
|
||||
// we will fetch it from the page settings stored in Contentstack.
|
||||
const selectedBookingCode =
|
||||
params.bookingCode ||
|
||||
data.bookingCode ||
|
||||
(pageSettingsBookingCodePromise !== null
|
||||
? use(pageSettingsBookingCodePromise)
|
||||
: "")
|
||||
|
||||
const defaultRoomsData: BookingWidgetSchema["rooms"] = params.rooms?.map(
|
||||
const defaultRoomsData: BookingWidgetSchema["rooms"] = data.rooms?.map(
|
||||
(room) => ({
|
||||
adults: room.adults,
|
||||
childrenInRoom: room.childrenInRoom || [],
|
||||
@@ -112,7 +108,7 @@ export default function BookingWidgetClient({
|
||||
childrenInRoom: [],
|
||||
},
|
||||
]
|
||||
const hotelId = isNaN(+params.hotelId) ? undefined : +params.hotelId
|
||||
const hotelId = data.hotelId ? parseInt(data.hotelId) : undefined
|
||||
const methods = useForm({
|
||||
defaultValues: {
|
||||
search: selectedLocation?.name ?? "",
|
||||
@@ -126,9 +122,9 @@ export default function BookingWidgetClient({
|
||||
value: selectedBookingCode,
|
||||
remember: false,
|
||||
},
|
||||
redemption: params?.searchType === REDEMPTION,
|
||||
redemption: data.searchType === REDEMPTION,
|
||||
rooms: defaultRoomsData,
|
||||
city: params.city || undefined,
|
||||
city: data.city || undefined,
|
||||
hotel: hotelId,
|
||||
},
|
||||
shouldFocusError: false,
|
||||
|
||||
@@ -8,7 +8,7 @@ import { FloatingBookingWidgetClient } from "./FloatingBookingWidgetClient"
|
||||
import type { BookingWidgetProps } from "@/types/components/bookingWidget"
|
||||
|
||||
export async function FloatingBookingWidget({
|
||||
bookingWidgetSearchParams,
|
||||
booking,
|
||||
}: Omit<BookingWidgetProps, "type">) {
|
||||
const isHidden = await isBookingWidgetHidden()
|
||||
|
||||
@@ -17,13 +17,13 @@ export async function FloatingBookingWidget({
|
||||
}
|
||||
|
||||
let pageSettingsBookingCodePromise: Promise<string> | null = null
|
||||
if (!bookingWidgetSearchParams.bookingCode) {
|
||||
if (!booking.bookingCode) {
|
||||
pageSettingsBookingCodePromise = getPageSettingsBookingCode()
|
||||
}
|
||||
|
||||
return (
|
||||
<FloatingBookingWidgetClient
|
||||
bookingWidgetSearchParams={bookingWidgetSearchParams}
|
||||
data={booking}
|
||||
pageSettingsBookingCodePromise={pageSettingsBookingCodePromise}
|
||||
/>
|
||||
)
|
||||
|
||||
@@ -17,10 +17,7 @@ export async function BookingWidget(props: BookingWidgetProps) {
|
||||
)
|
||||
}
|
||||
|
||||
async function InternalBookingWidget({
|
||||
type,
|
||||
bookingWidgetSearchParams,
|
||||
}: BookingWidgetProps) {
|
||||
async function InternalBookingWidget({ type, booking }: BookingWidgetProps) {
|
||||
const isHidden = await isBookingWidgetHidden()
|
||||
|
||||
if (isHidden) {
|
||||
@@ -28,14 +25,14 @@ async function InternalBookingWidget({
|
||||
}
|
||||
|
||||
let pageSettingsBookingCodePromise: Promise<string> | null = null
|
||||
if (!bookingWidgetSearchParams.bookingCode) {
|
||||
if (!booking.bookingCode) {
|
||||
pageSettingsBookingCodePromise = getPageSettingsBookingCode()
|
||||
}
|
||||
|
||||
return (
|
||||
<BookingWidgetClient
|
||||
type={type}
|
||||
bookingWidgetSearchParams={bookingWidgetSearchParams}
|
||||
data={booking}
|
||||
pageSettingsBookingCodePromise={pageSettingsBookingCodePromise}
|
||||
/>
|
||||
)
|
||||
|
||||
@@ -9,12 +9,13 @@ import TrackingSDK from "@/components/TrackingSDK"
|
||||
|
||||
import styles from "./startPage.module.css"
|
||||
|
||||
import type { BookingWidgetSearchData } from "@/types/components/bookingWidget"
|
||||
import { BlocksEnums } from "@/types/enums/blocks"
|
||||
|
||||
export default async function StartPage({
|
||||
searchParams,
|
||||
booking,
|
||||
}: {
|
||||
searchParams: { [key: string]: string }
|
||||
booking: BookingWidgetSearchData
|
||||
}) {
|
||||
const content = await getStartPage()
|
||||
if (!content) {
|
||||
@@ -30,7 +31,7 @@ export default async function StartPage({
|
||||
<Title color="white" textAlign="center">
|
||||
{header.heading}
|
||||
</Title>
|
||||
<FloatingBookingWidget bookingWidgetSearchParams={searchParams} />
|
||||
<FloatingBookingWidget booking={booking} />
|
||||
</div>
|
||||
{header.hero_image ? (
|
||||
<Image
|
||||
|
||||
@@ -9,7 +9,7 @@ import { REDEMPTION } from "@/constants/booking"
|
||||
import { selectHotel, selectRate } from "@/constants/routes/hotelReservation"
|
||||
|
||||
import useLang from "@/hooks/useLang"
|
||||
import { convertObjToSearchParams } from "@/utils/url"
|
||||
import { serializeBookingSearchParams } from "@/utils/url"
|
||||
|
||||
import FormContent, { BookingWidgetFormContentSkeleton } from "./FormContent"
|
||||
import { bookingWidgetVariants } from "./variants"
|
||||
@@ -38,7 +38,7 @@ export default function Form({ type, onClose }: BookingWidgetFormProps) {
|
||||
|
||||
function onSubmit(data: BookingWidgetSchema) {
|
||||
const bookingFlowPage = data.hotel ? selectRate(lang) : selectHotel(lang)
|
||||
const bookingWidgetParams = convertObjToSearchParams({
|
||||
const bookingWidgetParams = serializeBookingSearchParams({
|
||||
rooms: data.rooms,
|
||||
...data.date,
|
||||
...(data.city ? { city: data.city } : {}),
|
||||
|
||||
+5
-3
@@ -9,7 +9,7 @@ import { detailsStorageName } from "@/stores/enter-details"
|
||||
import LoadingSpinner from "@/components/LoadingSpinner"
|
||||
import { trackPaymentEvent } from "@/utils/tracking"
|
||||
import { trackEvent } from "@/utils/tracking/base"
|
||||
import { convertObjToSearchParams } from "@/utils/url"
|
||||
import { serializeBookingSearchParams } from "@/utils/url"
|
||||
|
||||
import { clearGlaSessionStorage, readGlaFromSessionStorage } from "./helpers"
|
||||
|
||||
@@ -33,9 +33,11 @@ export default function HandleErrorCallback({
|
||||
|
||||
if (bookingData) {
|
||||
const detailsStorage: PersistedState = JSON.parse(bookingData)
|
||||
const searchParams = convertObjToSearchParams(
|
||||
const searchParams = serializeBookingSearchParams(
|
||||
detailsStorage.booking,
|
||||
searchObject
|
||||
{
|
||||
initialSearchParams: searchObject,
|
||||
}
|
||||
)
|
||||
|
||||
const glaSessionData = readGlaFromSessionStorage()
|
||||
|
||||
@@ -7,14 +7,13 @@ import { useSearchHistory } from "@/hooks/useSearchHistory"
|
||||
|
||||
import { getTracking } from "./tracking"
|
||||
|
||||
import type { SelectRateSearchParams } from "@/types/components/hotelReservation/selectRate/selectRate"
|
||||
import type { DetailsBooking } from "@/types/components/hotelReservation/enterDetails/details"
|
||||
import type { Hotel } from "@/types/hotel"
|
||||
import type { Room } from "@/types/providers/details/room"
|
||||
import type { Lang } from "@/constants/languages"
|
||||
import type { SelectHotelParams } from "@/utils/url"
|
||||
|
||||
interface TrackingWrapperProps {
|
||||
booking: SelectHotelParams<SelectRateSearchParams>
|
||||
booking: DetailsBooking
|
||||
hotel: Hotel
|
||||
rooms: Room[]
|
||||
isMember: boolean
|
||||
|
||||
@@ -7,8 +7,8 @@ import { getSpecialRoomType } from "@/utils/specialRoomType"
|
||||
|
||||
import { ChildBedMapEnum } from "@/types/components/bookingWidget/enums"
|
||||
import type { BreakfastPackages } from "@/types/components/hotelReservation/breakfast"
|
||||
import type { DetailsBooking } from "@/types/components/hotelReservation/enterDetails/details"
|
||||
import { RoomPackageCodeEnum } from "@/types/components/hotelReservation/selectRate/roomFilter"
|
||||
import type { SelectRateSearchParams } from "@/types/components/hotelReservation/selectRate/selectRate"
|
||||
import {
|
||||
TrackingChannelEnum,
|
||||
type TrackingSDKAncillaries,
|
||||
@@ -25,10 +25,9 @@ import type {
|
||||
Product,
|
||||
} from "@/types/trpc/routers/hotel/roomAvailability"
|
||||
import type { Lang } from "@/constants/languages"
|
||||
import type { SelectHotelParams } from "@/utils/url"
|
||||
|
||||
export function getTracking(
|
||||
booking: SelectHotelParams<SelectRateSearchParams>,
|
||||
booking: DetailsBooking,
|
||||
hotel: Hotel,
|
||||
rooms: Room[],
|
||||
isMember: boolean,
|
||||
|
||||
+11
-9
@@ -37,23 +37,25 @@ export async function SelectHotelMapContainer({
|
||||
bookingCode,
|
||||
childrenInRoom,
|
||||
city,
|
||||
cityName,
|
||||
hotel: isAlternativeFor,
|
||||
noOfRooms,
|
||||
redemption,
|
||||
selectHotelParams,
|
||||
} = searchDetails
|
||||
|
||||
if (!city) {
|
||||
return notFound()
|
||||
}
|
||||
|
||||
const hotels = await getHotels(
|
||||
selectHotelParams,
|
||||
const hotels = await getHotels({
|
||||
fromDate: booking.fromDate,
|
||||
toDate: booking.toDate,
|
||||
rooms: booking.rooms,
|
||||
isAlternativeFor,
|
||||
bookingCode,
|
||||
city,
|
||||
!!redemption
|
||||
)
|
||||
redemption: !!redemption,
|
||||
})
|
||||
|
||||
const hotelPins = getHotelPins(hotels)
|
||||
const filterList = getFiltersFromHotels(hotels)
|
||||
@@ -62,8 +64,8 @@ export async function SelectHotelMapContainer({
|
||||
hotel: { address: hotels?.[0]?.hotel?.address.streetAddress },
|
||||
})
|
||||
|
||||
const arrivalDate = new Date(selectHotelParams.fromDate)
|
||||
const departureDate = new Date(selectHotelParams.toDate)
|
||||
const arrivalDate = new Date(booking.fromDate)
|
||||
const departureDate = new Date(booking.toDate)
|
||||
const isRedemptionAvailability = redemption
|
||||
? hotels.some(
|
||||
(hotel) => hotel.availability.productType?.redemptions?.length
|
||||
@@ -83,11 +85,11 @@ export async function SelectHotelMapContainer({
|
||||
adultsInRoom,
|
||||
childrenInRoom,
|
||||
hotels.length,
|
||||
selectHotelParams.hotelId,
|
||||
booking.hotelId,
|
||||
noOfRooms,
|
||||
hotels?.[0]?.hotel.address.country,
|
||||
hotels?.[0]?.hotel.address.city,
|
||||
selectHotelParams.city,
|
||||
cityName,
|
||||
bookingCode,
|
||||
isBookingCodeRateAvailable,
|
||||
redemption,
|
||||
|
||||
@@ -18,7 +18,7 @@ export function getTracking(
|
||||
adultsInRoom: number[],
|
||||
childrenInRoom: ChildrenInRoom,
|
||||
hotelsResult: number,
|
||||
hotelId: string,
|
||||
hotelId: string | undefined,
|
||||
noOfRooms: number,
|
||||
country: string | undefined,
|
||||
hotelCity: string | undefined,
|
||||
|
||||
@@ -14,17 +14,13 @@ import type {
|
||||
HotelFilter,
|
||||
} from "@/types/components/hotelReservation/selectHotel/hotelFilters"
|
||||
import { AvailabilityEnum } from "@/types/components/hotelReservation/selectHotel/selectHotel"
|
||||
import type {
|
||||
AlternativeHotelsSearchParams,
|
||||
SelectHotelSearchParams,
|
||||
} from "@/types/components/hotelReservation/selectHotel/selectHotelSearchParams"
|
||||
import type { Child } from "@/types/components/hotelReservation/selectRate/selectRate"
|
||||
import type { AdditionalData, Hotel } from "@/types/hotel"
|
||||
import type { HotelsAvailabilityItem } from "@/types/trpc/routers/hotel/availability"
|
||||
import type {
|
||||
HotelLocation,
|
||||
Location,
|
||||
} from "@/types/trpc/routers/hotel/locations"
|
||||
import type { SelectHotelParams } from "@/utils/url"
|
||||
|
||||
interface AvailabilityResponse {
|
||||
availability: HotelsAvailabilityItem[]
|
||||
@@ -162,19 +158,32 @@ function sortAndFilterHotelsByAvailability(
|
||||
].flat()
|
||||
}
|
||||
|
||||
export async function getHotels(
|
||||
booking: SelectHotelParams<
|
||||
SelectHotelSearchParams | AlternativeHotelsSearchParams
|
||||
>,
|
||||
isAlternativeFor: HotelLocation | null,
|
||||
bookingCode: string | undefined,
|
||||
city: Location,
|
||||
type GetHotelsInput = {
|
||||
fromDate: string
|
||||
toDate: string
|
||||
rooms: {
|
||||
adults: number
|
||||
childrenInRoom?: Child[]
|
||||
}[]
|
||||
isAlternativeFor: HotelLocation | null
|
||||
bookingCode: string | undefined
|
||||
city: Location
|
||||
redemption: boolean
|
||||
) {
|
||||
}
|
||||
|
||||
export async function getHotels({
|
||||
rooms,
|
||||
fromDate,
|
||||
toDate,
|
||||
isAlternativeFor,
|
||||
bookingCode,
|
||||
city,
|
||||
redemption,
|
||||
}: GetHotelsInput) {
|
||||
let availableHotelsResponse: SettledResult = []
|
||||
if (isAlternativeFor) {
|
||||
availableHotelsResponse = await Promise.allSettled(
|
||||
booking.rooms.map(async (room) => {
|
||||
rooms.map(async (room) => {
|
||||
return fetchAlternativeHotels(isAlternativeFor.id, {
|
||||
adults: room.adults,
|
||||
bookingCode,
|
||||
@@ -182,14 +191,14 @@ export async function getHotels(
|
||||
? generateChildrenString(room.childrenInRoom)
|
||||
: undefined,
|
||||
redemption,
|
||||
roomStayEndDate: booking.toDate,
|
||||
roomStayStartDate: booking.fromDate,
|
||||
roomStayEndDate: toDate,
|
||||
roomStayStartDate: fromDate,
|
||||
})
|
||||
})
|
||||
)
|
||||
} else if (bookingCode) {
|
||||
availableHotelsResponse = await Promise.allSettled(
|
||||
booking.rooms.map(async (room) => {
|
||||
rooms.map(async (room) => {
|
||||
return fetchBookingCodeAvailableHotels({
|
||||
adults: room.adults,
|
||||
bookingCode,
|
||||
@@ -197,14 +206,14 @@ export async function getHotels(
|
||||
? generateChildrenString(room.childrenInRoom)
|
||||
: undefined,
|
||||
cityId: city.id,
|
||||
roomStayStartDate: booking.fromDate,
|
||||
roomStayEndDate: booking.toDate,
|
||||
roomStayStartDate: fromDate,
|
||||
roomStayEndDate: toDate,
|
||||
})
|
||||
})
|
||||
)
|
||||
} else {
|
||||
availableHotelsResponse = await Promise.allSettled(
|
||||
booking.rooms.map(
|
||||
rooms.map(
|
||||
async (room) =>
|
||||
await fetchAvailableHotels({
|
||||
adults: room.adults,
|
||||
@@ -213,8 +222,8 @@ export async function getHotels(
|
||||
: undefined,
|
||||
cityId: city.id,
|
||||
redemption,
|
||||
roomStayEndDate: booking.toDate,
|
||||
roomStayStartDate: booking.fromDate,
|
||||
roomStayEndDate: toDate,
|
||||
roomStayStartDate: fromDate,
|
||||
})
|
||||
)
|
||||
)
|
||||
|
||||
@@ -17,7 +17,7 @@ export function getTracking(
|
||||
adultsInRoom: number[],
|
||||
childrenInRoom: ChildrenInRoom,
|
||||
hotelsResult: number,
|
||||
hotelId: string,
|
||||
hotelId: string | undefined,
|
||||
noOfRooms: number,
|
||||
country: string | undefined,
|
||||
hotelCity: string | undefined,
|
||||
|
||||
+1
-1
@@ -72,7 +72,7 @@ export default function Summary({
|
||||
)
|
||||
const showDiscounted = containsBookingCodeRate || isMember
|
||||
|
||||
const priceDetailsRooms = mapToPrice(rateSummary, booking, isMember)
|
||||
const priceDetailsRooms = mapToPrice(rateSummary, booking.rooms, isMember)
|
||||
|
||||
return (
|
||||
<section className={styles.summary}>
|
||||
|
||||
+3
-3
@@ -1,12 +1,12 @@
|
||||
import type {
|
||||
Rate,
|
||||
SelectRateSearchParams,
|
||||
Room as SelectRateRoom,
|
||||
} from "@/types/components/hotelReservation/selectRate/selectRate"
|
||||
import type { Room } from "@/components/HotelReservation/PriceDetailsModal/PriceDetailsTable"
|
||||
|
||||
export function mapToPrice(
|
||||
rooms: (Rate | null)[],
|
||||
booking: SelectRateSearchParams,
|
||||
bookingRooms: SelectRateRoom[],
|
||||
isUserLoggedIn: boolean
|
||||
) {
|
||||
return rooms
|
||||
@@ -43,7 +43,7 @@ export function mapToPrice(
|
||||
}
|
||||
}
|
||||
|
||||
const bookingRoom = booking.rooms[idx]
|
||||
const bookingRoom = bookingRooms[idx]
|
||||
return {
|
||||
adults: bookingRoom.adults,
|
||||
bedType: undefined,
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
"use client"
|
||||
|
||||
import { useSearchParams } from "next/navigation"
|
||||
import { notFound, useSearchParams } from "next/navigation"
|
||||
import { useIntl } from "react-intl"
|
||||
|
||||
import { trpc } from "@/lib/trpc/client"
|
||||
@@ -9,7 +9,7 @@ import { selectRateRoomsAvailabilityInputSchema } from "@/server/routers/hotels/
|
||||
import Alert from "@/components/TempDesignSystem/Alert"
|
||||
import useLang from "@/hooks/useLang"
|
||||
import RatesProvider from "@/providers/RatesProvider"
|
||||
import { convertSearchParamsToObj, searchParamsToRecord } from "@/utils/url"
|
||||
import { parseSelectRateSearchParams, searchParamsToRecord } from "@/utils/url"
|
||||
|
||||
import RateSummary from "./RateSummary"
|
||||
import Rooms from "./Rooms"
|
||||
@@ -18,7 +18,6 @@ import { RoomsContainerSkeleton } from "./RoomsContainerSkeleton"
|
||||
import styles from "./index.module.css"
|
||||
|
||||
import type { RoomsContainerProps } from "@/types/components/hotelReservation/selectRate/roomsContainer"
|
||||
import type { SelectRateSearchParams } from "@/types/components/hotelReservation/selectRate/selectRate"
|
||||
import { AlertTypeEnum } from "@/types/enums/alert"
|
||||
|
||||
export function RoomsContainer({
|
||||
@@ -30,10 +29,12 @@ export function RoomsContainer({
|
||||
const intl = useIntl()
|
||||
const searchParams = useSearchParams()
|
||||
|
||||
const booking = convertSearchParamsToObj<SelectRateSearchParams>(
|
||||
const booking = parseSelectRateSearchParams(
|
||||
searchParamsToRecord(searchParams)
|
||||
)
|
||||
|
||||
if (!booking) return notFound()
|
||||
|
||||
const bookingInput = selectRateRoomsAvailabilityInputSchema.safeParse({
|
||||
booking,
|
||||
lang,
|
||||
|
||||
@@ -7,12 +7,11 @@ import { REDEMPTION } from "@/constants/booking"
|
||||
|
||||
import TrackingSDK from "@/components/TrackingSDK"
|
||||
import useLang from "@/hooks/useLang"
|
||||
import { convertSearchParamsToObj, searchParamsToRecord } from "@/utils/url"
|
||||
import { parseSelectRateSearchParams, searchParamsToRecord } from "@/utils/url"
|
||||
|
||||
import { getValidDates } from "../getValidDates"
|
||||
import { getTracking } from "./tracking"
|
||||
|
||||
import type { SelectRateSearchParams } from "@/types/components/hotelReservation/selectRate/selectRate"
|
||||
import type { ChildrenInRoom } from "@/utils/hotelSearchDetails"
|
||||
|
||||
export default function Tracking({
|
||||
@@ -34,16 +33,13 @@ export default function Tracking({
|
||||
}) {
|
||||
const lang = useLang()
|
||||
const params = useSearchParams()
|
||||
const selectRateParams = convertSearchParamsToObj<SelectRateSearchParams>(
|
||||
searchParamsToRecord(params)
|
||||
)
|
||||
const booking = parseSelectRateSearchParams(searchParamsToRecord(params))
|
||||
|
||||
const { fromDate, toDate } = getValidDates(
|
||||
selectRateParams.fromDate,
|
||||
selectRateParams.toDate
|
||||
)
|
||||
if (!booking) return null
|
||||
|
||||
const { rooms, searchType, bookingCode, city: paramCity } = selectRateParams
|
||||
const { fromDate, toDate } = getValidDates(booking.fromDate, booking.toDate)
|
||||
|
||||
const { rooms, searchType, bookingCode, city: paramCity } = booking
|
||||
|
||||
const arrivalDate = fromDate.toDate()
|
||||
const departureDate = toDate.toDate()
|
||||
|
||||
@@ -12,16 +12,15 @@ import FnFNotAllowedAlert from "../FnFNotAllowedAlert/FnFNotAllowedAlert"
|
||||
import AvailabilityError from "./AvailabilityError"
|
||||
import Tracking from "./Tracking"
|
||||
|
||||
import type { SelectRateSearchParams } from "@/types/components/hotelReservation/selectRate/selectRate"
|
||||
import type { SelectRateBooking } from "@/types/components/hotelReservation/selectRate/selectRate"
|
||||
import type { Lang } from "@/constants/languages"
|
||||
import type { SelectHotelParams } from "@/utils/url"
|
||||
|
||||
export default async function SelectRatePage({
|
||||
lang,
|
||||
booking,
|
||||
}: {
|
||||
lang: Lang
|
||||
booking: SelectHotelParams<SelectRateSearchParams>
|
||||
booking: SelectRateBooking
|
||||
}) {
|
||||
const searchDetails = await getHotelSearchDetails(booking)
|
||||
if (!searchDetails?.hotel) {
|
||||
|
||||
Reference in New Issue
Block a user