chore(SW-3145): Move Title and Subtitle to design-system * Move Title and Subtitle to design-system * Fix export Approved-by: Linus Flood
133 lines
3.8 KiB
TypeScript
133 lines
3.8 KiB
TypeScript
import { useEffect } from "react"
|
|
import { useIntl } from "react-intl"
|
|
|
|
import { MaterialIcon } from "@scandic-hotels/design-system/Icons/MaterialIcon"
|
|
import Subtitle from "@scandic-hotels/design-system/Subtitle"
|
|
|
|
import { useRatesStore } from "@/stores/select-rate"
|
|
|
|
import Button from "@/components/TempDesignSystem/Button"
|
|
import { useRoomContext } from "@/contexts/SelectRate/Room"
|
|
import useStickyPosition from "@/hooks/useStickyPosition"
|
|
|
|
import SelectedRoomPanel from "./SelectedRoomPanel"
|
|
import { roomSelectionPanelVariants } from "./variants"
|
|
|
|
import styles from "./multiRoomWrapper.module.css"
|
|
|
|
export default function MultiRoomWrapper({
|
|
children,
|
|
isMultiRoom,
|
|
}: React.PropsWithChildren<{ isMultiRoom: boolean }>) {
|
|
const intl = useIntl()
|
|
const activeRoom = useRatesStore((state) => state.activeRoom)
|
|
const {
|
|
actions: { closeSection },
|
|
bookingRoom,
|
|
isActiveRoom,
|
|
roomNr,
|
|
selectedRate,
|
|
} = useRoomContext()
|
|
const { getTopOffset } = useStickyPosition()
|
|
|
|
const roomMsg = intl.formatMessage(
|
|
{
|
|
defaultMessage: "Room {roomIndex}",
|
|
},
|
|
{ roomIndex: roomNr }
|
|
)
|
|
|
|
const adultsMsg = intl.formatMessage(
|
|
{
|
|
defaultMessage: "{adults, plural, one {# adult} other {# adults}}",
|
|
},
|
|
{ adults: bookingRoom.adults }
|
|
)
|
|
|
|
const childrenMsg = intl.formatMessage(
|
|
{
|
|
defaultMessage: "{children, plural, one {# child} other {# children}}",
|
|
},
|
|
{
|
|
children: bookingRoom.childrenInRoom?.length,
|
|
}
|
|
)
|
|
|
|
const onlyAdultsMsg = adultsMsg
|
|
const adultsAndChildrenMsg = [adultsMsg, childrenMsg].join(", ")
|
|
const guestsMsg = bookingRoom.childrenInRoom?.length
|
|
? 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 =
|
|
activeRoom === -1 ? roomElements[0] : roomElements[activeRoom]
|
|
|
|
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
|
|
}, [activeRoom])
|
|
|
|
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={closeSection}
|
|
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 />
|
|
</div>
|
|
<div className={styles.roomSelectionPanel}>{children}</div>
|
|
</div>
|
|
</div>
|
|
)
|
|
}
|
|
|
|
return children
|
|
}
|