Merged in fix/SW-3198-prices-select-rate (pull request #2763)
fix(SW-3198): fix striketrhough/regular prices, the same in enter details as select rate * fix(SW-3198): fix striketrhough/regular prices, the same in enter details as select rate * fix(SW-3198): remove additonalcost if calculating cost per room * fix(SW-3198): include bookingcode in specialrate * fix(SW-3198): remove console log * fix(SW-3198): add or operator * fix(SW-3198): capture total return value * fix(SW-3198): rename and move function Approved-by: Joakim Jäderberg Approved-by: Hrishikesh Vaipurkar
This commit is contained in:
@@ -27,7 +27,9 @@ export default function BoldRow({
|
||||
<td className={styles.price}>
|
||||
{isDiscounted && regularValue ? (
|
||||
<Typography variant="Body/Supporting text (caption)/smRegular">
|
||||
<s className={styles.strikeThroughRate}>{regularValue}</s>
|
||||
<p>
|
||||
<s className={styles.strikeThroughRate}>{regularValue}</s>
|
||||
</p>
|
||||
</Typography>
|
||||
) : null}
|
||||
<Typography variant="Body/Supporting text (caption)/smBold">
|
||||
|
||||
@@ -52,7 +52,9 @@ export default function LargeRow({
|
||||
{isDiscounted && regularPrice ? (
|
||||
<>
|
||||
<Typography variant="Body/Paragraph/mdRegular">
|
||||
<s className={styles.strikeThroughRate}>{regularPrice}</s>
|
||||
<p>
|
||||
<s className={styles.strikeThroughRate}>{regularPrice}</s>
|
||||
</p>
|
||||
</Typography>
|
||||
</>
|
||||
) : null}
|
||||
|
||||
@@ -24,13 +24,13 @@ import styles from "./summaryContent.module.css"
|
||||
import type { Price } from "../../../../../../contexts/SelectRate/getTotalPrice"
|
||||
|
||||
export type SelectRateSummaryProps = {
|
||||
isMember: boolean
|
||||
isUserLoggedIn: boolean
|
||||
bookingCode?: string
|
||||
toggleSummaryOpen: () => void
|
||||
}
|
||||
|
||||
export default function SummaryContent({
|
||||
isMember,
|
||||
isUserLoggedIn,
|
||||
toggleSummaryOpen,
|
||||
}: SelectRateSummaryProps) {
|
||||
const { selectedRates, input } = useSelectRateContext()
|
||||
@@ -61,7 +61,7 @@ export default function SummaryContent({
|
||||
return null
|
||||
}
|
||||
|
||||
const showDiscounted = containsBookingCodeRate || isMember
|
||||
const showDiscounted = containsBookingCodeRate || isUserLoggedIn
|
||||
const totalRegularPrice = selectedRates?.totalPrice?.local?.regularPrice
|
||||
? selectedRates.totalPrice.local.regularPrice
|
||||
: 0
|
||||
@@ -117,7 +117,7 @@ export default function SummaryContent({
|
||||
<Room
|
||||
key={idx}
|
||||
room={mapToRoom({
|
||||
isMember,
|
||||
isUserLoggedIn,
|
||||
rate: room,
|
||||
input,
|
||||
idx,
|
||||
@@ -126,7 +126,7 @@ export default function SummaryContent({
|
||||
})}
|
||||
roomNumber={idx + 1}
|
||||
roomCount={selectedRates.rates.length}
|
||||
isMember={isMember}
|
||||
isMember={isUserLoggedIn && idx === 0}
|
||||
/>
|
||||
)
|
||||
})}
|
||||
@@ -192,13 +192,15 @@ export default function SummaryContent({
|
||||
showStrikeThroughPrice &&
|
||||
selectedRates.totalPrice.local.regularPrice ? (
|
||||
<Typography variant="Body/Paragraph/mdRegular">
|
||||
<s className={styles.strikeThroughRate}>
|
||||
{formatPrice(
|
||||
intl,
|
||||
selectedRates.totalPrice.local.regularPrice,
|
||||
selectedRates.totalPrice.local.currency
|
||||
)}
|
||||
</s>
|
||||
<p>
|
||||
<s className={styles.strikeThroughRate}>
|
||||
{formatPrice(
|
||||
intl,
|
||||
selectedRates.totalPrice.local.regularPrice,
|
||||
selectedRates.totalPrice.local.currency
|
||||
)}
|
||||
</s>
|
||||
</p>
|
||||
</Typography>
|
||||
) : null}
|
||||
</div>
|
||||
@@ -217,7 +219,7 @@ export default function SummaryContent({
|
||||
}
|
||||
|
||||
const mapped = mapToRoom({
|
||||
isMember,
|
||||
isUserLoggedIn,
|
||||
rate: room,
|
||||
input,
|
||||
idx,
|
||||
@@ -231,17 +233,26 @@ export default function SummaryContent({
|
||||
) {
|
||||
switch (room.type) {
|
||||
case "regular":
|
||||
const memberLocalPrice = room.member?.localPrice
|
||||
? {
|
||||
...room.member.localPrice,
|
||||
regularPricePerStay:
|
||||
room.public?.localPrice?.pricePerStay ||
|
||||
room.member.localPrice.regularPricePerStay,
|
||||
}
|
||||
: undefined
|
||||
return {
|
||||
regular:
|
||||
isMember && memberLocalPrice
|
||||
? memberLocalPrice
|
||||
: room.public?.localPrice,
|
||||
}
|
||||
case "campaign":
|
||||
return {
|
||||
regular: isMember
|
||||
? (room.member?.localPrice ?? room.public?.localPrice)
|
||||
: room.public?.localPrice,
|
||||
}
|
||||
case "campaign":
|
||||
return {
|
||||
campaign: isMember
|
||||
? (room.member ?? room.public)
|
||||
: room.public,
|
||||
}
|
||||
case "redemption":
|
||||
return {
|
||||
redemption: room.redemption,
|
||||
@@ -259,10 +270,19 @@ export default function SummaryContent({
|
||||
}
|
||||
}
|
||||
if ("public" in room) {
|
||||
const memberLocalPrice = room.member?.localPrice
|
||||
? {
|
||||
...room.member.localPrice,
|
||||
regularPricePerStay:
|
||||
room.public?.localPrice?.pricePerStay ||
|
||||
room.member.localPrice.regularPricePerStay,
|
||||
}
|
||||
: undefined
|
||||
return {
|
||||
regular: isMember
|
||||
? (room.member?.localPrice ?? room.public?.localPrice)
|
||||
: room.public?.localPrice,
|
||||
regular:
|
||||
isMember && memberLocalPrice
|
||||
? memberLocalPrice
|
||||
: room.public?.localPrice,
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -271,7 +291,7 @@ export default function SummaryContent({
|
||||
}
|
||||
}
|
||||
|
||||
const p = getPrice(room!, isMember)
|
||||
const p = getPrice(room!, isUserLoggedIn && idx === 0)
|
||||
|
||||
return {
|
||||
...mapped,
|
||||
@@ -293,7 +313,7 @@ export default function SummaryContent({
|
||||
vat={selectedRates.vat}
|
||||
/>
|
||||
</div>
|
||||
{!isMember && memberPrice ? (
|
||||
{!isUserLoggedIn && memberPrice ? (
|
||||
<SignupPromoDesktop
|
||||
memberPrice={{
|
||||
amount: memberPrice.localPrice.pricePerStay,
|
||||
@@ -307,14 +327,14 @@ export default function SummaryContent({
|
||||
}
|
||||
|
||||
function mapToRoom({
|
||||
isMember,
|
||||
isUserLoggedIn,
|
||||
rate,
|
||||
input,
|
||||
idx,
|
||||
getPriceForRoom,
|
||||
rateTitles,
|
||||
}: {
|
||||
isMember: boolean
|
||||
isUserLoggedIn: boolean
|
||||
rate: NonNullable<
|
||||
ReturnType<typeof useSelectRateContext>["selectedRates"]["rates"][number]
|
||||
>
|
||||
@@ -323,6 +343,7 @@ function mapToRoom({
|
||||
getPriceForRoom: (roomIndex: number) => Price | null
|
||||
rateTitles: ReturnType<typeof useRateTitles>
|
||||
}) {
|
||||
const useMemberPrice = isUserLoggedIn && idx === 0
|
||||
return {
|
||||
adults: input.data?.booking.rooms[idx].adults || 0,
|
||||
childrenInRoom: input.data?.booking.rooms[idx].childrenInRoom,
|
||||
@@ -335,7 +356,7 @@ function mapToRoom({
|
||||
local: { price: -1, currency: CurrencyEnum.Unknown },
|
||||
},
|
||||
},
|
||||
rateDetails: isMember
|
||||
rateDetails: useMemberPrice
|
||||
? (rate.rateDefinitionMember?.generalTerms ??
|
||||
rate.rateDefinition.generalTerms)
|
||||
: rate.rateDefinition.generalTerms,
|
||||
|
||||
@@ -10,7 +10,6 @@ import { Typography } from "@scandic-hotels/design-system/Typography"
|
||||
import { ChildBedMapEnum } from "@scandic-hotels/trpc/enums/childBedMapEnum"
|
||||
|
||||
import { isBookingCodeRate } from "../../utils"
|
||||
import { getMemberPrice } from "../utils"
|
||||
|
||||
import styles from "./room.module.css"
|
||||
|
||||
@@ -68,9 +67,7 @@ export default function Room({
|
||||
const childBedCrib = childrenBeds?.get(ChildBedMapEnum.IN_CRIB)
|
||||
const childBedExtraBed = childrenBeds?.get(ChildBedMapEnum.IN_EXTRA_BED)
|
||||
|
||||
const memberPrice = getMemberPrice(room.roomRate)
|
||||
const showMemberPrice = !!(isMember && memberPrice && roomNumber === 1)
|
||||
const showDiscounted = isBookingCodeRate(room.roomRate) || showMemberPrice
|
||||
const showDiscounted = isBookingCodeRate(room.roomRate) || isMember
|
||||
|
||||
const adultsMsg = intl.formatMessage(
|
||||
{
|
||||
@@ -130,25 +127,19 @@ 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
|
||||
)}
|
||||
{formatPrice(
|
||||
intl,
|
||||
room.roomPrice.perStay.local.price,
|
||||
room.roomPrice.perStay.local.currency,
|
||||
room.roomPrice.perStay.local.additionalPrice,
|
||||
room.roomPrice.perStay.local.additionalPriceCurrency
|
||||
)}
|
||||
</p>
|
||||
{showDiscounted && room.roomPrice.perStay.local.price ? (
|
||||
{showDiscounted && room.roomPrice.perStay.local.regularPrice ? (
|
||||
<s className={styles.strikeThroughRate}>
|
||||
{formatPrice(
|
||||
intl,
|
||||
room.roomPrice.perStay.local.price,
|
||||
room.roomPrice.perStay.local.regularPrice,
|
||||
room.roomPrice.perStay.local.currency
|
||||
)}
|
||||
</s>
|
||||
|
||||
@@ -61,19 +61,12 @@ export function MobileSummary() {
|
||||
return null
|
||||
}
|
||||
|
||||
const totalRegularPrice = selectedRates.totalPrice.local?.regularPrice
|
||||
? selectedRates.totalPrice.local.regularPrice
|
||||
: 0
|
||||
|
||||
const showStrikeThroughPrice =
|
||||
totalRegularPrice > selectedRates.totalPrice.local?.price
|
||||
|
||||
return (
|
||||
<div className={styles.wrapper} data-open={isSummaryOpen}>
|
||||
<div className={styles.content}>
|
||||
<div className={styles.summaryAccordion}>
|
||||
<SummaryContent
|
||||
isMember={isUserLoggedIn}
|
||||
isUserLoggedIn={isUserLoggedIn}
|
||||
toggleSummaryOpen={toggleSummaryOpen}
|
||||
/>
|
||||
</div>
|
||||
@@ -106,17 +99,17 @@ export function MobileSummary() {
|
||||
)}
|
||||
</span>
|
||||
</Typography>
|
||||
{showDiscounted &&
|
||||
showStrikeThroughPrice &&
|
||||
selectedRates.totalPrice.local.regularPrice ? (
|
||||
{showDiscounted && selectedRates.totalPrice.local?.regularPrice ? (
|
||||
<Typography variant="Body/Paragraph/mdRegular">
|
||||
<s className={styles.strikeThroughRate}>
|
||||
{formatPrice(
|
||||
intl,
|
||||
selectedRates.totalPrice.local.regularPrice,
|
||||
selectedRates.totalPrice.local.currency
|
||||
)}
|
||||
</s>
|
||||
<p>
|
||||
<s className={styles.strikeThroughRate}>
|
||||
{formatPrice(
|
||||
intl,
|
||||
selectedRates.totalPrice.local?.regularPrice,
|
||||
selectedRates.totalPrice.local.currency
|
||||
)}
|
||||
</s>
|
||||
</p>
|
||||
</Typography>
|
||||
) : null}
|
||||
|
||||
|
||||
@@ -1,13 +0,0 @@
|
||||
import type { Product } from "@scandic-hotels/trpc/types/roomAvailability"
|
||||
|
||||
export function getMemberPrice(roomRate: Product) {
|
||||
if ("member" in roomRate && roomRate.member) {
|
||||
return {
|
||||
amount: roomRate.member.localPrice.pricePerStay,
|
||||
currency: roomRate.member.localPrice.currency,
|
||||
pricePerNight: roomRate.member.localPrice.pricePerNight,
|
||||
}
|
||||
}
|
||||
|
||||
return null
|
||||
}
|
||||
@@ -230,7 +230,7 @@ export function SelectRateProvider({
|
||||
rate,
|
||||
roomConfiguration: roomAvailability[ix]?.[0],
|
||||
})),
|
||||
useMemberPrices: isUserLoggedIn,
|
||||
isMember: isUserLoggedIn,
|
||||
})
|
||||
|
||||
const getPriceForRoom = useCallback(
|
||||
@@ -249,7 +249,8 @@ export function SelectRateProvider({
|
||||
selectedRates: [
|
||||
{ rate, roomConfiguration: roomAvailability[roomIndex]?.[0] },
|
||||
],
|
||||
useMemberPrices: isUserLoggedIn,
|
||||
isMember: isUserLoggedIn && roomIndex === 0,
|
||||
addAdditionalCost: false,
|
||||
})
|
||||
},
|
||||
[selectedRates, roomAvailability, isUserLoggedIn]
|
||||
|
||||
@@ -6,7 +6,7 @@ describe("getTotalPrice", () => {
|
||||
it("should return null when no rates are selected", () => {
|
||||
const result = getTotalPrice({
|
||||
selectedRates: [],
|
||||
useMemberPrices: false,
|
||||
isMember: false,
|
||||
})
|
||||
|
||||
expect(result).toEqual({
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import { CurrencyEnum } from "@scandic-hotels/common/constants/currency"
|
||||
|
||||
import { sumPackages } from "../../utils/SelectRate"
|
||||
import { calculateRegularPrice } from "../../utils/calculateRegularPrice"
|
||||
import { sumPackages, sumPackagesRequestedPrice } from "../../utils/SelectRate"
|
||||
|
||||
import type { RedemptionProduct } from "@scandic-hotels/trpc/types/roomAvailability"
|
||||
|
||||
@@ -26,10 +27,12 @@ type SelectedRate = {
|
||||
|
||||
export function getTotalPrice({
|
||||
selectedRates,
|
||||
useMemberPrices,
|
||||
isMember,
|
||||
addAdditionalCost = true,
|
||||
}: {
|
||||
selectedRates: Array<SelectedRate | null>
|
||||
useMemberPrices: boolean
|
||||
isMember: boolean
|
||||
addAdditionalCost?: boolean
|
||||
}): Price | null {
|
||||
const mainRoom = selectedRates[0]
|
||||
const mainRoomRate = mainRoom?.rate
|
||||
@@ -42,7 +45,7 @@ export function getTotalPrice({
|
||||
}
|
||||
|
||||
if (!mainRoomRate) {
|
||||
return calculateTotalPrice(summaryArray, useMemberPrices)
|
||||
return calculateTotalPrice(summaryArray, isMember, addAdditionalCost)
|
||||
}
|
||||
|
||||
// In case of reward night (redemption) or voucher only single room booking is supported by business rules
|
||||
@@ -59,14 +62,15 @@ export function getTotalPrice({
|
||||
return voucherPrice
|
||||
}
|
||||
|
||||
return calculateTotalPrice(summaryArray, useMemberPrices)
|
||||
return calculateTotalPrice(summaryArray, isMember, addAdditionalCost)
|
||||
}
|
||||
|
||||
function calculateTotalPrice(
|
||||
selectedRateSummary: OneLevelNonNullable<SelectedRate>[],
|
||||
useMemberPrices: boolean
|
||||
isMember: boolean,
|
||||
addAdditionalCost: boolean
|
||||
) {
|
||||
return selectedRateSummary.reduce<Price>(
|
||||
const totalPrice = selectedRateSummary.reduce<Price>(
|
||||
(total, room, idx) => {
|
||||
if (!room.rate || !("member" in room.rate) || !("public" in room.rate)) {
|
||||
return total
|
||||
@@ -75,34 +79,25 @@ function calculateTotalPrice(
|
||||
const roomNr = idx + 1
|
||||
const isMainRoom = roomNr === 1
|
||||
|
||||
const useMemberRate = isMainRoom && useMemberPrices && room.rate.member
|
||||
const useMemberRate = isMainRoom && isMember && room.rate.member
|
||||
const rate = useMemberRate ? room.rate.member : room.rate.public
|
||||
const publicRate = room.rate.public
|
||||
const memberRate = room.rate.member
|
||||
|
||||
if (!rate) {
|
||||
return total
|
||||
}
|
||||
|
||||
const packagesPrice = room.roomConfiguration?.selectedPackages.reduce(
|
||||
(total, pkg) => {
|
||||
total.local = total.local + pkg.localPrice.totalPrice
|
||||
if (pkg.requestedPrice.totalPrice) {
|
||||
total.requested = total.requested + pkg.requestedPrice.totalPrice
|
||||
}
|
||||
return total
|
||||
},
|
||||
{ local: 0, requested: 0 }
|
||||
)
|
||||
const packagesPrice = addAdditionalCost
|
||||
? sumPackages(room.roomConfiguration?.selectedPackages)
|
||||
: { price: 0, currency: undefined }
|
||||
const packagesRequestedPrice = addAdditionalCost
|
||||
? sumPackagesRequestedPrice(room.roomConfiguration?.selectedPackages)
|
||||
: { price: 0, currency: undefined }
|
||||
|
||||
total.local.currency = rate.localPrice.currency
|
||||
total.local.price =
|
||||
total.local.price + rate.localPrice.pricePerStay + packagesPrice.local
|
||||
|
||||
if (rate.localPrice.regularPricePerStay) {
|
||||
total.local.regularPrice =
|
||||
(total.local.regularPrice || 0) +
|
||||
rate.localPrice.regularPricePerStay +
|
||||
packagesPrice.local
|
||||
}
|
||||
total.local.price + rate.localPrice.pricePerStay + packagesPrice.price
|
||||
|
||||
if (rate.requestedPrice) {
|
||||
if (!total.requested) {
|
||||
@@ -119,17 +114,33 @@ function calculateTotalPrice(
|
||||
total.requested.price =
|
||||
total.requested.price +
|
||||
rate.requestedPrice.pricePerStay +
|
||||
packagesPrice.requested
|
||||
packagesRequestedPrice.price
|
||||
|
||||
if (rate.requestedPrice.regularPricePerStay) {
|
||||
total.requested.regularPrice =
|
||||
(total.requested.regularPrice || 0) +
|
||||
rate.requestedPrice.regularPricePerStay +
|
||||
packagesPrice.requested
|
||||
packagesRequestedPrice.price
|
||||
}
|
||||
}
|
||||
return calculateRegularPrice({
|
||||
total,
|
||||
useMemberRate: !!useMemberRate,
|
||||
regularMemberPrice: memberRate
|
||||
? {
|
||||
pricePerStay: memberRate.localPrice.pricePerNight,
|
||||
regularPricePerStay: memberRate.localPrice.regularPricePerStay,
|
||||
}
|
||||
: undefined,
|
||||
regularPublicPrice: publicRate
|
||||
? {
|
||||
pricePerStay: publicRate.localPrice.pricePerNight,
|
||||
regularPricePerStay: publicRate.localPrice.regularPricePerStay,
|
||||
}
|
||||
: undefined,
|
||||
|
||||
return total
|
||||
additionalCost: packagesPrice.price,
|
||||
})
|
||||
},
|
||||
{
|
||||
local: {
|
||||
@@ -140,6 +151,15 @@ function calculateTotalPrice(
|
||||
requested: undefined,
|
||||
}
|
||||
)
|
||||
|
||||
if (
|
||||
totalPrice.local.regularPrice &&
|
||||
totalPrice.local.price >= totalPrice.local.regularPrice
|
||||
) {
|
||||
totalPrice.local.regularPrice = undefined
|
||||
}
|
||||
|
||||
return totalPrice
|
||||
}
|
||||
|
||||
function calculateRedemptionTotalPrice(
|
||||
@@ -196,6 +216,7 @@ function calculateVoucherPrice(
|
||||
local: {
|
||||
currency: CurrencyEnum.Voucher,
|
||||
price: 0,
|
||||
regularPrice: undefined,
|
||||
},
|
||||
requested: undefined,
|
||||
}
|
||||
|
||||
78
packages/booking-flow/lib/utils/calculateRegularPrice.ts
Normal file
78
packages/booking-flow/lib/utils/calculateRegularPrice.ts
Normal file
@@ -0,0 +1,78 @@
|
||||
import type { Price } from "../types/price"
|
||||
|
||||
type RegularPrice = {
|
||||
pricePerStay: number
|
||||
regularPricePerStay?: number
|
||||
}
|
||||
|
||||
// Helper function to calculate regular/strikethrough price
|
||||
export function calculateRegularPrice({
|
||||
total,
|
||||
useMemberRate,
|
||||
regularMemberPrice,
|
||||
regularPublicPrice,
|
||||
additionalCost = 0,
|
||||
}: {
|
||||
total: Price
|
||||
useMemberRate: boolean
|
||||
regularMemberPrice: RegularPrice | undefined
|
||||
regularPublicPrice: RegularPrice | undefined
|
||||
additionalCost?: number
|
||||
}) {
|
||||
if (
|
||||
!total ||
|
||||
(!useMemberRate && !regularPublicPrice) ||
|
||||
(useMemberRate && !regularMemberPrice)
|
||||
) {
|
||||
return total
|
||||
}
|
||||
|
||||
let basePrice = 0
|
||||
// Legend:
|
||||
// - total.local.price = Total Price = Black price, what the user pays
|
||||
// - total.local.regularPrice = Regular Price = Strikethrough price (could potentially be none)
|
||||
// - total.requested.price = Requested Price = EUR approx price
|
||||
|
||||
// We sometimes don't get all the required data to calculate the correct strikethrough total.
|
||||
// Therefore we try these different approach to get a number that is close
|
||||
// enough to the real number if all data would've been present.
|
||||
|
||||
if (useMemberRate && regularMemberPrice) {
|
||||
if (regularPublicPrice) {
|
||||
// #1 Member price uses public price as strikethrough
|
||||
basePrice = regularPublicPrice.pricePerStay
|
||||
} else if (regularMemberPrice.regularPricePerStay) {
|
||||
// #2 Member price uses member regular price as strikethrough
|
||||
basePrice = regularMemberPrice.regularPricePerStay
|
||||
} else {
|
||||
// #3 Member price uses member price as strikethrough
|
||||
basePrice = regularMemberPrice.pricePerStay
|
||||
}
|
||||
} else if (regularPublicPrice) {
|
||||
if (regularPublicPrice.regularPricePerStay) {
|
||||
// #1 Public price uses public regular price as strikethrough
|
||||
basePrice = regularPublicPrice.regularPricePerStay
|
||||
} else {
|
||||
// #2 Public price uses public price as strikethrough
|
||||
basePrice = regularPublicPrice.pricePerStay
|
||||
}
|
||||
}
|
||||
|
||||
total.local.regularPrice = add(
|
||||
total.local.regularPrice,
|
||||
basePrice,
|
||||
additionalCost
|
||||
)
|
||||
return total
|
||||
}
|
||||
|
||||
//copied from enter-details/helpers.ts
|
||||
export function add(...nums: (number | string | undefined)[]) {
|
||||
return nums.reduce((total: number, num) => {
|
||||
if (typeof num === "undefined") {
|
||||
num = 0
|
||||
}
|
||||
total = total + parseInt(`${num}`)
|
||||
return total
|
||||
}, 0)
|
||||
}
|
||||
@@ -62,6 +62,7 @@
|
||||
"./utils/isSameBooking": "./lib/utils/isSameBooking.ts",
|
||||
"./utils/url": "./lib/utils/url.ts",
|
||||
"./utils/SelectRate": "./lib/utils/SelectRate/index.tsx",
|
||||
"./utils/calculateRegularPrice": "./lib/utils/calculateRegularPrice.ts",
|
||||
"./utils/nuqs": "./lib/utils/nuqs.ts"
|
||||
},
|
||||
"dependencies": {
|
||||
|
||||
Reference in New Issue
Block a user