128 lines
3.6 KiB
TypeScript
128 lines
3.6 KiB
TypeScript
"use client"
|
|
import { useState } from "react"
|
|
import { Button, DialogTrigger } from "react-aria-components"
|
|
|
|
import { CheckCircleIcon, InfoCircleIcon } from "@/components/Icons"
|
|
import Caption from "@/components/TempDesignSystem/Text/Caption"
|
|
|
|
import PricePopover from "./Popover"
|
|
import PriceTable from "./PriceList"
|
|
|
|
import styles from "./flexibilityOption.module.css"
|
|
|
|
import { FlexibilityOptionProps } from "@/types/components/hotelReservation/selectRate/flexibilityOption"
|
|
|
|
export default function FlexibilityOption({
|
|
product,
|
|
name,
|
|
paymentTerm,
|
|
priceInformation,
|
|
roomType,
|
|
roomTypeCode,
|
|
features,
|
|
handleSelectRate,
|
|
}: FlexibilityOptionProps) {
|
|
const [rootDiv, setRootDiv] = useState<Element | undefined>(undefined)
|
|
const [isPopoverOpen, setIsPopoverOpen] = useState(false)
|
|
|
|
function setRef(node: Element | null) {
|
|
if (node) {
|
|
setRootDiv(node)
|
|
}
|
|
}
|
|
|
|
if (!product) {
|
|
return (
|
|
<div className={styles.disabledCard}>
|
|
<div className={styles.header}>
|
|
<InfoCircleIcon className={styles.infoIcon} />
|
|
<Caption color="disabled">{name}</Caption>
|
|
<Caption color="disabled">({paymentTerm})</Caption>
|
|
</div>
|
|
<PriceTable />
|
|
</div>
|
|
)
|
|
}
|
|
|
|
const { public: publicPrice, member: memberPrice } = product.productType
|
|
|
|
function onChange() {
|
|
const rate = {
|
|
roomTypeCode,
|
|
roomType,
|
|
priceName: name,
|
|
public: publicPrice,
|
|
member: memberPrice,
|
|
features,
|
|
}
|
|
handleSelectRate(rate)
|
|
}
|
|
|
|
return (
|
|
<label>
|
|
<input
|
|
type="radio"
|
|
name="rateCode"
|
|
value={publicPrice?.rateCode}
|
|
onChange={onChange}
|
|
/>
|
|
<div className={styles.card}>
|
|
<div className={styles.header} ref={setRef}>
|
|
<DialogTrigger>
|
|
<Button
|
|
aria-label="Help"
|
|
className={styles.button}
|
|
onPress={() => setIsPopoverOpen(true)}
|
|
>
|
|
<InfoCircleIcon className={styles.infoIcon} />
|
|
</Button>
|
|
<PricePopover
|
|
placement="bottom"
|
|
className={styles.popover}
|
|
isNonModal
|
|
shouldFlip={false}
|
|
shouldUpdatePosition={false}
|
|
/**
|
|
* react-aria uses portals to render Popover in body
|
|
* unless otherwise specified. We need it to be contained
|
|
* by this component to both access css variables assigned
|
|
* on the container as well as to not overflow it at any time.
|
|
*/
|
|
UNSTABLE_portalContainer={rootDiv}
|
|
isOpen={isPopoverOpen}
|
|
onOpenChange={setIsPopoverOpen}
|
|
>
|
|
<Caption
|
|
color="uiTextHighContrast"
|
|
type="bold"
|
|
className={styles.popoverHeading}
|
|
>
|
|
{name}
|
|
</Caption>
|
|
{priceInformation?.map((info) => (
|
|
<Caption
|
|
key={info}
|
|
color="uiTextHighContrast"
|
|
className={styles.popoverText}
|
|
>
|
|
{info}
|
|
</Caption>
|
|
))}
|
|
</PricePopover>
|
|
</DialogTrigger>
|
|
<Caption color="uiTextHighContrast">{name}</Caption>
|
|
<Caption color="uiTextPlaceholder">({paymentTerm})</Caption>
|
|
</div>
|
|
<PriceTable publicPrice={publicPrice} memberPrice={memberPrice} />
|
|
<CheckCircleIcon
|
|
color="blue"
|
|
className={styles.checkIcon}
|
|
width={24}
|
|
height={24}
|
|
stroke="white"
|
|
/>
|
|
</div>
|
|
</label>
|
|
)
|
|
}
|