feat: add multiroom signup
This commit is contained in:
@@ -10,8 +10,6 @@ import type {
|
||||
DetailsState,
|
||||
PersistedState,
|
||||
RoomState,
|
||||
RoomStatus,
|
||||
RoomStep,
|
||||
} from "@/types/stores/enter-details"
|
||||
import type { SafeUser } from "@/types/user"
|
||||
|
||||
@@ -160,7 +158,7 @@ export function getTotalPrice(roomRates: RoomRate[], isMember: boolean) {
|
||||
rate.requestedPrice.pricePerStay
|
||||
),
|
||||
}
|
||||
: undefined,
|
||||
: total.requested,
|
||||
local: {
|
||||
currency: rate.localPrice.currency,
|
||||
price: add(total.local.price ?? 0, rate.localPrice.pricePerStay),
|
||||
@@ -179,11 +177,12 @@ export function getTotalPrice(roomRates: RoomRate[], isMember: boolean) {
|
||||
|
||||
export function calcTotalPrice(
|
||||
rooms: RoomState[],
|
||||
totalPrice: Price,
|
||||
isMember: boolean
|
||||
currency: Price["local"]["currency"],
|
||||
isMember: boolean,
|
||||
nights: number
|
||||
) {
|
||||
return rooms.reduce<Price>(
|
||||
(acc, room, index) => {
|
||||
(acc, { room }, index) => {
|
||||
const isFirstRoomAndMember = index === 0 && isMember
|
||||
const join = Boolean(room.guest.join || room.guest.membershipNo)
|
||||
|
||||
@@ -193,10 +192,10 @@ export function calcTotalPrice(
|
||||
)
|
||||
|
||||
const breakfastRequestedPrice = room.breakfast
|
||||
? room.breakfast.requestedPrice?.totalPrice ?? 0
|
||||
? parseInt(room.breakfast.requestedPrice?.price ?? 0)
|
||||
: 0
|
||||
const breakfastLocalPrice = room.breakfast
|
||||
? room.breakfast.localPrice?.totalPrice ?? 0
|
||||
? parseInt(room.breakfast.localPrice?.price ?? 0)
|
||||
: 0
|
||||
|
||||
const roomFeaturesTotal = room.roomFeatures?.reduce((total, pkg) => {
|
||||
@@ -213,7 +212,7 @@ export function calcTotalPrice(
|
||||
price: add(
|
||||
acc.requested?.price ?? 0,
|
||||
roomPrice.perStay.requested.price,
|
||||
breakfastRequestedPrice
|
||||
breakfastRequestedPrice * room.adults * nights
|
||||
),
|
||||
}
|
||||
: undefined,
|
||||
@@ -222,7 +221,7 @@ export function calcTotalPrice(
|
||||
price: add(
|
||||
acc.local.price,
|
||||
roomPrice.perStay.local.price,
|
||||
breakfastLocalPrice,
|
||||
breakfastLocalPrice * room.adults * nights,
|
||||
roomFeaturesTotal
|
||||
),
|
||||
},
|
||||
@@ -232,57 +231,40 @@ export function calcTotalPrice(
|
||||
},
|
||||
{
|
||||
requested: undefined,
|
||||
local: { currency: totalPrice.local.currency, price: 0 },
|
||||
local: { currency, price: 0 },
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
export const selectRoomStatus = (state: DetailsState, index?: number) =>
|
||||
state.bookingProgress.roomStatuses[
|
||||
index ?? state.bookingProgress.currentRoomIndex
|
||||
]
|
||||
|
||||
export const selectRoom = (state: DetailsState, index?: number) =>
|
||||
state.rooms[index ?? state.bookingProgress.currentRoomIndex]
|
||||
|
||||
export const selectRoomSteps = (state: DetailsState, index?: number) =>
|
||||
state.bookingProgress.roomStatuses[
|
||||
index ?? state.bookingProgress.currentRoomIndex
|
||||
].steps
|
||||
|
||||
export const selectPreviousSteps = (
|
||||
state: DetailsState,
|
||||
index?: number
|
||||
): {
|
||||
[StepEnum.selectBed]?: RoomStep
|
||||
[StepEnum.breakfast]?: RoomStep
|
||||
[StepEnum.details]?: RoomStep
|
||||
} => {
|
||||
const roomStatus =
|
||||
state.bookingProgress.roomStatuses[
|
||||
index ?? state.bookingProgress.currentRoomIndex
|
||||
]
|
||||
const stepKeys = Object.keys(roomStatus.steps)
|
||||
const currentStepIndex = stepKeys.indexOf(`${roomStatus.currentStep}`)
|
||||
return Object.entries(roomStatus.steps)
|
||||
.slice(0, currentStepIndex)
|
||||
.reduce((acc, [key, value]) => {
|
||||
return { ...acc, [key]: value }
|
||||
}, {})
|
||||
export function getFirstInteractiveStepOfRoom(room: RoomState["room"]) {
|
||||
if (!room.bedType) {
|
||||
return StepEnum.selectBed
|
||||
}
|
||||
if (room.breakfast !== false) {
|
||||
return StepEnum.breakfast
|
||||
}
|
||||
return StepEnum.details
|
||||
}
|
||||
|
||||
export const selectNextStep = (roomStatus: RoomStatus) => {
|
||||
if (roomStatus.currentStep === null) {
|
||||
export function findNextInvalidStep(roomState: RoomState) {
|
||||
return (
|
||||
Object.values(roomState.steps).find((stp) => !stp.isValid)?.step ??
|
||||
getFirstInteractiveStepOfRoom(roomState.room)
|
||||
)
|
||||
}
|
||||
|
||||
export const selectNextStep = (room: RoomState) => {
|
||||
if (room.currentStep === null) {
|
||||
throw new Error("getNextStep: currentStep is null")
|
||||
}
|
||||
|
||||
if (!roomStatus.steps[roomStatus.currentStep]?.isValid) {
|
||||
return roomStatus.currentStep
|
||||
if (!room.steps[room.currentStep]?.isValid) {
|
||||
return room.currentStep
|
||||
}
|
||||
|
||||
const stepsArray = Object.values(roomStatus.steps)
|
||||
const stepsArray = Object.values(room.steps)
|
||||
const currentIndex = stepsArray.findIndex(
|
||||
(step) => step?.step === roomStatus.currentStep
|
||||
(step) => step?.step === room.currentStep
|
||||
)
|
||||
if (currentIndex === stepsArray.length - 1) {
|
||||
return null
|
||||
@@ -295,52 +277,27 @@ export const selectNextStep = (roomStatus: RoomStatus) => {
|
||||
return nextInvalidStep?.step ?? null
|
||||
}
|
||||
|
||||
export const selectBookingProgress = (state: DetailsState) =>
|
||||
state.bookingProgress
|
||||
|
||||
export const checkBookingProgress = (state: DetailsState) => {
|
||||
return state.bookingProgress.roomStatuses.every((r) => r.isComplete)
|
||||
}
|
||||
|
||||
export const checkRoomProgress = (state: DetailsState) => {
|
||||
const steps = selectRoomSteps(state)
|
||||
export const checkRoomProgress = (steps: RoomState["steps"]) => {
|
||||
return Object.values(steps)
|
||||
.filter(Boolean)
|
||||
.every((step) => step.isValid)
|
||||
}
|
||||
|
||||
export function handleStepProgression(state: DetailsState) {
|
||||
const isAllRoomsCompleted = checkBookingProgress(state)
|
||||
export function handleStepProgression(room: RoomState, state: DetailsState) {
|
||||
const isAllRoomsCompleted = state.rooms.every((r) => r.isComplete)
|
||||
if (isAllRoomsCompleted) {
|
||||
const roomStatus = selectRoomStatus(state)
|
||||
roomStatus.currentStep = null
|
||||
state.bookingProgress.canProceedToPayment = true
|
||||
return
|
||||
}
|
||||
room.currentStep = null
|
||||
state.canProceedToPayment = true
|
||||
} else if (room.isComplete) {
|
||||
room.currentStep = null
|
||||
const nextRoomIndex = state.rooms.findIndex((r) => !r.isComplete)
|
||||
state.activeRoom = nextRoomIndex
|
||||
|
||||
const roomStatus = selectRoomStatus(state)
|
||||
if (roomStatus.isComplete) {
|
||||
const nextRoomIndex = state.bookingProgress.roomStatuses.findIndex(
|
||||
(room) => !room.isComplete
|
||||
)
|
||||
roomStatus.lastCompletedStep = roomStatus.currentStep ?? undefined
|
||||
roomStatus.currentStep = null
|
||||
const nextRoomStatus = selectRoomStatus(state, nextRoomIndex)
|
||||
nextRoomStatus.currentStep =
|
||||
Object.values(nextRoomStatus.steps).find((step) => !step.isValid)?.step ??
|
||||
StepEnum.selectBed
|
||||
|
||||
const nextStep = selectNextStep(nextRoomStatus)
|
||||
nextRoomStatus.currentStep = nextStep
|
||||
state.bookingProgress.currentRoomIndex = nextRoomIndex
|
||||
return
|
||||
}
|
||||
|
||||
const nextStep = selectNextStep(roomStatus)
|
||||
if (nextStep !== null && roomStatus.currentStep !== null) {
|
||||
roomStatus.lastCompletedStep = roomStatus.currentStep
|
||||
roomStatus.currentStep = nextStep
|
||||
return
|
||||
const nextRoom = state.rooms[nextRoomIndex]
|
||||
const nextStep = selectNextStep(nextRoom)
|
||||
nextRoom.currentStep = nextStep
|
||||
} else if (selectNextStep(room)) {
|
||||
room.currentStep = selectNextStep(room)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -357,11 +314,7 @@ export function readFromSessionStorage(): PersistedState | undefined {
|
||||
|
||||
const parsedData = JSON.parse(storedData) as PersistedState
|
||||
|
||||
if (
|
||||
!parsedData.booking ||
|
||||
!parsedData.rooms ||
|
||||
!parsedData.bookingProgress
|
||||
) {
|
||||
if (!parsedData.booking || !parsedData.rooms) {
|
||||
return undefined
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user