Files
web/packages/booking-flow/lib/contexts/SelectRate/SelectRateContext/getLowestRoomPrice.ts
Joakim Jäderberg 9292c437f4 fix(SW-3442) getLowestRoomPrice - cannot read property of undefined
* fix: getLowestRoomPrice throws when given unexpected data
* dont track lowestRoomPrice if unavailable


Approved-by: Hrishikesh Vaipurkar
2025-10-03 13:16:25 +00:00

91 lines
2.2 KiB
TypeScript

import { CurrencyEnum } from "@scandic-hotels/common/constants/currency"
import type {
CorporateChequeProduct,
PriceProduct,
RedemptionProduct,
VoucherProduct,
} from "@scandic-hotels/trpc/types/roomAvailability"
import type { AvailabilityWithRoomInfo } from "../types"
export function getLowestRoomPrice(
roomAvailability: (AvailabilityWithRoomInfo | null)[][]
): { currency: CurrencyEnum; price: number } | null {
const products = roomAvailability
?.flatMap((room) => room?.flatMap((rates) => rates?.products))
.filter((x) => !!x)
if (!products || !products.length) {
return null
}
const sorted = sortRates(products as PriceInfo[])
return sorted.at(0) ?? null
}
type PriceInfo =
| Pick<PriceProduct, "member" | "public">
| Pick<RedemptionProduct, "redemption">
| Pick<CorporateChequeProduct, "corporateCheque">
| Pick<VoucherProduct, "voucher">
function sortRates(rates: PriceInfo[]) {
const mapped = rates.map((rate) => getPriceFromProduct(rate))
return mapped
.filter((x) => !!x)
.toSorted((a, b) => {
return a.price - b.price
})
}
function getPriceFromProduct(product: PriceInfo): {
currency: CurrencyEnum
price: number
} | null {
if (
("public" in product && product.public) ||
("member" in product && product.member)
) {
if (!product.public && !product.member) {
return null
}
const minPrice = Math.min(
product.member?.localPrice.pricePerNight || Infinity,
product.public?.localPrice.pricePerNight || Infinity
)
return {
currency:
(product.member?.localPrice.currency as CurrencyEnum) ||
(product.public?.localPrice.currency as CurrencyEnum) ||
CurrencyEnum.Unknown,
price: minPrice === Infinity ? 0 : minPrice,
}
}
if ("voucher" in product) {
return {
currency: CurrencyEnum.Voucher,
price: product.voucher?.numberOfVouchers,
}
}
if ("corporateCheque" in product) {
return {
currency: CurrencyEnum.CC,
price: product.corporateCheque?.localPrice.numberOfCheques,
}
}
if ("redemption" in product) {
return {
currency: CurrencyEnum.POINTS,
price: product.redemption.localPrice.pointsPerNight,
}
}
return null
}