Files
web/apps/scandic-web/components/Blocks/CampaignHotelListing/HotelListingItem/index.tsx
Matilda Landström ae77fa3028 Merged in refactor-tripadvisor-chip (pull request #3404)
Refactor TripadvisorChip

* feat: create new StaticChip componeny

* refactor tripadvisor chip to use ChipStatic

* refactor: use TripadvisorChip everywhere

* fix: use withChipStatic


Approved-by: Erik Tiekstra
2026-01-23 12:19:37 +00:00

129 lines
4.2 KiB
TypeScript

import { useIntl } from "react-intl"
import { getSingleDecimal } from "@scandic-hotels/common/utils/numberFormatting"
import ButtonLink from "@scandic-hotels/design-system/ButtonLink"
import { Divider } from "@scandic-hotels/design-system/Divider"
import { FacilityToIcon } from "@scandic-hotels/design-system/FacilityToIcon"
import HotelLogoIcon from "@scandic-hotels/design-system/Icons/HotelLogoIcon"
import ImageGallery from "@scandic-hotels/design-system/ImageGallery"
import { TripAdvisorChip } from "@scandic-hotels/design-system/TripAdvisorChip"
import { Typography } from "@scandic-hotels/design-system/Typography"
import { mapApiImagesToGalleryImages } from "@/utils/imageGallery"
import styles from "./hotelListingItem.module.css"
import type { HotelListingHotelData } from "@scandic-hotels/trpc/types/hotel"
interface HotelListingItemProps {
hotel: HotelListingHotelData["hotel"]
url: string | null
}
export default function HotelListingItem({
hotel,
url,
}: HotelListingItemProps) {
const intl = useIntl()
const galleryImages = mapApiImagesToGalleryImages(hotel.galleryImages)
const tripadvisorRating = hotel.tripadvisor
const address = `${hotel.address.streetAddress}, ${hotel.address.city}`
const amenities = hotel.detailedFacilities.slice(0, 5)
const hotelDescription = hotel.description
return (
<article className={styles.hotelListingItem}>
<div className={styles.imageWrapper}>
<ImageGallery
images={galleryImages}
fill
sizes="(min-width: 768px) 450px, 100vw"
title={intl.formatMessage(
{
id: "common.imageGalleryWithTitle",
defaultMessage: "{title} - Image gallery",
},
{ title: hotel.name }
)}
/>
{tripadvisorRating ? (
<TripAdvisorChip
color="Neutral"
rating={tripadvisorRating}
wrapper="x2"
size="sm"
/>
) : null}
</div>
<div className={styles.content}>
<div className={styles.intro}>
<HotelLogoIcon
hotelId={hotel.id}
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(
{
id: "common.kmToCityCenter",
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>
{url ? (
<div className={styles.ctaWrapper}>
<ButtonLink href={url} variant="Tertiary" color="Primary" size="sm">
{intl.formatMessage({
id: "destination.seeHotelDetails",
defaultMessage: "See hotel details",
})}
</ButtonLink>
</div>
) : null}
</article>
)
}