feat(SW-718) Refactor select rate to support multiroom
This commit is contained in:
@@ -0,0 +1,168 @@
|
||||
"use client"
|
||||
|
||||
import { useSearchParams } from "next/navigation"
|
||||
import { useEffect, useRef } from "react"
|
||||
import { useIntl } from "react-intl"
|
||||
|
||||
import { CheckCircleIcon, CheckIcon, InfoCircleIcon } from "@/components/Icons"
|
||||
import Modal from "@/components/Modal"
|
||||
import Button from "@/components/TempDesignSystem/Button"
|
||||
import Label from "@/components/TempDesignSystem/Form/Label"
|
||||
import Body from "@/components/TempDesignSystem/Text/Body"
|
||||
import Caption from "@/components/TempDesignSystem/Text/Caption"
|
||||
|
||||
import PriceTable from "./PriceList"
|
||||
|
||||
import styles from "./flexibilityOption.module.css"
|
||||
|
||||
import type { FlexibilityOptionProps } from "@/types/components/hotelReservation/selectRate/flexibilityOption"
|
||||
|
||||
export default function FlexibilityOption({
|
||||
product,
|
||||
name,
|
||||
paymentTerm,
|
||||
priceInformation,
|
||||
roomTypeCode,
|
||||
petRoomPackage,
|
||||
handleSelectRate,
|
||||
}: FlexibilityOptionProps) {
|
||||
const intl = useIntl()
|
||||
const inputElementRef = useRef<HTMLInputElement>(null)
|
||||
|
||||
const searchParams = useSearchParams()
|
||||
|
||||
// When entering the page with a room and rate selection already in the URL we
|
||||
// want to preselect the selection. This happens e.g. when you do a selection,
|
||||
// go to the enter details page and then want to change the room.
|
||||
useEffect(() => {
|
||||
const ratecodeSearchParam = searchParams.get("room[0].ratecode")
|
||||
const roomtypeSearchParam = searchParams.get("room[0].roomtype")
|
||||
|
||||
// If this is not the room and rate we want to preselect, abort
|
||||
if (
|
||||
!product ||
|
||||
ratecodeSearchParam !== product.productType.public.rateCode ||
|
||||
roomtypeSearchParam !== roomTypeCode
|
||||
) {
|
||||
return
|
||||
}
|
||||
|
||||
handleSelectRate((prev) => {
|
||||
// If the user already has made a new selection we respect that and don't do anything else
|
||||
if (prev) {
|
||||
return prev
|
||||
}
|
||||
|
||||
if (inputElementRef.current) {
|
||||
inputElementRef.current.checked = true
|
||||
}
|
||||
|
||||
return {
|
||||
publicRateCode: product.productType.public.rateCode,
|
||||
roomTypeCode: roomTypeCode,
|
||||
name: name,
|
||||
paymentTerm: paymentTerm,
|
||||
}
|
||||
})
|
||||
}, [handleSelectRate, name, paymentTerm, product, roomTypeCode, searchParams])
|
||||
|
||||
if (!product) {
|
||||
return (
|
||||
<div className={styles.noPricesCard}>
|
||||
<div className={styles.header}>
|
||||
<InfoCircleIcon width={16} height={16} color="uiTextMediumContrast" />
|
||||
<div className={styles.priceType}>
|
||||
<Caption>{name}</Caption>
|
||||
<Caption color="uiTextPlaceholder">({paymentTerm})</Caption>
|
||||
</div>
|
||||
</div>
|
||||
<Label size="regular" className={styles.noPricesLabel}>
|
||||
<Caption color="uiTextHighContrast" type="bold">
|
||||
{intl.formatMessage({ id: "No prices available" })}
|
||||
</Caption>
|
||||
</Label>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
const { public: publicPrice, member: memberPrice } = product.productType
|
||||
|
||||
const onClick: React.MouseEventHandler<HTMLInputElement> = (e) => {
|
||||
handleSelectRate((prev) => {
|
||||
if (
|
||||
prev &&
|
||||
prev.publicRateCode === publicPrice.rateCode &&
|
||||
prev.roomTypeCode === roomTypeCode
|
||||
) {
|
||||
if (e.currentTarget?.checked) e.currentTarget.checked = false
|
||||
return undefined
|
||||
} else
|
||||
return {
|
||||
publicRateCode: publicPrice.rateCode,
|
||||
roomTypeCode: roomTypeCode,
|
||||
name: name,
|
||||
paymentTerm: paymentTerm,
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
return (
|
||||
<label>
|
||||
<input
|
||||
type="radio"
|
||||
name="rateCode"
|
||||
value={publicPrice?.rateCode}
|
||||
onClick={onClick}
|
||||
ref={inputElementRef}
|
||||
/>
|
||||
<div className={styles.card}>
|
||||
<div className={styles.header}>
|
||||
<Modal
|
||||
trigger={
|
||||
<Button intent="text">
|
||||
<InfoCircleIcon
|
||||
width={16}
|
||||
height={16}
|
||||
color="uiTextMediumContrast"
|
||||
/>
|
||||
</Button>
|
||||
}
|
||||
title={name}
|
||||
subtitle={paymentTerm}
|
||||
>
|
||||
<div className={styles.terms}>
|
||||
{priceInformation?.map((info) => (
|
||||
<Body
|
||||
key={info}
|
||||
color="uiTextHighContrast"
|
||||
className={styles.termsText}
|
||||
>
|
||||
<CheckIcon
|
||||
color="uiSemanticSuccess"
|
||||
width={20}
|
||||
height={20}
|
||||
className={styles.termsIcon}
|
||||
></CheckIcon>
|
||||
{info}
|
||||
</Body>
|
||||
))}
|
||||
</div>
|
||||
</Modal>
|
||||
<div className={styles.priceType}>
|
||||
<Caption color="uiTextHighContrast">{name}</Caption>
|
||||
<Caption color="uiTextPlaceholder">({paymentTerm})</Caption>
|
||||
</div>
|
||||
</div>
|
||||
<PriceTable
|
||||
publicPrice={publicPrice}
|
||||
memberPrice={memberPrice}
|
||||
petRoomPackage={petRoomPackage}
|
||||
/>
|
||||
|
||||
<div className={styles.checkIcon}>
|
||||
<CheckIcon color="white" height="16" width="16" />
|
||||
</div>
|
||||
</div>
|
||||
</label>
|
||||
)
|
||||
}
|
||||
Reference in New Issue
Block a user