Files
web/apps/scandic-web/components/Blocks/CampaignHotelListing/HotelListingItem/index.tsx
Joakim Jäderberg c54c1ec540 Merged in SW-3270-move-interactive-map-to-design-system-or-booking-flow (pull request #2681)
SW-3270 move interactive map to design system or booking flow

* wip

* wip

* merge

* wip

* add support for locales in design-system

* add story for HotelCard

* setup alias

* .

* remove tracking from design-system for hotelcard

* pass isUserLoggedIn

* export design-system-new-deprecated.css from design-system

* Add HotelMarkerByType to Storybook

* Add interactive map to Storybook

* fix reactintl in vitest

* rename env variables

* .

* fix background colors

* add storybook stories for <Link />

* merge

* fix tracking for when clicking 'See rooms' in InteractiveMap

* Merge branch 'master' of bitbucket.org:scandic-swap/web into SW-3270-move-interactive-map-to-design-system-or-booking-flow

* remove deprecated comment


Approved-by: Anton Gunnarsson
2025-08-25 11:26:16 +00:00

132 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 TripadvisorIcon from "@scandic-hotels/design-system/Icons/TripadvisorIcon"
import ImageGallery from "@scandic-hotels/design-system/ImageGallery"
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(
{
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.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(
{
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="Small"
typography="Body/Supporting text (caption)/smBold"
>
{intl.formatMessage({
defaultMessage: "See hotel details",
})}
</ButtonLink>
</div>
) : null}
</article>
)
}