Feature/select rate vertical data flow * add fix from SW-2666 * use translations for room packages * move types to it's own file * Merge branch 'master' of bitbucket.org:scandic-swap/web into feature/select-rate-vertical-data-flow * merge * feature/select-rate: double rate for campaing rates * revert NODE_ENV check in Cookiebot script * revert testing values * fix(SW-3171): fix all filter selected in price details * fix(SW-3166): multiroom anchoring when changing filter * fix(SW-3172): check hotelType, show correct breakfast message * Merge branch 'feature/select-rate-vertical-data-flow' of bitbucket.org:scandic-swap/web into feature/select-rate-vertical-data-flow * fix: show special needs icons for subsequent roomTypes SW-3167 * fix: Display strike through text when logged in SW-3168 * fix: Reinstate the scrollToView behaviour when selecting a rate SW-3169 * merge * . * PR fixes * fix: don't return notFound() * . * always include defaults for room packages * merge * merge * merge * Remove floating h1 for new select-rate Approved-by: Anton Gunnarsson
155 lines
4.7 KiB
TypeScript
155 lines
4.7 KiB
TypeScript
"use client"
|
|
import { cx } from "class-variance-authority"
|
|
import { useEffect, useRef, useState } 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 { useSelectRateContext } from "@/contexts/SelectRate/SelectRateContext"
|
|
import { useIsUserLoggedIn } from "@/hooks/useIsUserLoggedIn"
|
|
|
|
import { isBookingCodeRate } from "../utils"
|
|
import SummaryContent from "./Content"
|
|
|
|
import styles from "./mobileSummary.module.css"
|
|
|
|
export function MobileSummary() {
|
|
const intl = useIntl()
|
|
const scrollY = useRef(0)
|
|
const [isSummaryOpen, setIsSummaryOpen] = useState(false)
|
|
const isUserLoggedIn = useIsUserLoggedIn()
|
|
|
|
const { selectedRates } = useSelectRateContext()
|
|
|
|
function toggleSummaryOpen() {
|
|
setIsSummaryOpen(!isSummaryOpen)
|
|
}
|
|
|
|
useEffect(() => {
|
|
if (isSummaryOpen) {
|
|
scrollY.current = window.scrollY
|
|
document.body.style.position = "fixed"
|
|
document.body.style.top = `-${scrollY.current}px`
|
|
document.body.style.width = "100%"
|
|
} else {
|
|
document.body.style.position = ""
|
|
document.body.style.top = ""
|
|
document.body.style.width = ""
|
|
window.scrollTo({
|
|
top: scrollY.current,
|
|
left: 0,
|
|
behavior: "instant",
|
|
})
|
|
}
|
|
|
|
return () => {
|
|
document.body.style.position = ""
|
|
document.body.style.top = ""
|
|
document.body.style.width = ""
|
|
}
|
|
}, [isSummaryOpen])
|
|
|
|
const containsBookingCodeRate = selectedRates.rates.find(
|
|
(r) => r && isBookingCodeRate(r)
|
|
)
|
|
const showDiscounted = containsBookingCodeRate || isUserLoggedIn
|
|
|
|
if (!selectedRates.totalPrice) {
|
|
return null
|
|
}
|
|
|
|
const totalRegularPrice = selectedRates.totalPrice.local?.regularPrice
|
|
? selectedRates.totalPrice.local.regularPrice
|
|
: 0
|
|
|
|
const showStrikeThroughPrice =
|
|
totalRegularPrice > selectedRates.totalPrice.local?.price
|
|
|
|
return (
|
|
<div className={styles.wrapper} data-open={isSummaryOpen}>
|
|
<div className={styles.content}>
|
|
<div className={styles.summaryAccordion}>
|
|
<SummaryContent
|
|
isMember={isUserLoggedIn}
|
|
toggleSummaryOpen={toggleSummaryOpen}
|
|
/>
|
|
</div>
|
|
</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({
|
|
defaultMessage: "Total price",
|
|
})}
|
|
</span>
|
|
</Typography>
|
|
<Typography variant="Title/Subtitle/lg">
|
|
<span
|
|
className={cx(styles.price, {
|
|
[styles.discounted]: showDiscounted,
|
|
})}
|
|
>
|
|
{formatPrice(
|
|
intl,
|
|
selectedRates.totalPrice.local.price,
|
|
selectedRates.totalPrice.local.currency,
|
|
selectedRates.totalPrice.local.additionalPrice,
|
|
selectedRates.totalPrice.local.additionalPriceCurrency
|
|
)}
|
|
</span>
|
|
</Typography>
|
|
{showDiscounted &&
|
|
showStrikeThroughPrice &&
|
|
selectedRates.totalPrice.local.regularPrice ? (
|
|
<Typography variant="Body/Paragraph/mdRegular">
|
|
<s className={styles.strikeThroughRate}>
|
|
{formatPrice(
|
|
intl,
|
|
selectedRates.totalPrice.local.regularPrice,
|
|
selectedRates.totalPrice.local.currency
|
|
)}
|
|
</s>
|
|
</Typography>
|
|
) : null}
|
|
|
|
<Typography variant="Body/Supporting text (caption)/smBold">
|
|
<span className={styles.seeDetails}>
|
|
<span>
|
|
{intl.formatMessage({
|
|
defaultMessage: "See details",
|
|
})}
|
|
</span>
|
|
<MaterialIcon
|
|
icon="chevron_right"
|
|
color="CurrentColor"
|
|
size={20}
|
|
/>
|
|
</span>
|
|
</Typography>
|
|
</ButtonRAC>
|
|
<Button
|
|
variant="Primary"
|
|
color="Primary"
|
|
size="Large"
|
|
type="submit"
|
|
typography="Body/Paragraph/mdBold"
|
|
isDisabled={selectedRates.state !== "ALL_SELECTED"}
|
|
>
|
|
{intl.formatMessage({
|
|
defaultMessage: "Continue",
|
|
})}
|
|
</Button>
|
|
</div>
|
|
</div>
|
|
)
|
|
}
|