Files
web/packages/booking-flow/lib/components/EnterDetails/Summary/Mobile/BottomSheet/index.tsx
Erik Tiekstra 3f632e6031 Merged in fix/BOOK-293-button-variants (pull request #3371)
fix(BOOK-293): changed variants and props on IconButton component

* fix(BOOK-293): changed variants and props on IconButton component

* fix(BOOK-293): inherit color for icon


Approved-by: Bianca Widstam
Approved-by: Christel Westerberg
2025-12-19 12:32:52 +00:00

149 lines
4.5 KiB
TypeScript

"use client"
import { cx } from "class-variance-authority"
import { useSearchParams } from "next/navigation"
import { type PropsWithChildren, useEffect, useRef } from "react"
import { Button as ButtonRAC } from "react-aria-components"
import { useIntl } from "react-intl"
import { formatPrice } from "@scandic-hotels/common/utils/numberFormatting"
import { Button } from "@scandic-hotels/design-system/Button"
import { MaterialIcon } from "@scandic-hotels/design-system/Icons/MaterialIcon"
import { Typography } from "@scandic-hotels/design-system/Typography"
import { useEnterDetailsStore } from "../../../../../stores/enter-details"
import { formId } from "../../../Payment/PaymentClient"
import { isDiscounted } from "../../UI/utils"
import styles from "./bottomSheet.module.css"
type SummaryBottomSheetProps = PropsWithChildren<{
isUserLoggedIn: boolean
}>
export default function SummaryBottomSheet({
children,
isUserLoggedIn,
}: SummaryBottomSheetProps) {
const intl = useIntl()
const scrollY = useRef(0)
const searchParams = useSearchParams()
const errorCode = searchParams.get("errorCode")
const { isSummaryOpen, toggleSummaryOpen, totalPrice, isSubmitting, rooms } =
useEnterDetailsStore((state) => ({
isSummaryOpen: state.isSummaryOpen,
toggleSummaryOpen: state.actions.toggleSummaryOpen,
totalPrice: state.totalPrice,
isSubmitting: state.isSubmitting,
rooms: state.rooms,
}))
useEffect(() => {
if (isSummaryOpen) {
scrollY.current = window.scrollY
document.body.style.position = "fixed"
document.body.style.top = `-${scrollY.current}px`
} else {
document.body.style.position = ""
document.body.style.top = ""
if (!errorCode) {
window.scrollTo({
top: scrollY.current,
left: 0,
behavior: "instant",
})
}
}
return () => {
document.body.style.position = ""
document.body.style.top = ""
}
}, [isSummaryOpen, errorCode])
const showDiscounted =
isUserLoggedIn || rooms.some((room) => isDiscounted(room.room))
return (
<div className={styles.wrapper} data-open={isSummaryOpen}>
<div className={styles.content}>{children}</div>
<div className={styles.bottomSheet}>
<ButtonRAC
data-open={isSummaryOpen}
onPress={toggleSummaryOpen}
className={styles.priceDetailsButton}
>
<Typography variant="Body/Supporting text (caption)/smRegular">
<span className={styles.priceLabel}>
{intl.formatMessage({
id: "common.totalPrice",
defaultMessage: "Total price",
})}
</span>
</Typography>
<Typography variant="Title/Subtitle/lg">
<span
className={cx(styles.price, {
[styles.discounted]: showDiscounted,
})}
>
{formatPrice(
intl,
totalPrice.local.price,
totalPrice.local.currency,
totalPrice.local.additionalPrice,
totalPrice.local.additionalPriceCurrency
)}
</span>
</Typography>
{showDiscounted && totalPrice.local.regularPrice ? (
<Typography variant="Body/Paragraph/mdRegular">
<p>
<s className={styles.strikeThroughRate}>
{formatPrice(
intl,
totalPrice.local.regularPrice,
totalPrice.local.currency
)}
</s>
</p>
</Typography>
) : null}
<Typography variant="Body/Supporting text (caption)/smBold">
<span className={styles.seeDetails}>
<span>
{intl.formatMessage({
id: "booking.seeDetails",
defaultMessage: "See details",
})}
</span>
<MaterialIcon
icon="chevron_right"
color="CurrentColor"
size={20}
/>
</span>
</Typography>
</ButtonRAC>
<Button
variant="Primary"
color="Primary"
size="lg"
type="submit"
isDisabled={isSubmitting}
isPending={isSubmitting}
form={formId}
>
{intl.formatMessage({
id: "enterDetails.completeBooking",
defaultMessage: "Complete booking",
})}
</Button>
</div>
</div>
)
}