Files
web/packages/booking-flow/lib/components/SelectHotel/index.tsx
Linus Flood 78ac93d836 Merged in feat/book-530-selectrate-tracking (pull request #3128)
feat(BOOK-530): fixed noAvailableRooms tracking on select rate page

* feat(BOOK-530): fixed noAvailableRooms tracking on select rate page


Approved-by: Bianca Widstam
2025-11-11 14:17:02 +00:00

139 lines
4.4 KiB
TypeScript

import {
alternativeHotelsMap,
selectHotelMap,
} from "@scandic-hotels/common/constants/routes/hotelReservation"
import Link from "@scandic-hotels/design-system/OldDSLink"
import { Typography } from "@scandic-hotels/design-system/Typography"
import BookingCodeFilter from "../BookingCodeFilter"
import HotelCardListing from "../HotelCardListing"
import { StaticMap } from "../StaticMap"
import HotelFilter from "./Filters/HotelFilter"
import { getFiltersFromHotels, type HotelResponse } from "./helpers"
import HotelCount from "./HotelCount"
import HotelSorter from "./HotelSorter"
import { MapWithButtonWrapper } from "./MapWithButtonWrapper"
import MobileMapButtonContainer from "./MobileMapButtonContainer"
import NoAvailabilityAlert from "./NoAvailabilityAlert"
import styles from "./selectHotel.module.css"
import type { Lang } from "@scandic-hotels/common/constants/language"
import type { Location } from "@scandic-hotels/trpc/types/locations"
import type { ReactNode } from "react"
export { SelectHotelSkeleton } from "./SelectHotelSkeleton"
interface SelectHotelProps {
isAlternative?: boolean
bookingCode?: string
city: Location
hotels: HotelResponse[]
isBookingCodeRateAvailable?: boolean
title: ReactNode
lang: Lang
}
export function SelectHotel({
bookingCode,
city,
hotels,
isAlternative = false,
isBookingCodeRateAvailable = false,
title,
lang,
}: SelectHotelProps) {
const isAllUnavailable = hotels.every(
(hotel) => hotel.availability.status !== "Available"
)
// eslint-disable-next-line @typescript-eslint/no-explicit-any
const isCityWithCountry = (city: any): city is { country: string } =>
"country" in city
// Special rates (corporate cheque, voucher) will not have regular rate hotels availability
const isSpecialRate = hotels.some(
(hotel) =>
hotel.availability.productType?.bonusCheque ||
hotel.availability.productType?.voucher
)
const showBookingCodeFilter = isBookingCodeRateAvailable && !isSpecialRate
const filterList = getFiltersFromHotels(hotels, showBookingCodeFilter)
return (
<>
<header className={styles.header}>
<div className={styles.headerContent}>
<div className={styles.title}>
<div className={styles.cityInformation}>
<Typography variant="Title/Subtitle/lg">
<p>{title}</p>
</Typography>
<HotelCount />
</div>
<div className={styles.sorter}>
<HotelSorter discreet />
</div>
</div>
<MobileMapButtonContainer
isAlternative={isAlternative}
filters={filterList}
/>
</div>
</header>
<main className={styles.main}>
{showBookingCodeFilter ? <BookingCodeFilter /> : null}
<div className={styles.sideBar}>
{hotels.length ? (
<Link
className={styles.link}
href={
isAlternative
? alternativeHotelsMap(lang)
: selectHotelMap(lang)
}
keepSearchParams
>
<MapWithButtonWrapper>
<StaticMap
city={city.name}
country={isCityWithCountry(city) ? city.country : undefined}
width={340}
height={200}
zoomLevel={11}
mapType="roadmap"
altText={`Map of ${city.name} city center`}
/>
</MapWithButtonWrapper>
</Link>
) : (
<div className={styles.mapContainer}>
<StaticMap
city={city.name}
width={340}
height={200}
zoomLevel={11}
mapType="roadmap"
altText={`Map of ${city.name} city center`}
/>
</div>
)}
<HotelFilter filters={filterList} className={styles.filter} />
</div>
<div className={styles.hotelList}>
<NoAvailabilityAlert
hotelsLength={hotels.length}
isAlternative={isAlternative}
isAllUnavailable={isAllUnavailable}
operaId={hotels?.[0]?.hotel.operaId}
bookingCode={bookingCode}
isBookingCodeRateNotAvailable={!isBookingCodeRateAvailable}
/>
<HotelCardListing hotelData={hotels} isAlternative={isAlternative} />
</div>
</main>
</>
)
}