feat(SW-1717): rewrite select-rate to show all variants of rate-cards
This commit is contained in:
committed by
Michael Zetterberg
parent
adde77eaa9
commit
ebaea78fb3
@@ -80,156 +80,187 @@ export function subtract(...nums: (number | string | undefined)[]) {
|
||||
}
|
||||
|
||||
export function getCurrency(roomRate: RoomRate) {
|
||||
const requestedCurrency = <CurrencyEnum>(
|
||||
(roomRate.publicRate?.requestedPrice?.currency ??
|
||||
(roomRate.chequeRate && CurrencyEnum.CC))
|
||||
)
|
||||
const localCurrency = <CurrencyEnum>(
|
||||
(roomRate.publicRate?.localPrice.currency ??
|
||||
(roomRate.voucherRate && CurrencyEnum.Voucher) ??
|
||||
(roomRate.chequeRate && CurrencyEnum.CC))
|
||||
)
|
||||
if ("corporateCheque" in roomRate) {
|
||||
return {
|
||||
localCurrency: CurrencyEnum.CC,
|
||||
requestedCurrency: CurrencyEnum.CC,
|
||||
}
|
||||
} else if ("redemption" in roomRate) {
|
||||
return {
|
||||
localCurrency: CurrencyEnum.POINTS,
|
||||
requestedCurrency: CurrencyEnum.POINTS,
|
||||
}
|
||||
} else if ("voucher" in roomRate) {
|
||||
return {
|
||||
localCurrency: CurrencyEnum.Voucher,
|
||||
requestedCurrency: CurrencyEnum.Voucher,
|
||||
}
|
||||
} else if ("public" in roomRate && roomRate.public) {
|
||||
return {
|
||||
localCurrency: roomRate.public.localPrice.currency,
|
||||
requestedCurrency: roomRate.public.requestedPrice?.currency,
|
||||
}
|
||||
} else if ("member" in roomRate && roomRate.member) {
|
||||
return {
|
||||
localCurrency: roomRate.member.localPrice.currency,
|
||||
requestedCurrency: roomRate.member.requestedPrice?.currency,
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
requestedCurrency,
|
||||
localCurrency,
|
||||
localCurrency: CurrencyEnum.Unknown,
|
||||
requestedCurrency: CurrencyEnum.Unknown,
|
||||
}
|
||||
}
|
||||
|
||||
export function getRoomPrice(roomRate: RoomRate, isMember: boolean) {
|
||||
if (isMember && roomRate.memberRate) {
|
||||
if (isMember && "member" in roomRate && roomRate.member) {
|
||||
return {
|
||||
perNight: {
|
||||
requested: roomRate.memberRate.requestedPrice && {
|
||||
currency: roomRate.memberRate.requestedPrice.currency,
|
||||
price: roomRate.memberRate.requestedPrice.pricePerNight,
|
||||
},
|
||||
requested: roomRate.member.requestedPrice
|
||||
? {
|
||||
currency: roomRate.member.requestedPrice.currency,
|
||||
price: roomRate.member.requestedPrice.pricePerNight,
|
||||
}
|
||||
: undefined,
|
||||
local: {
|
||||
currency: roomRate.memberRate.localPrice.currency,
|
||||
price: roomRate.memberRate.localPrice.pricePerNight,
|
||||
currency: roomRate.member.localPrice.currency,
|
||||
price: roomRate.member.localPrice.pricePerNight,
|
||||
},
|
||||
},
|
||||
perStay: {
|
||||
requested: roomRate.memberRate.requestedPrice && {
|
||||
currency: roomRate.memberRate.requestedPrice.currency,
|
||||
price: roomRate.memberRate.requestedPrice.pricePerStay,
|
||||
},
|
||||
requested: roomRate.member.requestedPrice
|
||||
? {
|
||||
currency: roomRate.member.requestedPrice.currency,
|
||||
price: roomRate.member.requestedPrice.pricePerStay,
|
||||
}
|
||||
: undefined,
|
||||
local: {
|
||||
currency: roomRate.memberRate.localPrice.currency,
|
||||
price: roomRate.memberRate.localPrice.pricePerStay,
|
||||
currency: roomRate.member.localPrice.currency,
|
||||
price: roomRate.member.localPrice.pricePerStay,
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
if (roomRate.publicRate) {
|
||||
if ("public" in roomRate && roomRate.public) {
|
||||
return {
|
||||
perNight: {
|
||||
requested: roomRate.publicRate.requestedPrice && {
|
||||
currency: roomRate.publicRate.requestedPrice.currency,
|
||||
price: roomRate.publicRate.requestedPrice.pricePerNight,
|
||||
},
|
||||
requested: roomRate.public.requestedPrice
|
||||
? {
|
||||
currency: roomRate.public.requestedPrice.currency,
|
||||
price: roomRate.public.requestedPrice.pricePerNight,
|
||||
}
|
||||
: undefined,
|
||||
local: {
|
||||
currency: roomRate.publicRate.localPrice.currency,
|
||||
price: roomRate.publicRate.localPrice.pricePerNight,
|
||||
regularPrice: roomRate.publicRate.localPrice.regularPricePerNight,
|
||||
currency: roomRate.public.localPrice.currency,
|
||||
price: roomRate.public.localPrice.pricePerNight,
|
||||
regularPrice: roomRate.public.localPrice.regularPricePerNight,
|
||||
},
|
||||
},
|
||||
perStay: {
|
||||
requested: roomRate.publicRate.requestedPrice && {
|
||||
currency: roomRate.publicRate.requestedPrice.currency,
|
||||
price: roomRate.publicRate.requestedPrice.pricePerStay,
|
||||
},
|
||||
requested: roomRate.public.requestedPrice
|
||||
? {
|
||||
currency: roomRate.public.requestedPrice.currency,
|
||||
price: roomRate.public.requestedPrice.pricePerStay,
|
||||
}
|
||||
: undefined,
|
||||
local: {
|
||||
currency: roomRate.publicRate.localPrice.currency,
|
||||
price: roomRate.publicRate.localPrice.pricePerStay,
|
||||
regularPrice: roomRate.publicRate.localPrice.regularPricePerStay,
|
||||
currency: roomRate.public.localPrice.currency,
|
||||
price: roomRate.public.localPrice.pricePerStay,
|
||||
regularPrice: roomRate.public.localPrice.regularPricePerStay,
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
if (roomRate.chequeRate) {
|
||||
if ("corporateCheque" in roomRate) {
|
||||
return {
|
||||
perNight: {
|
||||
requested: roomRate.chequeRate.requestedPrice && {
|
||||
currency: CurrencyEnum.CC,
|
||||
price: roomRate.chequeRate.requestedPrice.numberOfBonusCheques,
|
||||
additionalPrice:
|
||||
roomRate.chequeRate.requestedPrice.additionalPricePerStay,
|
||||
additionalPriceCurrency: roomRate.chequeRate.requestedPrice.currency,
|
||||
},
|
||||
requested: roomRate.corporateCheque.requestedPrice
|
||||
? {
|
||||
currency: CurrencyEnum.CC,
|
||||
price: roomRate.corporateCheque.requestedPrice.numberOfCheques,
|
||||
additionalPrice:
|
||||
roomRate.corporateCheque.requestedPrice.additionalPricePerStay,
|
||||
additionalPriceCurrency:
|
||||
roomRate.corporateCheque.requestedPrice.currency ?? undefined,
|
||||
}
|
||||
: undefined,
|
||||
local: {
|
||||
currency: CurrencyEnum.CC,
|
||||
price: roomRate.chequeRate.localPrice.numberOfBonusCheques,
|
||||
price: roomRate.corporateCheque.localPrice.numberOfCheques,
|
||||
additionalPrice:
|
||||
roomRate.chequeRate.localPrice.additionalPricePerStay,
|
||||
additionalPriceCurrency: roomRate.chequeRate.localPrice.currency,
|
||||
roomRate.corporateCheque.localPrice.additionalPricePerStay,
|
||||
additionalPriceCurrency:
|
||||
roomRate.corporateCheque.localPrice.currency ?? undefined,
|
||||
},
|
||||
},
|
||||
perStay: {
|
||||
requested: roomRate.chequeRate.requestedPrice && {
|
||||
currency: CurrencyEnum.CC,
|
||||
price: roomRate.chequeRate.requestedPrice.numberOfBonusCheques,
|
||||
additionalPrice:
|
||||
roomRate.chequeRate.requestedPrice.additionalPricePerStay,
|
||||
additionalPriceCurrency: roomRate.chequeRate.requestedPrice.currency,
|
||||
},
|
||||
requested: roomRate.corporateCheque.requestedPrice
|
||||
? {
|
||||
currency: CurrencyEnum.CC,
|
||||
price: roomRate.corporateCheque.requestedPrice.numberOfCheques,
|
||||
additionalPrice:
|
||||
roomRate.corporateCheque.requestedPrice.additionalPricePerStay,
|
||||
additionalPriceCurrency:
|
||||
roomRate.corporateCheque.requestedPrice.currency ?? undefined,
|
||||
}
|
||||
: undefined,
|
||||
local: {
|
||||
currency: CurrencyEnum.CC,
|
||||
price: roomRate.chequeRate.localPrice.numberOfBonusCheques,
|
||||
price: roomRate.corporateCheque.localPrice.numberOfCheques,
|
||||
additionalPrice:
|
||||
roomRate.chequeRate.localPrice.additionalPricePerStay,
|
||||
additionalPriceCurrency: roomRate.chequeRate.localPrice.currency,
|
||||
roomRate.corporateCheque.localPrice.additionalPricePerStay,
|
||||
additionalPriceCurrency:
|
||||
roomRate.corporateCheque.localPrice.currency ?? undefined,
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
if (roomRate.voucherRate) {
|
||||
if ("voucher" in roomRate) {
|
||||
return {
|
||||
perNight: {
|
||||
requested: undefined,
|
||||
local: {
|
||||
currency: CurrencyEnum.Voucher,
|
||||
price: roomRate.voucherRate.numberOfVouchers,
|
||||
price: roomRate.voucher.numberOfVouchers,
|
||||
},
|
||||
},
|
||||
perStay: {
|
||||
requested: undefined,
|
||||
local: {
|
||||
currency: CurrencyEnum.Voucher,
|
||||
price: roomRate.voucherRate.numberOfVouchers,
|
||||
price: roomRate.voucher.numberOfVouchers,
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
if (roomRate.redemptionRate) {
|
||||
if ("redemption" in roomRate) {
|
||||
return {
|
||||
// ToDo Handle perNight as undefined
|
||||
perNight: {
|
||||
requested: undefined,
|
||||
local: {
|
||||
currency:
|
||||
roomRate.redemptionRate.localPrice.currency ?? CurrencyEnum.POINTS,
|
||||
price: roomRate.redemptionRate.localPrice.pointsPerStay,
|
||||
currency: CurrencyEnum.POINTS,
|
||||
price: roomRate.redemption.localPrice.pointsPerStay,
|
||||
additionalPrice:
|
||||
roomRate.redemptionRate.localPrice.additionalPricePerStay,
|
||||
roomRate.redemption.localPrice.additionalPricePerStay,
|
||||
additionalPriceCurrency:
|
||||
roomRate.redemptionRate.localPrice.additionalPriceCurrency,
|
||||
roomRate.redemption.localPrice.currency ?? undefined,
|
||||
},
|
||||
},
|
||||
perStay: {
|
||||
requested: undefined,
|
||||
local: {
|
||||
currency:
|
||||
roomRate.redemptionRate.localPrice.currency ?? CurrencyEnum.POINTS,
|
||||
price: roomRate.redemptionRate.localPrice.pointsPerStay,
|
||||
currency: CurrencyEnum.POINTS,
|
||||
price: roomRate.redemption.localPrice.pointsPerStay,
|
||||
additionalPrice:
|
||||
roomRate.redemptionRate.localPrice.additionalPricePerStay,
|
||||
roomRate.redemption.localPrice.additionalPricePerStay,
|
||||
additionalPriceCurrency:
|
||||
roomRate.redemptionRate.localPrice.additionalPriceCurrency,
|
||||
roomRate.redemption.localPrice.currency ?? undefined,
|
||||
},
|
||||
},
|
||||
}
|
||||
@@ -243,58 +274,64 @@ export function getRoomPrice(roomRate: RoomRate, isMember: boolean) {
|
||||
export function getTotalPrice(roomRates: RoomRate[], isMember: boolean) {
|
||||
return roomRates.reduce<Price>(
|
||||
(total, roomRate, idx) => {
|
||||
const isFirstRoom = idx === 0
|
||||
const rate =
|
||||
isFirstRoom && isMember && roomRate.memberRate
|
||||
? roomRate.memberRate
|
||||
: roomRate.publicRate
|
||||
|
||||
const isMainRoom = idx === 0
|
||||
let rate
|
||||
if (isMainRoom && isMember && "member" in roomRate && roomRate.member) {
|
||||
rate = roomRate.member
|
||||
} else if ("public" in roomRate && roomRate.public) {
|
||||
rate = roomRate.public
|
||||
}
|
||||
// TODO: Handle other products?
|
||||
if (!rate) {
|
||||
return total
|
||||
}
|
||||
|
||||
return {
|
||||
requested: rate.requestedPrice
|
||||
? {
|
||||
currency: rate.requestedPrice.currency,
|
||||
price: add(
|
||||
total.requested?.price ?? 0,
|
||||
rate.requestedPrice.pricePerStay
|
||||
),
|
||||
}
|
||||
: total.requested,
|
||||
local: {
|
||||
currency: rate.localPrice.currency,
|
||||
price: add(total.local.price ?? 0, rate.localPrice.pricePerStay),
|
||||
regularPrice: rate.localPrice.regularPricePerStay
|
||||
? add(total.local.regularPrice, rate.localPrice.regularPricePerStay)
|
||||
: total.local.regularPrice,
|
||||
},
|
||||
total.local.currency = rate.localPrice.currency
|
||||
total.local.price = add(total.local.price, rate.localPrice.pricePerStay)
|
||||
if (rate.localPrice.regularPricePerStay) {
|
||||
total.local.regularPrice = add(
|
||||
total.local.regularPrice,
|
||||
rate.localPrice.regularPricePerStay
|
||||
)
|
||||
}
|
||||
|
||||
if (rate.requestedPrice) {
|
||||
if (total.requested) {
|
||||
total.requested.price = add(
|
||||
total.requested.price,
|
||||
rate.requestedPrice.pricePerStay
|
||||
)
|
||||
} else {
|
||||
total.requested = {
|
||||
currency: rate.requestedPrice.currency,
|
||||
price: rate.requestedPrice.pricePerStay,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return total
|
||||
},
|
||||
{
|
||||
requested: undefined,
|
||||
local: {
|
||||
currency: (roomRates[0].publicRate?.localPrice.currency ||
|
||||
roomRates[0].memberRate?.localPrice.currency)!,
|
||||
currency: CurrencyEnum.Unknown,
|
||||
price: 0,
|
||||
},
|
||||
requested: undefined,
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
export const calculateVoucherPrice = (roomRates: RoomRate[]) => {
|
||||
export function calculateVoucherPrice(roomRates: RoomRate[]) {
|
||||
return roomRates.reduce<Price>(
|
||||
(total, room) => {
|
||||
const rate = room.voucherRate
|
||||
if (!rate) {
|
||||
if (!("voucher" in room)) {
|
||||
return total
|
||||
}
|
||||
|
||||
return <Price>{
|
||||
return {
|
||||
local: {
|
||||
currency: total.local.currency,
|
||||
price: total.local.price + rate.numberOfVouchers,
|
||||
price: total.local.price + room.voucher.numberOfVouchers,
|
||||
},
|
||||
requested: undefined,
|
||||
}
|
||||
@@ -309,50 +346,56 @@ export const calculateVoucherPrice = (roomRates: RoomRate[]) => {
|
||||
)
|
||||
}
|
||||
|
||||
export const calculateChequePrice = (roomRates: RoomRate[]) => {
|
||||
export function calculateCorporateChequePrice(roomRates: RoomRate[]) {
|
||||
return roomRates.reduce<Price>(
|
||||
(total, room) => {
|
||||
const rate = room.chequeRate
|
||||
if (!rate) {
|
||||
if (!("corporateCheque" in room)) {
|
||||
return total
|
||||
}
|
||||
|
||||
const price = total.local.price + rate.localPrice.numberOfBonusCheques
|
||||
const rate = room.corporateCheque
|
||||
|
||||
const additionalPrice =
|
||||
rate.localPrice.numberOfBonusCheques &&
|
||||
(total.local.additionalPrice ?? 0) +
|
||||
(rate.localPrice.additionalPricePerStay ?? 0)
|
||||
const additionalPriceCurrency = (rate.localPrice.numberOfBonusCheques &&
|
||||
rate.localPrice.currency)!
|
||||
total.local.price = add(
|
||||
total.local.price,
|
||||
rate.localPrice.numberOfCheques
|
||||
)
|
||||
|
||||
const requestedPrice = rate.requestedPrice?.numberOfBonusCheques
|
||||
? (total.requested?.price ?? 0) +
|
||||
rate.requestedPrice?.numberOfBonusCheques
|
||||
: total.requested?.price
|
||||
|
||||
const requestedAdditionalPrice =
|
||||
rate.requestedPrice?.additionalPricePerStay &&
|
||||
(total.requested?.additionalPrice ??
|
||||
0 + rate.requestedPrice?.additionalPricePerStay ??
|
||||
0)
|
||||
|
||||
return <Price>{
|
||||
local: {
|
||||
currency: CurrencyEnum.CC,
|
||||
price,
|
||||
additionalPrice,
|
||||
additionalPriceCurrency,
|
||||
},
|
||||
requested: rate.requestedPrice
|
||||
? {
|
||||
currency: CurrencyEnum.CC,
|
||||
price: requestedPrice,
|
||||
additionalPrice: requestedAdditionalPrice,
|
||||
additionalPriceCurrency: rate.requestedPrice?.currency,
|
||||
}
|
||||
: undefined,
|
||||
if (rate.localPrice.additionalPricePerStay) {
|
||||
total.local.additionalPrice = add(
|
||||
total.local.additionalPrice,
|
||||
rate.localPrice.additionalPricePerStay
|
||||
)
|
||||
}
|
||||
if (rate.localPrice.currency) {
|
||||
total.local.additionalPriceCurrency = rate.localPrice.currency
|
||||
}
|
||||
|
||||
if (rate.requestedPrice) {
|
||||
if (total.requested) {
|
||||
total.requested.price = add(
|
||||
total.requested.price,
|
||||
rate.requestedPrice.numberOfCheques
|
||||
)
|
||||
} else {
|
||||
total.requested = {
|
||||
currency: CurrencyEnum.CC,
|
||||
price: rate.requestedPrice.numberOfCheques,
|
||||
}
|
||||
}
|
||||
|
||||
if (rate.requestedPrice.additionalPricePerStay) {
|
||||
total.requested.additionalPrice = add(
|
||||
total.requested.additionalPrice,
|
||||
rate.requestedPrice.additionalPricePerStay
|
||||
)
|
||||
}
|
||||
|
||||
if (rate.requestedPrice.currency) {
|
||||
total.requested.additionalPriceCurrency = rate.requestedPrice.currency
|
||||
}
|
||||
}
|
||||
|
||||
return total
|
||||
},
|
||||
{
|
||||
local: {
|
||||
@@ -437,8 +480,10 @@ export function calcTotalPrice(
|
||||
breakfastLocalPrice * room.adults * nights,
|
||||
roomFeaturesTotal?.local ?? 0
|
||||
),
|
||||
additionalPriceCurrency:
|
||||
roomPrice.perStay.local.additionalPriceCurrency,
|
||||
additionalPriceCurrency: roomPrice.perStay.local
|
||||
.additionalPriceCurrency
|
||||
? roomPrice.perStay.local.additionalPriceCurrency
|
||||
: undefined,
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
@@ -11,7 +11,7 @@ import { DetailsContext } from "@/contexts/Details"
|
||||
import {
|
||||
add,
|
||||
calcTotalPrice,
|
||||
calculateChequePrice,
|
||||
calculateCorporateChequePrice,
|
||||
calculateVoucherPrice,
|
||||
checkRoomProgress,
|
||||
extractGuestFromUser,
|
||||
@@ -23,9 +23,8 @@ import {
|
||||
} from "./helpers"
|
||||
|
||||
import type { BreakfastPackages } from "@/types/components/hotelReservation/breakfast"
|
||||
import {
|
||||
PointsPriceSchema,
|
||||
type Price} from "@/types/components/hotelReservation/price";
|
||||
import type { Price } from "@/types/components/hotelReservation/price"
|
||||
import { CurrencyEnum } from "@/types/enums/currency"
|
||||
import { StepEnum } from "@/types/enums/step"
|
||||
import type {
|
||||
DetailsState,
|
||||
@@ -58,20 +57,36 @@ export function createDetailsStore(
|
||||
const isRedemption =
|
||||
new URLSearchParams(searchParams).get("searchtype") === REDEMPTION
|
||||
|
||||
const isVoucher = initialState.rooms.some((room) => room.roomRate.voucherRate)
|
||||
const isCorpChq = initialState.rooms.some((room) => room.roomRate.chequeRate)
|
||||
const isVoucher = initialState.rooms.some(
|
||||
(room) => "voucher" in room.roomRate
|
||||
)
|
||||
const isCorpChq = initialState.rooms.some(
|
||||
(room) => "corporateCheque" in room.roomRate
|
||||
)
|
||||
|
||||
let initialTotalPrice: Price
|
||||
if (isRedemption && initialState.rooms[0].roomRate.redemptionRate) {
|
||||
initialTotalPrice = PointsPriceSchema.parse(
|
||||
initialState.rooms[0].roomRate.redemptionRate
|
||||
)
|
||||
const roomOneRoomRate = initialState.rooms[0].roomRate
|
||||
if (isRedemption && "redemption" in roomOneRoomRate) {
|
||||
initialTotalPrice = {
|
||||
local: {
|
||||
currency: CurrencyEnum.POINTS,
|
||||
price: roomOneRoomRate.redemption.localPrice.pointsPerStay,
|
||||
},
|
||||
}
|
||||
if (roomOneRoomRate.redemption.localPrice.currency) {
|
||||
initialTotalPrice.local.additionalPriceCurrency =
|
||||
roomOneRoomRate.redemption.localPrice.currency
|
||||
}
|
||||
if (roomOneRoomRate.redemption.localPrice.additionalPricePerStay) {
|
||||
initialTotalPrice.local.additionalPrice =
|
||||
roomOneRoomRate.redemption.localPrice.additionalPricePerStay
|
||||
}
|
||||
} else if (isVoucher) {
|
||||
initialTotalPrice = calculateVoucherPrice(
|
||||
initialState.rooms.map((r) => r.roomRate)
|
||||
)
|
||||
} else if (isCorpChq) {
|
||||
initialTotalPrice = calculateChequePrice(
|
||||
initialTotalPrice = calculateCorporateChequePrice(
|
||||
initialState.rooms.map((r) => r.roomRate)
|
||||
)
|
||||
} else {
|
||||
@@ -98,56 +113,6 @@ export function createDetailsStore(
|
||||
}
|
||||
})
|
||||
|
||||
const rooms: RoomState[] = initialState.rooms.map((room, idx) => {
|
||||
const steps: RoomState["steps"] = {
|
||||
[StepEnum.selectBed]: {
|
||||
step: StepEnum.selectBed,
|
||||
isValid: !!room.bedType,
|
||||
},
|
||||
[StepEnum.breakfast]: {
|
||||
step: StepEnum.breakfast,
|
||||
isValid: false,
|
||||
},
|
||||
[StepEnum.details]: {
|
||||
step: StepEnum.details,
|
||||
isValid: false,
|
||||
},
|
||||
}
|
||||
|
||||
if (room.breakfastIncluded || !breakfastPackages?.length) {
|
||||
delete steps[StepEnum.breakfast]
|
||||
}
|
||||
|
||||
const currentStep =
|
||||
Object.values(steps).find((step) => !step.isValid)?.step ??
|
||||
StepEnum.selectBed
|
||||
|
||||
return {
|
||||
room: {
|
||||
...room,
|
||||
adults: initialState.booking.rooms[idx].adults,
|
||||
childrenInRoom: initialState.booking.rooms[idx].childrenInRoom,
|
||||
bedType: room.bedType,
|
||||
breakfast:
|
||||
!breakfastPackages?.length || room.breakfastIncluded
|
||||
? false
|
||||
: undefined,
|
||||
guest:
|
||||
isMember && idx === 0
|
||||
? deepmerge(defaultGuestState, extractGuestFromUser(user))
|
||||
: defaultGuestState,
|
||||
roomPrice: getRoomPrice(room.roomRate, isMember && idx === 0),
|
||||
specialRequest: {
|
||||
comment: "",
|
||||
},
|
||||
},
|
||||
|
||||
currentStep,
|
||||
isComplete: false,
|
||||
steps,
|
||||
}
|
||||
})
|
||||
|
||||
return create<DetailsState>()((set) => ({
|
||||
activeRoom: 0,
|
||||
booking: initialState.booking,
|
||||
@@ -156,74 +121,386 @@ export function createDetailsStore(
|
||||
isSubmittingDisabled: false,
|
||||
isSummaryOpen: false,
|
||||
lastRoom: initialState.booking.rooms.length - 1,
|
||||
rooms,
|
||||
rooms: initialState.rooms.map((room, idx) => {
|
||||
const steps: RoomState["steps"] = {
|
||||
[StepEnum.selectBed]: {
|
||||
step: StepEnum.selectBed,
|
||||
isValid: !!room.bedType,
|
||||
},
|
||||
[StepEnum.breakfast]: {
|
||||
step: StepEnum.breakfast,
|
||||
isValid: false,
|
||||
},
|
||||
[StepEnum.details]: {
|
||||
step: StepEnum.details,
|
||||
isValid: false,
|
||||
},
|
||||
}
|
||||
|
||||
if (room.breakfastIncluded || !breakfastPackages?.length) {
|
||||
delete steps[StepEnum.breakfast]
|
||||
}
|
||||
|
||||
const currentStep =
|
||||
Object.values(steps).find((step) => !step.isValid)?.step ??
|
||||
StepEnum.selectBed
|
||||
|
||||
return {
|
||||
actions: {
|
||||
setStep(step) {
|
||||
return set(
|
||||
produce((state: DetailsState) => {
|
||||
const isSameRoom = idx === state.activeRoom
|
||||
const room = state.rooms[idx]
|
||||
if (isSameRoom) {
|
||||
// Closed same accordion as was open
|
||||
if (step === room.currentStep) {
|
||||
if (room.isComplete) {
|
||||
// Room is complete, move to next room or payment
|
||||
const nextRoomIdx = state.rooms.findIndex(
|
||||
(r) => !r.isComplete
|
||||
)
|
||||
state.activeRoom = nextRoomIdx
|
||||
// Done, proceed to payment
|
||||
if (nextRoomIdx === -1) {
|
||||
room.currentStep = null
|
||||
} else {
|
||||
const nextRoom = state.rooms[nextRoomIdx]
|
||||
const nextInvalidStep = findNextInvalidStep(nextRoom)
|
||||
nextRoom.currentStep = nextInvalidStep
|
||||
}
|
||||
} else {
|
||||
room.currentStep = findNextInvalidStep(room)
|
||||
}
|
||||
} else {
|
||||
if (room.steps[step]?.isValid) {
|
||||
room.currentStep = step
|
||||
} else {
|
||||
room.currentStep = findNextInvalidStep(room)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
const arePreviousRoomsCompleted = state.rooms
|
||||
.slice(0, idx)
|
||||
.every((room) => room.isComplete)
|
||||
if (arePreviousRoomsCompleted) {
|
||||
state.activeRoom = idx
|
||||
if (room.steps[step]?.isValid) {
|
||||
room.currentStep = step
|
||||
} else {
|
||||
room.currentStep = findNextInvalidStep(room)
|
||||
}
|
||||
} else {
|
||||
const firstIncompleteRoom = state.rooms.findIndex(
|
||||
(r) => !r.isComplete
|
||||
)
|
||||
state.activeRoom = firstIncompleteRoom
|
||||
if (firstIncompleteRoom === -1) {
|
||||
// All rooms are done, proceed to payment
|
||||
room.currentStep = null
|
||||
} else {
|
||||
const nextRoom = state.rooms[firstIncompleteRoom]
|
||||
nextRoom.currentStep = findNextInvalidStep(nextRoom)
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
)
|
||||
},
|
||||
updateBedType(bedType) {
|
||||
return set(
|
||||
produce((state: DetailsState) => {
|
||||
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({
|
||||
activeRoom: state.activeRoom,
|
||||
booking: state.booking,
|
||||
rooms: state.rooms,
|
||||
})
|
||||
})
|
||||
)
|
||||
},
|
||||
updateBreakfast(breakfast) {
|
||||
return set(
|
||||
produce((state: DetailsState) => {
|
||||
const currentRoom = state.rooms[idx]
|
||||
if (currentRoom.steps[StepEnum.breakfast]) {
|
||||
currentRoom.steps[StepEnum.breakfast].isValid = true
|
||||
}
|
||||
|
||||
const currentTotalPriceRequested = state.totalPrice.requested
|
||||
let stateTotalRequestedPrice = 0
|
||||
if (currentTotalPriceRequested) {
|
||||
stateTotalRequestedPrice =
|
||||
currentTotalPriceRequested.price ?? 0
|
||||
}
|
||||
|
||||
const stateTotalLocalPrice = state.totalPrice.local.price
|
||||
const stateTotalLocalRegularPrice =
|
||||
state.totalPrice.local.regularPrice
|
||||
|
||||
const addToTotalPrice =
|
||||
(currentRoom.room.breakfast === undefined ||
|
||||
currentRoom.room.breakfast === false) &&
|
||||
!!breakfast
|
||||
|
||||
const subtractFromTotalPrice =
|
||||
currentRoom.room.breakfast && breakfast === false
|
||||
|
||||
const nights = dt(state.booking.toDate).diff(
|
||||
state.booking.fromDate,
|
||||
"days"
|
||||
)
|
||||
|
||||
if (addToTotalPrice) {
|
||||
const breakfastTotalRequestedPrice =
|
||||
breakfast.requestedPrice.price *
|
||||
currentRoom.room.adults *
|
||||
nights
|
||||
const breakfastTotalPrice =
|
||||
breakfast.localPrice.price *
|
||||
currentRoom.room.adults *
|
||||
nights
|
||||
state.totalPrice = {
|
||||
requested: state.totalPrice.requested && {
|
||||
currency: state.totalPrice.requested.currency,
|
||||
price:
|
||||
stateTotalRequestedPrice + breakfastTotalRequestedPrice,
|
||||
},
|
||||
local: {
|
||||
currency: breakfast.localPrice.currency,
|
||||
price: stateTotalLocalPrice ?? 0 + breakfastTotalPrice,
|
||||
regularPrice: stateTotalLocalRegularPrice
|
||||
? stateTotalLocalRegularPrice + breakfastTotalPrice
|
||||
: undefined,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
if (subtractFromTotalPrice) {
|
||||
let currency = state.totalPrice.local.currency
|
||||
let currentBreakfastTotalPrice = 0
|
||||
let currentBreakfastTotalRequestedPrice = 0
|
||||
if (currentRoom.room.breakfast) {
|
||||
currentBreakfastTotalPrice =
|
||||
currentRoom.room.breakfast.localPrice.price *
|
||||
currentRoom.room.adults *
|
||||
nights
|
||||
currentBreakfastTotalRequestedPrice =
|
||||
currentRoom.room.breakfast.requestedPrice.totalPrice *
|
||||
currentRoom.room.adults *
|
||||
nights
|
||||
currency = currentRoom.room.breakfast.localPrice.currency
|
||||
}
|
||||
|
||||
let requestedPrice =
|
||||
stateTotalRequestedPrice -
|
||||
currentBreakfastTotalRequestedPrice
|
||||
if (requestedPrice < 0) {
|
||||
requestedPrice = 0
|
||||
}
|
||||
let localPrice =
|
||||
stateTotalLocalPrice - currentBreakfastTotalPrice
|
||||
if (localPrice < 0) {
|
||||
localPrice = 0
|
||||
}
|
||||
let regularPrice = stateTotalLocalRegularPrice
|
||||
? stateTotalLocalRegularPrice - currentBreakfastTotalPrice
|
||||
: undefined
|
||||
|
||||
state.totalPrice = {
|
||||
requested: state.totalPrice.requested && {
|
||||
currency: state.totalPrice.requested.currency,
|
||||
price: requestedPrice,
|
||||
},
|
||||
local: {
|
||||
currency,
|
||||
price: localPrice,
|
||||
regularPrice,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
currentRoom.room.breakfast = breakfast
|
||||
|
||||
const isAllStepsCompleted = checkRoomProgress(
|
||||
state.rooms[idx].steps
|
||||
)
|
||||
if (isAllStepsCompleted) {
|
||||
state.rooms[idx].isComplete = true
|
||||
}
|
||||
|
||||
handleStepProgression(currentRoom, state)
|
||||
|
||||
writeToSessionStorage({
|
||||
activeRoom: state.activeRoom,
|
||||
booking: state.booking,
|
||||
rooms: state.rooms,
|
||||
})
|
||||
})
|
||||
)
|
||||
},
|
||||
updateDetails(data) {
|
||||
return set(
|
||||
produce((state: DetailsState) => {
|
||||
state.rooms[idx].steps[StepEnum.details].isValid = true
|
||||
const currentRoom = state.rooms[idx].room
|
||||
|
||||
currentRoom.guest.countryCode = data.countryCode
|
||||
currentRoom.guest.email = data.email
|
||||
currentRoom.guest.firstName = data.firstName
|
||||
currentRoom.guest.join = data.join
|
||||
currentRoom.guest.lastName = data.lastName
|
||||
|
||||
if (data.specialRequest?.comment) {
|
||||
currentRoom.specialRequest.comment =
|
||||
data.specialRequest.comment
|
||||
}
|
||||
|
||||
if (data.join) {
|
||||
currentRoom.guest.membershipNo = undefined
|
||||
} else {
|
||||
currentRoom.guest.membershipNo = data.membershipNo
|
||||
}
|
||||
currentRoom.guest.phoneNumber = data.phoneNumber
|
||||
|
||||
// Only valid for room 1
|
||||
if (idx === 0 && data.join && !isMember) {
|
||||
if ("dateOfBirth" in currentRoom.guest) {
|
||||
currentRoom.guest.dateOfBirth = data.dateOfBirth
|
||||
}
|
||||
if ("zipCode" in currentRoom.guest) {
|
||||
currentRoom.guest.zipCode = data.zipCode
|
||||
}
|
||||
}
|
||||
|
||||
currentRoom.roomPrice = getRoomPrice(
|
||||
currentRoom.roomRate,
|
||||
Boolean(data.join || data.membershipNo || isMember)
|
||||
)
|
||||
|
||||
const nights = dt(state.booking.toDate).diff(
|
||||
state.booking.fromDate,
|
||||
"days"
|
||||
)
|
||||
|
||||
state.totalPrice = calcTotalPrice(
|
||||
state.rooms,
|
||||
state.totalPrice.local.currency,
|
||||
isMember,
|
||||
nights
|
||||
)
|
||||
|
||||
const isAllStepsCompleted = checkRoomProgress(
|
||||
state.rooms[idx].steps
|
||||
)
|
||||
if (isAllStepsCompleted) {
|
||||
state.rooms[idx].isComplete = true
|
||||
}
|
||||
|
||||
handleStepProgression(state.rooms[idx], state)
|
||||
|
||||
writeToSessionStorage({
|
||||
activeRoom: state.activeRoom,
|
||||
booking: state.booking,
|
||||
rooms: state.rooms,
|
||||
})
|
||||
})
|
||||
)
|
||||
},
|
||||
updateMultiroomDetails(data) {
|
||||
return set(
|
||||
produce((state: DetailsState) => {
|
||||
state.rooms[idx].steps[StepEnum.details].isValid = true
|
||||
|
||||
state.rooms[idx].room.guest.countryCode = data.countryCode
|
||||
state.rooms[idx].room.guest.email = data.email
|
||||
state.rooms[idx].room.guest.firstName = data.firstName
|
||||
state.rooms[idx].room.guest.join = data.join
|
||||
state.rooms[idx].room.guest.lastName = data.lastName
|
||||
|
||||
if (data.join) {
|
||||
state.rooms[idx].room.guest.membershipNo = undefined
|
||||
} else {
|
||||
state.rooms[idx].room.guest.membershipNo = data.membershipNo
|
||||
}
|
||||
state.rooms[idx].room.guest.phoneNumber = data.phoneNumber
|
||||
|
||||
const getMemberPrice = Boolean(data.join || data.membershipNo)
|
||||
state.rooms[idx].room.roomPrice = getRoomPrice(
|
||||
state.rooms[idx].room.roomRate,
|
||||
getMemberPrice
|
||||
)
|
||||
|
||||
const nights = dt(state.booking.toDate).diff(
|
||||
state.booking.fromDate,
|
||||
"days"
|
||||
)
|
||||
|
||||
state.totalPrice = calcTotalPrice(
|
||||
state.rooms,
|
||||
state.totalPrice.local.currency,
|
||||
getMemberPrice,
|
||||
nights
|
||||
)
|
||||
|
||||
const isAllStepsCompleted = checkRoomProgress(
|
||||
state.rooms[idx].steps
|
||||
)
|
||||
if (isAllStepsCompleted) {
|
||||
state.rooms[idx].isComplete = true
|
||||
}
|
||||
|
||||
handleStepProgression(state.rooms[idx], state)
|
||||
|
||||
writeToSessionStorage({
|
||||
activeRoom: state.activeRoom,
|
||||
booking: state.booking,
|
||||
rooms: state.rooms,
|
||||
})
|
||||
})
|
||||
)
|
||||
},
|
||||
},
|
||||
room: {
|
||||
...room,
|
||||
adults: initialState.booking.rooms[idx].adults,
|
||||
childrenInRoom: initialState.booking.rooms[idx].childrenInRoom,
|
||||
bedType: room.bedType,
|
||||
breakfast:
|
||||
!breakfastPackages?.length || room.breakfastIncluded
|
||||
? false
|
||||
: undefined,
|
||||
guest:
|
||||
isMember && idx === 0
|
||||
? deepmerge(defaultGuestState, extractGuestFromUser(user))
|
||||
: defaultGuestState,
|
||||
roomPrice: getRoomPrice(room.roomRate, isMember && idx === 0),
|
||||
specialRequest: {
|
||||
comment: "",
|
||||
},
|
||||
},
|
||||
|
||||
currentStep,
|
||||
isComplete: false,
|
||||
steps,
|
||||
}
|
||||
}),
|
||||
searchParamString: searchParams,
|
||||
totalPrice: initialTotalPrice,
|
||||
vat: initialState.vat,
|
||||
|
||||
actions: {
|
||||
setStep(idx) {
|
||||
return function (step) {
|
||||
return set(
|
||||
produce((state: DetailsState) => {
|
||||
const isSameRoom = idx === state.activeRoom
|
||||
const room = state.rooms[idx]
|
||||
if (isSameRoom) {
|
||||
// Closed same accordion as was open
|
||||
if (step === room.currentStep) {
|
||||
if (room.isComplete) {
|
||||
// Room is complete, move to next room or payment
|
||||
const nextRoomIdx = state.rooms.findIndex(
|
||||
(r) => !r.isComplete
|
||||
)
|
||||
state.activeRoom = nextRoomIdx
|
||||
// Done, proceed to payment
|
||||
if (nextRoomIdx === -1) {
|
||||
room.currentStep = null
|
||||
} else {
|
||||
const nextRoom = state.rooms[nextRoomIdx]
|
||||
const nextInvalidStep = findNextInvalidStep(nextRoom)
|
||||
nextRoom.currentStep = nextInvalidStep
|
||||
}
|
||||
} else {
|
||||
room.currentStep = findNextInvalidStep(room)
|
||||
}
|
||||
} else {
|
||||
if (room.steps[step]?.isValid) {
|
||||
room.currentStep = step
|
||||
} else {
|
||||
room.currentStep = findNextInvalidStep(room)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
const arePreviousRoomsCompleted = state.rooms
|
||||
.slice(0, idx)
|
||||
.every((room) => room.isComplete)
|
||||
if (arePreviousRoomsCompleted) {
|
||||
state.activeRoom = idx
|
||||
if (room.steps[step]?.isValid) {
|
||||
room.currentStep = step
|
||||
} else {
|
||||
room.currentStep = findNextInvalidStep(room)
|
||||
}
|
||||
} else {
|
||||
const firstIncompleteRoom = state.rooms.findIndex(
|
||||
(r) => !r.isComplete
|
||||
)
|
||||
state.activeRoom = firstIncompleteRoom
|
||||
if (firstIncompleteRoom === -1) {
|
||||
// All rooms are done, proceed to payment
|
||||
room.currentStep = null
|
||||
} else {
|
||||
const nextRoom = state.rooms[firstIncompleteRoom]
|
||||
nextRoom.currentStep = findNextInvalidStep(nextRoom)
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
)
|
||||
}
|
||||
},
|
||||
setIsSubmittingDisabled(isSubmittingDisabled) {
|
||||
return set(
|
||||
produce((state: DetailsState) => {
|
||||
@@ -246,273 +523,6 @@ export function createDetailsStore(
|
||||
})
|
||||
)
|
||||
},
|
||||
updateBedType(idx) {
|
||||
return function (bedType) {
|
||||
return set(
|
||||
produce((state: DetailsState) => {
|
||||
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({
|
||||
activeRoom: state.activeRoom,
|
||||
booking: state.booking,
|
||||
rooms: state.rooms,
|
||||
})
|
||||
})
|
||||
)
|
||||
}
|
||||
},
|
||||
updateBreakfast(idx) {
|
||||
return function (breakfast) {
|
||||
return set(
|
||||
produce((state: DetailsState) => {
|
||||
const currentRoom = state.rooms[idx]
|
||||
if (currentRoom.steps[StepEnum.breakfast]) {
|
||||
currentRoom.steps[StepEnum.breakfast].isValid = true
|
||||
}
|
||||
|
||||
const currentTotalPriceRequested = state.totalPrice.requested
|
||||
let stateTotalRequestedPrice = 0
|
||||
if (currentTotalPriceRequested) {
|
||||
stateTotalRequestedPrice = currentTotalPriceRequested.price ?? 0
|
||||
}
|
||||
|
||||
const stateTotalLocalPrice = state.totalPrice.local.price
|
||||
const stateTotalLocalRegularPrice =
|
||||
state.totalPrice.local.regularPrice
|
||||
|
||||
const addToTotalPrice =
|
||||
(currentRoom.room.breakfast === undefined ||
|
||||
currentRoom.room.breakfast === false) &&
|
||||
!!breakfast
|
||||
|
||||
const subtractFromTotalPrice =
|
||||
currentRoom.room.breakfast && breakfast === false
|
||||
|
||||
const nights = dt(state.booking.toDate).diff(
|
||||
state.booking.fromDate,
|
||||
"days"
|
||||
)
|
||||
|
||||
if (addToTotalPrice) {
|
||||
const breakfastTotalRequestedPrice =
|
||||
breakfast.requestedPrice.price *
|
||||
currentRoom.room.adults *
|
||||
nights
|
||||
const breakfastTotalPrice =
|
||||
breakfast.localPrice.price * currentRoom.room.adults * nights
|
||||
state.totalPrice = {
|
||||
requested: state.totalPrice.requested && {
|
||||
currency: state.totalPrice.requested.currency,
|
||||
price:
|
||||
stateTotalRequestedPrice + breakfastTotalRequestedPrice,
|
||||
},
|
||||
local: {
|
||||
currency: breakfast.localPrice.currency,
|
||||
price: stateTotalLocalPrice ?? 0 + breakfastTotalPrice,
|
||||
regularPrice: stateTotalLocalRegularPrice
|
||||
? stateTotalLocalRegularPrice + breakfastTotalPrice
|
||||
: undefined,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
if (subtractFromTotalPrice) {
|
||||
let currency = state.totalPrice.local.currency
|
||||
let currentBreakfastTotalPrice = 0
|
||||
let currentBreakfastTotalRequestedPrice = 0
|
||||
if (currentRoom.room.breakfast) {
|
||||
currentBreakfastTotalPrice =
|
||||
currentRoom.room.breakfast.localPrice.price *
|
||||
currentRoom.room.adults *
|
||||
nights
|
||||
currentBreakfastTotalRequestedPrice =
|
||||
currentRoom.room.breakfast.requestedPrice.totalPrice *
|
||||
currentRoom.room.adults *
|
||||
nights
|
||||
currency = currentRoom.room.breakfast.localPrice.currency
|
||||
}
|
||||
|
||||
let requestedPrice =
|
||||
stateTotalRequestedPrice - currentBreakfastTotalRequestedPrice
|
||||
if (requestedPrice < 0) {
|
||||
requestedPrice = 0
|
||||
}
|
||||
let localPrice =
|
||||
stateTotalLocalPrice - currentBreakfastTotalPrice
|
||||
if (localPrice < 0) {
|
||||
localPrice = 0
|
||||
}
|
||||
let regularPrice = stateTotalLocalRegularPrice
|
||||
? stateTotalLocalRegularPrice - currentBreakfastTotalPrice
|
||||
: undefined
|
||||
|
||||
state.totalPrice = {
|
||||
requested: state.totalPrice.requested && {
|
||||
currency: state.totalPrice.requested.currency,
|
||||
price: requestedPrice,
|
||||
},
|
||||
local: {
|
||||
currency,
|
||||
price: localPrice,
|
||||
regularPrice,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
currentRoom.room.breakfast = breakfast
|
||||
|
||||
const isAllStepsCompleted = checkRoomProgress(
|
||||
state.rooms[idx].steps
|
||||
)
|
||||
if (isAllStepsCompleted) {
|
||||
state.rooms[idx].isComplete = true
|
||||
}
|
||||
|
||||
handleStepProgression(currentRoom, state)
|
||||
|
||||
writeToSessionStorage({
|
||||
activeRoom: state.activeRoom,
|
||||
booking: state.booking,
|
||||
rooms: state.rooms,
|
||||
})
|
||||
})
|
||||
)
|
||||
}
|
||||
},
|
||||
updateDetails(idx) {
|
||||
return function (data) {
|
||||
return set(
|
||||
produce((state: DetailsState) => {
|
||||
state.rooms[idx].steps[StepEnum.details].isValid = true
|
||||
const currentRoom = state.rooms[idx].room
|
||||
|
||||
currentRoom.guest.countryCode = data.countryCode
|
||||
currentRoom.guest.email = data.email
|
||||
currentRoom.guest.firstName = data.firstName
|
||||
currentRoom.guest.join = data.join
|
||||
currentRoom.guest.lastName = data.lastName
|
||||
|
||||
if (data.specialRequest?.comment) {
|
||||
currentRoom.specialRequest.comment = data.specialRequest.comment
|
||||
}
|
||||
|
||||
if (data.join) {
|
||||
currentRoom.guest.membershipNo = undefined
|
||||
} else {
|
||||
currentRoom.guest.membershipNo = data.membershipNo
|
||||
}
|
||||
currentRoom.guest.phoneNumber = data.phoneNumber
|
||||
|
||||
// Only valid for room 1
|
||||
if (idx === 0 && data.join && !isMember) {
|
||||
if ("dateOfBirth" in currentRoom.guest) {
|
||||
currentRoom.guest.dateOfBirth = data.dateOfBirth
|
||||
}
|
||||
if ("zipCode" in currentRoom.guest) {
|
||||
currentRoom.guest.zipCode = data.zipCode
|
||||
}
|
||||
}
|
||||
|
||||
currentRoom.roomPrice = getRoomPrice(
|
||||
currentRoom.roomRate,
|
||||
Boolean(data.join || data.membershipNo || isMember)
|
||||
)
|
||||
|
||||
const nights = dt(state.booking.toDate).diff(
|
||||
state.booking.fromDate,
|
||||
"days"
|
||||
)
|
||||
|
||||
state.totalPrice = calcTotalPrice(
|
||||
state.rooms,
|
||||
state.totalPrice.local.currency,
|
||||
isMember,
|
||||
nights
|
||||
)
|
||||
|
||||
const isAllStepsCompleted = checkRoomProgress(
|
||||
state.rooms[idx].steps
|
||||
)
|
||||
if (isAllStepsCompleted) {
|
||||
state.rooms[idx].isComplete = true
|
||||
}
|
||||
|
||||
handleStepProgression(state.rooms[idx], state)
|
||||
|
||||
writeToSessionStorage({
|
||||
activeRoom: state.activeRoom,
|
||||
booking: state.booking,
|
||||
rooms: state.rooms,
|
||||
})
|
||||
})
|
||||
)
|
||||
}
|
||||
},
|
||||
updateMultiroomDetails(idx) {
|
||||
return function (data) {
|
||||
return set(
|
||||
produce((state: DetailsState) => {
|
||||
state.rooms[idx].steps[StepEnum.details].isValid = true
|
||||
|
||||
state.rooms[idx].room.guest.countryCode = data.countryCode
|
||||
state.rooms[idx].room.guest.email = data.email
|
||||
state.rooms[idx].room.guest.firstName = data.firstName
|
||||
state.rooms[idx].room.guest.join = data.join
|
||||
state.rooms[idx].room.guest.lastName = data.lastName
|
||||
|
||||
if (data.join) {
|
||||
state.rooms[idx].room.guest.membershipNo = undefined
|
||||
} else {
|
||||
state.rooms[idx].room.guest.membershipNo = data.membershipNo
|
||||
}
|
||||
state.rooms[idx].room.guest.phoneNumber = data.phoneNumber
|
||||
|
||||
const getMemberPrice = Boolean(data.join || data.membershipNo)
|
||||
state.rooms[idx].room.roomPrice = getRoomPrice(
|
||||
state.rooms[idx].room.roomRate,
|
||||
getMemberPrice
|
||||
)
|
||||
|
||||
const nights = dt(state.booking.toDate).diff(
|
||||
state.booking.fromDate,
|
||||
"days"
|
||||
)
|
||||
|
||||
state.totalPrice = calcTotalPrice(
|
||||
state.rooms,
|
||||
state.totalPrice.local.currency,
|
||||
getMemberPrice,
|
||||
nights
|
||||
)
|
||||
|
||||
const isAllStepsCompleted = checkRoomProgress(
|
||||
state.rooms[idx].steps
|
||||
)
|
||||
if (isAllStepsCompleted) {
|
||||
state.rooms[idx].isComplete = true
|
||||
}
|
||||
|
||||
handleStepProgression(state.rooms[idx], state)
|
||||
|
||||
writeToSessionStorage({
|
||||
activeRoom: state.activeRoom,
|
||||
booking: state.booking,
|
||||
rooms: state.rooms,
|
||||
})
|
||||
})
|
||||
)
|
||||
}
|
||||
},
|
||||
updateSeachParamString(searchParamString) {
|
||||
return set(
|
||||
produce((state: DetailsState) => {
|
||||
|
||||
80
apps/scandic-web/stores/select-rate/helpers.ts
Normal file
80
apps/scandic-web/stores/select-rate/helpers.ts
Normal file
@@ -0,0 +1,80 @@
|
||||
import type { AvailabilityError } from "@/types/stores/rates"
|
||||
import type {
|
||||
Product,
|
||||
RoomConfiguration,
|
||||
} from "@/types/trpc/routers/hotel/roomAvailability"
|
||||
|
||||
export function findProduct(rateCode: string, product: Product) {
|
||||
if ("corporateCheque" in product) {
|
||||
return product.corporateCheque.rateCode === rateCode
|
||||
}
|
||||
|
||||
if ("redemption" in product) {
|
||||
return product.redemption.rateCode === rateCode
|
||||
}
|
||||
|
||||
if ("voucher" in product) {
|
||||
return product.voucher.rateCode === rateCode
|
||||
}
|
||||
|
||||
if ("public" in product && product.public) {
|
||||
return product.public.rateCode === rateCode
|
||||
}
|
||||
|
||||
if ("member" in product && product.member) {
|
||||
return product.member.rateCode === rateCode
|
||||
}
|
||||
|
||||
return null
|
||||
}
|
||||
|
||||
export function findProductInRoom(rateCode: string, room: RoomConfiguration) {
|
||||
if (room.campaign.length) {
|
||||
const campaignProduct = room.campaign.find((product) =>
|
||||
findProduct(rateCode, product)
|
||||
)
|
||||
if (campaignProduct) {
|
||||
return campaignProduct
|
||||
}
|
||||
}
|
||||
if (room.code.length) {
|
||||
const codeProduct = room.code.find((product) =>
|
||||
findProduct(rateCode, product)
|
||||
)
|
||||
if (codeProduct) {
|
||||
return codeProduct
|
||||
}
|
||||
}
|
||||
if (room.redemptions.length) {
|
||||
const redemptionProduct = room.redemptions.find((product) =>
|
||||
findProduct(rateCode, product)
|
||||
)
|
||||
if (redemptionProduct) {
|
||||
return redemptionProduct
|
||||
}
|
||||
}
|
||||
if (room.regular.length) {
|
||||
const regularProduct = room.regular.find((product) =>
|
||||
findProduct(rateCode, product)
|
||||
)
|
||||
if (regularProduct) {
|
||||
return regularProduct
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export function findSelectedRate(
|
||||
rateCode: string,
|
||||
roomTypeCode: string,
|
||||
rooms: RoomConfiguration[] | AvailabilityError
|
||||
) {
|
||||
if (!Array.isArray(rooms)) {
|
||||
return null
|
||||
}
|
||||
return rooms.find((room) => {
|
||||
if (room.roomTypeCode !== roomTypeCode) {
|
||||
return false
|
||||
}
|
||||
return findProductInRoom(rateCode, room)
|
||||
})
|
||||
}
|
||||
@@ -5,35 +5,13 @@ import { create, useStore } from "zustand"
|
||||
|
||||
import { RatesContext } from "@/contexts/Rates"
|
||||
|
||||
import { RoomPackageCodeEnum } from "@/types/components/hotelReservation/selectRate/roomFilter"
|
||||
import { RateTypeEnum } from "@/types/enums/rateType"
|
||||
import type {
|
||||
AvailabilityError,
|
||||
InitialState,
|
||||
RatesState,
|
||||
} from "@/types/stores/rates"
|
||||
import type { RoomConfiguration } from "@/types/trpc/routers/hotel/roomAvailability"
|
||||
import { findProductInRoom, findSelectedRate } from "./helpers"
|
||||
|
||||
function findSelectedRate(
|
||||
rateCode: string,
|
||||
roomTypeCode: string,
|
||||
rooms: RoomConfiguration[] | AvailabilityError
|
||||
) {
|
||||
if (!Array.isArray(rooms)) {
|
||||
return null
|
||||
}
|
||||
return rooms.find(
|
||||
(room) =>
|
||||
room.roomTypeCode === roomTypeCode &&
|
||||
room.products.find(
|
||||
(product) =>
|
||||
product.public?.rateCode === rateCode ||
|
||||
product.member?.rateCode === rateCode ||
|
||||
product.bonusCheque?.rateCode === rateCode ||
|
||||
product.voucher?.rateCode === rateCode
|
||||
)
|
||||
)
|
||||
}
|
||||
import { RoomPackageCodeEnum } from "@/types/components/hotelReservation/selectRate/roomFilter"
|
||||
import { BookingCodeFilterEnum } from "@/types/enums/bookingCodeFilter"
|
||||
import { RateTypeEnum } from "@/types/enums/rateType"
|
||||
import type { InitialState, RatesState } from "@/types/stores/rates"
|
||||
import type { RoomConfiguration } from "@/types/trpc/routers/hotel/roomAvailability"
|
||||
|
||||
export function createRatesStore({
|
||||
booking,
|
||||
@@ -84,60 +62,31 @@ export function createRatesStore({
|
||||
}
|
||||
|
||||
const rateSummary: RatesState["rateSummary"] = []
|
||||
booking.rooms.forEach((room, idx) => {
|
||||
for (const [idx, room] of booking.rooms.entries()) {
|
||||
if (room.rateCode && room.roomTypeCode) {
|
||||
const roomConfiguration = roomConfigurations?.[idx]
|
||||
const selectedRoom = roomConfiguration.find(
|
||||
(rc) =>
|
||||
rc.roomTypeCode === room.roomTypeCode &&
|
||||
rc.products.find(
|
||||
(product) =>
|
||||
product.public?.rateCode === room.rateCode ||
|
||||
product.member?.rateCode === room.rateCode ||
|
||||
product.redemptions?.find(
|
||||
(redemption) => redemption?.rateCode === room.rateCode
|
||||
) ||
|
||||
product.bonusCheque?.rateCode === room.rateCode ||
|
||||
product.voucher?.rateCode === room.rateCode
|
||||
)
|
||||
const selectedRoom = findSelectedRate(
|
||||
room.rateCode,
|
||||
room.roomTypeCode,
|
||||
roomConfiguration
|
||||
)
|
||||
const redemptionProduct = selectedRoom?.products[0].redemptions?.find(
|
||||
(r) => r?.rateCode === room.rateCode
|
||||
)
|
||||
const product = selectedRoom?.products.find(
|
||||
(p) =>
|
||||
p.public?.rateCode === room.rateCode ||
|
||||
p.member?.rateCode === room.rateCode ||
|
||||
p.bonusCheque?.rateCode === room.rateCode ||
|
||||
p.voucher?.rateCode === room.rateCode
|
||||
)
|
||||
if (selectedRoom && product) {
|
||||
|
||||
if (!selectedRoom) {
|
||||
continue
|
||||
}
|
||||
|
||||
const product = findProductInRoom(room.rateCode, selectedRoom)
|
||||
if (product) {
|
||||
rateSummary[idx] = {
|
||||
features: selectedRoom.features,
|
||||
redemption: undefined,
|
||||
product,
|
||||
rate: product.rate,
|
||||
roomType: selectedRoom.roomType,
|
||||
roomTypeCode: selectedRoom.roomTypeCode,
|
||||
}
|
||||
if (product.member || product.public) {
|
||||
rateSummary[idx].member = product.member
|
||||
rateSummary[idx].public = product.public
|
||||
} else if (product.bonusCheque) {
|
||||
rateSummary[idx].bonusCheque = product.bonusCheque
|
||||
} else if (product.voucher) {
|
||||
rateSummary[idx].voucher = product.voucher
|
||||
}
|
||||
} else if (selectedRoom && redemptionProduct) {
|
||||
rateSummary[idx] = {
|
||||
features: selectedRoom.features,
|
||||
redemption: redemptionProduct,
|
||||
rate: selectedRoom?.products[0].rate,
|
||||
roomType: selectedRoom.roomType,
|
||||
roomTypeCode: selectedRoom.roomTypeCode,
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
let activeRoom = rateSummary.length
|
||||
if (searchParams.has("modifyRateIndex")) {
|
||||
@@ -148,320 +97,264 @@ export function createRatesStore({
|
||||
activeRoom = -1
|
||||
}
|
||||
|
||||
return create<RatesState>()((set) => ({
|
||||
actions: {
|
||||
closeSection(idx) {
|
||||
return function () {
|
||||
return set(
|
||||
produce((state: RatesState) => {
|
||||
if (state.rateSummary.length === state.booking.rooms.length) {
|
||||
state.activeRoom = -1
|
||||
} else {
|
||||
state.activeRoom = idx + 1
|
||||
}
|
||||
})
|
||||
return create<RatesState>()((set) => {
|
||||
return {
|
||||
activeRoom,
|
||||
booking,
|
||||
filterOptions,
|
||||
hotelType,
|
||||
isUserLoggedIn,
|
||||
packages,
|
||||
pathname,
|
||||
petRoomPackage: packages.find(
|
||||
(pkg) => pkg.code === RoomPackageCodeEnum.PET_ROOM
|
||||
),
|
||||
rateSummary,
|
||||
roomConfigurations,
|
||||
rooms: booking.rooms.map((room, idx) => {
|
||||
const roomConfiguration = roomConfigurations[idx]
|
||||
const selectedRate =
|
||||
findSelectedRate(
|
||||
room.rateCode,
|
||||
room.roomTypeCode,
|
||||
roomConfiguration
|
||||
) ?? null
|
||||
|
||||
let product = null
|
||||
if (selectedRate) {
|
||||
product = findProductInRoom(room.rateCode, selectedRate)
|
||||
}
|
||||
|
||||
const selectedPackage = room.packages?.[0]
|
||||
|
||||
let rooms: RoomConfiguration[] = roomConfiguration
|
||||
if (selectedPackage) {
|
||||
rooms = roomConfiguration.filter((r) =>
|
||||
r.features.find((f) => f.code === selectedPackage)
|
||||
)
|
||||
}
|
||||
},
|
||||
modifyRate(idx) {
|
||||
return function () {
|
||||
return set(
|
||||
produce((state: RatesState) => {
|
||||
state.activeRoom = idx
|
||||
})
|
||||
)
|
||||
}
|
||||
},
|
||||
selectFilter(idx) {
|
||||
return function (code) {
|
||||
return set(
|
||||
produce((state: RatesState) => {
|
||||
state.rooms[idx].selectedPackage = code
|
||||
const roomConfiguration = state.roomConfigurations[idx]
|
||||
if (roomConfiguration) {
|
||||
const searchParams = new URLSearchParams(state.searchParams)
|
||||
if (code) {
|
||||
state.rooms[idx].rooms = roomConfiguration.filter((room) =>
|
||||
room.features.find((feat) => feat.code === code)
|
||||
|
||||
return {
|
||||
actions: {
|
||||
appendRegularRates(roomConfigurations) {
|
||||
return set(
|
||||
produce((state: RatesState) => {
|
||||
const rooms = state.rooms[idx].rooms
|
||||
const updatedRooms = rooms.map((currentRoom) => {
|
||||
const incomingRoom = roomConfigurations.find(
|
||||
(room) =>
|
||||
room.roomType === currentRoom.roomType &&
|
||||
room.roomTypeCode === currentRoom.roomTypeCode
|
||||
)
|
||||
|
||||
if (incomingRoom) {
|
||||
return {
|
||||
...currentRoom,
|
||||
campaign: [
|
||||
...currentRoom.campaign,
|
||||
...incomingRoom.campaign,
|
||||
],
|
||||
products: [
|
||||
...currentRoom.products,
|
||||
...incomingRoom.products,
|
||||
],
|
||||
regular: incomingRoom.regular,
|
||||
}
|
||||
}
|
||||
|
||||
return currentRoom
|
||||
})
|
||||
|
||||
state.rooms[idx].rooms = updatedRooms
|
||||
})
|
||||
)
|
||||
},
|
||||
closeSection() {
|
||||
return set(
|
||||
produce((state: RatesState) => {
|
||||
if (state.rateSummary.length === state.booking.rooms.length) {
|
||||
state.activeRoom = -1
|
||||
} else {
|
||||
state.activeRoom = idx + 1
|
||||
}
|
||||
})
|
||||
)
|
||||
},
|
||||
modifyRate() {
|
||||
return set(
|
||||
produce((state: RatesState) => {
|
||||
state.activeRoom = idx
|
||||
})
|
||||
)
|
||||
},
|
||||
selectFilter(filter) {
|
||||
return set(
|
||||
produce((state: RatesState) => {
|
||||
state.rooms[idx].selectedFilter = filter
|
||||
})
|
||||
)
|
||||
},
|
||||
selectPackage(code) {
|
||||
return set(
|
||||
produce((state: RatesState) => {
|
||||
state.rooms[idx].selectedPackage = code
|
||||
const roomConfiguration = state.roomConfigurations[idx]
|
||||
if (roomConfiguration) {
|
||||
const searchParams = new URLSearchParams(state.searchParams)
|
||||
if (code) {
|
||||
state.rooms[idx].rooms = roomConfiguration.filter(
|
||||
(room) =>
|
||||
room.features.find((feat) => feat.code === code)
|
||||
)
|
||||
searchParams.set(`room[${idx}].packages`, code)
|
||||
|
||||
if (state.rateSummary[idx]) {
|
||||
state.rateSummary[idx].package = code
|
||||
}
|
||||
} else {
|
||||
state.rooms[idx].rooms = roomConfiguration
|
||||
searchParams.delete(`room[${idx}].packages`)
|
||||
|
||||
if (state.rateSummary[idx]) {
|
||||
state.rateSummary[idx].package = undefined
|
||||
}
|
||||
}
|
||||
|
||||
state.searchParams = new ReadonlyURLSearchParams(
|
||||
searchParams
|
||||
)
|
||||
window.history.pushState(
|
||||
{},
|
||||
"",
|
||||
`${state.pathname}?${searchParams}`
|
||||
)
|
||||
}
|
||||
})
|
||||
)
|
||||
},
|
||||
selectRate(selectedRate) {
|
||||
return set(
|
||||
produce((state: RatesState) => {
|
||||
if (!selectedRate.product) {
|
||||
return
|
||||
}
|
||||
|
||||
state.rooms[idx].selectedRate = selectedRate
|
||||
state.rateSummary[idx] = {
|
||||
features: selectedRate.features,
|
||||
package: state.rooms[idx].selectedPackage,
|
||||
product: selectedRate.product,
|
||||
rate: selectedRate.product.rate,
|
||||
roomType: selectedRate.roomType,
|
||||
roomTypeCode: selectedRate.roomTypeCode,
|
||||
}
|
||||
|
||||
const roomNr = idx + 1
|
||||
const isMainRoom = roomNr === 1
|
||||
|
||||
let productRateCode = ""
|
||||
if ("corporateCheque" in selectedRate.product) {
|
||||
productRateCode =
|
||||
selectedRate.product.corporateCheque.rateCode
|
||||
}
|
||||
|
||||
if ("redemption" in selectedRate.product) {
|
||||
productRateCode = selectedRate.product.redemption.rateCode
|
||||
}
|
||||
|
||||
if ("voucher" in selectedRate.product) {
|
||||
productRateCode = selectedRate.product.voucher.rateCode
|
||||
}
|
||||
|
||||
let isRegularRate = false
|
||||
if (
|
||||
"public" in selectedRate.product &&
|
||||
selectedRate.product.public
|
||||
) {
|
||||
isRegularRate =
|
||||
selectedRate.product.public.rateType ===
|
||||
RateTypeEnum.Regular
|
||||
productRateCode = selectedRate.product.public.rateCode
|
||||
}
|
||||
|
||||
let hasMemberRate = false
|
||||
let memberRateCode = ""
|
||||
if (
|
||||
"member" in selectedRate.product &&
|
||||
selectedRate.product.member
|
||||
) {
|
||||
hasMemberRate = true
|
||||
memberRateCode = selectedRate.product.member.rateCode
|
||||
}
|
||||
|
||||
const isMemberRate =
|
||||
isUserLoggedIn &&
|
||||
isMainRoom &&
|
||||
hasMemberRate &&
|
||||
isRegularRate
|
||||
const searchParams = new URLSearchParams(state.searchParams)
|
||||
const counterratecode = isMemberRate
|
||||
? productRateCode
|
||||
: memberRateCode
|
||||
if (counterratecode) {
|
||||
searchParams.set(
|
||||
`room[${idx}].counterratecode`,
|
||||
counterratecode
|
||||
)
|
||||
}
|
||||
|
||||
const rateCode = isMemberRate
|
||||
? memberRateCode
|
||||
: productRateCode
|
||||
if (rateCode) {
|
||||
searchParams.set(`room[${idx}].ratecode`, rateCode)
|
||||
}
|
||||
|
||||
searchParams.set(
|
||||
`room[${idx}].roomtype`,
|
||||
selectedRate.roomTypeCode
|
||||
)
|
||||
searchParams.set(`room[${idx}].packages`, code)
|
||||
|
||||
if (state.rateSummary[idx]) {
|
||||
state.rateSummary[idx].package = code
|
||||
if (state.rateSummary.length === state.booking.rooms.length) {
|
||||
state.activeRoom = -1
|
||||
} else {
|
||||
state.activeRoom = idx + 1
|
||||
}
|
||||
} else {
|
||||
state.rooms[idx].rooms = roomConfiguration
|
||||
searchParams.delete(`room[${idx}].packages`)
|
||||
|
||||
if (state.rateSummary[idx]) {
|
||||
state.rateSummary[idx].package = undefined
|
||||
}
|
||||
state.searchParams = new ReadonlyURLSearchParams(searchParams)
|
||||
window.history.pushState(
|
||||
{},
|
||||
"",
|
||||
`${state.pathname}?${searchParams}`
|
||||
)
|
||||
})
|
||||
)
|
||||
},
|
||||
},
|
||||
|
||||
bookingRoom: room,
|
||||
rooms,
|
||||
selectedFilter: booking.bookingCode
|
||||
? BookingCodeFilterEnum.Discounted
|
||||
: BookingCodeFilterEnum.All,
|
||||
selectedPackage,
|
||||
selectedRate:
|
||||
selectedRate && product
|
||||
? {
|
||||
features: selectedRate.features,
|
||||
product,
|
||||
roomType: selectedRate.roomType,
|
||||
roomTypeCode: selectedRate.roomTypeCode,
|
||||
}
|
||||
|
||||
state.searchParams = new ReadonlyURLSearchParams(searchParams)
|
||||
window.history.pushState(
|
||||
{},
|
||||
"",
|
||||
`${state.pathname}?${searchParams}`
|
||||
)
|
||||
}
|
||||
})
|
||||
)
|
||||
: null,
|
||||
}
|
||||
},
|
||||
selectRate(idx) {
|
||||
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.member,
|
||||
package: state.rooms[idx].selectedPackage,
|
||||
rate: selectedRate.product.rate,
|
||||
public: selectedRate.product.public,
|
||||
redemption: undefined,
|
||||
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 && isMainRoom && memberRate && !isBookingCodeRate
|
||||
const searchParams = new URLSearchParams(state.searchParams)
|
||||
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
|
||||
)
|
||||
|
||||
if (state.rateSummary.length === state.booking.rooms.length) {
|
||||
state.activeRoom = -1
|
||||
} else {
|
||||
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(
|
||||
{},
|
||||
"",
|
||||
`${state.pathname}?${searchParams}`
|
||||
)
|
||||
})
|
||||
)
|
||||
}
|
||||
},
|
||||
selectRateVoucher() {
|
||||
return function (selectedRate) {
|
||||
return set(
|
||||
produce((state: RatesState) => {
|
||||
const voucherRate = selectedRate.product.voucher
|
||||
if (!voucherRate) {
|
||||
return
|
||||
}
|
||||
|
||||
state.rooms[0].selectedRate = selectedRate
|
||||
state.rateSummary[0] = {
|
||||
features: selectedRate.features,
|
||||
voucher: selectedRate.product.voucher,
|
||||
bonusCheque: undefined,
|
||||
package: state.rooms[0].selectedPackage,
|
||||
rate: selectedRate.product.rate,
|
||||
roomType: selectedRate.roomType,
|
||||
roomTypeCode: selectedRate.roomTypeCode,
|
||||
}
|
||||
|
||||
const searchParams = new URLSearchParams(state.searchParams)
|
||||
searchParams.set(`room[0].ratecode`, voucherRate.rateCode)
|
||||
searchParams.set(`room[0].roomtype`, selectedRate.roomTypeCode)
|
||||
|
||||
if (state.rateSummary.length === state.booking.rooms.length) {
|
||||
state.activeRoom = -1
|
||||
} else {
|
||||
state.activeRoom = 1
|
||||
}
|
||||
|
||||
state.searchParams = new ReadonlyURLSearchParams(searchParams)
|
||||
window.history.pushState(
|
||||
{},
|
||||
"",
|
||||
`${state.pathname}?${searchParams}`
|
||||
)
|
||||
})
|
||||
)
|
||||
}
|
||||
},
|
||||
selectRateCheque(idx) {
|
||||
return function (selectedRate) {
|
||||
return set(
|
||||
produce((state: RatesState) => {
|
||||
const chequeRate = selectedRate.product.bonusCheque
|
||||
if (!chequeRate) {
|
||||
return
|
||||
}
|
||||
|
||||
state.rooms[idx].selectedRate = selectedRate
|
||||
state.rateSummary[idx] = {
|
||||
features: selectedRate.features,
|
||||
package: state.rooms[idx].selectedPackage,
|
||||
rate: selectedRate.product.rate,
|
||||
voucher: undefined,
|
||||
bonusCheque: chequeRate,
|
||||
roomType: selectedRate.roomType,
|
||||
roomTypeCode: selectedRate.roomTypeCode,
|
||||
}
|
||||
|
||||
const searchParams = new URLSearchParams(state.searchParams)
|
||||
searchParams.set(`room[${idx}].ratecode`, chequeRate.rateCode)
|
||||
|
||||
searchParams.set(
|
||||
`room[${idx}].roomtype`,
|
||||
selectedRate.roomTypeCode
|
||||
)
|
||||
|
||||
if (state.rateSummary.length === state.booking.rooms.length) {
|
||||
state.activeRoom = -1
|
||||
} else {
|
||||
state.activeRoom = idx + 1
|
||||
}
|
||||
|
||||
state.searchParams = new ReadonlyURLSearchParams(searchParams)
|
||||
window.history.pushState(
|
||||
{},
|
||||
"",
|
||||
`${state.pathname}?${searchParams}`
|
||||
)
|
||||
})
|
||||
)
|
||||
}
|
||||
},
|
||||
},
|
||||
activeRoom,
|
||||
booking,
|
||||
filterOptions,
|
||||
hotelType,
|
||||
isUserLoggedIn,
|
||||
packages,
|
||||
pathname,
|
||||
petRoomPackage: packages.find(
|
||||
(pkg) => pkg.code === RoomPackageCodeEnum.PET_ROOM
|
||||
),
|
||||
rateSummary,
|
||||
roomConfigurations,
|
||||
rooms: booking.rooms.map((room, idx) => {
|
||||
const roomConfiguration = roomConfigurations[idx]
|
||||
const selectedRate =
|
||||
findSelectedRate(room.rateCode, room.roomTypeCode, roomConfiguration) ??
|
||||
null
|
||||
|
||||
const product = selectedRate?.products.find(
|
||||
(prd) =>
|
||||
prd.public?.rateCode === room.rateCode ||
|
||||
prd.member?.rateCode === room.rateCode ||
|
||||
prd.bonusCheque?.rateCode === room.rateCode ||
|
||||
prd.voucher?.rateCode === room.rateCode
|
||||
)
|
||||
|
||||
const selectedPackage = room.packages?.[0]
|
||||
|
||||
let rooms: RoomConfiguration[] = roomConfiguration
|
||||
if (selectedPackage) {
|
||||
rooms = roomConfiguration.filter((r) =>
|
||||
r.features.find((f) => f.code === selectedPackage)
|
||||
)
|
||||
}
|
||||
|
||||
return {
|
||||
bookingRoom: room,
|
||||
rooms,
|
||||
selectedPackage,
|
||||
selectedRate:
|
||||
selectedRate && product
|
||||
? {
|
||||
features: selectedRate.features,
|
||||
product,
|
||||
roomType: selectedRate.roomType,
|
||||
roomTypeCode: selectedRate.roomTypeCode,
|
||||
}
|
||||
: null,
|
||||
}
|
||||
}),
|
||||
roomCategories,
|
||||
roomsAvailability,
|
||||
searchParams,
|
||||
vat,
|
||||
}))
|
||||
}),
|
||||
roomCategories,
|
||||
roomsAvailability,
|
||||
searchParams,
|
||||
vat,
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
export function useRatesStore<T>(selector: (store: RatesState) => T) {
|
||||
|
||||
Reference in New Issue
Block a user