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
@@ -1,12 +1,12 @@
import type { VariantProps } from "class-variance-authority"
import type { z } from "zod"
import type { SearchParams } from "@/types/params"
import type {
bookingCodeSchema,
bookingWidgetSchema,
} from "@/components/Forms/BookingWidget/schema"
import type { bookingWidgetVariants } from "@/components/Forms/BookingWidget/variants"
import type { BookingSearchType } from "../hotelReservation/booking"
import type { GuestsRoom } from "./guestsRoomsPicker"
export type BookingWidgetSchema = z.output<typeof bookingWidgetSchema>
@@ -14,12 +14,12 @@ export type BookingCodeSchema = z.output<typeof bookingCodeSchema>
export type BookingWidgetSearchData = {
city?: string
hotel?: string
hotelId?: string
fromDate?: string
toDate?: string
rooms?: GuestsRoom[]
bookingCode?: string
searchType?: "redemption"
searchType?: BookingSearchType
}
export type BookingWidgetType = VariantProps<
@@ -28,16 +28,12 @@ export type BookingWidgetType = VariantProps<
export interface BookingWidgetProps {
type?: BookingWidgetType
bookingWidgetSearchParams: Awaited<
SearchParams<BookingWidgetSearchData>["searchParams"]
>
booking: BookingWidgetSearchData
}
export interface BookingWidgetClientProps {
type?: BookingWidgetType
bookingWidgetSearchParams: Awaited<
SearchParams<BookingWidgetSearchData>["searchParams"]
>
data: BookingWidgetSearchData
pageSettingsBookingCodePromise: Promise<string> | null
}
@@ -0,0 +1,3 @@
import type { bookingSearchTypes } from "@/constants/booking"
export type BookingSearchType = (typeof bookingSearchTypes)[number]
@@ -1,5 +1,6 @@
import type { z } from "zod"
import type { PackageEnum } from "@/types/requests/packages"
import type { Product } from "@/types/trpc/routers/hotel/roomAvailability"
import type { SafeUser } from "@/types/user"
import type { getMultiroomDetailsSchema } from "@/components/HotelReservation/EnterDetails/Details/Multiroom/schema"
@@ -8,7 +9,9 @@ import type {
signedInDetailsSchema,
} from "@/components/HotelReservation/EnterDetails/Details/RoomOne/schema"
import type { productTypePointsSchema } from "@/server/routers/hotels/schemas/productTypePrice"
import type { BookingSearchType } from "../booking"
import type { Price } from "../price"
import type { Child } from "../selectRate/selectRate"
export type DetailsSchema = z.output<typeof guestDetailsSchema>
export type MultiroomDetailsSchema = z.output<
@@ -31,3 +34,21 @@ export type JoinScandicFriendsCardProps = {
}
export type RoomRate = Product
export type DetailsBooking = {
hotelId: string
fromDate: string
toDate: string
city?: string
bookingCode?: string
searchType?: BookingSearchType
rooms: {
adults: number
rateCode: string
roomTypeCode: string
bookingCode?: string
childrenInRoom?: Child[]
counterRateCode?: string
packages?: PackageEnum[]
}[]
}
@@ -5,12 +5,8 @@ import type { Amenities } from "@/types/hotel"
import type { ProductTypeCheque } from "@/types/trpc/routers/hotel/availability"
import type { HotelResponse } from "@/components/HotelReservation/SelectHotel/helpers"
import type { imageSchema } from "@/server/routers/hotels/schemas/image"
import type { SelectHotelParams } from "@/utils/url"
import type { CategorizedFilters } from "./hotelFilters"
import type {
AlternativeHotelsSearchParams,
SelectHotelSearchParams,
} from "./selectHotelSearchParams"
import type { SelectHotelBooking } from "./selectHotel"
export interface HotelListingProps {
hotels: HotelResponse[]
@@ -76,8 +72,6 @@ export interface HotelCardDialogListingProps {
}
export type SelectHotelMapContainerProps = {
booking: SelectHotelParams<
SelectHotelSearchParams | AlternativeHotelsSearchParams
>
booking: SelectHotelBooking
isAlternativeHotels?: boolean
}
@@ -1,8 +1,7 @@
import type { Hotel } from "@/types/hotel"
import type { Lang } from "@/constants/languages"
import type { SelectHotelParams } from "@/utils/url"
import type { BookingSearchType } from "../booking"
import type { Child } from "../selectRate/selectRate"
import type { SidePeekEnum } from "../sidePeek"
import type { AlternativeHotelsSearchParams } from "./selectHotelSearchParams"
export enum AvailabilityEnum {
Available = "Available",
@@ -20,8 +19,15 @@ export interface ContactProps {
hotel: Hotel
}
export interface SelectHotelProps {
booking: SelectHotelParams<AlternativeHotelsSearchParams>
lang: Lang
isAlternativeHotels?: boolean
export type SelectHotelBooking = {
hotelId?: string
city?: string
fromDate: string
toDate: string
rooms: {
adults: number
childrenInRoom?: Child[]
}[]
bookingCode?: string
searchType?: BookingSearchType
}
@@ -1,19 +0,0 @@
import type { Room } from "../selectRate/selectRate"
export interface SelectHotelSearchParams {
city: string
fromDate: string
toDate: string
rooms: Pick<Room, "adults" | "childrenInRoom">[]
bookingCode: string
searchType?: "redemption"
}
export interface AlternativeHotelsSearchParams {
hotel: string
fromDate: string
toDate: string
rooms: Pick<Room, "adults" | "childrenInRoom">[]
bookingCode: string
searchType?: "redemption"
}
@@ -5,6 +5,7 @@ import type {
RoomConfiguration,
} from "@/types/trpc/routers/hotel/roomAvailability"
import type { ChildBedMapEnum } from "../../bookingWidget/enums"
import type { BookingSearchType } from "../booking"
export interface Child {
bed: ChildBedMapEnum
@@ -15,21 +16,20 @@ export interface Room {
adults: number
bookingCode?: string
childrenInRoom?: Child[]
counterRateCode: string
counterRateCode?: string
packages?: PackageEnum[]
rateCode: string
roomTypeCode: string
rateCode?: string
roomTypeCode?: string
}
export interface SelectRateSearchParams {
export type SelectRateBooking = {
bookingCode?: string
city?: string
errorCode?: string
fromDate: string
hotelId: string
rooms: Room[]
searchType?: BookingSearchType
toDate: string
searchType?: "redemption"
}
export type Rate = {
@@ -1,9 +1,13 @@
import type { CurrencyEnum } from "@/types/enums/currency"
import type { Packages } from "@/types/requests/packages"
import type { RoomState } from "@/types/stores/enter-details"
import type { RoomPrice, RoomRate } from "./enterDetails/details"
import type {
DetailsBooking,
RoomPrice,
RoomRate,
} from "./enterDetails/details"
import type { Price } from "./price"
import type { Child, SelectRateSearchParams } from "./selectRate/selectRate"
import type { Child, SelectRateBooking } from "./selectRate/selectRate"
export type RoomsData = {
rateDetails: string[] | undefined
@@ -20,7 +24,7 @@ export interface SummaryProps {
}
export interface EnterDetailsSummaryProps {
booking: SelectRateSearchParams
booking: DetailsBooking
isMember: boolean
totalPrice: Price
vat: number
@@ -30,7 +34,7 @@ export interface EnterDetailsSummaryProps {
}
export interface SelectRateSummaryProps {
booking: SelectRateSearchParams
booking: SelectRateBooking
isMember: boolean
totalPrice: Price
vat: number
+2
View File
@@ -1,6 +1,8 @@
import type { Lang } from "@/constants/languages"
import type { PageContentTypeEnum } from "./requests/contentType"
export type NextSearchParams = { [key: string]: string | string[] | undefined }
export type SearchParams<S = {}> = {
searchParams: Promise<S & { [key: string]: string }>
}
@@ -1,10 +1,10 @@
import type { Room } from "@/types/providers/details/room"
import type { SafeUser } from "@/types/user"
import type { BreakfastPackages } from "../components/hotelReservation/breakfast"
import type { SelectRateSearchParams } from "../components/hotelReservation/selectRate/selectRate"
import type { DetailsBooking } from "../components/hotelReservation/enterDetails/details"
export interface DetailsProviderProps extends React.PropsWithChildren {
booking: SelectRateSearchParams
booking: DetailsBooking
breakfastPackages: BreakfastPackages
rooms: Room[]
searchParamsStr: string
+2 -2
View File
@@ -1,10 +1,10 @@
import type { Room } from "@/types/hotel"
import type { RoomsAvailability } from "@/types/trpc/routers/hotel/roomAvailability"
import type { SelectRateSearchParams } from "../components/hotelReservation/selectRate/selectRate"
import type { SelectRateBooking } from "../components/hotelReservation/selectRate/selectRate"
import type { AvailabilityError } from "../stores/rates"
export interface RatesProviderProps extends React.PropsWithChildren {
booking: SelectRateSearchParams
booking: SelectRateBooking
hotelType: string | undefined
roomCategories: Room[]
roomsAvailability: (RoomsAvailability | AvailabilityError)[] | undefined
@@ -7,19 +7,17 @@ import type {
BedTypeSelection,
} from "@/types/components/hotelReservation/enterDetails/bedType"
import type {
DetailsBooking,
DetailsSchema,
MultiroomDetailsSchema,
RoomPrice,
RoomRate,
SignedInDetailsSchema,
} from "@/types/components/hotelReservation/enterDetails/details"
import type { CurrencyEnum } from "@/types/enums/currency"
import type { Child } from "@/types/components/hotelReservation/selectRate/selectRate"
import type { StepEnum } from "@/types/enums/step"
import type { Price } from "../components/hotelReservation/price"
import type {
Child,
SelectRateSearchParams,
} from "../components/hotelReservation/selectRate/selectRate"
import type { CurrencyEnum } from "../enums/currency"
import type { Packages } from "../requests/packages"
export interface InitialRoomData {
@@ -78,7 +76,7 @@ export interface RoomState {
}
export type InitialState = {
booking: SelectRateSearchParams
booking: DetailsBooking
rooms: InitialRoomData[]
vat: number
}
@@ -92,7 +90,7 @@ export interface DetailsState {
addPreSubmitCallback: (name: string, callback: () => void) => void
}
availableBeds: Record<string, number>
booking: SelectRateSearchParams
booking: DetailsBooking
breakfastPackages: BreakfastPackages
canProceedToPayment: boolean
isSubmitting: boolean
@@ -107,6 +105,6 @@ export interface DetailsState {
}
export type PersistedState = {
booking: SelectRateSearchParams
booking: DetailsBooking
rooms: RoomState[]
}
+2 -2
View File
@@ -2,7 +2,7 @@ import type { DefaultFilterOptions } from "@/types/components/hotelReservation/s
import type {
Rate,
Room as RoomBooking,
SelectRateSearchParams,
SelectRateBooking,
} from "@/types/components/hotelReservation/selectRate/selectRate"
import type { CurrencyEnum } from "@/types/enums/currency"
import type { Room } from "@/types/hotel"
@@ -54,7 +54,7 @@ export interface SelectedRoom {
export interface RatesState {
activeRoom: number
booking: SelectRateSearchParams
booking: SelectRateBooking
hotelType: string | undefined
isRedemptionBooking: boolean
packageOptions: DefaultFilterOptions[]