feat: keep inventory of bedselections
This commit is contained in:
committed by
Michael Zetterberg
parent
39b89c5d51
commit
5ca30d02a0
@@ -1,12 +1,8 @@
|
|||||||
import { cookies } from "next/headers"
|
import { cookies } from "next/headers"
|
||||||
import { notFound, redirect } from "next/navigation"
|
import { notFound } from "next/navigation"
|
||||||
import { Suspense } from "react"
|
import { Suspense } from "react"
|
||||||
|
|
||||||
import {
|
import { FamilyAndFriendsCodes } from "@/constants/booking"
|
||||||
BookingErrorCodeEnum,
|
|
||||||
FamilyAndFriendsCodes,
|
|
||||||
} from "@/constants/booking"
|
|
||||||
import { selectRate } from "@/constants/routes/hotelReservation"
|
|
||||||
import {
|
import {
|
||||||
getBreakfastPackages,
|
getBreakfastPackages,
|
||||||
getHotel,
|
getHotel,
|
||||||
@@ -30,7 +26,6 @@ import styles from "./page.module.css"
|
|||||||
|
|
||||||
import type { SelectRateSearchParams } from "@/types/components/hotelReservation/selectRate/selectRate"
|
import type { SelectRateSearchParams } from "@/types/components/hotelReservation/selectRate/selectRate"
|
||||||
import type { LangParams, PageArgs } from "@/types/params"
|
import type { LangParams, PageArgs } from "@/types/params"
|
||||||
import type { Room } from "@/types/providers/details/room"
|
|
||||||
|
|
||||||
export default async function DetailsPage({
|
export default async function DetailsPage({
|
||||||
params: { lang },
|
params: { lang },
|
||||||
@@ -76,25 +71,11 @@ export default async function DetailsPage({
|
|||||||
void getBreakfastPackages(breakfastInput)
|
void getBreakfastPackages(breakfastInput)
|
||||||
void getProfileSafely()
|
void getProfileSafely()
|
||||||
|
|
||||||
const roomsAvailability = await getSelectedRoomsAvailabilityEnterDetails({
|
const rooms = await getSelectedRoomsAvailabilityEnterDetails({
|
||||||
booking,
|
booking,
|
||||||
lang,
|
lang,
|
||||||
})
|
})
|
||||||
|
|
||||||
const rooms: Room[] = []
|
|
||||||
for (let room of roomsAvailability) {
|
|
||||||
if (!room) {
|
|
||||||
// TODO: This could be done in the route already.
|
|
||||||
// (possibly also add an error case to url?)
|
|
||||||
// -------------------------------------------------------
|
|
||||||
// redirect back to select-rate if availability call fails
|
|
||||||
selectRoomParams.set("errorCode", BookingErrorCodeEnum.AvailabilityError)
|
|
||||||
redirect(`${selectRate(lang)}?${selectRoomParams.toString()}`)
|
|
||||||
}
|
|
||||||
|
|
||||||
rooms.push(room)
|
|
||||||
}
|
|
||||||
|
|
||||||
const hotelData = await getHotel(hotelInput)
|
const hotelData = await getHotel(hotelInput)
|
||||||
|
|
||||||
if (!hotelData || !rooms.length) {
|
if (!hotelData || !rooms.length) {
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ import {
|
|||||||
type BedTypeEnum,
|
type BedTypeEnum,
|
||||||
type ExtraBedTypeEnum,
|
type ExtraBedTypeEnum,
|
||||||
} from "@/constants/booking"
|
} from "@/constants/booking"
|
||||||
|
import { useEnterDetailsStore } from "@/stores/enter-details"
|
||||||
|
|
||||||
import RadioCard from "@/components/TempDesignSystem/Form/RadioCard"
|
import RadioCard from "@/components/TempDesignSystem/Form/RadioCard"
|
||||||
import { useRoomContext } from "@/contexts/Details/Room"
|
import { useRoomContext } from "@/contexts/Details/Room"
|
||||||
@@ -23,6 +24,7 @@ import type { IconProps } from "@scandic-hotels/design-system/Icons"
|
|||||||
import type { BedTypeFormSchema } from "@/types/components/hotelReservation/enterDetails/bedType"
|
import type { BedTypeFormSchema } from "@/types/components/hotelReservation/enterDetails/bedType"
|
||||||
|
|
||||||
export default function BedType() {
|
export default function BedType() {
|
||||||
|
const availableBeds = useEnterDetailsStore((state) => state.availableBeds)
|
||||||
const {
|
const {
|
||||||
actions: { updateBedType },
|
actions: { updateBedType },
|
||||||
room: { bedType, bedTypes },
|
room: { bedType, bedTypes },
|
||||||
@@ -79,6 +81,11 @@ export default function BedType() {
|
|||||||
roomType.size.max === roomType.size.min
|
roomType.size.max === roomType.size.min
|
||||||
? `${roomType.size.min} cm`
|
? `${roomType.size.min} cm`
|
||||||
: `${roomType.size.min} cm - ${roomType.size.max} cm`
|
: `${roomType.size.min} cm - ${roomType.size.max} cm`
|
||||||
|
|
||||||
|
const bedAvailable = availableBeds[roomType.value]
|
||||||
|
// This is needed since otherwise, picking the last room would make
|
||||||
|
// the card disabled
|
||||||
|
const isSameBedAsSelected = bedType?.roomTypeCode === roomType.value
|
||||||
return (
|
return (
|
||||||
<RadioCard
|
<RadioCard
|
||||||
key={roomType.value}
|
key={roomType.value}
|
||||||
@@ -89,6 +96,7 @@ export default function BedType() {
|
|||||||
props={props}
|
props={props}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
|
disabled={!bedAvailable && !isSameBedAsSelected}
|
||||||
id={roomType.value}
|
id={roomType.value}
|
||||||
name="bedType"
|
name="bedType"
|
||||||
subtitle={width}
|
subtitle={width}
|
||||||
|
|||||||
@@ -20,10 +20,9 @@ import { StepEnum } from "@/types/enums/step"
|
|||||||
export default function Multiroom() {
|
export default function Multiroom() {
|
||||||
const intl = useIntl()
|
const intl = useIntl()
|
||||||
const { room, roomNr } = useRoomContext()
|
const { room, roomNr } = useRoomContext()
|
||||||
const { breakfastPackages } = useEnterDetailsStore((state) => ({
|
const breakfastPackages = useEnterDetailsStore(
|
||||||
breakfastPackages: state.breakfastPackages,
|
(state) => state.breakfastPackages
|
||||||
rooms: state.rooms,
|
)
|
||||||
}))
|
|
||||||
|
|
||||||
const showBreakfastStep =
|
const showBreakfastStep =
|
||||||
!room.breakfastIncluded && !!breakfastPackages.length
|
!room.breakfastIncluded && !!breakfastPackages.length
|
||||||
@@ -55,7 +54,7 @@ export default function Multiroom() {
|
|||||||
|
|
||||||
<SelectedRoom />
|
<SelectedRoom />
|
||||||
|
|
||||||
{room.bedTypes ? (
|
{room.bedTypes.length ? (
|
||||||
<Section
|
<Section
|
||||||
header={intl.formatMessage({ defaultMessage: "Bed preference" })}
|
header={intl.formatMessage({ defaultMessage: "Bed preference" })}
|
||||||
label={intl.formatMessage({ defaultMessage: "Preferred bed type" })}
|
label={intl.formatMessage({ defaultMessage: "Preferred bed type" })}
|
||||||
|
|||||||
@@ -23,15 +23,13 @@ export default function AvailabilityError() {
|
|||||||
})
|
})
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!hasAvailabilityError) {
|
if (hasAvailabilityError) {
|
||||||
return
|
toast.error(errorMessage)
|
||||||
|
|
||||||
|
const newParams = new URLSearchParams(searchParams.toString())
|
||||||
|
newParams.delete("errorCode")
|
||||||
|
window.history.replaceState({}, "", `${pathname}?${newParams.toString()}`)
|
||||||
}
|
}
|
||||||
|
|
||||||
toast.error(errorMessage)
|
|
||||||
|
|
||||||
const newParams = new URLSearchParams(searchParams.toString())
|
|
||||||
newParams.delete("errorCode")
|
|
||||||
window.history.replaceState({}, "", `${pathname}?${newParams.toString()}`)
|
|
||||||
}, [errorMessage, hasAvailabilityError, pathname, searchParams])
|
}, [errorMessage, hasAvailabilityError, pathname, searchParams])
|
||||||
|
|
||||||
return null
|
return null
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
|
import { redirect } from "next/navigation"
|
||||||
|
|
||||||
import { isDefined } from "@/server/utils"
|
import { isDefined } from "@/server/utils"
|
||||||
|
|
||||||
import { getLang } from "@/i18n/serverContext"
|
import { getLang } from "@/i18n/serverContext"
|
||||||
@@ -365,6 +367,12 @@ export const getSelectedRoomsAvailabilityEnterDetails = cache(
|
|||||||
async function getMemoizedSelectedRoomsAvailability(
|
async function getMemoizedSelectedRoomsAvailability(
|
||||||
input: RoomsAvailabilityExtendedInputSchema
|
input: RoomsAvailabilityExtendedInputSchema
|
||||||
) {
|
) {
|
||||||
return serverClient().hotel.availability.enterDetails(input)
|
const result = await serverClient().hotel.availability.enterDetails(input)
|
||||||
|
|
||||||
|
if (typeof result === "string") {
|
||||||
|
redirect(result)
|
||||||
|
}
|
||||||
|
|
||||||
|
return result
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -39,7 +39,7 @@ export default function EnterDetailsProvider({
|
|||||||
.filter((r) => r.bedTypes?.length) // TODO: how to handle room without bedtypes?
|
.filter((r) => r.bedTypes?.length) // TODO: how to handle room without bedtypes?
|
||||||
.map((room) => ({
|
.map((room) => ({
|
||||||
isAvailable: room.isAvailable,
|
isAvailable: room.isAvailable,
|
||||||
breakfastIncluded: !!room.breakfastIncluded,
|
breakfastIncluded: room.breakfastIncluded,
|
||||||
cancellationText: room.cancellationText,
|
cancellationText: room.cancellationText,
|
||||||
rateDetails: room.rateDetails,
|
rateDetails: room.rateDetails,
|
||||||
memberRateDetails: room.memberRateDetails,
|
memberRateDetails: room.memberRateDetails,
|
||||||
@@ -48,7 +48,7 @@ export default function EnterDetailsProvider({
|
|||||||
roomRate: room.roomRate,
|
roomRate: room.roomRate,
|
||||||
roomType: room.roomType,
|
roomType: room.roomType,
|
||||||
roomTypeCode: room.roomTypeCode,
|
roomTypeCode: room.roomTypeCode,
|
||||||
bedTypes: room.bedTypes!,
|
bedTypes: room.bedTypes,
|
||||||
bedType:
|
bedType:
|
||||||
room.bedTypes?.length === 1
|
room.bedTypes?.length === 1
|
||||||
? {
|
? {
|
||||||
@@ -186,12 +186,25 @@ export default function EnterDetailsProvider({
|
|||||||
nights
|
nights
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// Need to create a deep new copy since store is readonly
|
||||||
|
const availableBeds = deepmerge({}, store.availableBeds)
|
||||||
|
for (const filteredOutMissingRoom of filteredOutMissingRooms) {
|
||||||
|
if (filteredOutMissingRoom.room.bedType) {
|
||||||
|
const roomTypeCode = filteredOutMissingRoom.room.bedType.roomTypeCode
|
||||||
|
availableBeds[roomTypeCode] = Math.max(
|
||||||
|
availableBeds[roomTypeCode] - 1,
|
||||||
|
0
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
writeToSessionStorage({
|
writeToSessionStorage({
|
||||||
booking,
|
booking,
|
||||||
rooms: filteredOutMissingRooms,
|
rooms: filteredOutMissingRooms,
|
||||||
})
|
})
|
||||||
|
|
||||||
storeRef.current?.setState({
|
storeRef.current?.setState({
|
||||||
|
availableBeds,
|
||||||
canProceedToPayment,
|
canProceedToPayment,
|
||||||
rooms: filteredOutMissingRooms,
|
rooms: filteredOutMissingRooms,
|
||||||
totalPrice,
|
totalPrice,
|
||||||
|
|||||||
@@ -64,6 +64,7 @@ import {
|
|||||||
getRoomsAvailability,
|
getRoomsAvailability,
|
||||||
getSelectedRoomAvailability,
|
getSelectedRoomAvailability,
|
||||||
mergeRoomTypes,
|
mergeRoomTypes,
|
||||||
|
selectRateRedirectURL,
|
||||||
} from "./utils"
|
} from "./utils"
|
||||||
|
|
||||||
import { AvailabilityEnum } from "@/types/components/hotelReservation/selectHotel/selectHotel"
|
import { AvailabilityEnum } from "@/types/components/hotelReservation/selectHotel/selectHotel"
|
||||||
@@ -71,6 +72,7 @@ import { BreakfastPackageEnum } from "@/types/enums/breakfast"
|
|||||||
import { RateEnum } from "@/types/enums/rate"
|
import { RateEnum } from "@/types/enums/rate"
|
||||||
import { RateTypeEnum } from "@/types/enums/rateType"
|
import { RateTypeEnum } from "@/types/enums/rateType"
|
||||||
import type { DestinationPagesHotelData, HotelDataWithUrl } from "@/types/hotel"
|
import type { DestinationPagesHotelData, HotelDataWithUrl } from "@/types/hotel"
|
||||||
|
import type { Room } from "@/types/providers/details/room"
|
||||||
import type { CityLocation } from "@/types/trpc/routers/hotel/locations"
|
import type { CityLocation } from "@/types/trpc/routers/hotel/locations"
|
||||||
|
|
||||||
export const hotelQueryRouter = router({
|
export const hotelQueryRouter = router({
|
||||||
@@ -252,7 +254,38 @@ export const hotelQueryRouter = router({
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
return selectedRooms
|
const totalBedsAvailableForRoomTypeCode: Record<string, number> = {}
|
||||||
|
for (const selectedRoom of selectedRooms) {
|
||||||
|
if (selectedRoom) {
|
||||||
|
if (!totalBedsAvailableForRoomTypeCode[selectedRoom.roomTypeCode]) {
|
||||||
|
totalBedsAvailableForRoomTypeCode[selectedRoom.roomTypeCode] =
|
||||||
|
selectedRoom.bedTypes.reduce(
|
||||||
|
(total, bedType) => total + bedType.roomsLeft,
|
||||||
|
0
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const [idx, selectedRoom] of selectedRooms.entries()) {
|
||||||
|
if (selectedRoom) {
|
||||||
|
const totalBedsLeft =
|
||||||
|
totalBedsAvailableForRoomTypeCode[selectedRoom.roomTypeCode]
|
||||||
|
if (totalBedsLeft <= 0) {
|
||||||
|
selectedRooms[idx] = null
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
totalBedsAvailableForRoomTypeCode[selectedRoom.roomTypeCode] =
|
||||||
|
totalBedsAvailableForRoomTypeCode[selectedRoom.roomTypeCode] - 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (selectedRooms.some((sr) => !sr)) {
|
||||||
|
return selectRateRedirectURL(input, selectedRooms.map(Boolean))
|
||||||
|
}
|
||||||
|
|
||||||
|
// Make TS show appropriate type
|
||||||
|
return selectedRooms.filter((sr): sr is Room => !!sr)
|
||||||
}),
|
}),
|
||||||
myStay: safeProtectedServiceProcedure
|
myStay: safeProtectedServiceProcedure
|
||||||
.input(myStayRoomAvailabilityInputSchema)
|
.input(myStayRoomAvailabilityInputSchema)
|
||||||
|
|||||||
@@ -1,8 +1,9 @@
|
|||||||
import deepmerge from "deepmerge"
|
import deepmerge from "deepmerge"
|
||||||
import stringify from "json-stable-stringify-without-jsonify"
|
import stringify from "json-stable-stringify-without-jsonify"
|
||||||
|
|
||||||
import { REDEMPTION } from "@/constants/booking"
|
import { BookingErrorCodeEnum, REDEMPTION } from "@/constants/booking"
|
||||||
import { Lang } from "@/constants/languages"
|
import { Lang } from "@/constants/languages"
|
||||||
|
import { selectRate } from "@/constants/routes/hotelReservation"
|
||||||
import { env } from "@/env/server"
|
import { env } from "@/env/server"
|
||||||
import * as api from "@/lib/api"
|
import * as api from "@/lib/api"
|
||||||
import { badRequestError } from "@/server/errors/trpc"
|
import { badRequestError } from "@/server/errors/trpc"
|
||||||
@@ -43,6 +44,7 @@ import type { PackagesOutput } from "@/types/requests/packages"
|
|||||||
import type {
|
import type {
|
||||||
HotelsAvailabilityInputSchema,
|
HotelsAvailabilityInputSchema,
|
||||||
HotelsByHotelIdsAvailabilityInputSchema,
|
HotelsByHotelIdsAvailabilityInputSchema,
|
||||||
|
RoomsAvailabilityExtendedInputSchema,
|
||||||
RoomsAvailabilityInputRoom,
|
RoomsAvailabilityInputRoom,
|
||||||
RoomsAvailabilityOutputSchema,
|
RoomsAvailabilityOutputSchema,
|
||||||
} from "@/types/trpc/routers/hotel/availability"
|
} from "@/types/trpc/routers/hotel/availability"
|
||||||
@@ -1245,6 +1247,7 @@ export function getBedTypes(
|
|||||||
size: matchingRoom.mainBed.widthRange,
|
size: matchingRoom.mainBed.widthRange,
|
||||||
value: matchingRoom.code,
|
value: matchingRoom.code,
|
||||||
type: matchingRoom.mainBed.type,
|
type: matchingRoom.mainBed.type,
|
||||||
|
roomsLeft: availRoom.roomsLeft,
|
||||||
extraBed: matchingRoom.fixedExtraBed
|
extraBed: matchingRoom.fixedExtraBed
|
||||||
? {
|
? {
|
||||||
type: matchingRoom.fixedExtraBed.type,
|
type: matchingRoom.fixedExtraBed.type,
|
||||||
@@ -1293,3 +1296,43 @@ export function mergeRoomTypes(roomConfigurations: RoomConfiguration[]) {
|
|||||||
}
|
}
|
||||||
return Array.from(roomConfigs.values())
|
return Array.from(roomConfigs.values())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function selectRateRedirectURL(
|
||||||
|
input: RoomsAvailabilityExtendedInputSchema,
|
||||||
|
selectedRooms: boolean[]
|
||||||
|
) {
|
||||||
|
const searchParams = new URLSearchParams({
|
||||||
|
errorCode: BookingErrorCodeEnum.AvailabilityError,
|
||||||
|
fromdate: input.booking.fromDate,
|
||||||
|
hotel: input.booking.hotelId,
|
||||||
|
todate: input.booking.toDate,
|
||||||
|
})
|
||||||
|
if (input.booking.searchType) {
|
||||||
|
searchParams.set("searchtype", input.booking.searchType)
|
||||||
|
}
|
||||||
|
for (const [idx, room] of input.booking.rooms.entries()) {
|
||||||
|
searchParams.set(`room[${idx}].adults`, room.adults.toString())
|
||||||
|
|
||||||
|
if (selectedRooms[idx]) {
|
||||||
|
if (room.counterRateCode) {
|
||||||
|
searchParams.set(`room[${idx}].counterratecode`, room.counterRateCode)
|
||||||
|
}
|
||||||
|
searchParams.set(`room[${idx}].ratecode`, room.rateCode)
|
||||||
|
searchParams.set(`room[${idx}].roomtype`, room.roomTypeCode)
|
||||||
|
}
|
||||||
|
if (room.bookingCode) {
|
||||||
|
searchParams.set(`room[${idx}].bookingCode`, room.bookingCode)
|
||||||
|
}
|
||||||
|
if (room.packages) {
|
||||||
|
searchParams.set(`room[${idx}].packages`, room.packages.join(","))
|
||||||
|
}
|
||||||
|
if (room.childrenInRoom?.length) {
|
||||||
|
for (const [i, kid] of room.childrenInRoom.entries()) {
|
||||||
|
searchParams.set(`room[${idx}].child[${i}].age`, kid.age.toString())
|
||||||
|
searchParams.set(`room[${idx}].child[${i}].bed`, kid.bed.toString())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return `${selectRate(input.lang)}?${searchParams.toString()}`
|
||||||
|
}
|
||||||
|
|||||||
@@ -139,7 +139,19 @@ export function createDetailsStore(
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
const availableBeds = initialState.rooms.reduce<
|
||||||
|
DetailsState["availableBeds"]
|
||||||
|
>((total, room) => {
|
||||||
|
for (const bed of room.bedTypes) {
|
||||||
|
if (!total[bed.value]) {
|
||||||
|
total[bed.value] = bed.roomsLeft
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return total
|
||||||
|
}, {})
|
||||||
|
|
||||||
return create<DetailsState>()((set) => ({
|
return create<DetailsState>()((set) => ({
|
||||||
|
availableBeds,
|
||||||
booking: initialState.booking,
|
booking: initialState.booking,
|
||||||
breakfastPackages,
|
breakfastPackages,
|
||||||
canProceedToPayment: false,
|
canProceedToPayment: false,
|
||||||
@@ -179,6 +191,15 @@ export function createDetailsStore(
|
|||||||
updateBedType(bedType) {
|
updateBedType(bedType) {
|
||||||
return set(
|
return set(
|
||||||
produce((state: DetailsState) => {
|
produce((state: DetailsState) => {
|
||||||
|
const currentlySelectedBed =
|
||||||
|
state.rooms[idx].room.bedType?.roomTypeCode
|
||||||
|
if (currentlySelectedBed) {
|
||||||
|
state.availableBeds[currentlySelectedBed] =
|
||||||
|
state.availableBeds[currentlySelectedBed] + 1
|
||||||
|
}
|
||||||
|
state.availableBeds[bedType.roomTypeCode] =
|
||||||
|
state.availableBeds[bedType.roomTypeCode] - 1
|
||||||
|
|
||||||
state.rooms[idx].steps[StepEnum.selectBed].isValid = true
|
state.rooms[idx].steps[StepEnum.selectBed].isValid = true
|
||||||
state.rooms[idx].room.bedType = bedType
|
state.rooms[idx].room.bedType = bedType
|
||||||
|
|
||||||
|
|||||||
@@ -14,6 +14,7 @@ export type BedTypeSelection = {
|
|||||||
}
|
}
|
||||||
value: string
|
value: string
|
||||||
type: BedTypeEnum
|
type: BedTypeEnum
|
||||||
|
roomsLeft: number
|
||||||
extraBed:
|
extraBed:
|
||||||
| {
|
| {
|
||||||
description: string
|
description: string
|
||||||
|
|||||||
@@ -1,21 +1,21 @@
|
|||||||
import type { BedTypeSelection } from "@/types/components/hotelReservation/enterDetails/bedType"
|
import type { BedTypeSelection } from "@/types/components/hotelReservation/enterDetails/bedType"
|
||||||
import type { RoomRate } from "@/types/components/hotelReservation/enterDetails/details"
|
import type { RoomRate } from "@/types/components/hotelReservation/enterDetails/details"
|
||||||
import type { RateEnum } from "@/types/enums/rate"
|
import type { RateEnum } from "@/types/enums/rate"
|
||||||
import type { Packages } from "@/types/requests/packages"
|
import type { Package } from "@/types/requests/packages"
|
||||||
|
|
||||||
export interface Room {
|
export interface Room {
|
||||||
bedTypes?: BedTypeSelection[]
|
bedTypes: BedTypeSelection[]
|
||||||
breakfastIncluded?: boolean
|
breakfastIncluded: boolean
|
||||||
cancellationRule?: string
|
cancellationRule?: string
|
||||||
cancellationText: string
|
cancellationText: string
|
||||||
mustBeGuaranteed: boolean
|
mustBeGuaranteed: boolean
|
||||||
memberMustBeGuaranteed?: boolean
|
memberMustBeGuaranteed: boolean | undefined
|
||||||
packages: Packages | null
|
packages: Package[]
|
||||||
rate: RateEnum
|
rate: RateEnum
|
||||||
rateDefinitionTitle: string
|
rateDefinitionTitle: string
|
||||||
rateDetails: string[]
|
rateDetails: string[]
|
||||||
memberRateDetails?: string[]
|
memberRateDetails: string[] | undefined
|
||||||
rateTitle?: string
|
rateTitle: string | undefined
|
||||||
rateType: string
|
rateType: string
|
||||||
roomRate: RoomRate
|
roomRate: RoomRate
|
||||||
roomType: string
|
roomType: string
|
||||||
|
|||||||
@@ -90,6 +90,7 @@ export interface DetailsState {
|
|||||||
updateSeachParamString: (searchParamString: string) => void
|
updateSeachParamString: (searchParamString: string) => void
|
||||||
addPreSubmitCallback: (name: string, callback: () => void) => void
|
addPreSubmitCallback: (name: string, callback: () => void) => void
|
||||||
}
|
}
|
||||||
|
availableBeds: Record<string, number>
|
||||||
booking: SelectRateSearchParams
|
booking: SelectRateSearchParams
|
||||||
breakfastPackages: BreakfastPackages
|
breakfastPackages: BreakfastPackages
|
||||||
canProceedToPayment: boolean
|
canProceedToPayment: boolean
|
||||||
|
|||||||
Reference in New Issue
Block a user