Files
web/packages/booking-flow/lib/components/EnterDetails/PriceChangeDialog/index.tsx
Bianca Widstam 68c1b3dc50 Merged in chore/BOOK-708-replace-title-component (pull request #3414)
Chore/BOOK-708 replace title component

* chore(BOOK-708): replace title with typography

* chore(BOOK-708): replace title with typography

* chore(BOOK-708): remove Title from package.json


Approved-by: Linus Flood
Approved-by: Anton Gunnarsson
2026-01-12 07:54:59 +00:00

171 lines
5.4 KiB
TypeScript

import { Dialog, Modal, ModalOverlay } from "react-aria-components"
import { useIntl } from "react-intl"
import { formatPrice } from "@scandic-hotels/common/utils/numberFormatting"
import Caption from "@scandic-hotels/design-system/Caption"
import { MaterialIcon } from "@scandic-hotels/design-system/Icons/MaterialIcon"
import { OldDSButton as Button } from "@scandic-hotels/design-system/OldDSButton"
import { Typography } from "@scandic-hotels/design-system/Typography"
import { useEnterDetailsStore } from "../../../stores/enter-details"
import { calculateTotalRoomPrice } from "../Payment/helpers"
import PriceChangeSummary from "./PriceChangeSummary"
import styles from "./priceChangeDialog.module.css"
import type { PriceChangeData } from "../PriceChangeData"
type PriceDetailsState = {
newTotalPrice: number
roomPrices: { prevPrice: number; newPrice?: number }[]
}
type PriceChangeDialogProps = {
isOpen: boolean
priceChangeData: PriceChangeData
prevTotalPrice: number
currency: string
onCancel: () => void
onAccept: () => void
}
export default function PriceChangeDialog({
isOpen,
priceChangeData,
prevTotalPrice,
currency,
onCancel,
onAccept,
}: PriceChangeDialogProps) {
const intl = useIntl()
const title = intl.formatMessage({
id: "enterDetails.priceChangeDialog.title",
defaultMessage: "Price change",
})
const rooms = useEnterDetailsStore((state) => state.rooms)
const { newTotalPrice, roomPrices } = rooms.reduce<PriceDetailsState>(
(acc, room, idx) => {
const roomPrice = room.room.roomPrice.perStay.local.price
const priceChange = priceChangeData[idx]
const { totalPrice } = calculateTotalRoomPrice(
room,
priceChange?.roomPrice
)
acc.newTotalPrice += totalPrice
acc.roomPrices.push({
prevPrice: roomPrice,
newPrice: priceChange?.roomPrice,
})
return acc
},
{ newTotalPrice: 0, roomPrices: [] }
)
const roomSelectionMsg = intl.formatMessage(
{
id: "enterDetails.priceChangeDialog.descriptionPreviousRooms",
defaultMessage: "{totalRooms, plural, one {room} other {rooms}}",
},
{
totalRooms: rooms.length,
}
)
const newRoomSelectionMsg = intl.formatMessage(
{
id: "enterDetails.priceChangeDialog.descriptionNewRooms",
defaultMessage:
"{totalRooms, plural, one {a new room} other {new rooms}}",
},
{
totalRooms: rooms.length,
}
)
return (
<ModalOverlay
className={styles.overlay}
isOpen={isOpen}
isKeyboardDismissDisabled
>
<Modal className={styles.modal}>
<Dialog aria-label={title} className={styles.dialog}>
<header className={styles.header}>
<div className={styles.titleContainer}>
<MaterialIcon
icon="info"
size={48}
color="Icon/Interactive/Default"
/>
<Typography variant="Title/sm">
<h3>{title}</h3>
</Typography>
</div>
<Typography variant="Body/Paragraph/mdRegular">
<p style={{ textAlign: "center" }}>
{intl.formatMessage(
{
id: "enterDetails.priceChangeDialog.description",
defaultMessage:
"Prices have increased since you selected your {roomSelection}.{linebreak} To continue your booking, accept the updated price,{linebreak} or go back to select {newRoomSelection}.",
},
{
roomSelection: roomSelectionMsg,
newRoomSelection: newRoomSelectionMsg,
linebreak: <br />,
}
)}
</p>
</Typography>
<div>
<Typography variant="Title/Subtitle/md">
<p style={{ textAlign: "center" }}>
{intl.formatMessage({
id: "enterDetails.priceChangeDialog.newTotalLabel",
defaultMessage: "New total",
})}
</p>
</Typography>
<div className={styles.prices}>
<Caption striked>
{formatPrice(intl, prevTotalPrice, currency)}
</Caption>
<Typography variant="Body/Paragraph/mdBold">
<p style={{ textAlign: "center" }}>
{formatPrice(intl, newTotalPrice, currency)}
</p>
</Typography>
</div>
</div>
<PriceChangeSummary
rooms={rooms}
roomPrices={roomPrices}
newTotalPrice={{ price: newTotalPrice, currency }}
onAccept={onAccept}
onCancel={onCancel}
/>
</header>
<footer className={styles.footer}>
<Button intent="secondary" onClick={onCancel}>
{intl.formatMessage({
id: "enterDetails.priceChangeDialog.cancelButton",
defaultMessage: "Back to room selection",
})}
</Button>
<Button onClick={onAccept}>
{intl.formatMessage({
id: "enterDetails.priceChangeDialog.acceptButton",
defaultMessage: "Continue with new price",
})}
</Button>
</footer>
</Dialog>
</Modal>
</ModalOverlay>
)
}