fix/SW-674-rate-cards-vertically-aligned (pull request #858)
Fix/SW-674 rate cards vertically aligned * fix(SW-674): fix cards aligned * fix(SW-674): fix columns for smaller ipad/tablet * fix(SW-674): fix height on flexibility options * fix(SW-674): fix comments * fix(SW-674): remove margin * fix(SW-674): auto fill with columns Approved-by: Simon.Emanuelsson Approved-by: Pontus Dreij Approved-by: Niclas Edenvin
This commit is contained in:
@@ -1,6 +1,6 @@
|
|||||||
"use client"
|
"use client"
|
||||||
|
|
||||||
import { createElement } from "react"
|
import { createElement, useCallback } from "react"
|
||||||
import { useIntl } from "react-intl"
|
import { useIntl } from "react-intl"
|
||||||
|
|
||||||
import { RateDefinition } from "@/server/routers/hotels/output"
|
import { RateDefinition } from "@/server/routers/hotels/output"
|
||||||
@@ -69,9 +69,61 @@ export default function RoomCard({
|
|||||||
const { roomSize, occupancy, descriptions, images } = selectedRoom || {}
|
const { roomSize, occupancy, descriptions, images } = selectedRoom || {}
|
||||||
const mainImage = images?.[0]
|
const mainImage = images?.[0]
|
||||||
|
|
||||||
|
const freeCancelation = intl.formatMessage({ id: "Free cancellation" })
|
||||||
|
const nonRefundable = intl.formatMessage({ id: "Non-refundable" })
|
||||||
|
const freeBooking = intl.formatMessage({ id: "Free rebooking" })
|
||||||
|
const payLater = intl.formatMessage({ id: "Pay later" })
|
||||||
|
const payNow = intl.formatMessage({ id: "Pay now" })
|
||||||
|
|
||||||
|
const rateKey = useCallback(
|
||||||
|
(key: string) => {
|
||||||
|
switch (key) {
|
||||||
|
case "flexRate":
|
||||||
|
return freeCancelation
|
||||||
|
case "saveRate":
|
||||||
|
return nonRefundable
|
||||||
|
default:
|
||||||
|
return freeBooking
|
||||||
|
}
|
||||||
|
},
|
||||||
|
[freeCancelation, freeBooking, nonRefundable]
|
||||||
|
)
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={styles.card}>
|
<div className={styles.card}>
|
||||||
<div className={styles.cardBody}>
|
<div>
|
||||||
|
{mainImage && (
|
||||||
|
<div className={styles.imageContainer}>
|
||||||
|
<div className={styles.chipContainer}>
|
||||||
|
{roomConfiguration.roomsLeft < 5 && (
|
||||||
|
<span className={styles.chip}>
|
||||||
|
<Footnote
|
||||||
|
color="burgundy"
|
||||||
|
textTransform="uppercase"
|
||||||
|
>{`${roomConfiguration.roomsLeft} ${intl.formatMessage({ id: "Left" })}`}</Footnote>
|
||||||
|
</span>
|
||||||
|
)}
|
||||||
|
{roomConfiguration.features
|
||||||
|
.filter((feature) => selectedPackages.includes(feature.code))
|
||||||
|
.map((feature) => (
|
||||||
|
<span className={styles.chip} key={feature.code}>
|
||||||
|
{createElement(getIconForFeatureCode(feature.code), {
|
||||||
|
width: 16,
|
||||||
|
height: 16,
|
||||||
|
color: "burgundy",
|
||||||
|
})}
|
||||||
|
</span>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
{/*NOTE: images from the test API are hosted on test3.scandichotels.com,
|
||||||
|
which can't be accessed unless on Scandic's Wifi or using Citrix. */}
|
||||||
|
<ImageGallery
|
||||||
|
images={images}
|
||||||
|
title={roomConfiguration.roomType}
|
||||||
|
fill
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
<div className={styles.specification}>
|
<div className={styles.specification}>
|
||||||
<Caption color="uiTextMediumContrast" className={styles.guests}>
|
<Caption color="uiTextMediumContrast" className={styles.guests}>
|
||||||
{intl.formatMessage(
|
{intl.formatMessage(
|
||||||
@@ -96,81 +148,39 @@ export default function RoomCard({
|
|||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className={styles.container}>
|
<div className={styles.roomDetails}>
|
||||||
<div className={styles.roomDetails}>
|
<Subtitle className={styles.name} type="two">
|
||||||
<Subtitle className={styles.name} type="two">
|
{roomConfiguration.roomType}
|
||||||
{roomConfiguration.roomType}
|
</Subtitle>
|
||||||
</Subtitle>
|
{/* Out of scope for now
|
||||||
{/* Out of scope for now
|
|
||||||
<Body>{descriptions?.short}</Body>
|
<Body>{descriptions?.short}</Body>
|
||||||
*/}
|
*/}
|
||||||
<Caption color="uiTextHighContrast" type="bold">
|
|
||||||
{intl.formatMessage({
|
|
||||||
id: "Breakfast selection in next step.",
|
|
||||||
})}
|
|
||||||
</Caption>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div className={styles.flexibilityOptions}>
|
|
||||||
{Object.entries(rates).map(([key, rate]) => (
|
|
||||||
<FlexibilityOption
|
|
||||||
key={key}
|
|
||||||
name={intl.formatMessage({
|
|
||||||
id:
|
|
||||||
key === "flexRate"
|
|
||||||
? "Free cancellation"
|
|
||||||
: key === "saveRate"
|
|
||||||
? "Non-refundable"
|
|
||||||
: "Free rebooking",
|
|
||||||
})}
|
|
||||||
value={key.toLowerCase()}
|
|
||||||
paymentTerm={intl.formatMessage({
|
|
||||||
id: key === "flexRate" ? "Pay later" : "Pay now",
|
|
||||||
})}
|
|
||||||
product={findProductForRate(rate)}
|
|
||||||
priceInformation={getPriceInformationForRate(rate)}
|
|
||||||
handleSelectRate={handleSelectRate}
|
|
||||||
roomType={roomConfiguration.roomType}
|
|
||||||
roomTypeCode={roomConfiguration.roomTypeCode}
|
|
||||||
features={roomConfiguration.features}
|
|
||||||
petRoomPackage={petRoomPackage}
|
|
||||||
/>
|
|
||||||
))}
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{mainImage && (
|
<div className={styles.container}>
|
||||||
<div className={styles.imageContainer}>
|
<Caption color="uiTextHighContrast" type="bold">
|
||||||
<div className={styles.chipContainer}>
|
{intl.formatMessage({
|
||||||
{roomConfiguration.roomsLeft < 5 && (
|
id: "Breakfast selection in next step.",
|
||||||
<span className={styles.chip}>
|
})}
|
||||||
<Footnote
|
</Caption>
|
||||||
color="burgundy"
|
<div className={styles.flexibilityOptions}>
|
||||||
textTransform="uppercase"
|
{Object.entries(rates).map(([key, rate]) => (
|
||||||
>{`${roomConfiguration.roomsLeft} ${intl.formatMessage({ id: "Left" })}`}</Footnote>
|
<FlexibilityOption
|
||||||
</span>
|
key={key}
|
||||||
)}
|
name={rateKey(key)}
|
||||||
{roomConfiguration.features
|
value={key.toLowerCase()}
|
||||||
.filter((feature) => selectedPackages.includes(feature.code))
|
paymentTerm={key === "flexRate" ? payLater : payNow}
|
||||||
.map((feature) => (
|
product={findProductForRate(rate)}
|
||||||
<span className={styles.chip} key={feature.code}>
|
priceInformation={getPriceInformationForRate(rate)}
|
||||||
{createElement(getIconForFeatureCode(feature.code), {
|
handleSelectRate={handleSelectRate}
|
||||||
width: 16,
|
roomType={roomConfiguration.roomType}
|
||||||
height: 16,
|
roomTypeCode={roomConfiguration.roomTypeCode}
|
||||||
color: "burgundy",
|
features={roomConfiguration.features}
|
||||||
})}
|
petRoomPackage={petRoomPackage}
|
||||||
</span>
|
/>
|
||||||
))}
|
))}
|
||||||
</div>
|
|
||||||
{/*NOTE: images from the test API are hosted on test3.scandichotels.com,
|
|
||||||
which can't be accessed unless on Scandic's Wifi or using Citrix. */}
|
|
||||||
<ImageGallery
|
|
||||||
images={images}
|
|
||||||
title={roomConfiguration.roomType}
|
|
||||||
fill
|
|
||||||
/>
|
|
||||||
</div>
|
</div>
|
||||||
)}
|
</div>
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,16 +1,13 @@
|
|||||||
.card {
|
.card {
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column-reverse;
|
flex-direction: column;
|
||||||
background-color: #fff;
|
background-color: #fff;
|
||||||
border-radius: var(--Corner-radius-Large);
|
border-radius: var(--Corner-radius-Large);
|
||||||
border: 1px solid var(--Base-Border-Subtle);
|
border: 1px solid var(--Base-Border-Subtle);
|
||||||
position: relative;
|
position: relative;
|
||||||
}
|
height: 100%;
|
||||||
|
justify-content: space-between;
|
||||||
.cardBody {
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.specification {
|
.specification {
|
||||||
@@ -41,7 +38,8 @@
|
|||||||
.roomDetails {
|
.roomDetails {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
gap: var(--Spacing-x2);
|
gap: var(--Spacing-x1);
|
||||||
|
padding: var(--Spacing-x1) var(--Spacing-x2) var(--Spacing-x2);
|
||||||
}
|
}
|
||||||
|
|
||||||
.name {
|
.name {
|
||||||
|
|||||||
@@ -19,14 +19,6 @@
|
|||||||
width: 0;
|
width: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@media (min-width: 767px) {
|
.roomList {
|
||||||
.roomList {
|
grid-template-columns: repeat(auto-fill, minmax(320px, 1fr));
|
||||||
grid-template-columns: repeat(3, minmax(240px, 1fr));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@media (min-width: 1367px) {
|
|
||||||
.roomList {
|
|
||||||
grid-template-columns: repeat(4, 1fr);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user