diff --git a/app/[lang]/(live)/(public)/hotelreservation/(standard)/select-rate/page.tsx b/app/[lang]/(live)/(public)/hotelreservation/(standard)/select-rate/page.tsx index dc5c7a6b5..29c602779 100644 --- a/app/[lang]/(live)/(public)/hotelreservation/(standard)/select-rate/page.tsx +++ b/app/[lang]/(live)/(public)/hotelreservation/(standard)/select-rate/page.tsx @@ -84,25 +84,33 @@ export default async function SelectRatePage({ getProfileSafely(), ]) - if (!roomsAvailability) { - return "No rooms found" // TODO: Add a proper error message - } - if (!hotelData) { return "No hotel data found" // TODO: Add a proper error message } const roomCategories = hotelData?.included + const noRoomsAvailable = roomsAvailability?.roomConfigurations.reduce( + (acc, room) => { + return acc && room.status === "NotAvailable" + }, + true + ) + return ( <> - - + {roomsAvailability ? ( + + ) : null} ) } diff --git a/components/HotelReservation/SelectRate/HotelInfoCard/index.tsx b/components/HotelReservation/SelectRate/HotelInfoCard/index.tsx index 28ce32377..8eabe85ba 100644 --- a/components/HotelReservation/SelectRate/HotelInfoCard/index.tsx +++ b/components/HotelReservation/SelectRate/HotelInfoCard/index.tsx @@ -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) { ) })} + {noAvailability ? ( +
+ +
+ ) : null} ) } diff --git a/components/HotelReservation/SelectRate/RoomSelection/FlexibilityOption/flexibilityOption.module.css b/components/HotelReservation/SelectRate/RoomSelection/FlexibilityOption/flexibilityOption.module.css index 1f1debe12..80da80184 100644 --- a/components/HotelReservation/SelectRate/RoomSelection/FlexibilityOption/flexibilityOption.module.css +++ b/components/HotelReservation/SelectRate/RoomSelection/FlexibilityOption/flexibilityOption.module.css @@ -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; diff --git a/components/HotelReservation/SelectRate/RoomSelection/FlexibilityOption/index.tsx b/components/HotelReservation/SelectRate/RoomSelection/FlexibilityOption/index.tsx index 9bc6ca1f3..5a046978c 100644 --- a/components/HotelReservation/SelectRate/RoomSelection/FlexibilityOption/index.tsx +++ b/components/HotelReservation/SelectRate/RoomSelection/FlexibilityOption/index.tsx @@ -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(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 ( -
+
- {name} - ({paymentTerm}) + {name} + ({paymentTerm})
- +
) } diff --git a/components/HotelReservation/SelectRate/RoomSelection/RoomCard/cardVariants.ts b/components/HotelReservation/SelectRate/RoomSelection/RoomCard/cardVariants.ts new file mode 100644 index 000000000..b34d00e23 --- /dev/null +++ b/components/HotelReservation/SelectRate/RoomSelection/RoomCard/cardVariants.ts @@ -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: "", + }, + }, +}) diff --git a/components/HotelReservation/SelectRate/RoomSelection/RoomCard/index.tsx b/components/HotelReservation/SelectRate/RoomSelection/RoomCard/index.tsx index 4f3b398db..47533dcdc 100644 --- a/components/HotelReservation/SelectRate/RoomSelection/RoomCard/index.tsx +++ b/components/HotelReservation/SelectRate/RoomSelection/RoomCard/index.tsx @@ -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 ( -
+
{mainImage && (
@@ -163,23 +172,36 @@ export default function RoomCard({ id: "Breakfast selection in next step.", })} -
- {Object.entries(rates).map(([key, rate]) => ( - - ))} -
+ {roomConfiguration.status === "NotAvailable" ? ( +
+
+ + + {intl.formatMessage({ + id: "This room is not available", + })} + +
+
+ ) : ( +
+ {Object.entries(rates).map(([key, rate]) => ( + + ))} +
+ )}
) diff --git a/components/HotelReservation/SelectRate/RoomSelection/RoomCard/roomCard.module.css b/components/HotelReservation/SelectRate/RoomSelection/RoomCard/roomCard.module.css index 1d7ac0a0e..8ec1978e6 100644 --- a/components/HotelReservation/SelectRate/RoomSelection/RoomCard/roomCard.module.css +++ b/components/HotelReservation/SelectRate/RoomSelection/RoomCard/roomCard.module.css @@ -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); +} diff --git a/i18n/dictionaries/da.json b/i18n/dictionaries/da.json index 47feb8b4e..7cd40f4c5 100644 --- a/i18n/dictionaries/da.json +++ b/i18n/dictionaries/da.json @@ -339,6 +339,7 @@ "There are no rooms available that match your request.": "Der er ingen værelser tilgængelige, der matcher din forespørgsel.", "There are no transactions to display": "Der er ingen transaktioner at vise", "Things nearby HOTEL_NAME": "Ting i nærheden af {hotelName}", + "This room is not available": "Dette værelse er ikke tilgængeligt", "To get the member price {amount} {currency}, log in or join when completing the booking.": "For at få medlemsprisen {amount} {currency}, log ind eller tilmeld dig, når du udfylder bookingen.", "To secure your reservation, we kindly ask you to provide your payment card details. Rest assured, no charges will be made at this time.": "For at sikre din reservation, beder vi om at du giver os dine betalingsoplysninger. Du kan så være sikker på, at ingen gebyrer vil blive opkrævet på dette tidspunkt.", "Total Points": "Samlet antal point", diff --git a/i18n/dictionaries/de.json b/i18n/dictionaries/de.json index 91256509d..2d28e2626 100644 --- a/i18n/dictionaries/de.json +++ b/i18n/dictionaries/de.json @@ -338,6 +338,7 @@ "There are no rooms available that match your request.": "Es sind keine Zimmer verfügbar, die Ihrer Anfrage entsprechen.", "There are no transactions to display": "Es sind keine Transaktionen zum Anzeigen vorhanden", "Things nearby HOTEL_NAME": "Dinge in der Nähe von {hotelName}", + "This room is not available": "Dieses Zimmer ist nicht verfügbar", "To get the member price {amount} {currency}, log in or join when completing the booking.": "Um den Mitgliederpreis von {amount} {currency} zu erhalten, loggen Sie sich ein oder treten Sie Scandic Friends bei, wenn Sie die Buchung abschließen.", "To secure your reservation, we kindly ask you to provide your payment card details. Rest assured, no charges will be made at this time.": "Um Ihre Reservierung zu sichern, bitten wir Sie, Ihre Zahlungskarteninformationen zu geben. Sie können sicher sein, dass keine Gebühren zu diesem Zeitpunkt erhoben werden.", "Total Points": "Gesamtpunktzahl", diff --git a/i18n/dictionaries/en.json b/i18n/dictionaries/en.json index 664069250..d5ab06e41 100644 --- a/i18n/dictionaries/en.json +++ b/i18n/dictionaries/en.json @@ -368,6 +368,7 @@ "There are no rooms available that match your request.": "There are no rooms available that match your request.", "There are no transactions to display": "There are no transactions to display", "Things nearby HOTEL_NAME": "Things nearby {hotelName}", + "This room is not available": "This room is not available", "To get the member price {amount} {currency}, log in or join when completing the booking.": "To get the member price {amount} {currency}, log in or join when completing the booking.", "To secure your reservation, we kindly ask you to provide your payment card details. Rest assured, no charges will be made at this time.": "To secure your reservation, we kindly ask you to provide your payment card details. Rest assured, no charges will be made at this time.", "Total Points": "Total Points", diff --git a/i18n/dictionaries/fi.json b/i18n/dictionaries/fi.json index ca9e330ea..114531609 100644 --- a/i18n/dictionaries/fi.json +++ b/i18n/dictionaries/fi.json @@ -340,6 +340,7 @@ "There are no rooms available that match your request.": "Ei huoneita saatavilla, jotka vastaavat pyyntöäsi.", "There are no transactions to display": "Näytettäviä tapahtumia ei ole", "Things nearby HOTEL_NAME": "Lähellä olevia asioita {hotelName}", + "This room is not available": "Tämä huone ei ole käytettävissä", "To get the member price {amount} {currency}, log in or join when completing the booking.": "Jäsenhintaan saavat sisäänkirjautuneet tai liittyneet jäsenet.", "To secure your reservation, we kindly ask you to provide your payment card details. Rest assured, no charges will be made at this time.": "Varmistaaksesi varauksen, pyydämme sinua antamaan meille maksukortin tiedot. Varmista, että ei veloiteta maksusi tällä hetkellä.", "Total Points": "Kokonaispisteet", diff --git a/i18n/dictionaries/no.json b/i18n/dictionaries/no.json index 2c61f1596..a2d8f8bee 100644 --- a/i18n/dictionaries/no.json +++ b/i18n/dictionaries/no.json @@ -337,6 +337,7 @@ "There are no rooms available that match your request.": "Det er ingen rom tilgjengelige som matcher din forespørsel.", "There are no transactions to display": "Det er ingen transaksjoner å vise", "Things nearby HOTEL_NAME": "Ting i nærheten av {hotelName}", + "This room is not available": "Dette rommet er ikke tilgjengelig", "To get the member price {amount} {currency}, log in or join when completing the booking.": "For å få medlemsprisen {amount} {currency}, logg inn eller bli med når du fullfører bestillingen.", "To secure your reservation, we kindly ask you to provide your payment card details. Rest assured, no charges will be made at this time.": "For å sikre din reservasjon, ber vi om at du gir oss dine betalingskortdetaljer. Vær sikker på at ingen gebyrer vil bli belastet på dette tidspunktet.", "Total Points": "Totale poeng", diff --git a/i18n/dictionaries/sv.json b/i18n/dictionaries/sv.json index 911553c7b..117af5485 100644 --- a/i18n/dictionaries/sv.json +++ b/i18n/dictionaries/sv.json @@ -337,6 +337,7 @@ "There are no rooms available that match your request.": "Det finns inga rum tillgängliga som matchar din begäran.", "There are no transactions to display": "Det finns inga transaktioner att visa", "Things nearby HOTEL_NAME": "Saker i närheten av {hotelName}", + "This room is not available": "Detta rum är inte tillgängligt", "To get the member price {amount} {currency}, log in or join when completing the booking.": "För att få medlemsprisen {amount} {currency}, logga in eller bli medlem när du slutför bokningen.", "To secure your reservation, we kindly ask you to provide your payment card details. Rest assured, no charges will be made at this time.": "För att säkra din bokning ber vi om att du ger oss dina betalkortdetaljer. Välj säker på att ingen avgifter kommer att debiteras just nu.", "Total Points": "Poäng totalt", diff --git a/types/components/hotelReservation/selectRate/hotelInfoCardProps.ts b/types/components/hotelReservation/selectRate/hotelInfoCardProps.ts index 0a3526167..088c54e51 100644 --- a/types/components/hotelReservation/selectRate/hotelInfoCardProps.ts +++ b/types/components/hotelReservation/selectRate/hotelInfoCardProps.ts @@ -2,4 +2,5 @@ import type { HotelData } from "@/types/hotel" export type HotelInfoCardProps = { hotelData: HotelData | null + noAvailability: boolean }