feat: add multiroom signup

This commit is contained in:
Simon Emanuelsson
2025-02-17 15:10:48 +01:00
parent 95917e5e4f
commit 92c5566c59
78 changed files with 2035 additions and 1545 deletions

View File

@@ -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
}