feat: translate Voucher everywhere during booking flow

This commit is contained in:
Simon Emanuelsson
2025-06-27 15:03:24 +02:00
committed by Simon.Emanuelsson
parent a0b0ed2544
commit 59f4a27cb1
10 changed files with 71 additions and 32 deletions

View File

@@ -57,7 +57,7 @@ export function mapRoomState(
formattedRoomCost = formatPrice(
intl,
booking.vouchers,
CurrencyEnum.Voucher
intl.formatMessage({ defaultMessage: "Voucher" })
)
}

View File

@@ -102,6 +102,30 @@ export default function Room({
const guests = guestsParts.join(", ")
const zeroPrice = formatPrice(intl, 0, defaultCurrency)
let price = showMemberPrice
? formatPrice(intl, memberPrice.amount, memberPrice.currency)
: formatPrice(
intl,
room.roomPrice.perStay.local.price,
room.roomPrice.perStay.local.currency,
room.roomPrice.perStay.local.additionalPrice,
room.roomPrice.perStay.local.additionalPriceCurrency
)
let currency: string = room.roomPrice.perStay.local.currency
const voucherCurrency = intl.formatMessage({ defaultMessage: "Voucher" })
const isVoucher = "voucher" in room.roomRate
if (isVoucher) {
currency = voucherCurrency
price = formatPrice(
intl,
room.roomPrice.perStay.local.price,
voucherCurrency,
room.roomPrice.perStay.local.additionalPrice,
room.roomPrice.perStay.local.additionalPriceCurrency
)
}
return (
<>
<div className={styles.room} data-testid={`summary-room-${roomNumber}`}>
@@ -139,19 +163,7 @@ export default function Room({
[styles.discounted]: showDiscounted,
})}
>
{showMemberPrice
? formatPrice(
intl,
memberPrice.amount,
memberPrice.currency
)
: formatPrice(
intl,
room.roomPrice.perStay.local.price,
room.roomPrice.perStay.local.currency,
room.roomPrice.perStay.local.additionalPrice,
room.roomPrice.perStay.local.additionalPriceCurrency
)}
{price}
</p>
{showDiscounted && publicPrice ? (
<s className={styles.strikeThroughRate}>
@@ -262,7 +274,7 @@ export default function Room({
</div>
<div className={styles.prices}>
<span className={styles.price}>
{formatPrice(intl, 0, room.roomPrice.perStay.local.currency)}
{formatPrice(intl, 0, currency)}
</span>
</div>
</div>
@@ -284,7 +296,7 @@ export default function Room({
</p>
<div className={styles.prices}>
<span className={styles.price}>
{formatPrice(intl, 0, room.roomPrice.perStay.local.currency)}
{formatPrice(intl, 0, currency)}
</span>
</div>
</div>

View File

@@ -4,6 +4,7 @@ import { cx } from "class-variance-authority"
import { useIntl } from "react-intl"
import { useMediaQuery } from "usehooks-ts"
import { CurrencyEnum } from "@scandic-hotels/common/constants/currency"
import { dt } from "@scandic-hotels/common/dt"
import { Divider } from "@scandic-hotels/design-system/Divider"
import { MaterialIcon } from "@scandic-hotels/design-system/Icons/MaterialIcon"
@@ -66,11 +67,12 @@ export default function SummaryUI({
const roomOneMemberPrice = getMemberPrice(rooms[0].room.roomRate)
const roomOneRoomRate = rooms[0].room.roomRate
const isVoucherRate = "voucher" in roomOneRoomRate
// In case of Redemption, voucher and Corporate cheque do not show approx price
const isSpecialRate =
"corporateCheque" in roomOneRoomRate ||
"redemption" in roomOneRoomRate ||
"voucher" in roomOneRoomRate
isVoucherRate
const priceDetailsRooms = mapToPrice(rooms, isMember)
const isAllCampaignRate = rooms.every(
@@ -84,6 +86,16 @@ export default function SummaryUI({
)
const showDiscounted = containsBookingCodeRate || isMember
const totalCurrency = isVoucherRate
? intl.formatMessage({ defaultMessage: "Voucher" })
: totalPrice.local.currency
if (isVoucherRate && defaultCurrency === CurrencyEnum.Voucher) {
defaultCurrency = intl.formatMessage({
defaultMessage: "Voucher",
}) as CurrencyEnum
}
return (
<section className={styles.summary}>
<header
@@ -179,7 +191,7 @@ export default function SummaryUI({
{formatPrice(
intl,
totalPrice.local.price,
totalPrice.local.currency,
totalCurrency,
totalPrice.local.additionalPrice,
totalPrice.local.additionalPriceCurrency
)}

View File

@@ -1,12 +1,13 @@
"use client"
import { useIntl } from "react-intl"
import { CurrencyEnum } from "@scandic-hotels/common/constants/currency"
import { Typography } from "@scandic-hotels/design-system/Typography"
import SkeletonShimmer from "@/components/SkeletonShimmer"
import { formatPrice } from "@/utils/numberFormatting"
import type { CurrencyEnum } from "@scandic-hotels/common/constants/currency"
export default function Vouchers({
currencyCode,
isCancelled,
@@ -27,7 +28,7 @@ export default function Vouchers({
const totalPrice = formatPrice(
intl,
vouchers,
CurrencyEnum.Voucher,
intl.formatMessage({ defaultMessage: "Voucher" }),
price,
currencyCode
)

View File

@@ -1,6 +1,7 @@
import { cx } from "class-variance-authority"
import { useIntl } from "react-intl"
import { CurrencyEnum } from "@scandic-hotels/common/constants/currency"
import { Typography } from "@scandic-hotels/design-system/Typography"
import { formatPrice } from "@/utils/numberFormatting"
@@ -21,10 +22,14 @@ export default function LargeRow({
price,
}: RowProps) {
const intl = useIntl()
const isVoucherRate = price.local.currency === CurrencyEnum.Voucher
const currency = isVoucherRate
? intl.formatMessage({ defaultMessage: "Voucher" })
: price.local.currency
const totalPrice = formatPrice(
intl,
price.local.price,
price.local.currency,
currency,
price.local.additionalPrice,
price.local.additionalPriceCurrency
)

View File

@@ -1,8 +1,6 @@
"use client"
import { useIntl } from "react-intl"
import { CurrencyEnum } from "@scandic-hotels/common/constants/currency"
import { formatPrice } from "@/utils/numberFormatting"
import BoldRow from "../Bold"
@@ -37,17 +35,19 @@ export default function VoucherPrice({
return null
}
const voucherCurrency = intl.formatMessage({ defaultMessage: "Voucher" })
const averagePriceTitle = intl.formatMessage({
defaultMessage: "Average price per night",
})
const averagePricePerNight = `${price.numberOfVouchers / nights} ${CurrencyEnum.Voucher}`
const averagePricePerNight = `${price.numberOfVouchers / nights} ${voucherCurrency}`
return (
<>
<BoldRow
label={intl.formatMessage({ defaultMessage: "Room charge" })}
value={formatPrice(intl, price.numberOfVouchers, CurrencyEnum.Voucher)}
value={formatPrice(intl, price.numberOfVouchers, voucherCurrency)}
/>
{nights > 1 ? (
<RegularRow label={averagePriceTitle} value={averagePricePerNight} />

View File

@@ -167,7 +167,8 @@ export default function RateSummary() {
const totalPriceToShow = getTotalPrice(
mainRoomProduct,
rateSummary,
isUserLoggedIn
isUserLoggedIn,
intl
)
const rateProduct = rateSummary.find((rate) => rate?.product)?.product

View File

@@ -5,6 +5,7 @@ import { sumPackages } from "@/components/HotelReservation/utils"
import type { Packages } from "@scandic-hotels/trpc/types/packages"
import type { RedemptionProduct } from "@scandic-hotels/trpc/types/roomAvailability"
import type { IntlShape } from "react-intl"
import type { Price } from "@/types/components/hotelReservation/price"
import type { Rate } from "@/types/components/hotelReservation/selectRate/selectRate"
@@ -218,7 +219,8 @@ export function calculateCorporateChequePrice(selectedRateSummary: Rate[]) {
export function getTotalPrice(
mainRoomProduct: Rate | null,
rateSummary: Array<Rate | null>,
isUserLoggedIn: boolean
isUserLoggedIn: boolean,
intl: IntlShape
): Price | null {
const summaryArray = rateSummary.filter((rate): rate is Rate => rate !== null)
@@ -237,7 +239,11 @@ export function getTotalPrice(
return calculateRedemptionTotalPrice(product.redemption, packages)
}
if ("voucher" in product) {
return calculateVoucherPrice(summaryArray)
const voucherPrice = calculateVoucherPrice(summaryArray)
voucherPrice.local.currency = intl.formatMessage({
defaultMessage: "Voucher",
}) as CurrencyEnum
return voucherPrice
}
return calculateTotalPrice(summaryArray, isUserLoggedIn)

View File

@@ -3,13 +3,14 @@
import { useRef } from "react"
import { useIntl } from "react-intl"
import { CurrencyEnum } from "@scandic-hotels/common/constants/currency"
import { createBookingConfirmationStore } from "@/stores/booking-confirmation"
import { BookingConfirmationContext } from "@/contexts/BookingConfirmation"
import { formatPrice } from "@/utils/numberFormatting"
import type { BookingConfirmationStore } from "@/types/contexts/booking-confirmation"
import { CurrencyEnum } from "@scandic-hotels/common/constants/currency"
import type { BookingConfirmationProviderProps } from "@/types/providers/booking-confirmation"
export default function BookingConfirmationProvider({
@@ -62,6 +63,7 @@ export default function BookingConfirmationProvider({
)
} else if (totalBookingVouchers) {
const room = rooms?.[0]
const voucherCurrency = intl.formatMessage({ defaultMessage: "Voucher" })
if (room?.packages) {
const pkgsSum = room.packages.reduce(
(total, pkg) => total + pkg.totalPrice,
@@ -72,7 +74,7 @@ export default function BookingConfirmationProvider({
formattedTotalCost = formatPrice(
intl,
totalBookingVouchers,
CurrencyEnum.Voucher,
voucherCurrency,
pkgsSum,
currency
)
@@ -81,7 +83,7 @@ export default function BookingConfirmationProvider({
formattedTotalCost = formatPrice(
intl,
totalBookingVouchers,
CurrencyEnum.Voucher
voucherCurrency
)
}
}

View File

@@ -52,7 +52,7 @@ export function calculateTotalPrice(
}
if (totals.vouchers) {
const appendTotalPrice = totalPrice ? `${totalPrice} + ` : ""
totalPrice = `${appendTotalPrice}${totals.vouchers} ${CurrencyEnum.Voucher}`
totalPrice = `${appendTotalPrice}${totals.vouchers} ${intl.formatMessage({ defaultMessage: "Voucher" })}`
}
if (totals.cash) {
const appendTotalPrice = totalPrice ? `${totalPrice} + ` : ""