chore(BOOK-701): replace subtitle with typography * chore(BOOK-701): replace subtitle with typography * chore(BOOK-701): align center * chore(BOOK-701): change token * chore(BOOK-701): change text color * fix(BOOK-704): revert pricechange dialog changes * chore(BOOK-701): remove subtitle from package.json Approved-by: Matilda Landström
177 lines
5.5 KiB
TypeScript
177 lines
5.5 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 Title from "@scandic-hotels/design-system/Title"
|
|
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"
|
|
/>
|
|
<Title
|
|
level="h1"
|
|
as="h3"
|
|
textAlign="center"
|
|
textTransform="uppercase"
|
|
>
|
|
{title}
|
|
</Title>
|
|
</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>
|
|
)
|
|
}
|