Merged in fix/allow-single-rateCode (pull request #1438)
fix: allow rates that only have either of member or public to be selectable * fix: allow rates that only have either of member or public to be selectable Approved-by: Michael Zetterberg
This commit is contained in:
committed by
Linus Flood
parent
3f01266a75
commit
c3e3fa62ec
@@ -25,13 +25,6 @@ export function extractGuestFromUser(user: NonNullable<SafeUser>) {
|
||||
}
|
||||
}
|
||||
|
||||
export function checkIsSameBedTypes(
|
||||
storedBedTypes: string,
|
||||
bedTypesData: string
|
||||
) {
|
||||
return storedBedTypes === bedTypesData
|
||||
}
|
||||
|
||||
export function checkIsSameBooking(
|
||||
prev: SelectRateSearchParams,
|
||||
next: SelectRateSearchParams
|
||||
@@ -111,28 +104,34 @@ export function getRoomPrice(roomRate: RoomRate, isMember: boolean) {
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
perNight: {
|
||||
requested: roomRate.publicRate.requestedPrice && {
|
||||
currency: roomRate.publicRate.requestedPrice.currency,
|
||||
price: roomRate.publicRate.requestedPrice.pricePerNight,
|
||||
if (roomRate.publicRate) {
|
||||
return {
|
||||
perNight: {
|
||||
requested: roomRate.publicRate.requestedPrice && {
|
||||
currency: roomRate.publicRate.requestedPrice.currency,
|
||||
price: roomRate.publicRate.requestedPrice.pricePerNight,
|
||||
},
|
||||
local: {
|
||||
currency: roomRate.publicRate.localPrice.currency,
|
||||
price: roomRate.publicRate.localPrice.pricePerNight,
|
||||
},
|
||||
},
|
||||
local: {
|
||||
currency: roomRate.publicRate.localPrice.currency,
|
||||
price: roomRate.publicRate.localPrice.pricePerNight,
|
||||
perStay: {
|
||||
requested: roomRate.publicRate.requestedPrice && {
|
||||
currency: roomRate.publicRate.requestedPrice.currency,
|
||||
price: roomRate.publicRate.requestedPrice.pricePerStay,
|
||||
},
|
||||
local: {
|
||||
currency: roomRate.publicRate.localPrice.currency,
|
||||
price: roomRate.publicRate.localPrice.pricePerStay,
|
||||
},
|
||||
},
|
||||
},
|
||||
perStay: {
|
||||
requested: roomRate.publicRate.requestedPrice && {
|
||||
currency: roomRate.publicRate.requestedPrice.currency,
|
||||
price: roomRate.publicRate.requestedPrice.pricePerStay,
|
||||
},
|
||||
local: {
|
||||
currency: roomRate.publicRate.localPrice.currency,
|
||||
price: roomRate.publicRate.localPrice.pricePerStay,
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
throw new Error(
|
||||
`Unable to calculate RoomPrice since user is neither a member or memberRate is missing, or publicRate is missing`
|
||||
)
|
||||
}
|
||||
|
||||
type TotalPrice = {
|
||||
@@ -149,6 +148,10 @@ export function getTotalPrice(roomRates: RoomRate[], isMember: boolean) {
|
||||
? roomRate.memberRate
|
||||
: roomRate.publicRate
|
||||
|
||||
if (!rate) {
|
||||
return total
|
||||
}
|
||||
|
||||
return {
|
||||
requested: rate.requestedPrice
|
||||
? {
|
||||
@@ -168,7 +171,8 @@ export function getTotalPrice(roomRates: RoomRate[], isMember: boolean) {
|
||||
{
|
||||
requested: undefined,
|
||||
local: {
|
||||
currency: roomRates[0].publicRate.localPrice.currency,
|
||||
currency: (roomRates[0].publicRate?.localPrice.currency ||
|
||||
roomRates[0].memberRate?.localPrice.currency)!,
|
||||
price: 0,
|
||||
},
|
||||
}
|
||||
@@ -191,6 +195,10 @@ export function calcTotalPrice(
|
||||
isFirstRoomAndMember || join
|
||||
)
|
||||
|
||||
if (!roomPrice) {
|
||||
return acc
|
||||
}
|
||||
|
||||
const breakfastRequestedPrice = room.breakfast
|
||||
? parseInt(room.breakfast.requestedPrice?.price ?? 0)
|
||||
: 0
|
||||
|
||||
@@ -25,7 +25,6 @@ import type {
|
||||
DetailsState,
|
||||
InitialState,
|
||||
RoomState,
|
||||
RoomStatus,
|
||||
} from "@/types/stores/enter-details"
|
||||
import type { SafeUser } from "@/types/user"
|
||||
|
||||
@@ -74,7 +73,7 @@ export function createDetailsStore(
|
||||
})
|
||||
|
||||
const rooms: RoomState[] = initialState.rooms.map((room, idx) => {
|
||||
const steps: RoomStatus["steps"] = {
|
||||
const steps: RoomState["steps"] = {
|
||||
[StepEnum.selectBed]: {
|
||||
step: StepEnum.selectBed,
|
||||
isValid: !!room.bedType,
|
||||
@@ -225,6 +224,13 @@ export function createDetailsStore(
|
||||
state.rooms[idx].steps[StepEnum.selectBed].isValid = true
|
||||
state.rooms[idx].room.bedType = bedType
|
||||
|
||||
const isAllStepsCompleted = checkRoomProgress(
|
||||
state.rooms[idx].steps
|
||||
)
|
||||
if (isAllStepsCompleted) {
|
||||
state.rooms[idx].isComplete = true
|
||||
}
|
||||
|
||||
handleStepProgression(state.rooms[idx], state)
|
||||
|
||||
writeToSessionStorage({
|
||||
@@ -331,6 +337,13 @@ export function createDetailsStore(
|
||||
|
||||
currentRoom.room.breakfast = breakfast
|
||||
|
||||
const isAllStepsCompleted = checkRoomProgress(
|
||||
state.rooms[idx].steps
|
||||
)
|
||||
if (isAllStepsCompleted) {
|
||||
state.rooms[idx].isComplete = true
|
||||
}
|
||||
|
||||
handleStepProgression(currentRoom, state)
|
||||
|
||||
writeToSessionStorage({
|
||||
|
||||
@@ -1,70 +1,6 @@
|
||||
import { AvailabilityEnum } from "@/types/components/hotelReservation/selectHotel/selectHotel"
|
||||
import {
|
||||
RoomPackageCodeEnum,
|
||||
type RoomPackages,
|
||||
} from "@/types/components/hotelReservation/selectRate/roomFilter"
|
||||
import type {
|
||||
Rate,
|
||||
RateCode,
|
||||
} from "@/types/components/hotelReservation/selectRate/selectRate"
|
||||
import type { RoomConfiguration } from "@/types/trpc/routers/hotel/roomAvailability"
|
||||
|
||||
interface CalculateRoomSummaryParams {
|
||||
availablePackages: RoomPackages
|
||||
getFilteredRooms: (roomIndex: number) => RoomConfiguration[]
|
||||
roomCategories: Array<{ name: string; roomTypes: Array<{ code: string }> }>
|
||||
selectedPackagesByRoom: Record<number, RoomPackageCodeEnum[]>
|
||||
selectedRate: RateCode
|
||||
roomIndex: number
|
||||
}
|
||||
|
||||
export function calculateRoomSummary({
|
||||
selectedRate,
|
||||
roomIndex,
|
||||
getFilteredRooms,
|
||||
availablePackages,
|
||||
roomCategories,
|
||||
selectedPackagesByRoom,
|
||||
}: CalculateRoomSummaryParams): Rate | null {
|
||||
const filteredRooms = getFilteredRooms(roomIndex)
|
||||
const selectedPackages = selectedPackagesByRoom[roomIndex] || []
|
||||
|
||||
const room = filteredRooms.find(
|
||||
(room) => room.roomTypeCode === selectedRate.roomTypeCode
|
||||
)
|
||||
if (!room) return null
|
||||
|
||||
const product = room.products.find(
|
||||
(product) =>
|
||||
product.productType.public.rateCode === selectedRate.publicRateCode
|
||||
)
|
||||
if (!product) return null
|
||||
|
||||
const petRoomPackage = selectedPackages.includes(RoomPackageCodeEnum.PET_ROOM)
|
||||
? availablePackages.find((pkg) => pkg.code === RoomPackageCodeEnum.PET_ROOM)
|
||||
: undefined
|
||||
|
||||
const features = filteredRooms.find((room) =>
|
||||
room.features.some(
|
||||
(feature) => feature.code === RoomPackageCodeEnum.PET_ROOM
|
||||
)
|
||||
)?.features
|
||||
|
||||
const roomType = roomCategories.find((roomCategory) =>
|
||||
roomCategory.roomTypes.some((type) => type.code === room.roomTypeCode)
|
||||
)
|
||||
|
||||
return {
|
||||
features: petRoomPackage && features ? features : [],
|
||||
priceName: selectedRate.name,
|
||||
priceTerm: selectedRate.paymentTerm,
|
||||
public: product.productType.public,
|
||||
member: product.productType.member,
|
||||
roomType: roomType?.name ?? room.roomType,
|
||||
roomTypeCode: room.roomTypeCode,
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the lowest priced room for each room type that appears more than once.
|
||||
*/
|
||||
@@ -119,12 +55,11 @@ export function filterDuplicateRoomTypesByLowestPrice(
|
||||
|
||||
if (previousRoom) {
|
||||
products.forEach((product) => {
|
||||
const { productType } = product
|
||||
const publicProduct = productType.public || {
|
||||
const publicProduct = product?.public || {
|
||||
requestedPrice: null,
|
||||
localPrice: null,
|
||||
}
|
||||
const memberProduct = productType.member || {
|
||||
const memberProduct = product?.member || {
|
||||
requestedPrice: null,
|
||||
localPrice: null,
|
||||
}
|
||||
@@ -154,34 +89,28 @@ export function filterDuplicateRoomTypesByLowestPrice(
|
||||
currentRequestedPrice <
|
||||
Math.min(
|
||||
Number(
|
||||
previousLowest.products[0].productType.public.requestedPrice
|
||||
?.pricePerNight
|
||||
previousLowest.products[0].public?.requestedPrice?.pricePerNight
|
||||
) ?? Infinity,
|
||||
Number(
|
||||
previousLowest.products[0].productType.member?.requestedPrice
|
||||
?.pricePerNight
|
||||
previousLowest.products[0].member?.requestedPrice?.pricePerNight
|
||||
) ?? Infinity
|
||||
) ||
|
||||
(currentRequestedPrice ===
|
||||
Math.min(
|
||||
Number(
|
||||
previousLowest.products[0].productType.public.requestedPrice
|
||||
?.pricePerNight
|
||||
previousLowest.products[0].public?.requestedPrice?.pricePerNight
|
||||
) ?? Infinity,
|
||||
Number(
|
||||
previousLowest.products[0].productType.member?.requestedPrice
|
||||
?.pricePerNight
|
||||
previousLowest.products[0].member?.requestedPrice?.pricePerNight
|
||||
) ?? Infinity
|
||||
) &&
|
||||
currentLocalPrice <
|
||||
Math.min(
|
||||
Number(
|
||||
previousLowest.products[0].productType.public.localPrice
|
||||
?.pricePerNight
|
||||
previousLowest.products[0].public?.localPrice?.pricePerNight
|
||||
) ?? Infinity,
|
||||
Number(
|
||||
previousLowest.products[0].productType.member?.localPrice
|
||||
?.pricePerNight
|
||||
previousLowest.products[0].member?.localPrice?.pricePerNight
|
||||
) ?? Infinity
|
||||
))
|
||||
) {
|
||||
|
||||
@@ -9,6 +9,7 @@ import { RatesContext } from "@/contexts/Rates"
|
||||
|
||||
import { AvailabilityEnum } from "@/types/components/hotelReservation/selectHotel/selectHotel"
|
||||
import { RoomPackageCodeEnum } from "@/types/components/hotelReservation/selectRate/roomFilter"
|
||||
import { RateTypeEnum } from "@/types/enums/rateType"
|
||||
import type { InitialState, RatesState } from "@/types/stores/rates"
|
||||
import type { RoomConfiguration } from "@/types/trpc/routers/hotel/roomAvailability"
|
||||
|
||||
@@ -27,8 +28,8 @@ function findSelectedRate(
|
||||
room.roomTypeCode === roomTypeCode &&
|
||||
room.products.find(
|
||||
(product) =>
|
||||
product.productType.public.rateCode === rateCode ||
|
||||
product.productType.member?.rateCode === rateCode
|
||||
product.public?.rateCode === rateCode ||
|
||||
product.member?.rateCode === rateCode
|
||||
)
|
||||
)
|
||||
}
|
||||
@@ -87,21 +88,22 @@ export function createRatesStore({
|
||||
roomConf.roomTypeCode === room.roomTypeCode &&
|
||||
roomConf.products.find(
|
||||
(product) =>
|
||||
product.productType.public.rateCode === room.rateCode ||
|
||||
product.productType.member?.rateCode === room.rateCode
|
||||
product.public?.rateCode === room.rateCode ||
|
||||
product.member?.rateCode === room.rateCode
|
||||
)
|
||||
)
|
||||
|
||||
const product = selectedRoom?.products.find(
|
||||
(p) =>
|
||||
p.productType.public.rateCode === room.rateCode ||
|
||||
p.productType.member?.rateCode === room.rateCode
|
||||
p.public?.rateCode === room.rateCode ||
|
||||
p.member?.rateCode === room.rateCode
|
||||
)
|
||||
if (selectedRoom && product) {
|
||||
rateSummary[idx] = {
|
||||
features: selectedRoom.features,
|
||||
member: product.productType.member,
|
||||
public: product.productType.public,
|
||||
member: product.member,
|
||||
public: product.public,
|
||||
rate: product.rate,
|
||||
roomType: selectedRoom.roomType,
|
||||
roomTypeCode: selectedRoom.roomTypeCode,
|
||||
}
|
||||
@@ -180,35 +182,48 @@ export function createRatesStore({
|
||||
return function (selectedRate) {
|
||||
return set(
|
||||
produce((state: RatesState) => {
|
||||
const memberRate = selectedRate.product.member
|
||||
const publicRate = selectedRate.product.public
|
||||
if (!memberRate && !publicRate) {
|
||||
return
|
||||
}
|
||||
|
||||
state.rooms[idx].selectedRate = selectedRate
|
||||
state.rateSummary[idx] = {
|
||||
features: selectedRate.features,
|
||||
member: selectedRate.product.productType.member,
|
||||
member: selectedRate.product.member,
|
||||
package: state.rooms[idx].selectedPackage,
|
||||
public: selectedRate.product.productType.public,
|
||||
rate: selectedRate.product.rate,
|
||||
public: selectedRate.product.public,
|
||||
roomType: selectedRate.roomType,
|
||||
roomTypeCode: selectedRate.roomTypeCode,
|
||||
}
|
||||
|
||||
const isBookingCodeRate =
|
||||
selectedRate.product.public?.rateType !== RateTypeEnum.Regular
|
||||
|
||||
const roomNr = idx + 1
|
||||
const isMainRoom = roomNr + 1
|
||||
const isMemberRate =
|
||||
isUserLoggedIn &&
|
||||
roomNr === 1 &&
|
||||
selectedRate.product.productType.member
|
||||
isUserLoggedIn && isMainRoom && memberRate && !isBookingCodeRate
|
||||
const searchParams = new URLSearchParams(state.searchParams)
|
||||
searchParams.set(
|
||||
`room[${idx}].counterratecode`,
|
||||
isMemberRate
|
||||
? selectedRate.product.productType.public.rateCode
|
||||
: (selectedRate.product.productType.member?.rateCode ?? "")
|
||||
)
|
||||
searchParams.set(
|
||||
`room[${idx}].ratecode`,
|
||||
isMemberRate
|
||||
? // already checked in isMemberRate
|
||||
selectedRate.product.productType.member!.rateCode
|
||||
: selectedRate.product.productType.public.rateCode
|
||||
)
|
||||
const counterratecode = isMemberRate
|
||||
? (publicRate?.rateCode ?? "")
|
||||
: (memberRate?.rateCode ?? "")
|
||||
if (counterratecode) {
|
||||
searchParams.set(
|
||||
`room[${idx}].counterratecode`,
|
||||
counterratecode
|
||||
)
|
||||
}
|
||||
|
||||
const rateCode = isMemberRate
|
||||
? memberRate.rateCode
|
||||
: (publicRate?.rateCode ?? "")
|
||||
if (rateCode) {
|
||||
searchParams.set(`room[${idx}].ratecode`, rateCode)
|
||||
}
|
||||
|
||||
searchParams.set(
|
||||
`room[${idx}].roomtype`,
|
||||
selectedRate.roomTypeCode
|
||||
@@ -249,8 +264,8 @@ export function createRatesStore({
|
||||
|
||||
const product = selectedRate?.products.find(
|
||||
(prd) =>
|
||||
prd.productType.public.rateCode === room.rateCode ||
|
||||
prd.productType.member?.rateCode === room.rateCode
|
||||
prd.public?.rateCode === room.rateCode ||
|
||||
prd.member?.rateCode === room.rateCode
|
||||
)
|
||||
|
||||
const selectedPackage = room.packages?.[0]
|
||||
@@ -259,18 +274,18 @@ export function createRatesStore({
|
||||
bookingRoom: room,
|
||||
rooms: selectedPackage
|
||||
? allRooms.filter((r) =>
|
||||
r.features.find((f) => f.code === selectedPackage)
|
||||
)
|
||||
r.features.find((f) => f.code === selectedPackage)
|
||||
)
|
||||
: allRooms,
|
||||
selectedPackage,
|
||||
selectedRate:
|
||||
selectedRate && product
|
||||
? {
|
||||
features: selectedRate.features,
|
||||
product,
|
||||
roomType: selectedRate.roomType,
|
||||
roomTypeCode: selectedRate.roomTypeCode,
|
||||
}
|
||||
features: selectedRate.features,
|
||||
product,
|
||||
roomType: selectedRate.roomType,
|
||||
roomTypeCode: selectedRate.roomTypeCode,
|
||||
}
|
||||
: null,
|
||||
}
|
||||
}),
|
||||
|
||||
Reference in New Issue
Block a user