Merged in fix/SW-1119-select-room-same-currency (pull request #1075)

fix(SW-1119): remove approx currency if same and synchronize price option height

* fix(SW-1119): remove approx currency if same and synchronize price option height

* fix(SW-1119): use debounce and observer for performance

* fix(SW-1119): export selector variable to utils


Approved-by: Pontus Dreij
Approved-by: Niclas Edenvin
This commit is contained in:
Bianca Widstam
2024-12-13 10:21:59 +00:00
parent aa8cfe86c4
commit ec0c6234ef
4 changed files with 95 additions and 26 deletions

View File

@@ -28,7 +28,10 @@ export default function PriceList({
const petRoomLocalPrice = petRoomPackage?.localPrice const petRoomLocalPrice = petRoomPackage?.localPrice
const petRoomRequestedPrice = petRoomPackage?.requestedPrice const petRoomRequestedPrice = petRoomPackage?.requestedPrice
const showRequestedPrice = publicRequestedPrice && memberRequestedPrice const showRequestedPrice =
publicRequestedPrice &&
memberRequestedPrice &&
publicRequestedPrice.currency !== publicLocalPrice.currency
const searchParams = useSearchParams() const searchParams = useSearchParams()
const fromDate = searchParams.get("fromDate") const fromDate = searchParams.get("fromDate")
const toDate = searchParams.get("toDate") const toDate = searchParams.get("toDate")
@@ -114,27 +117,22 @@ export default function PriceList({
)} )}
</dd> </dd>
</div> </div>
{showRequestedPrice && (
<div className={styles.priceRow}> <div className={styles.priceRow}>
<dt> <dt>
<Caption <Caption color="uiTextMediumContrast">
color={showRequestedPrice ? "uiTextMediumContrast" : "disabled"} {intl.formatMessage({ id: "Approx." })}
> </Caption>
{intl.formatMessage({ id: "Approx." })} </dt>
</Caption> <dd>
</dt>
<dd>
{showRequestedPrice ? (
<Caption color="uiTextMediumContrast"> <Caption color="uiTextMediumContrast">
{totalPublicRequestedPricePerNight}/ {totalPublicRequestedPricePerNight}/
{totalMemberRequestedPricePerNight}{" "} {totalMemberRequestedPricePerNight}{" "}
{publicRequestedPrice.currency} {publicRequestedPrice.currency}
</Caption> </Caption>
) : ( </dd>
<Caption color="disabled">- / - EUR</Caption> </div>
)} )}
</dd>
</div>
</dl> </dl>
) )
} }

View File

@@ -7,6 +7,7 @@ import Label from "@/components/TempDesignSystem/Form/Label"
import Popover from "@/components/TempDesignSystem/Popover" import Popover from "@/components/TempDesignSystem/Popover"
import Caption from "@/components/TempDesignSystem/Text/Caption" import Caption from "@/components/TempDesignSystem/Text/Caption"
import { rateCardEqualHeightSelector } from "../utils"
import PriceTable from "./PriceList" import PriceTable from "./PriceList"
import styles from "./flexibilityOption.module.css" import styles from "./flexibilityOption.module.css"
@@ -26,11 +27,13 @@ export default function FlexibilityOption({
if (!product) { if (!product) {
return ( return (
<div className={styles.noPricesCard}> <div className={`${styles.noPricesCard} ${rateCardEqualHeightSelector}`}>
<div className={styles.header}> <div className={styles.header}>
<InfoCircleIcon width={16} height={16} color="uiTextMediumContrast" /> <InfoCircleIcon width={16} height={16} color="uiTextMediumContrast" />
<Caption>{name}</Caption> <div className={styles.priceType}>
<Caption color="uiTextPlaceholder">({paymentTerm})</Caption> <Caption>{name}</Caption>
<Caption color="uiTextPlaceholder">({paymentTerm})</Caption>
</div>
</div> </div>
<Label size="regular" className={styles.noPricesLabel}> <Label size="regular" className={styles.noPricesLabel}>
<Caption color="uiTextHighContrast" type="bold"> <Caption color="uiTextHighContrast" type="bold">
@@ -70,7 +73,7 @@ export default function FlexibilityOption({
value={publicPrice?.rateCode} value={publicPrice?.rateCode}
onClick={onClick} onClick={onClick}
/> />
<div className={styles.card}> <div className={`${styles.card} ${rateCardEqualHeightSelector}`}>
<div className={styles.header}> <div className={styles.header}>
<Popover <Popover
placement="bottom left" placement="bottom left"

View File

@@ -1,10 +1,15 @@
"use client" "use client"
import { useRouter, useSearchParams } from "next/navigation" import { useRouter, useSearchParams } from "next/navigation"
import { useMemo } from "react" import { useCallback, useEffect, useMemo, useRef } from "react"
import { debounce } from "@/utils/debounce"
import RateSummary from "./RateSummary" import RateSummary from "./RateSummary"
import RoomCard from "./RoomCard" import RoomCard from "./RoomCard"
import { getHotelReservationQueryParams } from "./utils" import {
getHotelReservationQueryParams,
rateCardEqualHeightSelector,
} from "./utils"
import styles from "./roomSelection.module.css" import styles from "./roomSelection.module.css"
@@ -23,9 +28,65 @@ export default function RoomSelection({
const router = useRouter() const router = useRouter()
const searchParams = useSearchParams() const searchParams = useSearchParams()
const isUserLoggedIn = !!user const isUserLoggedIn = !!user
const roomRefs = useRef<HTMLLIElement[]>([])
const { roomConfigurations, rateDefinitions } = roomsAvailability const { roomConfigurations, rateDefinitions } = roomsAvailability
const equalizePriceOptionHeights = useCallback(() => {
if (!roomRefs.current.length) return
roomRefs.current.forEach((room) => {
const options = room.querySelectorAll<HTMLDivElement>(
`.${rateCardEqualHeightSelector}`
)
options.forEach((option) => {
option.style.height = "auto"
})
})
const numOptions =
roomRefs.current[0]?.querySelectorAll<HTMLDivElement>(
`.${rateCardEqualHeightSelector}`
).length || 0
for (let i = 0; i < numOptions; i++) {
let maxHeight = 0
roomRefs.current.forEach((room) => {
const option = room.querySelectorAll<HTMLDivElement>(
`.${rateCardEqualHeightSelector}`
)[i]
if (option) {
maxHeight = Math.max(maxHeight, option.offsetHeight)
}
})
roomRefs.current.forEach((room) => {
const option = room.querySelectorAll<HTMLDivElement>(
`.${rateCardEqualHeightSelector}`
)[i]
if (option) {
option.style.height = `${maxHeight}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)
@@ -64,8 +125,13 @@ export default function RoomSelection({
onSubmit={handleSubmit} onSubmit={handleSubmit}
> >
<ul className={styles.roomList}> <ul className={styles.roomList}>
{roomConfigurations.map((roomConfiguration) => ( {roomConfigurations.map((roomConfiguration, index) => (
<li key={roomConfiguration.roomTypeCode}> <li
key={roomConfiguration.roomTypeCode}
ref={(el) => {
if (el) roomRefs.current[index] = el
}}
>
<RoomCard <RoomCard
hotelId={roomsAvailability.hotelId.toString()} hotelId={roomsAvailability.hotelId.toString()}
hotelType={hotelType} hotelType={hotelType}

View File

@@ -101,3 +101,5 @@ export function createQueryParamsForEnterDetails(
return searchParams return searchParams
} }
export const rateCardEqualHeightSelector = "rateCardEqualHeight"