Merged in feat/BOOK-485-campaign-rate-my-stay (pull request #3120)

feat(BOOK-485): add campaign tag on my stay and update design

* feat(BOOK-485): add campaign tag on my stay and update design

* feat(BOOK-485): update rightAligned


Approved-by: Erik Tiekstra
This commit is contained in:
Bianca Widstam
2025-11-12 08:19:24 +00:00
parent c8cc4138b5
commit 2c044de187
12 changed files with 102 additions and 186 deletions

View File

@@ -37,6 +37,7 @@ export default function PriceDetails() {
totalPrice={totalPrice}
vat={bookedRoom.vatPercentage}
defaultCurrency={bookedRoom.currencyCode}
isCampaignRate={bookedRoom.isCampaignRate}
/>
</div>
)

View File

@@ -1,5 +1,9 @@
.row {
align-items: center;
display: flex;
align-items: center;
justify-content: space-between;
&.rightAligned {
justify-content: flex-end;
}
}

View File

@@ -1,8 +1,8 @@
"use client"
import { cx } from "class-variance-authority"
import { useIntl } from "react-intl"
import IconChip from "@scandic-hotels/design-system/IconChip"
import DiscountIcon from "@scandic-hotels/design-system/Icons/DiscountIcon"
import { BookingCodeChip } from "@scandic-hotels/design-system/BookingCodeChip"
import { Typography } from "@scandic-hotels/design-system/Typography"
import { useMyStayStore } from "@/stores/my-stay"
@@ -11,31 +11,40 @@ import styles from "./bookingCode.module.css"
export default function BookingCode() {
const intl = useIntl()
const bookingCode = useMyStayStore((state) => state.bookedRoom.bookingCode)
const { bookingCode, isCampaignRate } = useMyStayStore((state) => ({
bookingCode: state.bookedRoom.bookingCode,
isCampaignRate: state.bookedRoom.isCampaignRate,
}))
if (!bookingCode) {
if (!bookingCode && !isCampaignRate) {
return null
}
return (
<div className={styles.row}>
<Typography variant="Body/Supporting text (caption)/smRegular">
<p>
{intl.formatMessage({
id: "booking.bookingCode",
defaultMessage: "Booking code",
})}
</p>
</Typography>
const codeType = isCampaignRate
? intl.formatMessage({
id: "booking.campaignCode",
defaultMessage: "Campaign code",
})
: intl.formatMessage({
id: "booking.bookingCode",
defaultMessage: "Booking code",
})
<IconChip
color="blue"
icon={<DiscountIcon color="Icon/Feedback/Information" />}
>
const showCodeType = bookingCode || !isCampaignRate
return (
<div className={cx(styles.row, { [styles.rightAligned]: !showCodeType })}>
{showCodeType && (
<Typography variant="Body/Supporting text (caption)/smRegular">
<span>{bookingCode}</span>
<p>{codeType}</p>
</Typography>
</IconChip>
)}
<BookingCodeChip
bookingCode={bookingCode}
isCampaign={isCampaignRate}
withText={!showCodeType}
/>
</div>
)
}

View File

@@ -1,42 +0,0 @@
"use client"
import { useIntl } from "react-intl"
import IconChip from "@scandic-hotels/design-system/IconChip"
import DiscountIcon from "@scandic-hotels/design-system/Icons/DiscountIcon"
import { Typography } from "@scandic-hotels/design-system/Typography"
import { useMyStayStore } from "@/stores/my-stay"
export default function BookingCode() {
const intl = useIntl()
const bookingCode = useMyStayStore((state) => state.bookedRoom.bookingCode)
if (!bookingCode) {
return null
}
return (
<Typography variant="Body/Supporting text (caption)/smBold">
<IconChip
color="blue"
icon={<DiscountIcon color="Icon/Feedback/Information" />}
>
{intl.formatMessage(
{
id: "booking.bookingCodeWithValue",
defaultMessage: "<strong>Booking code</strong>: {value}",
},
{
value: bookingCode,
strong: (text) => (
<Typography variant="Body/Supporting text (caption)/smBold">
<strong>{text}</strong>
</Typography>
),
}
)}
</IconChip>
</Typography>
)
}

View File

@@ -1,12 +1,19 @@
import BookingCode from "./BookingCode"
import { BookingCodeChip } from "@scandic-hotels/design-system/BookingCodeChip"
import { useMyStayStore } from "@/stores/my-stay"
import PriceDetails from "./PriceDetails"
import styles from "./information.module.css"
export default function BookingInformation() {
const { bookingCode, isCampaignRate } = useMyStayStore((state) => ({
bookingCode: state.bookedRoom.bookingCode,
isCampaignRate: state.bookedRoom.isCampaignRate,
}))
return (
<div className={styles.bookingInformation}>
<BookingCode />
<BookingCodeChip bookingCode={bookingCode} isCampaign={isCampaignRate} />
<PriceDetails />
</div>
)

View File

@@ -138,6 +138,7 @@ export function mapRoomDetails({
return {
...booking,
isCampaignRate: booking.rateDefinition.isCampaignRate,
bedType: {
description: room?.bedType.mainBed.description ?? "",
roomTypeCode: room?.bedType.code ?? "",

View File

@@ -7,8 +7,8 @@ import { dt } from "@scandic-hotels/common/dt"
import { formatPrice } from "@scandic-hotels/common/utils/numberFormatting"
import Accordion from "@scandic-hotels/design-system/Accordion"
import AccordionItem from "@scandic-hotels/design-system/Accordion/AccordionItem"
import { BookingCodeChip } from "@scandic-hotels/design-system/BookingCodeChip"
import IconChip from "@scandic-hotels/design-system/IconChip"
import DiscountIcon from "@scandic-hotels/design-system/Icons/DiscountIcon"
import { MaterialIcon } from "@scandic-hotels/design-system/Icons/MaterialIcon"
import ImageGallery from "@scandic-hotels/design-system/ImageGallery"
import { Typography } from "@scandic-hotels/design-system/Typography"
@@ -422,29 +422,10 @@ export default function BookedRoomSidePeekContent({
</div>
</div>
</div>
{bookingCode && (
<Typography variant="Body/Supporting text (caption)/smBold">
<IconChip
color="blue"
icon={<DiscountIcon color="Icon/Feedback/Information" />}
>
{intl.formatMessage(
{
id: "booking.bookingCodeWithValue",
defaultMessage: "<strong>Booking code</strong>: {value}",
},
{
value: bookingCode,
strong: (text) => (
<Typography variant="Body/Supporting text (caption)/smBold">
<strong>{text}</strong>
</Typography>
),
}
)}
</IconChip>
</Typography>
)}
<BookingCodeChip
bookingCode={bookingCode}
isCampaign={rateDefinition.isCampaignRate}
/>
<GuestDetails
refId={refId}

View File

@@ -18,6 +18,7 @@ export type Room = Omit<
BookingConfirmation["booking"],
"packages" | "roomPrice"
> & {
isCampaignRate: boolean
bedType: BedTypeSchema
breakfast: Omit<BreakfastPackage, "requestedPrice"> | undefined | false
breakfastChildren: Omit<BreakfastPackage, "requestedPrice"> | null