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:
Anton Gunnarsson
2025-06-02 13:38:01 +00:00
parent 81887c83ff
commit 03468ad824
49 changed files with 1257 additions and 444 deletions

View File

@@ -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,

View File

@@ -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}
/>
)

View File

@@ -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}
/>
)