269 lines
7.1 KiB
TypeScript
269 lines
7.1 KiB
TypeScript
import deepmerge from "deepmerge"
|
|
import isEqual from "fast-deep-equal"
|
|
|
|
import { Lang } from "@/constants/languages"
|
|
|
|
import { getLang } from "@/i18n/serverContext"
|
|
import { arrayMerge } from "@/utils/merge"
|
|
|
|
import { detailsStorageName } from "."
|
|
|
|
import type { BookingData } from "@/types/components/hotelReservation/enterDetails/bookingData"
|
|
import { CurrencyEnum } from "@/types/enums/currency"
|
|
import { StepEnum } from "@/types/enums/step"
|
|
import type {
|
|
DetailsState,
|
|
PersistedState,
|
|
PersistedStatePart,
|
|
RoomRate,
|
|
} from "@/types/stores/enter-details"
|
|
import type { SafeUser } from "@/types/user"
|
|
|
|
export function langToCurrency() {
|
|
const lang = getLang()
|
|
switch (lang) {
|
|
case Lang.da:
|
|
return CurrencyEnum.DKK
|
|
case Lang.de:
|
|
case Lang.en:
|
|
case Lang.fi:
|
|
return CurrencyEnum.EUR
|
|
case Lang.no:
|
|
return CurrencyEnum.NOK
|
|
case Lang.sv:
|
|
return CurrencyEnum.SEK
|
|
default:
|
|
throw new Error(`Unexpected lang: ${lang}`)
|
|
}
|
|
}
|
|
|
|
export function extractGuestFromUser(user: NonNullable<SafeUser>) {
|
|
return {
|
|
countryCode: user.address.countryCode?.toString(),
|
|
email: user.email,
|
|
firstName: user.firstName,
|
|
lastName: user.lastName,
|
|
join: false,
|
|
membershipNo: user.membership?.membershipNumber,
|
|
phoneNumber: user.phoneNumber ?? "",
|
|
}
|
|
}
|
|
|
|
export function navigate(step: StepEnum, searchParams: string) {
|
|
window.history.pushState({ step }, "", `${step}?${searchParams}`)
|
|
}
|
|
|
|
export function checkIsSameRoom(prev: BookingData, next: BookingData) {
|
|
const { rooms: prevRooms, ...prevBooking } = prev
|
|
|
|
const prevRoomsWithoutRateCodes = prevRooms.map(
|
|
({ rateCode, counterRateCode, ...room }) => room
|
|
)
|
|
const { rooms: nextRooms, ...nextBooking } = next
|
|
|
|
const nextRoomsWithoutRateCodes = nextRooms.map(
|
|
({ rateCode, counterRateCode, ...room }) => room
|
|
)
|
|
|
|
return isEqual(
|
|
{
|
|
...prevBooking,
|
|
rooms: prevRoomsWithoutRateCodes,
|
|
},
|
|
{
|
|
...nextBooking,
|
|
rooms: nextRoomsWithoutRateCodes,
|
|
}
|
|
)
|
|
}
|
|
|
|
export function add(...nums: (number | string | undefined)[]) {
|
|
return nums.reduce((total: number, num) => {
|
|
if (typeof num === "undefined") {
|
|
num = 0
|
|
}
|
|
total = total + parseInt(`${num}`)
|
|
return total
|
|
}, 0)
|
|
}
|
|
|
|
export function subtract(...nums: (number | string | undefined)[]) {
|
|
return nums.reduce((total: number, num, idx) => {
|
|
if (typeof num === "undefined") {
|
|
num = 0
|
|
}
|
|
if (idx === 0) {
|
|
return parseInt(`${num}`)
|
|
}
|
|
total = total - parseInt(`${num}`)
|
|
if (total < 0) {
|
|
return 0
|
|
}
|
|
return total
|
|
}, 0)
|
|
}
|
|
|
|
export function getInitialRoomPrice(roomRate: RoomRate, isMember: boolean) {
|
|
if (isMember && roomRate.memberRate) {
|
|
return {
|
|
requested: roomRate.memberRate.requestedPrice && {
|
|
currency: roomRate.memberRate.requestedPrice.currency,
|
|
price: roomRate.memberRate.requestedPrice.pricePerStay,
|
|
},
|
|
local: {
|
|
currency: roomRate.memberRate.localPrice.currency,
|
|
price: roomRate.memberRate.localPrice.pricePerStay,
|
|
},
|
|
}
|
|
}
|
|
|
|
return {
|
|
requested: roomRate.publicRate.requestedPrice && {
|
|
currency: roomRate.publicRate.requestedPrice.currency,
|
|
price: roomRate.publicRate.requestedPrice.pricePerStay,
|
|
},
|
|
local: {
|
|
currency: roomRate.publicRate.localPrice.currency,
|
|
price: roomRate.publicRate.localPrice.pricePerStay,
|
|
},
|
|
}
|
|
}
|
|
|
|
export function getInitialTotalPrice(roomRate: RoomRate, isMember: boolean) {
|
|
if (isMember && roomRate.memberRate) {
|
|
return {
|
|
requested: roomRate.memberRate.requestedPrice && {
|
|
currency: roomRate.memberRate.requestedPrice.currency,
|
|
price: roomRate.memberRate.requestedPrice.pricePerStay,
|
|
},
|
|
local: {
|
|
currency: roomRate.memberRate.localPrice.currency,
|
|
price: roomRate.memberRate.localPrice.pricePerStay,
|
|
},
|
|
}
|
|
}
|
|
|
|
return {
|
|
requested: roomRate.publicRate.requestedPrice && {
|
|
currency: roomRate.publicRate.requestedPrice.currency,
|
|
price: roomRate.publicRate.requestedPrice.pricePerStay,
|
|
},
|
|
local: {
|
|
currency: roomRate.publicRate.localPrice.currency,
|
|
price: roomRate.publicRate.localPrice.pricePerStay,
|
|
},
|
|
}
|
|
}
|
|
|
|
export function calcTotalMemberPrice(state: DetailsState) {
|
|
if (!state.roomRate.memberRate) {
|
|
return {
|
|
roomPrice: state.roomPrice,
|
|
totalPrice: state.totalPrice,
|
|
}
|
|
}
|
|
|
|
return calcTotalPrice({
|
|
breakfast: state.breakfast,
|
|
packages: state.packages,
|
|
roomPrice: state.roomPrice,
|
|
totalPrice: state.totalPrice,
|
|
...state.roomRate.memberRate,
|
|
})
|
|
}
|
|
|
|
export function calcTotalPublicPrice(state: DetailsState) {
|
|
return calcTotalPrice({
|
|
breakfast: state.breakfast,
|
|
packages: state.packages,
|
|
roomPrice: state.roomPrice,
|
|
totalPrice: state.totalPrice,
|
|
...state.roomRate.publicRate,
|
|
})
|
|
}
|
|
|
|
export function calcTotalPrice(
|
|
state: Pick<
|
|
DetailsState,
|
|
"breakfast" | "packages" | "roomPrice" | "totalPrice"
|
|
> &
|
|
DetailsState["roomRate"]["publicRate"]
|
|
) {
|
|
// state is sometimes read-only, thus we
|
|
// need to create a copy of the values
|
|
const roomAndTotalPrice = {
|
|
roomPrice: { ...state.roomPrice },
|
|
totalPrice: { ...state.totalPrice },
|
|
}
|
|
if (state.requestedPrice?.pricePerStay) {
|
|
roomAndTotalPrice.roomPrice.requested = {
|
|
currency: state.requestedPrice.currency,
|
|
price: state.requestedPrice.pricePerStay,
|
|
}
|
|
|
|
let totalPriceRequested = state.requestedPrice.pricePerStay
|
|
if (state.breakfast) {
|
|
totalPriceRequested = add(
|
|
totalPriceRequested,
|
|
state.breakfast.requestedPrice.totalPrice
|
|
)
|
|
}
|
|
|
|
if (state.packages) {
|
|
totalPriceRequested = state.packages.reduce((total, pkg) => {
|
|
if (pkg.requestedPrice.totalPrice) {
|
|
total = add(total, pkg.requestedPrice.totalPrice)
|
|
}
|
|
return total
|
|
}, totalPriceRequested)
|
|
}
|
|
|
|
roomAndTotalPrice.totalPrice.requested = {
|
|
currency: state.requestedPrice.currency,
|
|
price: totalPriceRequested,
|
|
}
|
|
}
|
|
|
|
const roomPriceLocal = state.localPrice
|
|
roomAndTotalPrice.roomPrice.local = {
|
|
currency: roomPriceLocal.currency,
|
|
price: roomPriceLocal.pricePerStay,
|
|
}
|
|
|
|
let totalPriceLocal = roomPriceLocal.pricePerStay
|
|
if (state.breakfast) {
|
|
totalPriceLocal = add(
|
|
totalPriceLocal,
|
|
state.breakfast.localPrice.totalPrice
|
|
)
|
|
}
|
|
|
|
if (state.packages) {
|
|
totalPriceLocal = state.packages.reduce((total, pkg) => {
|
|
if (pkg.localPrice.totalPrice) {
|
|
total = add(total, pkg.localPrice.totalPrice)
|
|
}
|
|
return total
|
|
}, totalPriceLocal)
|
|
}
|
|
roomAndTotalPrice.totalPrice.local = {
|
|
currency: roomPriceLocal.currency,
|
|
price: totalPriceLocal,
|
|
}
|
|
|
|
return roomAndTotalPrice
|
|
}
|
|
|
|
export function writeToSessionStorage(part: PersistedStatePart) {
|
|
const unparsedData = sessionStorage.getItem(detailsStorageName)
|
|
if (unparsedData) {
|
|
const data: PersistedState = JSON.parse(unparsedData)
|
|
// @ts-expect-error - deepmerge is not to happy with
|
|
// the part type
|
|
const updated = deepmerge(data, part, { arrayMerge })
|
|
sessionStorage.setItem(detailsStorageName, JSON.stringify(updated))
|
|
} else {
|
|
sessionStorage.setItem(detailsStorageName, JSON.stringify(part))
|
|
}
|
|
}
|