Files
web/components/HotelReservation/SelectRate/RateSummary/MobileSummary/index.tsx
Tobias Johansson b394d54c3f Merged in feat/enter-details-multiroom (pull request #1280)
feat(SW-1259): Enter details multiroom

* refactor: remove per-step URLs

* WIP: map multiroom data

* fix: lint errors in details page

* fix: made useEnterDetailsStore tests pass

* fix: WIP refactor enter details store

* fix: WIP enter details store update

* fix: added room index to select correct room

* fix: added logic for navigating between steps and rooms

* fix: update summary to work with store changes

* fix: added room and total price calculation

* fix: removed unused code and added test for breakfast included

* refactor: move store selectors into helpers

* refactor: session storage state for multiroom booking

* feat: update enter details accordion navigation

* fix: added room index to each form component so they select correct room

* fix: added unique id to input to handle case when multiple inputs have same name

* fix: update payment step with store changes

* fix: rebase issues

* fix: now you should only be able to go to a step if previous room is completed

* refactor: cleanup

* fix: if no availability just skip that room for now

* fix: add select-rate Summary and adjust typings


Approved-by: Arvid Norlin
2025-02-11 14:24:24 +00:00

146 lines
4.0 KiB
TypeScript

import { useEffect, useRef } from "react"
import { useIntl } from "react-intl"
import { useRateSelectionStore } from "@/stores/select-rate/rate-selection"
import Button from "@/components/TempDesignSystem/Button"
import Caption from "@/components/TempDesignSystem/Text/Caption"
import Subtitle from "@/components/TempDesignSystem/Text/Subtitle"
import { formatPrice } from "@/utils/numberFormatting"
import Summary from "./Summary"
import styles from "./mobileSummary.module.css"
import type { MobileSummaryProps } from "@/types/components/hotelReservation/selectRate/rateSummary"
export default function MobileSummary({
totalPriceToShow,
isAllRoomsSelected,
booking,
isUserLoggedIn,
vat,
roomsAvailability,
}: MobileSummaryProps) {
const intl = useIntl()
const scrollY = useRef(0)
const {
guestsInRooms,
isSummaryOpen,
getSelectedRateSummary,
toggleSummaryOpen,
togglePriceDetailsModalOpen,
} = useRateSelectionStore()
const selectedRateSummary = getSelectedRateSummary()
const rooms = selectedRateSummary.map((room, index) => ({
adults: guestsInRooms[index].adults,
childrenInRoom: guestsInRooms[index].children,
roomType: room.roomType,
roomPrice: {
perNight: {
local: {
price: room.public.localPrice.pricePerNight,
currency: room.public.localPrice.currency,
},
requested: undefined,
},
perStay: {
local: {
price: room.public.localPrice.pricePerStay,
currency: room.public.localPrice.currency,
},
requested: undefined,
},
currency: room.public.localPrice.currency,
},
roomRate: {
...room.public,
memberRate: room.member,
publicRate: room.public,
},
rateDetails: roomsAvailability.rateDefinitions.find(
(rate) => rate.rateCode === room.public.rateCode
)?.generalTerms,
cancellationText:
roomsAvailability.rateDefinitions.find(
(rate) => rate.rateCode === room.public.rateCode
)?.cancellationText ?? "",
}))
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 = ""
}
}, [isSummaryOpen])
return (
<div className={styles.wrapper} data-open={isSummaryOpen}>
<div className={styles.content}>
<div className={styles.summaryAccordion}>
<Summary
booking={booking}
rooms={rooms}
isMember={isUserLoggedIn}
totalPrice={totalPriceToShow}
vat={vat}
toggleSummaryOpen={toggleSummaryOpen}
togglePriceDetailsModalOpen={togglePriceDetailsModalOpen}
/>
</div>
</div>
<div className={styles.bottomSheet}>
<button
data-open={isSummaryOpen}
onClick={(e) => {
e.preventDefault()
toggleSummaryOpen()
}}
className={styles.priceDetailsButton}
>
<Caption>{intl.formatMessage({ id: "Total price" })}</Caption>
<Subtitle>
{formatPrice(
intl,
totalPriceToShow.local.price,
totalPriceToShow.local.currency
)}
</Subtitle>
<Caption color="baseTextHighContrast" type="underline">
{intl.formatMessage({ id: "See details" })}
</Caption>
</button>
<Button
intent="primary"
theme="base"
size="large"
type="submit"
fullWidth
disabled={!isAllRoomsSelected}
>
{intl.formatMessage({ id: "Continue" })}
</Button>
</div>
</div>
)
}