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
This commit is contained in:
@@ -2,8 +2,6 @@
|
||||
|
||||
import { createContext, useContext } from "react"
|
||||
|
||||
import { CurrencyEnum } from "@scandic-hotels/common/constants/currency"
|
||||
|
||||
import type { BookingFlowConfig } from "./bookingFlowConfig"
|
||||
|
||||
type BookingFlowConfigContextData = BookingFlowConfig
|
||||
@@ -24,20 +22,6 @@ export const useBookingFlowConfig = (): BookingFlowConfigContextData => {
|
||||
return context
|
||||
}
|
||||
|
||||
export const useGetPointsCurrency = () => {
|
||||
const config = useBookingFlowConfig()
|
||||
|
||||
switch (config.variant) {
|
||||
case "scandic":
|
||||
return CurrencyEnum.POINTS
|
||||
case "partner-sas":
|
||||
return CurrencyEnum.EUROBONUS
|
||||
default:
|
||||
const _exhaustiveCheck: never = config.variant
|
||||
throw new Error(`Unknown variant: ${config.variant}`)
|
||||
}
|
||||
}
|
||||
|
||||
export function BookingFlowConfigContextProvider({
|
||||
children,
|
||||
config,
|
||||
|
||||
@@ -11,7 +11,7 @@ import { Typography } from "@scandic-hotels/design-system/Typography"
|
||||
|
||||
import useLang from "../../../hooks/useLang"
|
||||
import { useBookingConfirmationStore } from "../../../stores/booking-confirmation"
|
||||
import { ReceiptRoom as Room } from "./Room"
|
||||
import { ReceiptRoom } from "./Room"
|
||||
import TotalPrice from "./TotalPrice"
|
||||
|
||||
import styles from "./receipt.module.css"
|
||||
@@ -69,7 +69,7 @@ export function Receipt() {
|
||||
<Divider color="Border/Divider/Subtle" />
|
||||
|
||||
{filteredRooms.map((room, idx) => (
|
||||
<Room
|
||||
<ReceiptRoom
|
||||
key={room ? room.confirmationNumber : `loader-${idx}`}
|
||||
room={room}
|
||||
roomNumber={idx + 1}
|
||||
|
||||
@@ -60,7 +60,14 @@ export function LinkedReservation({
|
||||
totalBookingPrice,
|
||||
currencyCode
|
||||
)
|
||||
: formatPrice(intl, totalBookingPrice, currencyCode)
|
||||
: formatPrice(
|
||||
intl,
|
||||
totalBookingPrice,
|
||||
currencyCode,
|
||||
undefined,
|
||||
undefined,
|
||||
roomData.pointsType
|
||||
)
|
||||
|
||||
setFormattedTotalCost(formattedTotalCost)
|
||||
}
|
||||
|
||||
@@ -42,7 +42,8 @@ export function mapRoomState(
|
||||
booking.roomPoints,
|
||||
CurrencyEnum.POINTS,
|
||||
booking.roomPrice,
|
||||
booking.currencyCode
|
||||
booking.currencyCode,
|
||||
booking.roomPointType
|
||||
)
|
||||
} else if (booking.cheques) {
|
||||
formattedRoomCost = formatPrice(
|
||||
@@ -72,6 +73,7 @@ export function mapRoomState(
|
||||
childBedPreferences: booking.childBedPreferences,
|
||||
confirmationNumber: booking.confirmationNumber,
|
||||
currencyCode: booking.currencyCode,
|
||||
pointsType: booking.roomPointType,
|
||||
formattedRoomCost,
|
||||
fromDate: booking.checkInDate,
|
||||
name: room.name,
|
||||
|
||||
@@ -113,7 +113,8 @@ export default function Room({
|
||||
room.roomPrice.perStay.local.price,
|
||||
room.roomPrice.perStay.local.currency,
|
||||
room.roomPrice.perStay.local.additionalPrice,
|
||||
room.roomPrice.perStay.local.additionalPriceCurrency
|
||||
room.roomPrice.perStay.local.additionalPriceCurrency,
|
||||
room.roomPrice.perStay.local.pointsType
|
||||
)
|
||||
|
||||
let currency: string = room.roomPrice.perStay.local.currency
|
||||
|
||||
@@ -203,7 +203,8 @@ export default function SummaryUI({
|
||||
totalPrice.local.price,
|
||||
totalCurrency,
|
||||
totalPrice.local.additionalPrice,
|
||||
totalPrice.local.additionalPriceCurrency
|
||||
totalPrice.local.additionalPriceCurrency,
|
||||
totalPrice.local.pointsType
|
||||
)}
|
||||
</span>
|
||||
</Typography>
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import type { PointType } from "@scandic-hotels/common/constants/pointType"
|
||||
import type { imageSchema } from "@scandic-hotels/trpc/routers/hotels/schemas/image"
|
||||
import type { ProductTypeCheque } from "@scandic-hotels/trpc/types/availability"
|
||||
import type { Amenities } from "@scandic-hotels/trpc/types/hotel"
|
||||
@@ -19,6 +20,7 @@ export type HotelPin = {
|
||||
publicPrice: number | null
|
||||
memberPrice: number | null
|
||||
redemptionPrice: number | null
|
||||
pointsType: PointType | null
|
||||
voucherPrice: number | null
|
||||
rateType: string | null
|
||||
currency: string
|
||||
@@ -59,6 +61,7 @@ export function getHotelPins(
|
||||
publicPrice: productType?.public?.localPrice.pricePerNight ?? null,
|
||||
memberPrice: productType?.member?.localPrice.pricePerNight ?? null,
|
||||
redemptionPrice: redemptionRate?.localPrice.pointsPerStay ?? null,
|
||||
pointsType: redemptionRate?.localPrice.pointsType ?? null,
|
||||
voucherPrice: voucherPrice ?? null,
|
||||
rateType:
|
||||
productType?.public?.rateType ?? productType?.member?.rateType ?? null,
|
||||
|
||||
@@ -13,10 +13,7 @@ import { useScrollToTop } from "@scandic-hotels/common/hooks/useScrollToTop"
|
||||
import { BackToTopButton } from "@scandic-hotels/design-system/BackToTopButton"
|
||||
import { HotelCard } from "@scandic-hotels/design-system/HotelCard"
|
||||
|
||||
import {
|
||||
useBookingFlowConfig,
|
||||
useGetPointsCurrency,
|
||||
} from "../../bookingFlowConfig/bookingFlowConfigContext"
|
||||
import { useBookingFlowConfig } from "../../bookingFlowConfig/bookingFlowConfigContext"
|
||||
import { useIsLoggedIn } from "../../hooks/useIsLoggedIn"
|
||||
import useLang from "../../hooks/useLang"
|
||||
import { mapApiImagesToGalleryImages } from "../../misc/imageGallery"
|
||||
@@ -65,7 +62,6 @@ export default function HotelCardListing({
|
||||
const { activeHotel, activate, disengage, engage } = useHotelsMapStore()
|
||||
const { showBackToTop, scrollToTop } = useScrollToTop({ threshold: 490 })
|
||||
const activeCardRef = useRef<HTMLDivElement | null>(null)
|
||||
const pointsCurrency = useGetPointsCurrency()
|
||||
const config = useBookingFlowConfig()
|
||||
|
||||
const sortBy = searchParams.get("sort") ?? DEFAULT_SORT
|
||||
@@ -183,7 +179,6 @@ export default function HotelCardListing({
|
||||
tripAdvisor: hotel.hotel.ratings?.tripAdvisor.rating,
|
||||
},
|
||||
}}
|
||||
pointsCurrency={pointsCurrency}
|
||||
lang={lang}
|
||||
fullPrice={!hotel.availability.bookingCode}
|
||||
prices={
|
||||
|
||||
@@ -14,7 +14,6 @@ import { OldDSButton as Button } from "@scandic-hotels/design-system/OldDSButton
|
||||
import Link from "@scandic-hotels/design-system/OldDSLink"
|
||||
import { Typography } from "@scandic-hotels/design-system/Typography"
|
||||
|
||||
import { useGetPointsCurrency } from "../../bookingFlowConfig/bookingFlowConfigContext"
|
||||
import { useIsLoggedIn } from "../../hooks/useIsLoggedIn"
|
||||
import useLang from "../../hooks/useLang"
|
||||
|
||||
@@ -33,7 +32,6 @@ export default function ListingHotelCardDialog({
|
||||
}: ListingHotelCardProps) {
|
||||
const intl = useIntl()
|
||||
const lang = useLang()
|
||||
const pointsCurrency = useGetPointsCurrency()
|
||||
|
||||
const [imageError, setImageError] = useState(false)
|
||||
|
||||
@@ -49,6 +47,7 @@ export default function ListingHotelCardDialog({
|
||||
ratings,
|
||||
operaId,
|
||||
redemptionPrice,
|
||||
pointsType,
|
||||
chequePrice,
|
||||
voucherPrice,
|
||||
hasEnoughPoints,
|
||||
@@ -183,7 +182,7 @@ export default function ListingHotelCardDialog({
|
||||
{redemptionPrice && (
|
||||
<HotelPointsRow
|
||||
pointsPerStay={redemptionPrice}
|
||||
pointsCurrency={pointsCurrency}
|
||||
pointsType={pointsType}
|
||||
/>
|
||||
)}
|
||||
{chequePrice && (
|
||||
|
||||
@@ -26,7 +26,8 @@ export default function LargeRow({
|
||||
price.local.price,
|
||||
price.local.currency,
|
||||
price.local.additionalPrice,
|
||||
price.local.additionalPriceCurrency
|
||||
price.local.additionalPriceCurrency,
|
||||
price.local.pointsType
|
||||
)
|
||||
const regularPrice = price.local.regularPrice
|
||||
? formatPrice(
|
||||
@@ -34,7 +35,8 @@ export default function LargeRow({
|
||||
price.local.regularPrice,
|
||||
price.local.currency,
|
||||
price.local.additionalPrice,
|
||||
price.local.additionalPriceCurrency
|
||||
price.local.additionalPriceCurrency,
|
||||
price.local.pointsType
|
||||
)
|
||||
: null
|
||||
|
||||
|
||||
@@ -1,16 +1,15 @@
|
||||
"use client"
|
||||
import { useIntl } from "react-intl"
|
||||
import { type IntlShape, useIntl } from "react-intl"
|
||||
|
||||
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 { useGetPointsCurrency } from "../../../../../bookingFlowConfig/bookingFlowConfigContext"
|
||||
import BoldRow from "../Bold"
|
||||
import RegularRow from "../Regular"
|
||||
import BedTypeRow from "./BedType"
|
||||
import PackagesRow from "./Packages"
|
||||
|
||||
import type { CurrencyEnum } from "@scandic-hotels/common/constants/currency"
|
||||
|
||||
import type { SharedPriceRowProps } from "./price"
|
||||
|
||||
export interface RedemptionPriceType {
|
||||
@@ -19,11 +18,12 @@ export interface RedemptionPriceType {
|
||||
currency?: CurrencyEnum
|
||||
pointsPerNight: number
|
||||
pointsPerStay: number
|
||||
pointsType: PointType
|
||||
}
|
||||
}
|
||||
|
||||
interface RedemptionPriceProps extends SharedPriceRowProps {
|
||||
currency: string
|
||||
currency: CurrencyEnum
|
||||
nights: number
|
||||
price: RedemptionPriceType["redemption"]
|
||||
}
|
||||
@@ -36,7 +36,6 @@ export default function RedemptionPrice({
|
||||
price,
|
||||
}: RedemptionPriceProps) {
|
||||
const intl = useIntl()
|
||||
const pointsCurrency = useGetPointsCurrency()
|
||||
|
||||
if (!price) {
|
||||
return null
|
||||
@@ -53,10 +52,17 @@ export default function RedemptionPrice({
|
||||
? Math.ceil(additionalPricePerStay / nights)
|
||||
: null
|
||||
|
||||
const additionalCurrency = price.currency ?? currency
|
||||
let averagePricePerNight = `${price.pointsPerNight} ${pointsCurrency}`
|
||||
const actualCurrency = price.currency || currency
|
||||
const formattedCurrency = getCurrencyText(
|
||||
price.pointsPerStay,
|
||||
actualCurrency,
|
||||
price.pointsType,
|
||||
intl
|
||||
)
|
||||
|
||||
let averagePricePerNight = `${price.pointsPerNight} ${formattedCurrency}`
|
||||
if (averageAdditionalPricePerNight) {
|
||||
averagePricePerNight = `${averagePricePerNight} + ${averageAdditionalPricePerNight} ${additionalCurrency}`
|
||||
averagePricePerNight = `${averagePricePerNight} + ${averageAdditionalPricePerNight} ${formattedCurrency}`
|
||||
}
|
||||
|
||||
return (
|
||||
@@ -69,9 +75,10 @@ export default function RedemptionPrice({
|
||||
value={formatPrice(
|
||||
intl,
|
||||
price.pointsPerStay,
|
||||
pointsCurrency,
|
||||
currency,
|
||||
additionalPricePerStay,
|
||||
additionalCurrency
|
||||
formattedCurrency,
|
||||
price.pointsType
|
||||
)}
|
||||
/>
|
||||
{nights > 1 ? (
|
||||
@@ -82,3 +89,47 @@ export default function RedemptionPrice({
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
function getCurrencyText(
|
||||
points: number,
|
||||
currency: CurrencyEnum | undefined,
|
||||
pointsType: PointType,
|
||||
intl: IntlShape
|
||||
) {
|
||||
if (!currency) return currency
|
||||
|
||||
if (currency === CurrencyEnum.POINTS) {
|
||||
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 currency
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return currency
|
||||
}
|
||||
|
||||
@@ -17,7 +17,6 @@ interface VatProps {
|
||||
const noVatCurrencies = [
|
||||
CurrencyEnum.CC,
|
||||
CurrencyEnum.POINTS,
|
||||
CurrencyEnum.EUROBONUS,
|
||||
CurrencyEnum.Voucher,
|
||||
CurrencyEnum.Unknown,
|
||||
]
|
||||
|
||||
@@ -119,7 +119,7 @@ export default function PriceDetailsTable({
|
||||
return (
|
||||
<table className={styles.priceDetailsTable}>
|
||||
{rooms.map((room, idx) => {
|
||||
let currency = ""
|
||||
let currency: CurrencyEnum = defaultCurrency
|
||||
let chequePrice: CorporateChequePriceType["corporateCheque"] | undefined
|
||||
if ("corporateCheque" in room.price && room.price.corporateCheque) {
|
||||
chequePrice = room.price.corporateCheque
|
||||
@@ -151,10 +151,6 @@ export default function PriceDetailsTable({
|
||||
voucherPrice = room.price.voucher
|
||||
}
|
||||
|
||||
if (!currency) {
|
||||
currency = defaultCurrency
|
||||
}
|
||||
|
||||
if (!price && !voucherPrice && !chequePrice && !redemptionPrice) {
|
||||
return null
|
||||
}
|
||||
|
||||
@@ -19,7 +19,6 @@ import Link from "@scandic-hotels/design-system/OldDSLink"
|
||||
import { Typography } from "@scandic-hotels/design-system/Typography"
|
||||
import { trackEvent } from "@scandic-hotels/tracking/base"
|
||||
|
||||
import { useGetPointsCurrency } from "../../../../bookingFlowConfig/bookingFlowConfigContext"
|
||||
import { useIsLoggedIn } from "../../../../hooks/useIsLoggedIn"
|
||||
import useLang from "../../../../hooks/useLang"
|
||||
import { mapApiImagesToGalleryImages } from "../../../../misc/imageGallery"
|
||||
@@ -80,7 +79,6 @@ export function SelectHotelMapContent({
|
||||
const setResultCount = useHotelResultCountStore(
|
||||
(state) => state.setResultCount
|
||||
)
|
||||
const pointsCurrency = useGetPointsCurrency()
|
||||
|
||||
const hotelMapStore = useHotelsMapStore()
|
||||
|
||||
@@ -266,7 +264,6 @@ export function SelectHotelMapContent({
|
||||
)}
|
||||
</div>
|
||||
<InteractiveMap
|
||||
pointsCurrency={pointsCurrency}
|
||||
closeButton={closeButton}
|
||||
coordinates={coordinates}
|
||||
hotelPins={filteredHotelPins.map((pin) => {
|
||||
|
||||
@@ -167,7 +167,8 @@ export function DesktopSummary({
|
||||
selectedRates.totalPrice.local.price,
|
||||
selectedRates.totalPrice.local.currency,
|
||||
selectedRates.totalPrice.local.additionalPrice,
|
||||
selectedRates.totalPrice.local.additionalPriceCurrency
|
||||
selectedRates.totalPrice.local.additionalPriceCurrency,
|
||||
selectedRates.totalPrice.local.pointsType
|
||||
)}
|
||||
</p>
|
||||
</Typography>
|
||||
@@ -203,7 +204,8 @@ export function DesktopSummary({
|
||||
selectedRates.totalPrice.requested.currency,
|
||||
selectedRates.totalPrice.requested.additionalPrice,
|
||||
selectedRates.totalPrice.requested
|
||||
.additionalPriceCurrency
|
||||
.additionalPriceCurrency,
|
||||
selectedRates.totalPrice.local.pointsType
|
||||
),
|
||||
}
|
||||
)}
|
||||
|
||||
@@ -195,7 +195,8 @@ export default function SummaryContent({
|
||||
selectedRates.totalPrice.local.price,
|
||||
selectedRates.totalPrice.local.currency,
|
||||
selectedRates.totalPrice.local.additionalPrice,
|
||||
selectedRates.totalPrice.local.additionalPriceCurrency
|
||||
selectedRates.totalPrice.local.additionalPriceCurrency,
|
||||
selectedRates.totalPrice.local.pointsType
|
||||
)}
|
||||
</span>
|
||||
</Typography>
|
||||
|
||||
@@ -137,7 +137,8 @@ export default function Room({
|
||||
room.roomPrice.perStay.local.price,
|
||||
room.roomPrice.perStay.local.currency,
|
||||
room.roomPrice.perStay.local.additionalPrice,
|
||||
room.roomPrice.perStay.local.additionalPriceCurrency
|
||||
room.roomPrice.perStay.local.additionalPriceCurrency,
|
||||
room.roomPrice.perStay.local.pointsType
|
||||
)}
|
||||
</p>
|
||||
{showDiscounted && room.roomPrice.perStay.local.regularPrice ? (
|
||||
|
||||
@@ -100,7 +100,8 @@ export function MobileSummary() {
|
||||
selectedRates.totalPrice.local.price,
|
||||
selectedRates.totalPrice.local.currency,
|
||||
selectedRates.totalPrice.local.additionalPrice,
|
||||
selectedRates.totalPrice.local.additionalPriceCurrency
|
||||
selectedRates.totalPrice.local.additionalPriceCurrency,
|
||||
selectedRates.totalPrice.local.pointsType
|
||||
)}
|
||||
</span>
|
||||
</Typography>
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
"use client"
|
||||
import { useIntl } from "react-intl"
|
||||
|
||||
import { CurrencyEnum } from "@scandic-hotels/common/constants/currency"
|
||||
import PointsRateCard from "@scandic-hotels/design-system/PointsRateCard"
|
||||
|
||||
import { useGetPointsCurrency } from "../../../../../../../bookingFlowConfig/bookingFlowConfigContext"
|
||||
import { useSelectRateContext } from "../../../../../../../contexts/SelectRate/SelectRateContext"
|
||||
import { BookingCodeFilterEnum } from "../../../../../../../stores/bookingCode-filter"
|
||||
import { sumPackages } from "../../../../../../../utils/SelectRate"
|
||||
@@ -35,7 +35,6 @@ export default function Redemptions({
|
||||
selectedRates,
|
||||
} = useSelectRateContext()
|
||||
const roomNr = roomIndex + 1
|
||||
const pointsCurrency = useGetPointsCurrency()
|
||||
|
||||
// TODO: Replace with context value when we have support for dropdown "Show all rates"
|
||||
const selectedFilter = BookingCodeFilterEnum.All as BookingCodeFilterEnum
|
||||
@@ -92,9 +91,10 @@ export default function Redemptions({
|
||||
price: additionalPrice.toString(),
|
||||
}
|
||||
: undefined,
|
||||
currency: pointsCurrency ?? "PTS",
|
||||
currency: CurrencyEnum.POINTS,
|
||||
isDisabled: !r.redemption.hasEnoughPoints,
|
||||
points: r.redemption.localPrice.pointsPerStay.toString(),
|
||||
points: r.redemption.localPrice.pointsPerStay,
|
||||
pointsType: r.redemption.localPrice.pointsType,
|
||||
rateCode: r.redemption.rateCode,
|
||||
}
|
||||
})
|
||||
|
||||
@@ -6,7 +6,6 @@ import { createContext, useEffect, useRef, useState } from "react"
|
||||
import { dt } from "@scandic-hotels/common/dt"
|
||||
import { LoadingSpinner } from "@scandic-hotels/design-system/LoadingSpinner"
|
||||
|
||||
import { useGetPointsCurrency } from "../../bookingFlowConfig/bookingFlowConfigContext"
|
||||
import { getMultiroomDetailsSchema } from "../../components/EnterDetails/Details/Multiroom/schema"
|
||||
import { guestDetailsSchema } from "../../components/EnterDetails/Details/RoomOne/schema"
|
||||
import {
|
||||
@@ -65,7 +64,6 @@ export default function EnterDetailsProvider({
|
||||
// rendering the form until that has been done.
|
||||
const [hasInitializedStore, setHasInitializedStore] = useState(false)
|
||||
const storeRef = useRef<EnterDetailsStore>(undefined)
|
||||
const pointsCurrency = useGetPointsCurrency()
|
||||
// eslint-disable-next-line react-hooks/refs
|
||||
if (!storeRef.current) {
|
||||
const initialData: InitialState = {
|
||||
@@ -108,8 +106,7 @@ export default function EnterDetailsProvider({
|
||||
searchParamsStr,
|
||||
user,
|
||||
breakfastPackages,
|
||||
lang,
|
||||
pointsCurrency
|
||||
lang
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
@@ -12,7 +12,6 @@ import { RoomPackageCodeEnum } from "@scandic-hotels/trpc/enums/roomFilter"
|
||||
import { AvailabilityEnum } from "@scandic-hotels/trpc/enums/selectHotel"
|
||||
import { selectRateRoomsAvailabilityInputSchema } from "@scandic-hotels/trpc/routers/hotels/availability/selectRate/rooms/schema"
|
||||
|
||||
import { useGetPointsCurrency } from "../../../bookingFlowConfig/bookingFlowConfigContext"
|
||||
import { useIsLoggedIn } from "../../../hooks/useIsLoggedIn"
|
||||
import useLang from "../../../hooks/useLang"
|
||||
import { BookingCodeFilterEnum } from "../../../stores/bookingCode-filter"
|
||||
@@ -63,7 +62,6 @@ export function SelectRateProvider({
|
||||
const updateBooking = useUpdateBooking()
|
||||
const isUserLoggedIn = useIsLoggedIn()
|
||||
const intl = useIntl()
|
||||
const pointsCurrency = useGetPointsCurrency()
|
||||
|
||||
const [activeRoomIndex, setInternalActiveRoomIndex] = useQueryState<number>(
|
||||
"activeRoomIndex",
|
||||
@@ -228,7 +226,6 @@ export function SelectRateProvider({
|
||||
roomConfiguration: roomAvailability[ix]?.[0],
|
||||
})),
|
||||
isMember: isUserLoggedIn,
|
||||
pointsCurrency,
|
||||
})
|
||||
|
||||
const getPriceForRoom = useCallback(
|
||||
@@ -249,10 +246,9 @@ export function SelectRateProvider({
|
||||
],
|
||||
isMember: isUserLoggedIn && roomIndex === 0,
|
||||
addAdditionalCost: false,
|
||||
pointsCurrency,
|
||||
})
|
||||
},
|
||||
[selectedRates, roomAvailability, isUserLoggedIn, pointsCurrency]
|
||||
[selectedRates, roomAvailability, isUserLoggedIn]
|
||||
)
|
||||
|
||||
const setActiveRoomIndex = useCallback(
|
||||
|
||||
@@ -17,12 +17,10 @@ export function getTotalPrice({
|
||||
selectedRates,
|
||||
isMember,
|
||||
addAdditionalCost = true,
|
||||
pointsCurrency,
|
||||
}: {
|
||||
selectedRates: Array<SelectedRate | null>
|
||||
isMember: boolean
|
||||
addAdditionalCost?: boolean
|
||||
pointsCurrency?: CurrencyEnum
|
||||
}): Price | null {
|
||||
const mainRoom = selectedRates[0]
|
||||
const mainRoomRate = mainRoom?.rate
|
||||
@@ -47,8 +45,7 @@ export function getTotalPrice({
|
||||
mainRoom.roomConfiguration?.selectedPackages.filter(
|
||||
(pkg) => "localPrice" in pkg
|
||||
) ?? null,
|
||||
addAdditionalCost,
|
||||
pointsCurrency
|
||||
addAdditionalCost
|
||||
)
|
||||
}
|
||||
if ("voucher" in mainRoomRate) {
|
||||
@@ -159,8 +156,7 @@ function calculateTotalPrice(
|
||||
function calculateRedemptionTotalPrice(
|
||||
redemption: RedemptionProduct["redemption"],
|
||||
packages: RoomPackage[] | null,
|
||||
addAdditonalCost: boolean,
|
||||
pointsCurrency?: CurrencyEnum
|
||||
addAdditonalCost: boolean
|
||||
) {
|
||||
const pkgsSum = addAdditonalCost
|
||||
? sumPackages(packages)
|
||||
@@ -183,8 +179,9 @@ function calculateRedemptionTotalPrice(
|
||||
local: {
|
||||
additionalPrice,
|
||||
additionalPriceCurrency,
|
||||
currency: pointsCurrency ?? CurrencyEnum.POINTS,
|
||||
currency: CurrencyEnum.POINTS,
|
||||
price: redemption.localPrice.pointsPerStay,
|
||||
pointsType: redemption.localPrice.pointsType,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
@@ -45,13 +45,16 @@ export function BookingConfirmationProvider({
|
||||
|
||||
let isVatCurrency = true
|
||||
if (totalBookingPoints) {
|
||||
// We can assume all rooms have the same point type
|
||||
const pointsType = rooms?.[0]?.pointsType
|
||||
isVatCurrency = false
|
||||
formattedTotalCost = formatPrice(
|
||||
intl,
|
||||
totalBookingPoints,
|
||||
CurrencyEnum.POINTS,
|
||||
totalBookingPrice,
|
||||
currencyCode
|
||||
currencyCode,
|
||||
pointsType
|
||||
)
|
||||
} else if (totalBookingCheques) {
|
||||
isVatCurrency = false
|
||||
|
||||
@@ -15,7 +15,6 @@ import {
|
||||
} from "./helpers"
|
||||
import { getRoomPrice, getTotalPrice } from "./priceCalculations"
|
||||
|
||||
import type { CurrencyEnum } from "@scandic-hotels/common/constants/currency"
|
||||
import type { Lang } from "@scandic-hotels/common/constants/language"
|
||||
import type { BreakfastPackages } from "@scandic-hotels/trpc/routers/hotels/output"
|
||||
import type { User } from "@scandic-hotels/trpc/types/user"
|
||||
@@ -41,8 +40,7 @@ export function createDetailsStore(
|
||||
searchParams: string,
|
||||
user: User | null,
|
||||
breakfastPackages: BreakfastPackages,
|
||||
lang: Lang,
|
||||
pointsCurrency?: CurrencyEnum
|
||||
lang: Lang
|
||||
) {
|
||||
const isMember = !!user
|
||||
const nights = dt(initialState.booking.toDate).diff(
|
||||
@@ -67,23 +65,14 @@ export function createDetailsStore(
|
||||
...defaultGuestState,
|
||||
phoneNumberCC: getDefaultCountryFromLang(lang),
|
||||
},
|
||||
roomPrice: getRoomPrice(
|
||||
room.roomRate,
|
||||
isMember && idx === 0,
|
||||
pointsCurrency
|
||||
),
|
||||
roomPrice: getRoomPrice(room.roomRate, isMember && idx === 0),
|
||||
specialRequest: {
|
||||
comment: "",
|
||||
},
|
||||
}
|
||||
})
|
||||
|
||||
const initialTotalPrice = getTotalPrice(
|
||||
initialRooms,
|
||||
isMember,
|
||||
nights,
|
||||
pointsCurrency
|
||||
)
|
||||
const initialTotalPrice = getTotalPrice(initialRooms, isMember, nights)
|
||||
|
||||
const availableBeds = initialState.rooms.reduce<
|
||||
DetailsState["availableBeds"]
|
||||
@@ -184,8 +173,7 @@ export function createDetailsStore(
|
||||
state.totalPrice = getTotalPrice(
|
||||
state.rooms.map((r) => r.room),
|
||||
isMember,
|
||||
nights,
|
||||
pointsCurrency
|
||||
nights
|
||||
)
|
||||
|
||||
const isAllStepsCompleted = checkRoomProgress(
|
||||
@@ -216,8 +204,7 @@ export function createDetailsStore(
|
||||
}
|
||||
currentRoom.roomPrice = getRoomPrice(
|
||||
currentRoom.roomRate,
|
||||
isValidMembershipNo || currentRoom.guest.join,
|
||||
pointsCurrency
|
||||
isValidMembershipNo || currentRoom.guest.join
|
||||
)
|
||||
|
||||
const nights = dt(state.booking.toDate).diff(
|
||||
@@ -228,8 +215,7 @@ export function createDetailsStore(
|
||||
state.totalPrice = getTotalPrice(
|
||||
state.rooms.map((r) => r.room),
|
||||
isMember,
|
||||
nights,
|
||||
pointsCurrency
|
||||
nights
|
||||
)
|
||||
|
||||
writeToSessionStorage({
|
||||
@@ -252,8 +238,7 @@ export function createDetailsStore(
|
||||
|
||||
currentRoom.roomPrice = getRoomPrice(
|
||||
currentRoom.roomRate,
|
||||
join || !!currentRoom.guest.membershipNo,
|
||||
pointsCurrency
|
||||
join || !!currentRoom.guest.membershipNo
|
||||
)
|
||||
|
||||
const nights = dt(state.booking.toDate).diff(
|
||||
@@ -264,8 +249,7 @@ export function createDetailsStore(
|
||||
state.totalPrice = getTotalPrice(
|
||||
state.rooms.map((r) => r.room),
|
||||
isMember,
|
||||
nights,
|
||||
pointsCurrency
|
||||
nights
|
||||
)
|
||||
|
||||
writeToSessionStorage({
|
||||
@@ -330,8 +314,7 @@ export function createDetailsStore(
|
||||
|
||||
currentRoom.roomPrice = getRoomPrice(
|
||||
currentRoom.roomRate,
|
||||
Boolean(data.join || data.membershipNo || isMemberAndRoomOne),
|
||||
pointsCurrency
|
||||
Boolean(data.join || data.membershipNo || isMemberAndRoomOne)
|
||||
)
|
||||
|
||||
const nights = dt(state.booking.toDate).diff(
|
||||
@@ -342,8 +325,7 @@ export function createDetailsStore(
|
||||
state.totalPrice = getTotalPrice(
|
||||
state.rooms.map((r) => r.room),
|
||||
isMember,
|
||||
nights,
|
||||
pointsCurrency
|
||||
nights
|
||||
)
|
||||
|
||||
const isAllStepsCompleted = checkRoomProgress(
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import { describe, expect, it } from "vitest"
|
||||
|
||||
import { CurrencyEnum } from "@scandic-hotels/common/constants/currency"
|
||||
import { PointType } from "@scandic-hotels/common/constants/pointType"
|
||||
import { RoomPackageCodeEnum } from "@scandic-hotels/trpc/enums/roomFilter"
|
||||
|
||||
import {
|
||||
@@ -998,16 +999,24 @@ describe("getRedemptionPrice", () => {
|
||||
const result = getRedemptionPrice([], 1)
|
||||
|
||||
expect(result).toEqual({
|
||||
local: { price: 0, currency: CurrencyEnum.POINTS },
|
||||
local: {
|
||||
price: 0,
|
||||
currency: CurrencyEnum.POINTS,
|
||||
pointsType: PointType.SCANDIC,
|
||||
},
|
||||
requested: undefined,
|
||||
})
|
||||
})
|
||||
|
||||
it("returns price 0 and set currency when rooms are empty", () => {
|
||||
const result = getRedemptionPrice([], 1, CurrencyEnum.EUROBONUS)
|
||||
const result = getRedemptionPrice([], 1)
|
||||
|
||||
expect(result).toEqual({
|
||||
local: { price: 0, currency: CurrencyEnum.EUROBONUS },
|
||||
local: {
|
||||
price: 0,
|
||||
currency: CurrencyEnum.POINTS,
|
||||
pointsType: PointType.SCANDIC,
|
||||
},
|
||||
requested: undefined,
|
||||
})
|
||||
})
|
||||
@@ -1026,6 +1035,7 @@ describe("getRedemptionPrice", () => {
|
||||
pointsPerStay: 100,
|
||||
currency: CurrencyEnum.POINTS,
|
||||
additionalPricePerStay: 0,
|
||||
pointsType: PointType.SCANDIC,
|
||||
},
|
||||
},
|
||||
},
|
||||
@@ -1040,6 +1050,7 @@ describe("getRedemptionPrice", () => {
|
||||
currency: CurrencyEnum.POINTS,
|
||||
additionalPrice: 0,
|
||||
additionalPriceCurrency: CurrencyEnum.POINTS,
|
||||
pointsType: PointType.SCANDIC,
|
||||
},
|
||||
requested: undefined,
|
||||
})
|
||||
@@ -1059,6 +1070,7 @@ describe("getRedemptionPrice", () => {
|
||||
pointsPerStay: 100,
|
||||
currency: CurrencyEnum.POINTS,
|
||||
additionalPricePerStay: 0,
|
||||
pointsType: PointType.SCANDIC,
|
||||
},
|
||||
},
|
||||
},
|
||||
@@ -1073,6 +1085,7 @@ describe("getRedemptionPrice", () => {
|
||||
currency: CurrencyEnum.POINTS,
|
||||
additionalPrice: 0,
|
||||
additionalPriceCurrency: CurrencyEnum.POINTS,
|
||||
pointsType: PointType.SCANDIC,
|
||||
},
|
||||
requested: undefined,
|
||||
})
|
||||
@@ -1092,6 +1105,7 @@ describe("getRedemptionPrice", () => {
|
||||
pointsPerStay: 100,
|
||||
currency: CurrencyEnum.POINTS,
|
||||
additionalPricePerStay: 0,
|
||||
pointsType: PointType.SCANDIC,
|
||||
},
|
||||
},
|
||||
},
|
||||
@@ -1106,6 +1120,7 @@ describe("getRedemptionPrice", () => {
|
||||
pointsPerStay: 150,
|
||||
currency: CurrencyEnum.POINTS,
|
||||
additionalPricePerStay: 0,
|
||||
pointsType: PointType.SCANDIC,
|
||||
},
|
||||
},
|
||||
},
|
||||
@@ -1120,6 +1135,7 @@ describe("getRedemptionPrice", () => {
|
||||
currency: CurrencyEnum.POINTS,
|
||||
additionalPrice: 0,
|
||||
additionalPriceCurrency: CurrencyEnum.POINTS,
|
||||
pointsType: PointType.SCANDIC,
|
||||
},
|
||||
requested: undefined,
|
||||
})
|
||||
@@ -1144,6 +1160,7 @@ describe("getRedemptionPrice", () => {
|
||||
pointsPerStay: 100,
|
||||
currency: CurrencyEnum.POINTS,
|
||||
additionalPricePerStay: 0,
|
||||
pointsType: PointType.SCANDIC,
|
||||
},
|
||||
},
|
||||
},
|
||||
@@ -1158,6 +1175,7 @@ describe("getRedemptionPrice", () => {
|
||||
currency: CurrencyEnum.POINTS,
|
||||
additionalPrice: 33,
|
||||
additionalPriceCurrency: CurrencyEnum.POINTS,
|
||||
pointsType: PointType.SCANDIC,
|
||||
},
|
||||
requested: undefined,
|
||||
})
|
||||
@@ -1818,6 +1836,7 @@ describe("getTotalPrice", () => {
|
||||
pointsPerStay: 100,
|
||||
currency: CurrencyEnum.POINTS,
|
||||
additionalPricePerStay: 0,
|
||||
pointsType: PointType.SCANDIC,
|
||||
},
|
||||
},
|
||||
},
|
||||
@@ -1856,6 +1875,7 @@ describe("getTotalPrice", () => {
|
||||
currency: CurrencyEnum.POINTS,
|
||||
additionalPrice: 0,
|
||||
additionalPriceCurrency: CurrencyEnum.POINTS,
|
||||
pointsType: PointType.SCANDIC,
|
||||
},
|
||||
requested: undefined,
|
||||
})
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import { CurrencyEnum } from "@scandic-hotels/common/constants/currency"
|
||||
import { PointType } from "@scandic-hotels/common/constants/pointType"
|
||||
import { RateTypeEnum } from "@scandic-hotels/common/constants/rateType"
|
||||
import { logger } from "@scandic-hotels/common/logger"
|
||||
|
||||
@@ -19,11 +20,7 @@ function add(...nums: (number | string | undefined)[]) {
|
||||
}, 0)
|
||||
}
|
||||
|
||||
export function getRoomPrice(
|
||||
roomRate: Product,
|
||||
isMember: boolean,
|
||||
pointsCurrency?: CurrencyEnum
|
||||
) {
|
||||
export function getRoomPrice(roomRate: Product, isMember: boolean) {
|
||||
if (isMember && "member" in roomRate && roomRate.member) {
|
||||
let publicRate
|
||||
if (
|
||||
@@ -167,23 +164,25 @@ export function getRoomPrice(
|
||||
perNight: {
|
||||
requested: undefined,
|
||||
local: {
|
||||
currency: pointsCurrency ?? CurrencyEnum.POINTS,
|
||||
currency: CurrencyEnum.POINTS,
|
||||
price: roomRate.redemption.localPrice.pointsPerStay,
|
||||
additionalPrice:
|
||||
roomRate.redemption.localPrice.additionalPricePerStay,
|
||||
additionalPriceCurrency:
|
||||
roomRate.redemption.localPrice.currency ?? undefined,
|
||||
pointsType: roomRate.redemption.localPrice.pointsType,
|
||||
},
|
||||
},
|
||||
perStay: {
|
||||
requested: undefined,
|
||||
local: {
|
||||
currency: pointsCurrency ?? CurrencyEnum.POINTS,
|
||||
currency: CurrencyEnum.POINTS,
|
||||
price: roomRate.redemption.localPrice.pointsPerStay,
|
||||
additionalPrice:
|
||||
roomRate.redemption.localPrice.additionalPricePerStay,
|
||||
additionalPriceCurrency:
|
||||
roomRate.redemption.localPrice.currency ?? undefined,
|
||||
pointsType: roomRate.redemption.localPrice.pointsType,
|
||||
},
|
||||
},
|
||||
}
|
||||
@@ -410,17 +409,18 @@ type RedemptionRoom = BasePriceCalculationRoom & {
|
||||
localPrice: {
|
||||
pointsPerStay: number
|
||||
additionalPricePerStay: number
|
||||
pointsType: PointType
|
||||
currency?: CurrencyEnum
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export function getRedemptionPrice(
|
||||
rooms: RedemptionRoom[],
|
||||
nights: number,
|
||||
pointsCurrency?: CurrencyEnum
|
||||
) {
|
||||
export function getRedemptionPrice(rooms: RedemptionRoom[], nights: number) {
|
||||
// We can assume that all rooms have the same pointsType
|
||||
const pointsType =
|
||||
rooms[0]?.roomRate.redemption.localPrice.pointsType || PointType.SCANDIC
|
||||
|
||||
return rooms.reduce<Price>(
|
||||
(total, room) => {
|
||||
const redemption = room.roomRate.redemption
|
||||
@@ -444,8 +444,9 @@ export function getRedemptionPrice(
|
||||
},
|
||||
{
|
||||
local: {
|
||||
currency: pointsCurrency ?? CurrencyEnum.POINTS,
|
||||
currency: CurrencyEnum.POINTS,
|
||||
price: 0,
|
||||
pointsType,
|
||||
},
|
||||
requested: undefined,
|
||||
}
|
||||
@@ -580,8 +581,7 @@ export function getTotalPrice(
|
||||
| VoucherRoom
|
||||
)[],
|
||||
isMember: boolean,
|
||||
nights: number,
|
||||
pointsCurrency?: CurrencyEnum
|
||||
nights: number
|
||||
) {
|
||||
const corporateChequeRooms = rooms.filter(
|
||||
(x): x is CorporateCheckRoom => "corporateCheque" in x.roomRate
|
||||
@@ -594,7 +594,7 @@ export function getTotalPrice(
|
||||
(x): x is RedemptionRoom => "redemption" in x.roomRate
|
||||
)
|
||||
if (redemptionRooms.length > 0) {
|
||||
return getRedemptionPrice(redemptionRooms, nights, pointsCurrency)
|
||||
return getRedemptionPrice(redemptionRooms, nights)
|
||||
}
|
||||
|
||||
const voucherRooms = rooms.filter(
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import type { CurrencyEnum } from "@scandic-hotels/common/constants/currency"
|
||||
import type { PointType } from "@scandic-hotels/common/constants/pointType"
|
||||
|
||||
interface TPrice {
|
||||
additionalPrice?: number
|
||||
@@ -6,6 +7,7 @@ interface TPrice {
|
||||
currency: CurrencyEnum
|
||||
price: number
|
||||
regularPrice?: number
|
||||
pointsType?: PointType | null
|
||||
}
|
||||
|
||||
// TODO after migration, check this type for duplicates and maybe move to better location
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import type { CurrencyEnum } from "@scandic-hotels/common/constants/currency"
|
||||
import type { PointType } from "@scandic-hotels/common/constants/pointType"
|
||||
import type { ChildBedTypeEnum } from "@scandic-hotels/trpc/enums/childBedTypeEnum"
|
||||
import type {
|
||||
BookingConfirmation,
|
||||
@@ -32,6 +33,7 @@ export interface Room {
|
||||
refId: string
|
||||
roomFeatures?: PackageSchema[] | null
|
||||
roomPoints: number
|
||||
pointsType: PointType | null
|
||||
roomPrice: number
|
||||
roomTypeCode: string | null
|
||||
toDate: string
|
||||
|
||||
Reference in New Issue
Block a user