130 lines
4.4 KiB
TypeScript
130 lines
4.4 KiB
TypeScript
import { Suspense } from "react"
|
|
|
|
import { getHotelData } from "@/lib/trpc/memoizedRequests"
|
|
|
|
import { mapFacilityToIcon } from "@/components/ContentType/HotelPage/data"
|
|
import ImageGallery from "@/components/ImageGallery"
|
|
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 getSingleDecimal from "@/utils/numberFormatting"
|
|
|
|
import ReadMore from "../../ReadMore"
|
|
import TripAdvisorChip from "../../TripAdvisorChip"
|
|
import { NoRoomsAlert } from "./NoRoomsAlert"
|
|
|
|
import styles from "./hotelInfoCard.module.css"
|
|
|
|
import type { Child } from "@/types/components/hotelReservation/selectRate/selectRate"
|
|
import type { Lang } from "@/constants/languages"
|
|
|
|
type Props = {
|
|
hotelId: number
|
|
lang: Lang
|
|
fromDate: Date
|
|
toDate: Date
|
|
adultCount: number
|
|
childArray?: Child[]
|
|
}
|
|
|
|
export default async function HotelInfoCard({
|
|
hotelId,
|
|
lang,
|
|
...props
|
|
}: Props) {
|
|
const hotelData = await getHotelData({
|
|
hotelId: hotelId.toString(),
|
|
language: lang,
|
|
})
|
|
|
|
const hotelAttributes = hotelData?.data.attributes
|
|
const intl = await getIntl()
|
|
|
|
const sortedFacilities = hotelAttributes?.detailedFacilities
|
|
.sort((a, b) => b.sortOrder - a.sortOrder)
|
|
.slice(0, 5)
|
|
|
|
return (
|
|
<article className={styles.container}>
|
|
{hotelAttributes && (
|
|
<section className={styles.wrapper}>
|
|
<div className={styles.imageWrapper}>
|
|
<ImageGallery
|
|
title={hotelAttributes.name}
|
|
images={hotelAttributes.galleryImages}
|
|
fill
|
|
/>
|
|
{hotelAttributes.ratings?.tripAdvisor && (
|
|
<TripAdvisorChip
|
|
rating={hotelAttributes.ratings.tripAdvisor.rating}
|
|
/>
|
|
)}
|
|
</div>
|
|
<div className={styles.hotelContent}>
|
|
<div className={styles.hotelInformation}>
|
|
<Title as="h2" textTransform="uppercase">
|
|
{hotelAttributes.name}
|
|
</Title>
|
|
<div className={styles.hotelAddressDescription}>
|
|
<Caption color="uiTextMediumContrast">
|
|
{`${hotelAttributes.address.streetAddress}, ${hotelAttributes.address.city} ∙ ${getSingleDecimal(hotelAttributes.location.distanceToCentre / 1000)} ${intl.formatMessage({ id: "km to city center" })}`}
|
|
</Caption>
|
|
<Body color="uiTextHighContrast">
|
|
{hotelAttributes.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={hotelAttributes.operaId}
|
|
hotel={hotelAttributes}
|
|
showCTA={false}
|
|
/>
|
|
</div>
|
|
</div>
|
|
</section>
|
|
)}
|
|
{hotelAttributes?.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>
|
|
)
|
|
})}
|
|
|
|
<Suspense fallback={null} key={hotelId}>
|
|
<NoRoomsAlert hotelId={hotelId} lang={lang} {...props} />
|
|
</Suspense>
|
|
</article>
|
|
)
|
|
}
|