Merged in feat/BOOK-479-scandic-go-hotels-rm-brf- (pull request #3143)

feat(BOOK-479): Updated breakfast UI for ScandicGo hotels

Approved-by: Erik Tiekstra
This commit is contained in:
Hrishikesh Vaipurkar
2025-11-18 13:03:46 +00:00
parent 93c481fea8
commit 4c0daf8062
23 changed files with 144 additions and 213 deletions

View File

@@ -1,6 +1,5 @@
"use client"
import { useEnterDetailsStore } from "../../../stores/enter-details"
import { SidePanel } from "../../SidePanel"
import SummaryUI from "./UI"
@@ -9,30 +8,9 @@ type Props = {
}
export default function DesktopSummary({ isUserLoggedIn }: Props) {
const toggleSummaryOpen = useEnterDetailsStore(
(state) => state.actions.toggleSummaryOpen
)
const { booking, rooms, totalPrice, vat, defaultCurrency } =
useEnterDetailsStore((state) => ({
booking: state.booking,
rooms: state.rooms,
totalPrice: state.totalPrice,
vat: state.vat,
defaultCurrency: state.defaultCurrency,
}))
return (
<SidePanel variant="summary">
<SummaryUI
booking={booking}
rooms={rooms}
isUserLoggedIn={isUserLoggedIn}
totalPrice={totalPrice}
vat={vat}
toggleSummaryOpen={toggleSummaryOpen}
defaultCurrency={defaultCurrency}
/>
<SummaryUI isUserLoggedIn={isUserLoggedIn} />
</SidePanel>
)
}

View File

@@ -11,22 +11,14 @@ type Props = {
isUserLoggedIn: boolean
}
export default function MobileSummary({ isUserLoggedIn }: Props) {
const { isSummaryOpen, toggleSummaryOpen } = useEnterDetailsStore(
const { rooms, isSummaryOpen, toggleSummaryOpen } = useEnterDetailsStore(
(state) => ({
rooms: state.rooms,
isSummaryOpen: state.isSummaryOpen,
toggleSummaryOpen: state.actions.toggleSummaryOpen,
})
)
const { booking, rooms, totalPrice, vat, defaultCurrency } =
useEnterDetailsStore((state) => ({
booking: state.booking,
rooms: state.rooms,
totalPrice: state.totalPrice,
vat: state.vat,
defaultCurrency: state.defaultCurrency,
}))
const showPromo =
!isUserLoggedIn &&
rooms.length === 1 &&
@@ -52,15 +44,7 @@ export default function MobileSummary({ isUserLoggedIn }: Props) {
<SummaryBottomSheet isUserLoggedIn={isUserLoggedIn}>
<div className={styles.wrapper}>
<SummaryUI
booking={booking}
rooms={rooms}
isUserLoggedIn={isUserLoggedIn}
totalPrice={totalPrice}
vat={vat}
toggleSummaryOpen={toggleSummaryOpen}
defaultCurrency={defaultCurrency}
/>
<SummaryUI isUserLoggedIn={isUserLoggedIn} />
</div>
</SummaryBottomSheet>
</div>

View File

@@ -1,13 +0,0 @@
.entry {
display: flex;
gap: var(--Space-x05);
justify-content: space-between;
}
.textDefault {
color: var(--Text-Default);
}
.uiTextMediumContrast {
color: var(--UI-Text-Medium-contrast);
}

View File

@@ -1,79 +0,0 @@
"use client"
import { useIntl } from "react-intl"
import { formatPrice } from "@scandic-hotels/common/utils/numberFormatting"
import { Typography } from "@scandic-hotels/design-system/Typography"
import styles from "./breakfast.module.css"
import type { BreakfastPackage } from "@scandic-hotels/trpc/routers/hotels/schemas/packages"
interface BreakfastProps {
adults: number
breakfast: BreakfastPackage | false | undefined
breakfastIncluded: boolean
guests: string
nights: number
}
export default function Breakfast({
adults,
breakfast,
breakfastIncluded,
guests,
nights,
}: BreakfastProps) {
const intl = useIntl()
const breakfastBuffet = intl.formatMessage({
id: "common.breakfastBuffet",
defaultMessage: "Breakfast buffet",
})
if (breakfastIncluded || breakfast) {
const price = breakfast
? formatPrice(
intl,
breakfast.localPrice.price * adults * nights,
breakfast.localPrice.currency
)
: intl.formatMessage({
id: "common.included",
defaultMessage: "Included",
})
return (
<div className={styles.entry}>
<div>
<Typography variant="Body/Paragraph/mdRegular">
<p className={styles.textDefault}>{breakfastBuffet}</p>
</Typography>
<Typography variant="Body/Supporting text (caption)/smRegular">
<p className={styles.uiTextMediumContrast}>{guests}</p>
</Typography>
</div>
<Typography variant="Body/Paragraph/mdRegular">
<p className={styles.textDefault}>{price}</p>
</Typography>
</div>
)
}
if (breakfast === false) {
const noBreakfast = intl.formatMessage({
id: "common.noBreakfast",
defaultMessage: "No breakfast",
})
return (
<div className={styles.entry}>
<Typography variant="Body/Paragraph/mdRegular">
<p className={styles.textDefault}>{breakfastBuffet}</p>
</Typography>
<Typography variant="Body/Paragraph/mdRegular">
<p className={styles.textDefault}>{noBreakfast}</p>
</Typography>
</div>
)
}
return null
}

View File

@@ -12,7 +12,7 @@ import { Typography } from "@scandic-hotels/design-system/Typography"
import { ChildBedMapEnum } from "@scandic-hotels/trpc/enums/childBedMapEnum"
import { getRoomFeatureDescription } from "../../../../../utils/getRoomFeatureDescription"
import Breakfast from "./Breakfast"
import { SummaryBreakfast } from "../../../../SummaryBreakfast"
import styles from "./room.module.css"
@@ -26,6 +26,7 @@ interface RoomProps {
nightsCount: number
defaultCurrency: CurrencyEnum
showBookingCodeChip?: boolean
hotelOffersBreakfast?: boolean
}
export default function Room({
@@ -36,6 +37,7 @@ export default function Room({
nightsCount,
defaultCurrency,
showBookingCodeChip = false,
hotelOffersBreakfast = true,
}: RoomProps) {
const intl = useIntl()
const adults = room.adults
@@ -132,6 +134,13 @@ export default function Room({
)
}
const breakfastPrice = room.breakfast
? room.breakfast?.localPrice.price * adults * nightsCount
: room.breakfast
const breakfastCurrency = room.breakfast
? room.breakfast?.localPrice.currency
: null
return (
<>
<div className={styles.room} data-testid={`summary-room-${roomNumber}`}>
@@ -340,12 +349,12 @@ export default function Room({
</Typography>
) : null}
<Breakfast
adults={room.adults}
breakfast={room.breakfast}
<SummaryBreakfast
breakfastIncluded={room.breakfastIncluded}
breakfastPrice={breakfastPrice}
breakfastCurrency={breakfastCurrency}
guests={guests}
nights={nightsCount}
hotelOffersBreakfast={hotelOffersBreakfast}
/>
</div>
{showBookingCodeChip && (

View File

@@ -16,6 +16,7 @@ import Subtitle from "@scandic-hotels/design-system/Subtitle"
import { Typography } from "@scandic-hotels/design-system/Typography"
import useLang from "../../../../hooks/useLang"
import { useEnterDetailsStore } from "../../../../stores/enter-details"
import PriceDetailsModal from "../../../PriceDetailsModal"
import { isBookingCodeRate } from "../../../SelectRate/RoomsContainer/RateSummary/utils"
import SignupPromoDesktop from "../../../SignupPromo/Desktop"
@@ -25,33 +26,33 @@ import { getMemberPrice } from "./utils"
import styles from "./ui.module.css"
import type { RoomState } from "../../../../stores/enter-details/types"
import type { Price } from "../../../../types/price"
import type { DetailsBooking } from "../../../../utils/url"
type EnterDetailsSummaryProps = {
booking: DetailsBooking
isUserLoggedIn: boolean
totalPrice: Price
vat: number
rooms: RoomState[]
toggleSummaryOpen: () => void
defaultCurrency: CurrencyEnum
}
export default function SummaryUI({
booking,
rooms,
totalPrice,
isUserLoggedIn,
vat,
toggleSummaryOpen,
defaultCurrency,
}: EnterDetailsSummaryProps) {
}: {
isUserLoggedIn: boolean
}) {
const intl = useIntl()
const lang = useLang()
const isDesktop = useMediaQuery("(min-width: 1367px)")
const {
booking,
defaultCurrency,
hotelOffersBreakfast,
rooms,
totalPrice,
vat,
toggleSummaryOpen,
} = useEnterDetailsStore((state) => ({
booking: state.booking,
defaultCurrency: state.defaultCurrency,
hotelOffersBreakfast: state.hotelOffersBreakfast,
rooms: state.rooms,
totalPrice: state.totalPrice,
vat: state.vat,
toggleSummaryOpen: state.actions.toggleSummaryOpen,
}))
const nights = dt(booking.toDate).diff(booking.fromDate, "days")
const nightsMsg = intl.formatMessage(
@@ -143,6 +144,7 @@ export default function SummaryUI({
(room.roomRate.rateDefinition.isCampaignRate ||
!!room.roomRate.bookingCode)
}
hotelOffersBreakfast={hotelOffersBreakfast}
/>
))}
@@ -231,6 +233,7 @@ export default function SummaryUI({
totalPrice={totalPrice}
vat={vat}
isCampaignRate={!!containsCampaignRate}
hotelOffersBreakfast={hotelOffersBreakfast}
/>
</div>
</div>