import { CurrencyEnum } from "@scandic-hotels/common/constants/currency" import { PointType } from "@scandic-hotels/common/constants/pointType" import { formatPrice } from "@scandic-hotels/common/utils/numberFormatting" import type { IntlShape } from "react-intl" import type { Room } from "@/types/stores/my-stay" export function calculateTotalPrice( rooms: Pick< Room, | "cheques" | "vouchers" | "roomPointType" | "roomPoints" | "totalPoints" | "totalPrice" | "isCancelled" >[], currency: CurrencyEnum, intl: IntlShape, allRoomsAreCancelled: boolean ) { const totals = rooms.reduce( (total, room) => { if (!allRoomsAreCancelled && room.isCancelled) { return total } if (room.cheques) { total.cheques = total.cheques + room.cheques } if (room.vouchers) { total.vouchers = total.vouchers + room.vouchers } // If roomPointType isn't Scandic, these should be counted as partnerPoints. // If they're not Scandic points, we can ignore them on roomPoints as they // are included in totalPoints, which in turn never contain partner points. if ( room.roomPoints && room.roomPointType && room.roomPointType !== "Scandic" ) { total.partnerPoints = total.partnerPoints + room.roomPoints } if (room.totalPoints) { total.scandicPoints = total.scandicPoints + room.totalPoints } // room.totalPrice is a negative value when // its a vouchers booking (╯°□°)╯︵ ┻━┻ if (room.totalPrice > 0) { total.cash = total.cash + room.totalPrice } return total }, { cash: 0, cheques: 0, scandicPoints: 0, partnerPoints: 0, vouchers: 0, } ) const priceParts: string[] = [] if (totals.vouchers) { priceParts.push( `${totals.vouchers} ${intl.formatMessage( { id: "price.numberOfVouchers", defaultMessage: "{numberOfVouchers, plural, one {Voucher} other {Vouchers}}", }, { numberOfVouchers: totals.vouchers, } )}` ) } if (totals.cheques) { priceParts.push(`${totals.cheques} ${CurrencyEnum.CC}`) } if (totals.partnerPoints) { // We can assume that all rooms has the same point type const roomPointType = rooms[0]?.roomPointType || PointType.SCANDIC const currencyText = getPointsCurrencyText( totals.partnerPoints, roomPointType, intl ) priceParts.push(`${totals.partnerPoints} ${currencyText}`) } if (totals.scandicPoints) { const currencyText = getPointsCurrencyText( totals.scandicPoints, PointType.SCANDIC, intl ) priceParts.push(`${totals.scandicPoints} ${currencyText}`) } if (totals.cash) { const cashPrice = formatPrice(intl, totals.cash, currency) priceParts.push(cashPrice) } return priceParts.join(" + ") } export function isAllRoomsCancelled(rooms: Room[]) { return !rooms.some((room) => room.isCancelled === false) } function getPointsCurrencyText( points: number, pointsType: PointType, intl: IntlShape ) { switch (pointsType) { case PointType.SCANDIC: { return intl.formatMessage( { id: "price.numberOfScandicPoints", defaultMessage: "{numberOfScandicPoints, plural, one {Point} other {Points}}", }, { numberOfScandicPoints: points, } ) } case PointType.EUROBONUS: { return intl.formatMessage( { id: "price.numberOfEuroBonusPoints", defaultMessage: "{numberOfEuroBonusPoints, plural, one {EB Point} other {EB Points}}", }, { numberOfEuroBonusPoints: points, } ) } default: { const _exhaustiveCheck: never = pointsType return "Points" } } }