feat(SW-340): Added HotelCardDialog component

This commit is contained in:
Pontus Dreij
2024-11-07 16:07:54 +01:00
parent 7a49d4a393
commit 2748120890
19 changed files with 309 additions and 41 deletions

View File

@@ -67,7 +67,7 @@
}
@media screen and (min-width: 1367px) {
.card.listing {
.card.pageListing {
grid-template-areas:
"image header"
"image hotel"
@@ -76,30 +76,30 @@
padding: 0;
}
.listing .imageContainer {
.pageListing .imageContainer {
position: relative;
min-height: 200px;
width: 518px;
}
.listing .tripAdvisor {
.pageListing .tripAdvisor {
position: absolute;
display: block;
left: 7px;
top: 7px;
}
.listing .hotelInformation {
.pageListing .hotelInformation {
padding-top: var(--Spacing-x2);
padding-right: var(--Spacing-x2);
}
.listing .hotel {
.pageListing .hotel {
gap: var(--Spacing-x2);
padding-right: var(--Spacing-x2);
}
.listing .prices {
.pageListing .prices {
flex-direction: row;
align-items: center;
justify-content: space-between;
@@ -107,11 +107,11 @@
padding-bottom: var(--Spacing-x2);
}
.listing .detailsButton {
.pageListing .detailsButton {
border-bottom: none;
}
.listing .button {
.pageListing .button {
width: 160px;
}
}

View File

@@ -17,9 +17,13 @@ import { hotelCardVariants } from "./variants"
import styles from "./hotelCard.module.css"
import { HotelCardListingType } from "@/types/components/hotelReservation/selectHotel/hotelCardListingProps"
import type { HotelCardProps } from "@/types/components/hotelReservation/selectHotel/hotelCardProps"
export default function HotelCard({ hotel, type = "listing" }: HotelCardProps) {
export default function HotelCard({
hotel,
type = HotelCardListingType.PageListing,
}: HotelCardProps) {
const intl = useIntl()
const { hotelData } = hotel

View File

@@ -5,11 +5,11 @@ import styles from "./hotelCard.module.css"
export const hotelCardVariants = cva(styles.card, {
variants: {
type: {
listing: styles.listing,
map: styles.map,
pageListing: styles.pageListing,
mapListing: styles.mapListing,
},
},
defaultVariants: {
type: "listing",
type: "pageListing",
},
})

View File

@@ -0,0 +1,70 @@
.dialog {
padding-bottom: var(--Spacing-x1);
bottom: 32px;
left: 50%;
transform: translateX(-50%);
border: none;
background: transparent;
}
.dialogContainer {
border: 1px solid var(--Base-Border-Subtle);
border-radius: var(--Corner-radius-Medium);
width: 402px;
min-height: 227px;
background: var(--Base-Surface-Primary-light-Normal);
box-shadow: 0px 0px 8px 3px rgba(0, 0, 0, 0.1);
flex-direction: row;
display: flex;
}
.imageContainer {
position: relative;
min-height: 227px;
width: 177px;
}
.tripAdvisor {
display: none;
}
.imageContainer img {
object-fit: cover;
}
.content {
width: 100%;
padding: var(--Spacing-x-one-and-half);
gap: var(--Spacing-x1);
display: flex;
flex-direction: column;
}
.facilities {
display: flex;
flex-wrap: wrap;
gap: var(--Spacing-x1);
}
.facilitiesItem {
display: flex;
align-items: center;
gap: var(--Spacing-x-half);
}
.prices {
border-radius: var(--Corner-radius-Medium);
padding: var(--Spacing-x-half) var(--Spacing-x1);
background: var(--Base-Surface-Secondary-light-Normal);
display: flex;
flex-direction: column;
gap: var(--Spacing-x-half);
}
.perNight {
color: var(--Base-Text-Subtle-light-Normal);
}
.button {
margin-top: auto;
}

View File

@@ -0,0 +1,90 @@
"use client"
import { useIntl } from "react-intl"
import { mapFacilityToIcon } from "@/components/ContentType/HotelPage/data"
import TripAdvisorIcon from "@/components/Icons/TripAdvisor"
import Image from "@/components/Image"
import Button from "@/components/TempDesignSystem/Button"
import Chip from "@/components/TempDesignSystem/Chip"
import Body from "@/components/TempDesignSystem/Text/Body"
import Caption from "@/components/TempDesignSystem/Text/Caption"
import Subtitle from "@/components/TempDesignSystem/Text/Subtitle"
import styles from "./hotelCardDialog.module.css"
import { HotelPin } from "@/types/components/hotelReservation/selectHotel/map"
export default function HotelCardDialog({
pin,
isOpen,
}: {
isOpen: boolean
pin: HotelPin
}) {
const intl = useIntl()
const {
name,
publicPrice,
memberPrice,
currency,
amenities,
images,
ratings,
} = pin
return (
<dialog open={isOpen} className={styles.dialog}>
<div className={styles.dialogContainer}>
<div className={styles.imageContainer}>
<Image
src={images[0].imageSizes.small}
alt={images[0].metaData.altText}
fill
/>
<div className={styles.tripAdvisor}>
<Chip intent="primary" className={styles.tripAdvisor}>
<TripAdvisorIcon color="white" />
{ratings}
</Chip>
</div>
</div>
<div className={styles.content}>
<Body textTransform="bold">{name}</Body>
<div className={styles.facilities}>
{amenities.map((facility) => {
const IconComponent = mapFacilityToIcon(facility.id)
return (
<div className={styles.facilitiesItem} key={facility.id}>
{IconComponent && <IconComponent color="grey80" />}
<Caption color="textMediumContrast">{facility.name}</Caption>
</div>
)
})}
</div>
<div className={styles.prices}>
<Caption type="bold">{intl.formatMessage({ id: "From" })}</Caption>
<Subtitle type="two">
{publicPrice} {currency}
<Body asChild>
<span>/{intl.formatMessage({ id: "night" })}</span>
</Body>
</Subtitle>
{memberPrice && (
<Subtitle type="two" color="red">
{memberPrice} {currency}
<Body asChild color="red">
<span>/{intl.formatMessage({ id: "night" })}</span>
</Body>
</Subtitle>
)}
</div>
<Button size="small" theme="base" className={styles.button}>
{intl.formatMessage({ id: "See rooms" })}
</Button>
</div>
</div>
</dialog>
)
}

View File

@@ -8,11 +8,14 @@ import HotelCard from "../HotelCard"
import styles from "./hotelCardListing.module.css"
import { HotelCardListingProps } from "@/types/components/hotelReservation/selectHotel/hotelCardListingProps"
import {
HotelCardListingProps,
HotelCardListingType,
} from "@/types/components/hotelReservation/selectHotel/hotelCardListingProps"
export default function HotelCardListing({
hotelData,
type = "listing",
type = HotelCardListingType.PageListing,
}: HotelCardListingProps) {
const searchParams = useSearchParams()

View File

@@ -4,12 +4,16 @@ import HotelCardListing from "@/components/HotelReservation/HotelCardListing"
import styles from "./hotelListing.module.css"
import { HotelCardListingType } from "@/types/components/hotelReservation/selectHotel/hotelCardListingProps"
import type { HotelListingProps } from "@/types/components/hotelReservation/selectHotel/map"
export default function HotelListing({ hotels }: HotelListingProps) {
return (
<div className={styles.hotelListing}>
<HotelCardListing hotelData={hotels} type="map" />
<HotelCardListing
hotelData={hotels}
type={HotelCardListingType.MapListing}
/>
</div>
)
}

View File

@@ -72,6 +72,7 @@ export default function SelectHotelMap({
closeButton={closeButton}
coordinates={coordinates}
hotelPins={hotelPins}
hotels={hotels}
activeHotelPin={activeHotelPin}
onActiveHotelPinChange={setActiveHotelPin}
mapId={mapId}