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}
|
||||
/>
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user