Files
web/apps/scandic-web/stores/my-stay/helpers.ts
Anton Gunnarsson 16fbdb7ae0 Merged in fix/refactor-currency-display (pull request #3434)
fix(SW-3616): Handle EuroBonus point type everywhere

* Add tests to formatPrice

* formatPrice

* More work replacing config with api points type

* More work replacing config with api points type

* More fixing with currency

* maybe actually fixed it

* Fix MyStay

* Clean up

* Fix comments

* Merge branch 'master' into fix/refactor-currency-display

* Fix calculateTotalPrice for EB points + SF points + cash


Approved-by: Joakim Jäderberg
2026-01-15 09:32:17 +00:00

158 lines
3.9 KiB
TypeScript

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