feat: SW-602 Implemented no availability states

This commit is contained in:
Hrishikesh Vaipurkar
2024-11-14 23:20:04 +01:00
parent dc3516f4e1
commit a17010a431
14 changed files with 144 additions and 38 deletions

View File

@@ -15,8 +15,12 @@ import TripAdvisorChip from "../../TripAdvisorChip"
import styles from "./hotelInfoCard.module.css"
import type { HotelInfoCardProps } from "@/types/components/hotelReservation/selectRate/hotelInfoCardProps"
import { AlertTypeEnum } from "@/types/enums/alert"
export default function HotelInfoCard({ hotelData }: HotelInfoCardProps) {
export default function HotelInfoCard({
hotelData,
noAvailability = false,
}: HotelInfoCardProps) {
const hotelAttributes = hotelData?.data.attributes
const intl = useIntl()
@@ -97,6 +101,16 @@ export default function HotelInfoCard({ hotelData }: HotelInfoCardProps) {
</div>
)
})}
{noAvailability ? (
<div className={styles.hotelAlert}>
<Alert
type={AlertTypeEnum.Info}
text={intl.formatMessage({
id: "There are no rooms available that match your request",
})}
/>
</div>
) : null}
</article>
)
}

View File

@@ -1,5 +1,5 @@
.card,
.disabledCard {
.noPricesCard {
border-radius: var(--Corner-radius-Large);
padding: var(--Spacing-x-one-and-half) var(--Spacing-x2);
background-color: var(--Base-Surface-Secondary-light-Normal);
@@ -10,11 +10,11 @@
gap: var(--Spacing-x-half);
}
.disabledCard {
opacity: 0.6;
.noPricesCard {
gap: var(--Spacing-x2);
}
.disabledCard:hover {
.noPricesCard:hover {
cursor: not-allowed;
}
@@ -62,9 +62,16 @@ input[type="radio"]:checked + .card .checkIcon {
outline: none;
}
.noPricesLabel {
padding: var(--Spacing-x-one-and-half) var(--Spacing-x2);
text-align: center;
background-color: var(--Base-Surface-Subtle-Normal);
border-radius: var(--Corner-radius-Rounded);
margin: 0 auto var(--Spacing-x2);
}
.popover {
background-color: var(--Main-Grey-White);
border-radius: var(--Corner-radius-Medium);
left: 0px;
max-height: 400px;

View File

@@ -1,8 +1,10 @@
"use client"
import { useRef, useState } from "react"
import { Button } from "react-aria-components"
import { useIntl } from "react-intl"
import { CheckIcon, InfoCircleIcon } from "@/components/Icons"
import Label from "@/components/TempDesignSystem/Form/Label"
import Caption from "@/components/TempDesignSystem/Text/Caption"
import PricePopover from "./Popover"
@@ -27,6 +29,7 @@ export default function FlexibilityOption({
const [isPopoverOpen, setIsPopoverOpen] = useState(false)
let triggerRef = useRef<HTMLButtonElement>(null)
const buttonClickedRef = useRef(false)
const intl = useIntl()
function setRef(node: Element | null) {
if (node) {
@@ -36,13 +39,17 @@ export default function FlexibilityOption({
if (!product) {
return (
<div className={styles.disabledCard}>
<div className={styles.noPricesCard}>
<div className={styles.header}>
<InfoCircleIcon width={16} height={16} color="uiTextMediumContrast" />
<Caption color="disabled">{name}</Caption>
<Caption color="disabled">({paymentTerm})</Caption>
<Caption>{name}</Caption>
<Caption color="uiTextPlaceholder">({paymentTerm})</Caption>
</div>
<PriceTable />
<Label size="regular" className={styles.noPricesLabel}>
<Caption color="uiTextHighContrast" type="bold">
{intl.formatMessage({ id: "No Prices available" })}
</Caption>
</Label>
</div>
)
}

View File

@@ -0,0 +1,12 @@
import { cva } from "class-variance-authority"
import styles from "./roomCard.module.css"
export const cardVariants = cva(styles.card, {
variants: {
availability: {
noAvailability: styles.noAvailability,
default: "",
},
},
})

View File

@@ -7,12 +7,14 @@ import { RateDefinition } from "@/server/routers/hotels/output"
import ToggleSidePeek from "@/components/HotelReservation/EnterDetails/SelectedRoom/ToggleSidePeek"
import FlexibilityOption from "@/components/HotelReservation/SelectRate/RoomSelection/FlexibilityOption"
import { ErrorCircleIcon } from "@/components/Icons"
import ImageGallery from "@/components/ImageGallery"
import Caption from "@/components/TempDesignSystem/Text/Caption"
import Footnote from "@/components/TempDesignSystem/Text/Footnote"
import Subtitle from "@/components/TempDesignSystem/Text/Subtitle"
import { getIconForFeatureCode } from "../../utils"
import { cardVariants } from "./cardVariants"
import styles from "./roomCard.module.css"
@@ -89,8 +91,15 @@ export default function RoomCard({
[freeCancelation, freeBooking, nonRefundable]
)
const classNames = cardVariants({
availability:
roomConfiguration.status === "NotAvailable"
? "noAvailability"
: "default",
})
return (
<div className={styles.card}>
<div className={classNames}>
<div>
{mainImage && (
<div className={styles.imageContainer}>
@@ -163,23 +172,36 @@ export default function RoomCard({
id: "Breakfast selection in next step.",
})}
</Caption>
<div className={styles.flexibilityOptions}>
{Object.entries(rates).map(([key, rate]) => (
<FlexibilityOption
key={key}
name={rateKey(key)}
value={key.toLowerCase()}
paymentTerm={key === "flexRate" ? payLater : payNow}
product={findProductForRate(rate)}
priceInformation={getPriceInformationForRate(rate)}
handleSelectRate={handleSelectRate}
roomType={roomConfiguration.roomType}
roomTypeCode={roomConfiguration.roomTypeCode}
features={roomConfiguration.features}
petRoomPackage={petRoomPackage}
/>
))}
</div>
{roomConfiguration.status === "NotAvailable" ? (
<div className={styles.noRoomsContainer}>
<div className={styles.noRooms}>
<ErrorCircleIcon color="red" width={16} />
<Caption color="uiTextHighContrast" type="bold">
{intl.formatMessage({
id: "This room is not available",
})}
</Caption>
</div>
</div>
) : (
<div className={styles.flexibilityOptions}>
{Object.entries(rates).map(([key, rate]) => (
<FlexibilityOption
key={key}
name={rateKey(key)}
value={key.toLowerCase()}
paymentTerm={key === "flexRate" ? payLater : payNow}
product={findProductForRate(rate)}
priceInformation={getPriceInformationForRate(rate)}
handleSelectRate={handleSelectRate}
roomType={roomConfiguration.roomType}
roomTypeCode={roomConfiguration.roomTypeCode}
features={roomConfiguration.features}
petRoomPackage={petRoomPackage}
/>
))}
</div>
)}
</div>
</div>
)

View File

@@ -10,6 +10,22 @@
justify-content: space-between;
}
.card.noAvailability {
justify-content: flex-start;
}
.card.noAvailability:before {
background-color: rgba(0, 0, 0, 40%);
content: "";
display: block;
position: absolute;
top: 0;
bottom: 0;
left: 0;
right: 0;
z-index: 2;
}
.specification {
display: flex;
flex-direction: row;
@@ -79,3 +95,16 @@
min-height: 190px;
position: relative;
}
.noRoomsContainer {
padding: var(--Spacing-x2);
background-color: var(--Base-Surface-Secondary-light-Normal);
border-radius: var(--Corner-radius-Medium);
margin: 0;
width: 100%;
}
.noRooms {
display: flex;
gap: var(--Spacing-x1);
}