Files
web/packages/booking-flow/lib/components/SelectRate/RoomsContainer/Rooms/MultiRoomWrapper/index.tsx
Anton Gunnarsson f7ef58eafa Merged in feat/sw-2874-move-select-rate (pull request #2750)
Approved-by: Joakim Jäderberg
2025-09-03 08:30:05 +00:00

137 lines
4.1 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 Subtitle from "@scandic-hotels/design-system/Subtitle"
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(
{
defaultMessage: "Room {roomIndex}",
},
{ roomIndex: roomNr }
)
const adultsMsg = intl.formatMessage(
{
defaultMessage: "{adults, plural, one {# adult} other {# adults}}",
},
{ adults: adultCount }
)
const childrenMsg = intl.formatMessage(
{
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">
<div className={styles.header}>
{selectedRate && !isActiveRoom ? null : (
<Subtitle color="uiTextHighContrast">{title}</Subtitle>
)}
{selectedRate && isActiveRoom ? (
<Button
intent="text"
onClick={() => {
setActiveRoom("deselect")
}}
size="medium"
theme="base"
variant="icon"
>
{intl.formatMessage({
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
}