Merged in feat/SW-1719-strikethrough-rates (pull request #2266)

Feat/SW-1719 strikethrough rates

* feat(SW-1719): Strikethrough rate if logged in on regular rate cards

* feat(SW-1719): Strikethrough rate if logged in on rate summary

* feat(SW-1719): Strikethrough rate if logged in on mobile rate summary

* feat(SW-1719): Strikethrough rate if logged in on enter details

* feat(SW-1719): Strikethrough rate support for multiple rooms

* feat(SW-1719): booking receipt fixes on confirmation page

* feat(SW-1719): improve initial total price calculation

* feat: harmonize enter details total price to use one and the same function


Approved-by: Michael Zetterberg
This commit is contained in:
Simon.Emanuelsson
2025-06-13 12:01:16 +00:00
committed by Michael Zetterberg
parent e1ede52014
commit 85acd3453d
52 changed files with 2403 additions and 1380 deletions

View File

@@ -1,3 +1,5 @@
import { cx } from "class-variance-authority"
import { Typography } from "@scandic-hotels/design-system/Typography"
import styles from "./row.module.css"
@@ -5,9 +7,16 @@ import styles from "./row.module.css"
interface RowProps {
label: string
value: string
regularValue?: string
isDiscounted?: boolean
}
export default function BoldRow({ label, value }: RowProps) {
export default function BoldRow({
label,
value,
regularValue,
isDiscounted = false,
}: RowProps) {
return (
<tr className={styles.row}>
<td>
@@ -16,8 +25,15 @@ export default function BoldRow({ label, value }: RowProps) {
</Typography>
</td>
<td className={styles.price}>
{isDiscounted && regularValue ? (
<Typography variant="Body/Supporting text (caption)/smRegular">
<s className={styles.strikeThroughRate}>{regularValue}</s>
</Typography>
) : null}
<Typography variant="Body/Supporting text (caption)/smBold">
<span>{value}</span>
<span className={cx({ [styles.discounted]: isDiscounted })}>
{value}
</span>
</Typography>
</td>
</tr>

View File

@@ -1,51 +0,0 @@
"use client"
import { useIntl } from "react-intl"
import { Typography } from "@scandic-hotels/design-system/Typography"
import Caption from "@/components/TempDesignSystem/Text/Caption"
import { formatPrice } from "@/utils/numberFormatting"
import styles from "./row.module.css"
import type { CurrencyEnum } from "@/types/enums/currency"
import type { Package } from "@/types/requests/packages"
interface DiscountedRegularPriceRowProps {
currency: CurrencyEnum
packages: Package[]
regularPrice?: number
}
export default function DiscountedRegularPriceRow({
currency,
packages,
regularPrice,
}: DiscountedRegularPriceRowProps) {
const intl = useIntl()
if (!regularPrice) {
return null
}
const totalPackagesPrice = packages.reduce(
(total, pkg) => total + pkg.localPrice.totalPrice,
0
)
const price = formatPrice(intl, regularPrice + totalPackagesPrice, currency)
return (
<tr className={styles.row}>
<td></td>
<td className={styles.price}>
<Typography variant="Body/Supporting text (caption)/smRegular">
<span>
<s>{price}</s>
</span>
</Typography>
<Caption color="uiTextMediumContrast" striked></Caption>
</td>
</tr>
)
}

View File

@@ -1,25 +1,66 @@
import { cx } from "class-variance-authority"
import { useIntl } from "react-intl"
import { Typography } from "@scandic-hotels/design-system/Typography"
import { formatPrice } from "@/utils/numberFormatting"
import styles from "./row.module.css"
import type { Price } from "@/types/components/hotelReservation/price"
interface RowProps {
allPricesIsDiscounted: boolean
label: string
value: string
price: Price
}
export default function LargeRow({ label, value }: RowProps) {
export default function LargeRow({
allPricesIsDiscounted,
label,
price,
}: RowProps) {
const intl = useIntl()
const totalPrice = formatPrice(
intl,
price.local.price,
price.local.currency,
price.local.additionalPrice,
price.local.additionalPriceCurrency
)
const regularPrice = price.local.regularPrice
? formatPrice(
intl,
price.local.regularPrice,
price.local.currency,
price.local.additionalPrice,
price.local.additionalPriceCurrency
)
: null
const isDiscounted =
allPricesIsDiscounted ||
(price.local.regularPrice !== undefined &&
price.local.regularPrice > price.local.price)
return (
<tr className={styles.row}>
<td>
<Typography variant="Body/Paragraph/mdBold">
<Typography variant="Body/Paragraph/mdBold">
<tr className={styles.row}>
<td>
<span>{label}</span>
</Typography>
</td>
<td className={styles.price}>
<Typography variant="Body/Paragraph/mdBold">
<span>{value}</span>
</Typography>
</td>
</tr>
</td>
<td className={styles.price}>
{isDiscounted && regularPrice ? (
<>
<Typography variant="Body/Paragraph/mdRegular">
<s className={styles.strikeThroughRate}>{regularPrice}</s>
</Typography>
</>
) : null}
<span className={cx({ [styles.discounted]: isDiscounted })}>
{totalPrice}
</span>
</td>
</tr>
</Typography>
)
}

View File

@@ -16,15 +16,18 @@ export interface RegularPriceType {
currency: CurrencyEnum
pricePerNight: number
pricePerStay: number
regularPricePerStay: number
}
}
interface RegularPriceProps extends SharedPriceRowProps {
isMemberRate: boolean
price: RegularPriceType["regular"]
}
export default function RegularPrice({
bedType,
isMemberRate,
nights,
packages,
price,
@@ -47,11 +50,21 @@ export default function RegularPrice({
const roomCharge = formatPrice(intl, price.pricePerStay, price.currency)
const regularPriceIsHigherThanPrice =
price.regularPricePerStay > price.pricePerStay
let regularCharge = undefined
if (regularPriceIsHigherThanPrice) {
regularCharge = formatPrice(intl, price.regularPricePerStay, price.currency)
}
const isDiscounted = isMemberRate || regularPriceIsHigherThanPrice
return (
<>
<BoldRow
label={intl.formatMessage({ defaultMessage: "Room charge" })}
value={roomCharge}
regularValue={regularCharge}
isDiscounted={isDiscounted}
/>
{nights > 1 ? (
<RegularRow label={averagePriceTitle} value={avgeragePricePerNight} />

View File

@@ -1,8 +1,21 @@
.row {
display: flex;
justify-content: space-between;
color: var(--Text-Default);
}
.price {
text-align: end;
display: flex;
align-items: center;
gap: var(--Space-x1);
}
.discounted {
color: var(--Text-Accent-Primary);
}
.price .strikeThroughRate {
text-decoration: line-through;
color: var(--Text-Secondary);
}