Files
web/apps/scandic-web/components/Blocks/CampaignHotelListing/HotelListingItem/index.tsx
Anton Gunnarsson 002d093af4 Merged in feat/sw-2863-move-contentstack-router-to-trpc-package (pull request #2389)
feat(SW-2863): Move contentstack router to trpc package

* Add exports to packages and lint rule to prevent relative imports

* Add env to trpc package

* Add eslint to trpc package

* Apply lint rules

* Use direct imports from trpc package

* Add lint-staged config to trpc

* Move lang enum to common

* Restructure trpc package folder structure

* WIP first step

* update internal imports in trpc

* Fix most errors in scandic-web

Just 100 left...

* Move Props type out of trpc

* Fix CategorizedFilters types

* Move more schemas in hotel router

* Fix deps

* fix getNonContentstackUrls

* Fix import error

* Fix entry error handling

* Fix generateMetadata metrics

* Fix alertType enum

* Fix duplicated types

* lint:fix

* Merge branch 'master' into feat/sw-2863-move-contentstack-router-to-trpc-package

* Fix broken imports

* Merge branch 'master' into feat/sw-2863-move-contentstack-router-to-trpc-package


Approved-by: Linus Flood
2025-06-26 07:53:01 +00:00

130 lines
4.1 KiB
TypeScript

import { useIntl } from "react-intl"
import { Divider } from "@scandic-hotels/design-system/Divider"
import HotelLogoIcon from "@scandic-hotels/design-system/Icons/HotelLogoIcon"
import TripadvisorIcon from "@scandic-hotels/design-system/Icons/TripadvisorIcon"
import { Typography } from "@scandic-hotels/design-system/Typography"
import ButtonLink from "@/components/ButtonLink"
import { FacilityToIcon } from "@/components/ContentType/HotelPage/data"
import ImageGallery from "@/components/ImageGallery"
import { mapApiImagesToGalleryImages } from "@/utils/imageGallery"
import { getSingleDecimal } from "@/utils/numberFormatting"
import styles from "./hotelListingItem.module.css"
import type { Hotel } from "@scandic-hotels/trpc/types/hotel"
interface HotelListingItemProps {
hotel: Hotel
url: string
}
export default function HotelListingItem({
hotel,
url,
}: HotelListingItemProps) {
const intl = useIntl()
const galleryImages = mapApiImagesToGalleryImages(hotel.galleryImages || [])
const tripadvisorRating = hotel.ratings?.tripAdvisor.rating
const address = `${hotel.address.streetAddress}, ${hotel.address.city}`
const amenities = hotel.detailedFacilities.slice(0, 5)
const hotelDescription = hotel.hotelContent.texts.descriptions?.short
return (
<article className={styles.hotelListingItem}>
<div className={styles.imageWrapper}>
<ImageGallery
images={galleryImages}
fill
sizes="(min-width: 768px) 450px, 100vw"
title={intl.formatMessage(
{
defaultMessage: "{title} - Image gallery",
},
{ title: hotel.name }
)}
/>
{tripadvisorRating ? (
<Typography variant="Title/Overline/sm">
<div className={styles.tripAdvisor}>
<TripadvisorIcon color="CurrentColor" />
<span>{tripadvisorRating}</span>
</div>
</Typography>
) : null}
</div>
<div className={styles.content}>
<div className={styles.intro}>
<HotelLogoIcon
hotelId={hotel.operaId}
hotelType={hotel.hotelType}
height={30}
/>
<Typography variant="Title/Subtitle/md">
<h3>{hotel.name}</h3>
</Typography>
<Typography variant="Body/Supporting text (caption)/smRegular">
<div className={styles.captions}>
<span>{address}</span>
<span>
<Divider
className={styles.divider}
variant="vertical"
color="Border/Divider/Default"
/>
</span>
<span>
{intl.formatMessage(
{
defaultMessage: "{number} km to city center",
},
{
number: getSingleDecimal(
hotel.location.distanceToCentre / 1000
),
}
)}
</span>
</div>
</Typography>
</div>
{hotelDescription ? (
<Typography variant="Body/Paragraph/mdRegular">
<p>{hotelDescription}</p>
</Typography>
) : null}
<Typography variant="Body/Supporting text (caption)/smRegular">
<ul className={styles.amenityList}>
{amenities.map((amenity) => {
return (
<li className={styles.amenityItem} key={amenity.id}>
<FacilityToIcon
id={amenity.id}
color="CurrentColor"
size={20}
/>
{amenity.name}
</li>
)
})}
</ul>
</Typography>
</div>
<div className={styles.ctaWrapper}>
<ButtonLink
href={url}
variant="Tertiary"
color="Primary"
size="Small"
typography="Body/Supporting text (caption)/smBold"
>
{intl.formatMessage({
defaultMessage: "See hotel details",
})}
</ButtonLink>
</div>
</article>
)
}