Merged in feat/SW-1356-reward-night-booking-2- (pull request #1559)

feat: SW-1356 Reward night bookingflow

* feat: SW-1356 Reward night bookingflow

* feat: SW-1356 Removed extra param booking call

* feat: SW-1356 Optimized as review comments

* feat: SW-1356 Schema validation updates

* feat: SW-1356 Fix after rebase

* feat: SW-1356 Optimised price.redemptions check

* feat: SW-1356 Updated Props naming


Approved-by: Arvid Norlin
This commit is contained in:
Hrishikesh Vaipurkar
2025-03-24 08:54:02 +00:00
parent b972679c6e
commit c5e294c7ea
57 changed files with 1113 additions and 657 deletions
@@ -2,9 +2,10 @@ import isEqual from "fast-deep-equal"
import { detailsStorageName } from "."
import type { RoomRate } from "@/types/components/hotelReservation/enterDetails/details"
import { type RoomRate } from "@/types/components/hotelReservation/enterDetails/details"
import type { Price } from "@/types/components/hotelReservation/price"
import type { SelectRateSearchParams } from "@/types/components/hotelReservation/selectRate/selectRate"
import { CurrencyEnum } from "@/types/enums/currency"
import { StepEnum } from "@/types/enums/step"
import type {
DetailsState,
@@ -131,18 +132,43 @@ export function getRoomPrice(roomRate: RoomRate, isMember: boolean) {
}
}
if (roomRate.redemptionRate) {
return {
// ToDo Handle perNight as undefined
perNight: {
requested: undefined,
local: {
currency:
roomRate.redemptionRate.localPrice.currency ?? CurrencyEnum.POINTS,
price: roomRate.redemptionRate.localPrice.pointsPerStay,
additionalPrice:
roomRate.redemptionRate.localPrice.additionalPricePerStay,
additionalPriceCurrency:
roomRate.redemptionRate.localPrice.additionalPriceCurrency,
},
},
perStay: {
requested: undefined,
local: {
currency:
roomRate.redemptionRate.localPrice.currency ?? CurrencyEnum.POINTS,
price: roomRate.redemptionRate.localPrice.pointsPerStay,
additionalPrice:
roomRate.redemptionRate.localPrice.additionalPricePerStay,
additionalPriceCurrency:
roomRate.redemptionRate.localPrice.additionalPriceCurrency,
},
},
}
}
throw new Error(
`Unable to calculate RoomPrice since user is neither a member or memberRate is missing, or publicRate is missing`
)
}
type TotalPrice = {
requested: { currency: string; price: number } | undefined
local: { currency: string; price: number; regularPrice?: number }
}
export function getTotalPrice(roomRates: RoomRate[], isMember: boolean) {
return roomRates.reduce<TotalPrice>(
return roomRates.reduce<Price>(
(total, roomRate, idx) => {
const isFirstRoom = idx === 0
const rate =
+17 -4
View File
@@ -3,6 +3,7 @@ import { produce } from "immer"
import { useContext } from "react"
import { create, useStore } from "zustand"
import { REDEMPTION } from "@/constants/booking"
import { dt } from "@/lib/dt"
import { DetailsContext } from "@/contexts/Details"
@@ -20,6 +21,9 @@ import {
} from "./helpers"
import type { BreakfastPackages } from "@/types/components/hotelReservation/breakfast"
import {
PointsPriceSchema,
type Price} from "@/types/components/hotelReservation/price";
import { StepEnum } from "@/types/enums/step"
import type {
DetailsState,
@@ -49,11 +53,20 @@ export function createDetailsStore(
breakfastPackages: BreakfastPackages | null
) {
const isMember = !!user
const isRedemption =
new URLSearchParams(searchParams).get("searchtype") === REDEMPTION
const initialTotalPrice = getTotalPrice(
initialState.rooms.map((r) => r.roomRate),
isMember
)
let initialTotalPrice: Price
if (isRedemption && initialState.rooms[0].roomRate.redemptionRate) {
initialTotalPrice = PointsPriceSchema.parse(
initialState.rooms[0].roomRate.redemptionRate
)
} else {
initialTotalPrice = getTotalPrice(
initialState.rooms.map((r) => r.roomRate),
isMember
)
}
initialState.rooms.forEach((room) => {
if (room.roomFeatures) {
+67 -7
View File
@@ -91,10 +91,15 @@ export function createRatesStore({
rc.products.find(
(product) =>
product.public?.rateCode === room.rateCode ||
product.member?.rateCode === room.rateCode
product.member?.rateCode === room.rateCode ||
product.redemptions?.find(
(redemption) => redemption?.rateCode === room.rateCode
)
)
)
const redemptionProduct = selectedRoom?.products[0].redemptions?.find(
(r) => r?.rateCode === room.rateCode
)
const product = selectedRoom?.products.find(
(p) =>
p.public?.rateCode === room.rateCode ||
@@ -105,10 +110,19 @@ export function createRatesStore({
features: selectedRoom.features,
member: product.member,
public: product.public,
redemption: undefined,
rate: product.rate,
roomType: selectedRoom.roomType,
roomTypeCode: selectedRoom.roomTypeCode,
}
} else if (selectedRoom && redemptionProduct) {
rateSummary[idx] = {
features: selectedRoom.features,
redemption: redemptionProduct,
rate: selectedRoom?.products[0].rate,
roomType: selectedRoom.roomType,
roomTypeCode: selectedRoom.roomTypeCode,
}
}
}
})
@@ -200,6 +214,7 @@ export function createRatesStore({
package: state.rooms[idx].selectedPackage,
rate: selectedRate.product.rate,
public: selectedRate.product.public,
redemption: undefined,
roomType: selectedRate.roomType,
roomTypeCode: selectedRate.roomTypeCode,
}
@@ -240,6 +255,51 @@ export function createRatesStore({
state.activeRoom = idx + 1
}
state.searchParams = new ReadonlyURLSearchParams(searchParams)
window.history.pushState(
{},
"",
`${state.pathname}?${searchParams}`
)
})
)
}
},
selectRateRedemption(idx) {
return function (selectedRate, selectedRateCode?: string) {
return set(
produce((state: RatesState) => {
const redemptionRate = selectedRate.product.redemptions?.find(
(r) => r?.rateCode === selectedRateCode
)
if (!redemptionRate) {
return
}
state.rooms[idx].selectedRate = selectedRate
state.rateSummary[idx] = {
features: selectedRate.features,
package: state.rooms[idx].selectedPackage,
rate: selectedRate.product.rate,
roomType: selectedRate.roomType,
roomTypeCode: selectedRate.roomTypeCode,
redemption: redemptionRate,
}
const searchParams = new URLSearchParams(state.searchParams)
if (redemptionRate.rateCode) {
searchParams.set(
`room[${idx}].ratecode`,
redemptionRate.rateCode
)
}
searchParams.set(
`room[${idx}].roomtype`,
selectedRate.roomTypeCode
)
state.searchParams = new ReadonlyURLSearchParams(searchParams)
window.history.pushState(
{},
@@ -291,11 +351,11 @@ export function createRatesStore({
selectedRate:
selectedRate && product
? {
features: selectedRate.features,
product,
roomType: selectedRate.roomType,
roomTypeCode: selectedRate.roomTypeCode,
}
features: selectedRate.features,
product,
roomType: selectedRate.roomType,
roomTypeCode: selectedRate.roomTypeCode,
}
: null,
}
}),