Merged in feat/SW-1943-ancillaries-with-points (pull request #1598)
feat(SW-1943): fix design to pay with points * feat(SW-1943): fix design to pay with points Approved-by: Niclas Edenvin
This commit is contained in:
@@ -9,7 +9,7 @@
|
||||
display: flex;
|
||||
padding: 0 var(--Space-x15);
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
align-items: baseline;
|
||||
}
|
||||
|
||||
.priceButton {
|
||||
|
||||
@@ -0,0 +1,38 @@
|
||||
import { Typography } from "@scandic-hotels/design-system/Typography"
|
||||
|
||||
import styles from "./priceRow.module.css"
|
||||
|
||||
interface PriceRowProps {
|
||||
title: string
|
||||
quantity: number
|
||||
label: string
|
||||
value: string
|
||||
}
|
||||
|
||||
export default function PriceRow({
|
||||
title,
|
||||
quantity,
|
||||
label,
|
||||
value,
|
||||
}: PriceRowProps) {
|
||||
return (
|
||||
<>
|
||||
<div className={styles.column}>
|
||||
<Typography variant="Body/Paragraph/mdBold">
|
||||
<h2>{title}</h2>
|
||||
</Typography>
|
||||
<Typography variant="Body/Paragraph/mdBold">
|
||||
<p>{`X${quantity}`}</p>
|
||||
</Typography>
|
||||
</div>
|
||||
<div className={styles.column}>
|
||||
<Typography variant="Body/Paragraph/mdRegular">
|
||||
<h2>{label}</h2>
|
||||
</Typography>
|
||||
<Typography variant="Body/Paragraph/mdRegular">
|
||||
<h2>{value}</h2>
|
||||
</Typography>
|
||||
</div>
|
||||
</>
|
||||
)
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
.column {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
}
|
||||
@@ -5,6 +5,8 @@ import { Typography } from "@scandic-hotels/design-system/Typography"
|
||||
import Divider from "@/components/TempDesignSystem/Divider"
|
||||
import { formatPrice } from "@/utils/numberFormatting"
|
||||
|
||||
import PriceRow from "./PriceRow"
|
||||
|
||||
import styles from "./priceSummary.module.css"
|
||||
|
||||
import type { Ancillary } from "@/types/components/myPages/myStay/ancillaries"
|
||||
@@ -12,14 +14,16 @@ import type { Ancillary } from "@/types/components/myPages/myStay/ancillaries"
|
||||
interface PriceSummaryProps {
|
||||
totalPrice: number | null
|
||||
totalPoints: number | null
|
||||
totalUnits: number
|
||||
quantityWithPoints: number
|
||||
quantityWithCard: number
|
||||
selectedAncillary: NonNullable<Ancillary["ancillaryContent"][number]>
|
||||
}
|
||||
|
||||
export default function PriceSummary({
|
||||
totalPrice,
|
||||
totalPoints,
|
||||
totalUnits,
|
||||
quantityWithPoints,
|
||||
quantityWithCard,
|
||||
selectedAncillary,
|
||||
}: PriceSummaryProps) {
|
||||
const intl = useIntl()
|
||||
@@ -33,61 +37,48 @@ export default function PriceSummary({
|
||||
</Typography>
|
||||
<Divider color="subtle" />
|
||||
|
||||
<div className={styles.column}>
|
||||
<Typography variant="Body/Paragraph/mdBold">
|
||||
<h2>{selectedAncillary.title}</h2>
|
||||
</Typography>
|
||||
<Typography variant="Body/Paragraph/mdBold">
|
||||
<p>{`X${totalUnits}`}</p>
|
||||
</Typography>
|
||||
</div>
|
||||
|
||||
<div className={styles.column}>
|
||||
<Typography variant="Body/Paragraph/mdRegular">
|
||||
<h2>{intl.formatMessage({ id: "Price including VAT" })}</h2>
|
||||
</Typography>
|
||||
<Typography variant="Body/Paragraph/mdRegular">
|
||||
<h2>
|
||||
{formatPrice(
|
||||
intl,
|
||||
selectedAncillary.price.total,
|
||||
selectedAncillary.price.currency
|
||||
)}
|
||||
</h2>
|
||||
</Typography>
|
||||
</div>
|
||||
{hasTotalPrice && (
|
||||
<PriceRow
|
||||
title={selectedAncillary.title}
|
||||
quantity={quantityWithCard}
|
||||
label={intl.formatMessage({ id: "Price including VAT" })}
|
||||
value={formatPrice(
|
||||
intl,
|
||||
selectedAncillary.price.total,
|
||||
selectedAncillary.price.currency
|
||||
)}
|
||||
/>
|
||||
)}
|
||||
{hasTotalPoints && (
|
||||
<PriceRow
|
||||
title={selectedAncillary.title}
|
||||
quantity={quantityWithPoints}
|
||||
label={intl.formatMessage({ id: "Points" })}
|
||||
value={`${selectedAncillary.points} ${intl.formatMessage({ id: "points" })}`}
|
||||
/>
|
||||
)}
|
||||
<Divider color="subtle" />
|
||||
<div className={styles.column}>
|
||||
<Typography variant="Body/Paragraph/mdRegular">
|
||||
<Typography variant="Body/Paragraph/mdBold">
|
||||
<p>
|
||||
{intl.formatMessage(
|
||||
{ id: "<b>Total price</b> (incl VAT)" },
|
||||
{ b: (str) => <b>{str}</b> }
|
||||
)}
|
||||
{hasTotalPrice
|
||||
? intl.formatMessage({ id: "Total price including VAT" })
|
||||
: intl.formatMessage({ id: "Total points" })}
|
||||
</p>
|
||||
</Typography>
|
||||
<div className={styles.totalPrice}>
|
||||
{hasTotalPoints && (
|
||||
<div>
|
||||
<div>
|
||||
<Divider variant="vertical" color="subtle" />
|
||||
</div>
|
||||
<Typography variant="Body/Paragraph/mdBold">
|
||||
<p>
|
||||
{totalPoints} {intl.formatMessage({ id: "points" })}
|
||||
{hasTotalPrice && "+"}
|
||||
</p>
|
||||
</Typography>
|
||||
</div>
|
||||
)}
|
||||
{hasTotalPrice && (
|
||||
{(hasTotalPoints || hasTotalPrice) && (
|
||||
<Typography variant="Body/Paragraph/mdBold">
|
||||
<p>
|
||||
{formatPrice(
|
||||
intl,
|
||||
totalPrice,
|
||||
selectedAncillary.price.currency
|
||||
)}
|
||||
{hasTotalPrice &&
|
||||
formatPrice(
|
||||
intl,
|
||||
totalPrice,
|
||||
selectedAncillary.price.currency
|
||||
)}
|
||||
{hasTotalPoints && hasTotalPrice && " + "}
|
||||
{hasTotalPoints &&
|
||||
`${totalPoints} ${intl.formatMessage({ id: "points" })}`}
|
||||
</p>
|
||||
</Typography>
|
||||
)}
|
||||
|
||||
@@ -43,44 +43,59 @@ export default function PriceDetails({
|
||||
quantityWithPoints && selectedAncillary?.points
|
||||
? selectedAncillary.points * quantityWithPoints
|
||||
: null
|
||||
const totalUnits = (quantityWithCard ?? 0) + (quantityWithPoints ?? 0)
|
||||
|
||||
const hasTotalPoints = typeof totalPoints === "number"
|
||||
const hasTotalPrice = typeof totalPrice === "number"
|
||||
|
||||
return (
|
||||
<>
|
||||
<div className={styles.totalPrice}>
|
||||
<Typography variant="Body/Paragraph/mdRegular">
|
||||
<p>
|
||||
{intl.formatMessage(
|
||||
{ id: "<b>Total price</b> (incl VAT)" },
|
||||
{ b: (str) => <b>{str}</b> }
|
||||
)}
|
||||
</p>
|
||||
</Typography>
|
||||
{totalPrice !== null && (
|
||||
<div className={styles.totalPriceInclVAT}>
|
||||
<Typography variant="Body/Paragraph/mdBold">
|
||||
<p>
|
||||
{formatPrice(intl, totalPrice, selectedAncillary.price.currency)}
|
||||
</p>
|
||||
<p>{intl.formatMessage({ id: "Total" })}</p>
|
||||
</Typography>
|
||||
)}
|
||||
{totalPoints !== null && (
|
||||
<div>
|
||||
<div>
|
||||
<Divider variant="vertical" color="subtle" />
|
||||
</div>
|
||||
{totalPrice && (
|
||||
<Typography variant="Body/Paragraph/mdRegular">
|
||||
<p>({intl.formatMessage({ id: "Incl. VAT" })})</p>
|
||||
</Typography>
|
||||
)}
|
||||
</div>
|
||||
<div className={styles.totalPriceValue}>
|
||||
{hasTotalPrice && (
|
||||
<Typography variant="Body/Paragraph/mdBold">
|
||||
<p>
|
||||
{totalPoints} {intl.formatMessage({ id: "points" })}
|
||||
{formatPrice(
|
||||
intl,
|
||||
totalPrice,
|
||||
selectedAncillary.price.currency
|
||||
)}
|
||||
</p>
|
||||
</Typography>
|
||||
</div>
|
||||
)}
|
||||
)}
|
||||
{hasTotalPoints && hasTotalPrice && (
|
||||
<Divider variant="vertical" color="subtle" />
|
||||
)}
|
||||
{hasTotalPoints && (
|
||||
<div>
|
||||
<div>
|
||||
<Divider variant="vertical" color="subtle" />
|
||||
</div>
|
||||
<Typography variant="Body/Paragraph/mdBold">
|
||||
<p>
|
||||
{totalPoints} {intl.formatMessage({ id: "points" })}
|
||||
</p>
|
||||
</Typography>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
<Divider color="subtle" />
|
||||
{isPriceDetailsOpen && (
|
||||
<PriceSummary
|
||||
totalPrice={totalPrice}
|
||||
totalPoints={totalPoints}
|
||||
totalUnits={totalUnits}
|
||||
quantityWithCard={quantityWithCard ?? 0}
|
||||
quantityWithPoints={quantityWithPoints ?? 0}
|
||||
selectedAncillary={selectedAncillary}
|
||||
/>
|
||||
)}
|
||||
|
||||
@@ -7,3 +7,14 @@
|
||||
background-color: var(--Base-Surface-Secondary-light-Normal);
|
||||
border-radius: var(--Corner-radius-Medium);
|
||||
}
|
||||
|
||||
.totalPriceInclVAT {
|
||||
display: flex;
|
||||
gap: var(--Space-x05);
|
||||
}
|
||||
|
||||
.totalPriceValue {
|
||||
display: flex;
|
||||
gap: var(--Space-x1);
|
||||
height: 20px;
|
||||
}
|
||||
|
||||
@@ -42,10 +42,9 @@ export default function SelectQuantityStep({ user }: SelectQuantityStepProps) {
|
||||
|
||||
const insufficientPoints = currentPoints < pointsCost || currentPoints === 0
|
||||
|
||||
const pointsLabel =
|
||||
insufficientPoints && user
|
||||
? intl.formatMessage({ id: "Insufficient points" })
|
||||
: intl.formatMessage({ id: "Select quantity" })
|
||||
const pointsLabel = insufficientPoints
|
||||
? intl.formatMessage({ id: "Insufficient points" })
|
||||
: intl.formatMessage({ id: "Select quantity" })
|
||||
|
||||
return (
|
||||
<div className={styles.selectContainer}>
|
||||
|
||||
@@ -57,7 +57,6 @@
|
||||
bottom: 0;
|
||||
z-index: 10;
|
||||
background: var(--Surface-Primary-OnSurface-Default);
|
||||
border-top: 1px solid var(--Base-Border-Normal);
|
||||
padding-bottom: var(--Space-x15);
|
||||
}
|
||||
|
||||
|
||||
@@ -111,6 +111,7 @@ export default function AddAncillaryFlowModal({
|
||||
{ ancillary: selectedAncillary?.title }
|
||||
)
|
||||
)
|
||||
router.refresh()
|
||||
} else {
|
||||
toast.error(ancillaryErrorMessage)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user