Files
web/components/HotelReservation/SelectRate/HotelInfoCard/index.tsx
Linus Flood 5a0edc9187 Merged in fix/hoteinfocard-pass-hotel (pull request #1295)
feat:hotel info card - pass hoteldata since we already fetching it on page level

* feat:hotel info card - pass hoteldata since we already fetching it on page level
2025-02-10 14:31:41 +00:00

156 lines
5.8 KiB
TypeScript

import { mapFacilityToIcon } from "@/components/ContentType/HotelPage/data"
import ImageGallery from "@/components/ImageGallery"
import SkeletonShimmer from "@/components/SkeletonShimmer"
import Alert from "@/components/TempDesignSystem/Alert"
import Divider from "@/components/TempDesignSystem/Divider"
import Body from "@/components/TempDesignSystem/Text/Body"
import Caption from "@/components/TempDesignSystem/Text/Caption"
import Title from "@/components/TempDesignSystem/Text/Title"
import { getIntl } from "@/i18n"
import { mapApiImagesToGalleryImages } from "@/utils/imageGallery"
import { getSingleDecimal } from "@/utils/numberFormatting"
import ReadMore from "../../ReadMore"
import TripAdvisorChip from "../../TripAdvisorChip"
import styles from "./hotelInfoCard.module.css"
import type { HotelInfoCardProps } from "@/types/components/hotelReservation/selectRate/hotelInfoCard"
export default async function HotelInfoCard({ hotelData }: HotelInfoCardProps) {
const hotel = hotelData?.hotel
const intl = await getIntl()
const sortedFacilities = hotel?.detailedFacilities
.sort((a, b) => b.sortOrder - a.sortOrder)
.slice(0, 5)
const galleryImages = mapApiImagesToGalleryImages(hotel?.galleryImages || [])
return (
<article className={styles.container}>
{hotel && (
<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}>
<Title as="h2" textTransform="uppercase">
{hotel.name}
</Title>
<div className={styles.hotelAddressDescription}>
<Caption color="uiTextMediumContrast">
{intl.formatMessage(
{
id: "{address}, {city} ∙ {distanceToCityCenterInKm} km to city center",
},
{
address: hotel.address.streetAddress,
city: hotel.address.city,
distanceToCityCenterInKm: getSingleDecimal(
hotel.location.distanceToCentre / 1000
),
}
)}
</Caption>
<Body color="uiTextHighContrast">
{hotel.hotelContent.texts.descriptions.medium}
</Body>
</div>
</div>
<Divider color="subtle" variant="vertical" />
<div className={styles.facilities}>
<div className={styles.facilityList}>
<Body textTransform="bold" className={styles.facilityTitle}>
{intl.formatMessage({ id: "At the hotel" })}
</Body>
{sortedFacilities?.map((facility) => {
const IconComponent = mapFacilityToIcon(facility.id)
return (
<div className={styles.facilitiesItem} key={facility.id}>
{IconComponent && (
<IconComponent
className={styles.facilitiesIcon}
color="grey80"
/>
)}
<Body color="uiTextHighContrast">{facility.name}</Body>
</div>
)
})}
</div>
<ReadMore
label={intl.formatMessage({ id: "Show all amenities" })}
hotelId={hotel.operaId}
hotel={hotel}
showCTA={false}
/>
</div>
</div>
</section>
)}
{hotel?.specialAlerts.map((alert) => {
return (
<div className={styles.hotelAlert} key={`wrapper_${alert.id}`}>
<Alert
key={alert.id}
type={alert.type}
heading={alert.heading}
text={alert.text}
/>
</div>
)
})}
</article>
)
}
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}>
<Caption color="uiTextMediumContrast">
<SkeletonShimmer width={"40ch"} />
</Caption>
<Body color="uiTextHighContrast">
<SkeletonShimmer width={"60ch"} />
<SkeletonShimmer width={"58ch"} />
<SkeletonShimmer width={"45ch"} />
</Body>
</div>
</div>
<Divider color="subtle" variant="vertical" />
<div className={styles.facilities}>
<div className={styles.facilityList}>
<Body textTransform="bold" className={styles.facilityTitle}>
<SkeletonShimmer width={"20ch"} />
</Body>
{[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>
)
}