Feat/SW-1889 * fix: remove download invoice from confirmation page * feat: remove EnterDetails Accordions Approved-by: Simon.Emanuelsson
205 lines
6.0 KiB
TypeScript
205 lines
6.0 KiB
TypeScript
"use client"
|
|
import deepmerge from "deepmerge"
|
|
import { useEffect, useRef } from "react"
|
|
|
|
import { dt } from "@/lib/dt"
|
|
import { createDetailsStore } from "@/stores/enter-details"
|
|
import {
|
|
calcTotalPrice,
|
|
checkIsSameBooking as checkIsSameBooking,
|
|
clearSessionStorage,
|
|
readFromSessionStorage,
|
|
writeToSessionStorage,
|
|
} from "@/stores/enter-details/helpers"
|
|
|
|
import { multiroomDetailsSchema } from "@/components/HotelReservation/EnterDetails/Details/Multiroom/schema"
|
|
import { guestDetailsSchema } from "@/components/HotelReservation/EnterDetails/Details/RoomOne/schema"
|
|
import { DetailsContext } from "@/contexts/Details"
|
|
|
|
import type { DetailsStore } from "@/types/contexts/enter-details"
|
|
import { CurrencyEnum } from "@/types/enums/currency"
|
|
import { StepEnum } from "@/types/enums/step"
|
|
import type { DetailsProviderProps } from "@/types/providers/enter-details"
|
|
import type { InitialState, RoomState } from "@/types/stores/enter-details"
|
|
|
|
export default function EnterDetailsProvider({
|
|
booking,
|
|
breakfastPackages,
|
|
children,
|
|
rooms,
|
|
searchParamsStr,
|
|
user,
|
|
vat,
|
|
}: DetailsProviderProps) {
|
|
const storeRef = useRef<DetailsStore>()
|
|
if (!storeRef.current) {
|
|
const initialData: InitialState = {
|
|
booking,
|
|
rooms: rooms
|
|
.filter((r) => r.bedTypes?.length) // TODO: how to handle room without bedtypes?
|
|
.map((room) => ({
|
|
isAvailable: room.isAvailable,
|
|
breakfastIncluded: !!room.breakfastIncluded,
|
|
cancellationText: room.cancellationText,
|
|
rateDetails: room.rateDetails,
|
|
rateTitle: room.rateTitle,
|
|
roomFeatures: room.packages,
|
|
roomRate: room.roomRate,
|
|
roomType: room.roomType,
|
|
roomTypeCode: room.roomTypeCode,
|
|
bedTypes: room.bedTypes!,
|
|
bedType:
|
|
room.bedTypes?.length === 1
|
|
? {
|
|
roomTypeCode: room.bedTypes[0].value,
|
|
description: room.bedTypes[0].description,
|
|
}
|
|
: undefined,
|
|
mustBeGuaranteed: room.mustBeGuaranteed,
|
|
isFlexRate: room.isFlexRate,
|
|
})),
|
|
vat,
|
|
}
|
|
|
|
storeRef.current = createDetailsStore(
|
|
initialData,
|
|
searchParamsStr,
|
|
user,
|
|
breakfastPackages
|
|
)
|
|
}
|
|
|
|
useEffect(() => {
|
|
const storedValues = readFromSessionStorage()
|
|
if (!storedValues) {
|
|
return
|
|
}
|
|
const isSameBooking = checkIsSameBooking(storedValues.booking, booking)
|
|
if (!isSameBooking) {
|
|
clearSessionStorage()
|
|
return
|
|
}
|
|
|
|
const store = storeRef.current?.getState()
|
|
if (!store) {
|
|
return
|
|
}
|
|
|
|
const updatedRooms = storedValues.rooms.map((storedRoom, idx) => {
|
|
const room = store.rooms[idx]
|
|
if (!room) {
|
|
return null
|
|
}
|
|
// Need to create a deep new copy
|
|
// since store is readonly
|
|
const currentRoom = deepmerge({}, room)
|
|
|
|
if (!currentRoom.room.isAvailable) {
|
|
return currentRoom
|
|
}
|
|
|
|
if (!currentRoom.room.bedType && storedRoom.room.bedType) {
|
|
const sameBed = currentRoom.room.bedTypes.find(
|
|
(bedType) => bedType.value === storedRoom.room.bedType?.roomTypeCode
|
|
)
|
|
if (sameBed) {
|
|
currentRoom.room.bedType = {
|
|
description: sameBed.description,
|
|
roomTypeCode: sameBed.value,
|
|
}
|
|
currentRoom.steps[StepEnum.selectBed].isValid = true
|
|
}
|
|
}
|
|
|
|
if (
|
|
currentRoom.steps[StepEnum.breakfast] &&
|
|
currentRoom.room.breakfast === undefined &&
|
|
(storedRoom.room.breakfast || storedRoom.room.breakfast === false)
|
|
) {
|
|
currentRoom.room.breakfast = storedRoom.room.breakfast
|
|
currentRoom.steps[StepEnum.breakfast].isValid = true
|
|
}
|
|
|
|
// User is already added for main room
|
|
if (!user || (user && idx > 0)) {
|
|
currentRoom.room.guest = deepmerge(
|
|
currentRoom.room.guest,
|
|
storedRoom.room.guest
|
|
)
|
|
}
|
|
if (
|
|
!currentRoom.room.specialRequest.comment &&
|
|
storedRoom.room.specialRequest.comment
|
|
) {
|
|
currentRoom.room.specialRequest.comment =
|
|
storedRoom.room.specialRequest.comment
|
|
}
|
|
const validGuest =
|
|
idx > 0
|
|
? multiroomDetailsSchema.safeParse(currentRoom.room.guest)
|
|
: guestDetailsSchema.safeParse(currentRoom.room.guest)
|
|
if (validGuest.success) {
|
|
currentRoom.steps[StepEnum.details].isValid = true
|
|
}
|
|
|
|
const invalidStep = Object.values(currentRoom.steps).find(
|
|
(step) => !step.isValid
|
|
)
|
|
|
|
currentRoom.isComplete = !invalidStep
|
|
|
|
return currentRoom
|
|
})
|
|
|
|
const canProceedToPayment = updatedRooms.every(
|
|
(room) => room?.isComplete && room?.room.isAvailable
|
|
)
|
|
|
|
const filteredOutMissingRooms = updatedRooms.filter(
|
|
(room): room is RoomState => !!room
|
|
)
|
|
|
|
const nights = dt(booking.toDate).diff(booking.fromDate, "days")
|
|
|
|
// We only extract the first room for its currency,
|
|
// the value is the same for the rest of the rooms
|
|
const product = filteredOutMissingRooms[0].room.roomRate
|
|
let currency = CurrencyEnum.Unknown
|
|
if ("corporateCheque" in product) {
|
|
currency = CurrencyEnum.CC
|
|
} else if ("redemption" in product) {
|
|
currency = CurrencyEnum.POINTS
|
|
} else if ("voucher" in product) {
|
|
currency = CurrencyEnum.Voucher
|
|
} else if ("public" in product && product.public) {
|
|
currency = product.public.localPrice.currency
|
|
} else if ("member" in product && product.member) {
|
|
currency = product.member.localPrice.currency
|
|
}
|
|
|
|
const totalPrice = calcTotalPrice(
|
|
filteredOutMissingRooms,
|
|
currency,
|
|
!!user,
|
|
nights
|
|
)
|
|
|
|
writeToSessionStorage({
|
|
booking,
|
|
rooms: filteredOutMissingRooms,
|
|
})
|
|
|
|
storeRef.current?.setState({
|
|
canProceedToPayment,
|
|
rooms: filteredOutMissingRooms,
|
|
totalPrice,
|
|
})
|
|
}, [booking, rooms, user])
|
|
|
|
return (
|
|
<DetailsContext.Provider value={storeRef.current}>
|
|
{children}
|
|
</DetailsContext.Provider>
|
|
)
|
|
}
|