Merged in feature/SW-3327-move-hotel-info-card-to-design-system (pull request #2730)
Feature/SW-3327 move hotel info card to design system * wip * wip * wip * wip moving hotelinfocard * add controls for HotelInfoCard in storybook * merge Approved-by: Anton Gunnarsson
This commit is contained in:
185
packages/design-system/lib/components/HotelInfoCard/index.tsx
Normal file
185
packages/design-system/lib/components/HotelInfoCard/index.tsx
Normal file
@@ -0,0 +1,185 @@
|
||||
'use client'
|
||||
|
||||
import { getSingleDecimal } from '@scandic-hotels/common/utils/numberFormatting'
|
||||
import { Alert } from '../Alert'
|
||||
import { Divider } from '../Divider'
|
||||
import { FacilityToIcon } from '../FacilityToIcon'
|
||||
import ImageGallery, { GalleryImage } from '../ImageGallery'
|
||||
import SkeletonShimmer from '../SkeletonShimmer'
|
||||
import { TripAdvisorChip } from '../TripAdvisorChip'
|
||||
import { Typography } from '../Typography'
|
||||
|
||||
import HotelDescription from './HotelDescription'
|
||||
|
||||
import styles from './hotelInfoCard.module.css'
|
||||
import { useIntl } from 'react-intl'
|
||||
import { AlertTypeEnum } from '@scandic-hotels/common/constants/alert'
|
||||
import { FacilityEnum } from '@scandic-hotels/common/constants/facilities'
|
||||
|
||||
export type HotelInfoCardProps = {
|
||||
hotel: {
|
||||
id: string
|
||||
name: string
|
||||
url: string | null
|
||||
ratings?: {
|
||||
tripAdvisor?: { rating: number }
|
||||
}
|
||||
}
|
||||
description: string
|
||||
address: {
|
||||
streetAddress: string
|
||||
city: string
|
||||
kilometersToCentre: number
|
||||
}
|
||||
galleryImages: GalleryImage[]
|
||||
alerts: SpecialAlertProps['alert'][]
|
||||
facilities: {
|
||||
id: FacilityEnum
|
||||
name: string
|
||||
}[]
|
||||
slot?: React.ReactNode
|
||||
}
|
||||
|
||||
export function HotelInfoCard({
|
||||
hotel,
|
||||
galleryImages,
|
||||
address,
|
||||
facilities,
|
||||
alerts,
|
||||
description,
|
||||
slot,
|
||||
}: HotelInfoCardProps) {
|
||||
const intl = useIntl()
|
||||
|
||||
const firstFacilities = facilities.slice(0, 5)
|
||||
|
||||
return (
|
||||
<article className={styles.container}>
|
||||
<section className={styles.wrapper}>
|
||||
<div className={styles.imageWrapper}>
|
||||
<ImageGallery title={hotel.name} images={galleryImages} fill />
|
||||
{hotel.ratings?.tripAdvisor && (
|
||||
<TripAdvisorChip rating={hotel.ratings.tripAdvisor.rating} />
|
||||
)}
|
||||
</div>
|
||||
<div className={styles.hotelContent}>
|
||||
<div className={styles.hotelInformation}>
|
||||
<Typography variant="Title/md">
|
||||
<h1 className={styles.hotelName}>{hotel.name}</h1>
|
||||
</Typography>
|
||||
<div className={styles.hotelAddressDescription}>
|
||||
<Typography variant="Body/Supporting text (caption)/smRegular">
|
||||
<p className={styles.hotelAddress}>
|
||||
{intl.formatMessage(
|
||||
{
|
||||
defaultMessage:
|
||||
'{address}, {city} ∙ {distanceToCityCenterInKm} km to city center',
|
||||
},
|
||||
{
|
||||
address: address.streetAddress,
|
||||
city: address.city,
|
||||
distanceToCityCenterInKm: getSingleDecimal(
|
||||
address.kilometersToCentre
|
||||
),
|
||||
}
|
||||
)}
|
||||
</p>
|
||||
</Typography>
|
||||
<Typography variant="Body/Paragraph/mdRegular">
|
||||
<p className={styles.hotelDescription}>{description}</p>
|
||||
</Typography>
|
||||
<HotelDescription
|
||||
description={description}
|
||||
facilities={firstFacilities}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<Divider variant="vertical" />
|
||||
<div className={styles.facilities}>
|
||||
<div className={styles.facilityList}>
|
||||
{firstFacilities?.map((facility) => (
|
||||
<div className={styles.facilitiesItem} key={facility.id}>
|
||||
<FacilityToIcon id={facility.id} color="Icon/Default" />
|
||||
<Typography variant="Body/Supporting text (caption)/smRegular">
|
||||
<p>{facility.name}</p>
|
||||
</Typography>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
{slot}
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
<div className={styles.slotWrapper}>{slot}</div>
|
||||
{alerts.map((alert) => (
|
||||
<SpecialAlert key={alert.id} alert={alert} />
|
||||
))}
|
||||
</article>
|
||||
)
|
||||
}
|
||||
|
||||
type SpecialAlertProps = {
|
||||
alert: { id: string; type: AlertTypeEnum; heading: string; text: string }
|
||||
}
|
||||
function SpecialAlert({ alert }: SpecialAlertProps) {
|
||||
return (
|
||||
<div className={styles.hotelAlert} key={`wrapper_${alert.id}`}>
|
||||
<Alert
|
||||
key={alert.id}
|
||||
type={alert.type}
|
||||
heading={alert.heading}
|
||||
text={alert.text}
|
||||
/>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export function HotelInfoCardSkeleton() {
|
||||
return (
|
||||
<article className={styles.container}>
|
||||
<section className={styles.wrapper}>
|
||||
<div className={styles.imageWrapper}>
|
||||
<SkeletonShimmer height="100%" width="100%" />
|
||||
</div>
|
||||
<div className={styles.hotelContent}>
|
||||
<div className={styles.hotelInformation}>
|
||||
<SkeletonShimmer width="60ch" height="40px" />
|
||||
<div className={styles.hotelAddressDescription}>
|
||||
<Typography variant="Body/Supporting text (caption)/smRegular">
|
||||
<SkeletonShimmer width="40ch" />
|
||||
</Typography>
|
||||
<Typography variant="Body/Paragraph/mdRegular">
|
||||
<p>
|
||||
<SkeletonShimmer width="60ch" />
|
||||
<SkeletonShimmer width="58ch" />
|
||||
<SkeletonShimmer width="45ch" />
|
||||
</p>
|
||||
</Typography>
|
||||
</div>
|
||||
</div>
|
||||
<Divider variant="vertical" />
|
||||
<div className={styles.facilities}>
|
||||
<div className={styles.facilityList}>
|
||||
<Typography
|
||||
variant="Body/Paragraph/mdBold"
|
||||
className={styles.facilityTitle}
|
||||
>
|
||||
<SkeletonShimmer width="20ch" />
|
||||
</Typography>
|
||||
{[1, 2, 3, 4, 5]?.map((id) => {
|
||||
return (
|
||||
<div className={styles.facilitiesItem} key={id}>
|
||||
<SkeletonShimmer width="10ch" />
|
||||
</div>
|
||||
)
|
||||
})}
|
||||
</div>
|
||||
<div className={styles.hotelAlert}>
|
||||
<SkeletonShimmer width="18ch" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
</article>
|
||||
)
|
||||
}
|
||||
Reference in New Issue
Block a user