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:
Bianca Widstam
2024-11-14 10:31:11 +00:00
parent 3698d6a5bb
commit 3e62df27cc
3 changed files with 89 additions and 89 deletions

View File

@@ -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>
) )
} }

View File

@@ -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 {

View File

@@ -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);
}
} }