Files
web/packages/booking-flow/lib/components/SelectRate/RoomsContainer/Rooms/MultiRoomWrapper/index.tsx
Bianca Widstam 1b9273136a Merged in chore/BOOK-701-replace-subtitle-component (pull request #3398)
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
2026-01-12 07:40:30 +00:00

157 lines
4.7 KiB
TypeScript

import { useEffect } from "react"
import { useIntl } from "react-intl"
import useStickyPosition from "@scandic-hotels/common/hooks/useStickyPosition"
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 { useSelectRateContext } from "../../../../../contexts/SelectRate/SelectRateContext"
import { SelectedRoomPanel } from "./SelectedRoomPanel"
import { roomSelectionPanelVariants } from "./variants"
import styles from "./multiRoomWrapper.module.css"
type Props = {
children: React.ReactNode
isMultiRoom: boolean
roomIndex: number
}
export function MultiRoomWrapper({ children, isMultiRoom, roomIndex }: Props) {
const intl = useIntl()
const { getTopOffset } = useStickyPosition()
const {
activeRoomIndex,
selectedRates,
actions: { setActiveRoom },
input: { data },
} = useSelectRateContext()
const roomNr = roomIndex + 1
const adultCount = data?.booking.rooms[roomIndex]?.adults || 0
const childCount = data?.booking.rooms[roomIndex]?.childrenInRoom?.length || 0
const isActiveRoom = activeRoomIndex === roomIndex
const roomMsg = intl.formatMessage(
{ id: "booking.roomIndex", defaultMessage: "Room {roomIndex}" },
{ roomIndex: roomNr }
)
const adultsMsg = intl.formatMessage(
{
id: "booking.numberOfAdults",
defaultMessage: "{adults, plural, one {# adult} other {# adults}}",
},
{ adults: adultCount }
)
const childrenMsg = intl.formatMessage(
{
id: "booking.numberOfChildren",
defaultMessage: "{children, plural, one {# child} other {# children}}",
},
{
children: childCount,
}
)
const onlyAdultsMsg = adultsMsg
const adultsAndChildrenMsg = [adultsMsg, childrenMsg].join(", ")
const guestsMsg = childCount ? adultsAndChildrenMsg : onlyAdultsMsg
const title = [roomMsg, guestsMsg].join(", ")
useEffect(() => {
requestAnimationFrame(() => {
const SCROLL_OFFSET = 12 + getTopOffset()
const roomElements = document.querySelectorAll(`.${styles.roomContainer}`)
// If no room is active we will show all rooms collapsed, hence we want
// to scroll to the first room.
const selectedRoom =
activeRoomIndex === -1 ? roomElements[0] : roomElements[activeRoomIndex]
if (selectedRoom) {
const elementPosition = selectedRoom.getBoundingClientRect().top
const offsetPosition = elementPosition + window.scrollY - SCROLL_OFFSET
// Setting a tiny delay for the scrolling. Without it the browser sometimes doesn't scroll up
// after modifying the first room.
setTimeout(() => {
window.scrollTo({
top: offsetPosition,
behavior: "smooth",
})
}, 5)
}
})
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [activeRoomIndex])
const selectedRate = selectedRates.rateSelectedForRoom(roomIndex)
if (isMultiRoom) {
const classNames = roomSelectionPanelVariants({
active: isActiveRoom,
selected: !!selectedRate && !isActiveRoom,
})
return (
<div
className={styles.roomContainer}
data-multiroom="true"
aria-labelledby={`room-${roomNr}-heading`}
role="region"
>
<h2 id={`room-${roomNr}-heading`} className="sr-only">
{intl.formatMessage(
{
id: "booking.roomIndex",
defaultMessage: "Room {roomIndex}",
},
{
roomIndex: roomNr,
}
)}
</h2>
<div className={styles.header}>
{selectedRate && !isActiveRoom ? null : (
<Typography variant="Title/Subtitle/md">
<p>{title}</p>
</Typography>
)}
{selectedRate && isActiveRoom ? (
<Button
intent="text"
onClick={() => {
setActiveRoom("deselect")
}}
size="medium"
theme="base"
variant="icon"
>
{intl.formatMessage({
id: "common.close",
defaultMessage: "Close",
})}
<MaterialIcon
icon="keyboard_arrow_up"
size={20}
color="CurrentColor"
/>
</Button>
) : null}
</div>
<div className={classNames}>
<div className={styles.roomPanel}>
<SelectedRoomPanel roomIndex={roomIndex} />
</div>
<div className={styles.roomSelectionPanel}>{children}</div>
</div>
</div>
)
}
return children
}