fix: handle card grids in css instead of js
This commit is contained in:
@@ -8,6 +8,7 @@
|
|||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
gap: var(--Spacing-x-half);
|
gap: var(--Spacing-x-half);
|
||||||
|
height: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
.noPricesCard {
|
.noPricesCard {
|
||||||
|
|||||||
@@ -11,7 +11,6 @@ import Label from "@/components/TempDesignSystem/Form/Label"
|
|||||||
import Body from "@/components/TempDesignSystem/Text/Body"
|
import Body from "@/components/TempDesignSystem/Text/Body"
|
||||||
import Caption from "@/components/TempDesignSystem/Text/Caption"
|
import Caption from "@/components/TempDesignSystem/Text/Caption"
|
||||||
|
|
||||||
import { RATE_CARD_EQUAL_HEIGHT_CLASS } from "../utils"
|
|
||||||
import PriceTable from "./PriceList"
|
import PriceTable from "./PriceList"
|
||||||
|
|
||||||
import styles from "./flexibilityOption.module.css"
|
import styles from "./flexibilityOption.module.css"
|
||||||
@@ -69,7 +68,7 @@ export default function FlexibilityOption({
|
|||||||
|
|
||||||
if (!product) {
|
if (!product) {
|
||||||
return (
|
return (
|
||||||
<div className={`${styles.noPricesCard} ${RATE_CARD_EQUAL_HEIGHT_CLASS}`}>
|
<div className={styles.noPricesCard}>
|
||||||
<div className={styles.header}>
|
<div className={styles.header}>
|
||||||
<InfoCircleIcon width={16} height={16} color="uiTextMediumContrast" />
|
<InfoCircleIcon width={16} height={16} color="uiTextMediumContrast" />
|
||||||
<div className={styles.priceType}>
|
<div className={styles.priceType}>
|
||||||
@@ -116,7 +115,7 @@ export default function FlexibilityOption({
|
|||||||
onClick={onClick}
|
onClick={onClick}
|
||||||
ref={inputElementRef}
|
ref={inputElementRef}
|
||||||
/>
|
/>
|
||||||
<div className={`${styles.card} ${RATE_CARD_EQUAL_HEIGHT_CLASS}`}>
|
<div className={styles.card}>
|
||||||
<div className={styles.header}>
|
<div className={styles.header}>
|
||||||
<Modal
|
<Modal
|
||||||
trigger={
|
trigger={
|
||||||
|
|||||||
@@ -12,10 +12,6 @@ import Footnote from "@/components/TempDesignSystem/Text/Footnote"
|
|||||||
import Subtitle from "@/components/TempDesignSystem/Text/Subtitle"
|
import Subtitle from "@/components/TempDesignSystem/Text/Subtitle"
|
||||||
|
|
||||||
import { getIconForFeatureCode } from "../../utils"
|
import { getIconForFeatureCode } from "../../utils"
|
||||||
import {
|
|
||||||
RATE_CARDS_AVAILABLE_HEIGHT_CLASS,
|
|
||||||
RATE_CARDS_NOT_AVAILABLE_HEIGHT_CLASS,
|
|
||||||
} from "../utils"
|
|
||||||
import { cardVariants } from "./cardVariants"
|
import { cardVariants } from "./cardVariants"
|
||||||
|
|
||||||
import styles from "./roomCard.module.css"
|
import styles from "./roomCard.module.css"
|
||||||
@@ -115,7 +111,7 @@ export default function RoomCard({
|
|||||||
})
|
})
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={classNames}>
|
<li className={classNames}>
|
||||||
<div>
|
<div>
|
||||||
<div className={styles.imageContainer}>
|
<div className={styles.imageContainer}>
|
||||||
<div className={styles.chipContainer}>
|
<div className={styles.chipContainer}>
|
||||||
@@ -186,9 +182,7 @@ export default function RoomCard({
|
|||||||
*/}
|
*/}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div
|
<div className={styles.container}>
|
||||||
className={`${styles.container} ${roomConfiguration.status === "NotAvailable" ? RATE_CARDS_NOT_AVAILABLE_HEIGHT_CLASS : RATE_CARDS_AVAILABLE_HEIGHT_CLASS}`}
|
|
||||||
>
|
|
||||||
<Caption color="uiTextHighContrast" type="bold">
|
<Caption color="uiTextHighContrast" type="bold">
|
||||||
{getBreakfastMessage(rates.flexRate)}
|
{getBreakfastMessage(rates.flexRate)}
|
||||||
</Caption>
|
</Caption>
|
||||||
@@ -204,23 +198,21 @@ export default function RoomCard({
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
) : (
|
) : (
|
||||||
<div className={styles.flexibilityOptions}>
|
Object.entries(rates).map(([key, rate]) => (
|
||||||
{Object.entries(rates).map(([key, rate]) => (
|
<FlexibilityOption
|
||||||
<FlexibilityOption
|
key={key}
|
||||||
key={key}
|
name={rateKey(key)}
|
||||||
name={rateKey(key)}
|
value={key.toLowerCase()}
|
||||||
value={key.toLowerCase()}
|
paymentTerm={key === "flexRate" ? payLater : payNow}
|
||||||
paymentTerm={key === "flexRate" ? payLater : payNow}
|
product={findProductForRate(rate)}
|
||||||
product={findProductForRate(rate)}
|
priceInformation={getRateDefinitionForRate(rate)?.generalTerms}
|
||||||
priceInformation={getRateDefinitionForRate(rate)?.generalTerms}
|
handleSelectRate={handleSelectRate}
|
||||||
handleSelectRate={handleSelectRate}
|
roomTypeCode={roomConfiguration.roomTypeCode}
|
||||||
roomTypeCode={roomConfiguration.roomTypeCode}
|
petRoomPackage={petRoomPackage}
|
||||||
petRoomPackage={petRoomPackage}
|
/>
|
||||||
/>
|
))
|
||||||
))}
|
|
||||||
</div>
|
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</li>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,13 +1,14 @@
|
|||||||
.card {
|
.card {
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
display: flex;
|
display: grid;
|
||||||
flex-direction: column;
|
grid-template-columns: 1fr;
|
||||||
|
grid-template-rows: subgrid;
|
||||||
background-color: #fff;
|
background-color: #fff;
|
||||||
border-radius: var(--Corner-radius-Large);
|
border-radius: var(--Corner-radius-Large);
|
||||||
border: 1px solid var(--Base-Border-Subtle);
|
border: 1px solid var(--Base-Border-Subtle);
|
||||||
position: relative;
|
position: relative;
|
||||||
height: 100%;
|
|
||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
|
grid-row: span 5;
|
||||||
}
|
}
|
||||||
|
|
||||||
.card.noAvailability {
|
.card.noAvailability {
|
||||||
@@ -38,9 +39,16 @@
|
|||||||
|
|
||||||
.container {
|
.container {
|
||||||
padding: var(--Spacing-x1) var(--Spacing-x2) var(--Spacing-x2);
|
padding: var(--Spacing-x1) var(--Spacing-x2) var(--Spacing-x2);
|
||||||
display: flex;
|
display: grid;
|
||||||
flex-direction: column;
|
grid-template-rows: subgrid;
|
||||||
gap: var(--Spacing-x-one-and-half);
|
gap: var(--Spacing-x-one-and-half);
|
||||||
|
grid-row: span 4;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Make sure rows with only unavailable rooms still has a min-height */
|
||||||
|
.container:has(.noRoomsContainer) {
|
||||||
|
min-height: 400px;
|
||||||
|
grid-template-rows: auto repeat(3, 1fr);
|
||||||
}
|
}
|
||||||
|
|
||||||
.roomDetails {
|
.roomDetails {
|
||||||
@@ -62,9 +70,9 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.flexibilityOptions {
|
.flexibilityOptions {
|
||||||
display: flex;
|
display: grid;
|
||||||
flex-direction: column;
|
|
||||||
gap: var(--Spacing-x2);
|
gap: var(--Spacing-x2);
|
||||||
|
grid-template-rows: repeat(3, 1fr);
|
||||||
}
|
}
|
||||||
|
|
||||||
.chipContainer {
|
.chipContainer {
|
||||||
@@ -89,14 +97,16 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.noRoomsContainer {
|
.noRoomsContainer {
|
||||||
padding: var(--Spacing-x2);
|
height: 100%;
|
||||||
background-color: var(--Base-Surface-Secondary-light-Normal);
|
|
||||||
border-radius: var(--Corner-radius-Medium);
|
|
||||||
margin: 0;
|
|
||||||
width: 100%;
|
width: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
.noRooms {
|
.noRooms {
|
||||||
|
padding: var(--Spacing-x2);
|
||||||
|
background-color: var(--Base-Surface-Secondary-light-Normal);
|
||||||
|
border-radius: var(--Corner-radius-Medium);
|
||||||
|
margin: 0;
|
||||||
|
|
||||||
display: flex;
|
display: flex;
|
||||||
gap: var(--Spacing-x1);
|
gap: var(--Spacing-x1);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,19 +1,10 @@
|
|||||||
"use client"
|
"use client"
|
||||||
import { usePathname, useRouter, useSearchParams } from "next/navigation"
|
import { usePathname, useRouter, useSearchParams } from "next/navigation"
|
||||||
import { useSession } from "next-auth/react"
|
import { useMemo } from "react"
|
||||||
import { useCallback, useEffect, useMemo, useRef } from "react"
|
|
||||||
|
|
||||||
import { debounce } from "@/utils/debounce"
|
|
||||||
import { isValidSession } from "@/utils/session"
|
|
||||||
|
|
||||||
import RateSummary from "./RateSummary"
|
import RateSummary from "./RateSummary"
|
||||||
import RoomCard from "./RoomCard"
|
import RoomCard from "./RoomCard"
|
||||||
import {
|
import { getHotelReservationQueryParams } from "./utils"
|
||||||
getHotelReservationQueryParams,
|
|
||||||
RATE_CARD_EQUAL_HEIGHT_CLASS,
|
|
||||||
RATE_CARDS_AVAILABLE_HEIGHT_CLASS,
|
|
||||||
RATE_CARDS_NOT_AVAILABLE_HEIGHT_CLASS,
|
|
||||||
} from "./utils"
|
|
||||||
|
|
||||||
import styles from "./roomSelection.module.css"
|
import styles from "./roomSelection.module.css"
|
||||||
|
|
||||||
@@ -32,68 +23,8 @@ export default function RoomSelection({
|
|||||||
const router = useRouter()
|
const router = useRouter()
|
||||||
const pathname = usePathname()
|
const pathname = usePathname()
|
||||||
const searchParams = useSearchParams()
|
const searchParams = useSearchParams()
|
||||||
const roomRefs = useRef<HTMLLIElement[]>([])
|
|
||||||
const { roomConfigurations, rateDefinitions } = roomsAvailability
|
const { roomConfigurations, rateDefinitions } = roomsAvailability
|
||||||
|
|
||||||
const equalizePriceOptionHeights = useCallback(() => {
|
|
||||||
if (!roomRefs.current.length) return
|
|
||||||
|
|
||||||
const optionsSelector = `.${RATE_CARD_EQUAL_HEIGHT_CLASS}`
|
|
||||||
const availableSelector = `.${RATE_CARDS_AVAILABLE_HEIGHT_CLASS}`
|
|
||||||
const notAvailableSelector = `.${RATE_CARDS_NOT_AVAILABLE_HEIGHT_CLASS}`
|
|
||||||
const DEFAULT_RATE_CARD_HEIGHT = 380
|
|
||||||
|
|
||||||
const maxOptionHeights: number[] = []
|
|
||||||
let maxPriceCardHeight = DEFAULT_RATE_CARD_HEIGHT
|
|
||||||
|
|
||||||
roomRefs.current.forEach((room) => {
|
|
||||||
const options = room.querySelectorAll<HTMLDivElement>(optionsSelector)
|
|
||||||
options.forEach((option, i) => {
|
|
||||||
option.style.height = "auto"
|
|
||||||
const optionHeight = option.getBoundingClientRect().height
|
|
||||||
maxOptionHeights[i] = Math.max(maxOptionHeights[i] || 0, optionHeight)
|
|
||||||
})
|
|
||||||
|
|
||||||
const priceCard = room.querySelector(availableSelector) as HTMLElement
|
|
||||||
if (priceCard) {
|
|
||||||
const priceCardHeight = priceCard.getBoundingClientRect().height
|
|
||||||
maxPriceCardHeight = Math.max(maxPriceCardHeight, priceCardHeight)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
roomRefs.current.forEach((room) => {
|
|
||||||
const options = room.querySelectorAll<HTMLDivElement>(optionsSelector)
|
|
||||||
options.forEach((option, i) => {
|
|
||||||
if (option) {
|
|
||||||
option.style.height = `${maxOptionHeights[i]}px`
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
const noPriceCard = room.querySelector(
|
|
||||||
notAvailableSelector
|
|
||||||
) as HTMLElement
|
|
||||||
if (noPriceCard) {
|
|
||||||
noPriceCard.style.height = `${maxPriceCardHeight}px`
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}, [])
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
const debouncedResizeHandler = debounce(function () {
|
|
||||||
equalizePriceOptionHeights()
|
|
||||||
})
|
|
||||||
|
|
||||||
const observer = new ResizeObserver(debouncedResizeHandler)
|
|
||||||
|
|
||||||
observer.observe(document.documentElement)
|
|
||||||
|
|
||||||
return () => {
|
|
||||||
if (observer) {
|
|
||||||
observer.unobserve(document.documentElement)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}, [roomRefs, equalizePriceOptionHeights])
|
|
||||||
|
|
||||||
const queryParams = useMemo(() => {
|
const queryParams = useMemo(() => {
|
||||||
const params = new URLSearchParams(searchParams)
|
const params = new URLSearchParams(searchParams)
|
||||||
const searchParamsObject = getHotelReservationQueryParams(searchParams)
|
const searchParamsObject = getHotelReservationQueryParams(searchParams)
|
||||||
@@ -139,23 +70,17 @@ export default function RoomSelection({
|
|||||||
>
|
>
|
||||||
<ul className={styles.roomList}>
|
<ul className={styles.roomList}>
|
||||||
{roomConfigurations.map((roomConfiguration, index) => (
|
{roomConfigurations.map((roomConfiguration, index) => (
|
||||||
<li
|
<RoomCard
|
||||||
|
hotelId={roomsAvailability.hotelId.toString()}
|
||||||
|
hotelType={hotelType}
|
||||||
|
rateDefinitions={rateDefinitions}
|
||||||
|
roomConfiguration={roomConfiguration}
|
||||||
|
roomCategories={roomCategories}
|
||||||
|
handleSelectRate={setRateCode}
|
||||||
|
selectedPackages={selectedPackages}
|
||||||
|
packages={availablePackages}
|
||||||
key={roomConfiguration.roomTypeCode}
|
key={roomConfiguration.roomTypeCode}
|
||||||
ref={(el) => {
|
/>
|
||||||
if (el) roomRefs.current[index] = el
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<RoomCard
|
|
||||||
hotelId={roomsAvailability.hotelId.toString()}
|
|
||||||
hotelType={hotelType}
|
|
||||||
rateDefinitions={rateDefinitions}
|
|
||||||
roomConfiguration={roomConfiguration}
|
|
||||||
roomCategories={roomCategories}
|
|
||||||
handleSelectRate={setRateCode}
|
|
||||||
selectedPackages={selectedPackages}
|
|
||||||
packages={availablePackages}
|
|
||||||
/>
|
|
||||||
</li>
|
|
||||||
))}
|
))}
|
||||||
</ul>
|
</ul>
|
||||||
{rateSummary && (
|
{rateSummary && (
|
||||||
|
|||||||
@@ -5,8 +5,8 @@
|
|||||||
.roomList {
|
.roomList {
|
||||||
list-style: none;
|
list-style: none;
|
||||||
display: grid;
|
display: grid;
|
||||||
grid-template-columns: 1fr;
|
|
||||||
gap: var(--Spacing-x3);
|
gap: var(--Spacing-x3);
|
||||||
|
grid-template-columns: repeat(auto-fill, minmax(320px, 1fr));
|
||||||
}
|
}
|
||||||
|
|
||||||
.roomList > li {
|
.roomList > li {
|
||||||
@@ -18,7 +18,3 @@
|
|||||||
position: fixed;
|
position: fixed;
|
||||||
width: 0;
|
width: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.roomList {
|
|
||||||
grid-template-columns: repeat(auto-fill, minmax(320px, 1fr));
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -111,9 +111,3 @@ export function createQueryParamsForEnterDetails(
|
|||||||
|
|
||||||
return searchParams
|
return searchParams
|
||||||
}
|
}
|
||||||
|
|
||||||
export const RATE_CARD_EQUAL_HEIGHT_CLASS = "rateCardEqualHeightSelector"
|
|
||||||
export const RATE_CARDS_AVAILABLE_HEIGHT_CLASS =
|
|
||||||
"rateCardAvailableEqualHeightSelector"
|
|
||||||
export const RATE_CARDS_NOT_AVAILABLE_HEIGHT_CLASS =
|
|
||||||
"rateCardNotAvailableEqualHeightSelector"
|
|
||||||
|
|||||||
Reference in New Issue
Block a user