151 lines
4.7 KiB
TypeScript
151 lines
4.7 KiB
TypeScript
"use client"
|
|
|
|
import { useParams } from "next/navigation"
|
|
import { useState } from "react"
|
|
import { useIntl } from "react-intl"
|
|
|
|
import { selectRate } from "@/constants/routes/hotelReservation"
|
|
|
|
import { mapFacilityToIcon } from "@/components/ContentType/HotelPage/data"
|
|
import { CloseLargeIcon, TripAdvisorIcon } from "@/components/Icons"
|
|
import Image from "@/components/Image"
|
|
import Button from "@/components/TempDesignSystem/Button"
|
|
import Chip from "@/components/TempDesignSystem/Chip"
|
|
import Link from "@/components/TempDesignSystem/Link"
|
|
import Body from "@/components/TempDesignSystem/Text/Body"
|
|
import Caption from "@/components/TempDesignSystem/Text/Caption"
|
|
import Subtitle from "@/components/TempDesignSystem/Text/Subtitle"
|
|
|
|
import NoPriceAvailableCard from "../HotelCard/NoPriceAvailableCard"
|
|
|
|
import styles from "./hotelCardDialog.module.css"
|
|
|
|
import type { HotelCardDialogProps } from "@/types/components/hotelReservation/selectHotel/map"
|
|
import type { Lang } from "@/constants/languages"
|
|
|
|
export default function HotelCardDialog({
|
|
data,
|
|
isOpen,
|
|
handleClose,
|
|
}: HotelCardDialogProps) {
|
|
const params = useParams()
|
|
const lang = params.lang as Lang
|
|
const intl = useIntl()
|
|
const [imageError, setImageError] = useState(false)
|
|
|
|
if (!data) {
|
|
return null
|
|
}
|
|
|
|
const {
|
|
name,
|
|
publicPrice,
|
|
memberPrice,
|
|
currency,
|
|
amenities,
|
|
images,
|
|
ratings,
|
|
} = data
|
|
|
|
const firstImage = images[0]?.imageSizes?.small
|
|
const altText = images[0]?.metaData?.altText
|
|
|
|
return (
|
|
<dialog open={isOpen} className={styles.dialog}>
|
|
<div className={styles.dialogContainer}>
|
|
<CloseLargeIcon
|
|
onClick={handleClose}
|
|
className={styles.closeIcon}
|
|
width={16}
|
|
height={16}
|
|
/>
|
|
<div className={styles.imageContainer}>
|
|
{!firstImage || imageError ? (
|
|
<div className={styles.imagePlaceholder} />
|
|
) : (
|
|
<Image
|
|
src={firstImage}
|
|
alt={altText}
|
|
fill
|
|
onError={() => setImageError(true)}
|
|
/>
|
|
)}
|
|
<div className={styles.tripAdvisor}>
|
|
<Chip intent="secondary" className={styles.tripAdvisor}>
|
|
<TripAdvisorIcon color="burgundy" />
|
|
{ratings}
|
|
</Chip>
|
|
</div>
|
|
</div>
|
|
<div className={styles.content}>
|
|
<div className={styles.name}>
|
|
<Body textTransform="bold">{name}</Body>
|
|
</div>
|
|
<div className={styles.facilities}>
|
|
{amenities.map((facility) => {
|
|
const IconComponent = mapFacilityToIcon(facility.id)
|
|
return (
|
|
<div className={styles.facilitiesItem} key={facility.id}>
|
|
{IconComponent && (
|
|
<IconComponent width={16} height={16} color="grey80" />
|
|
)}
|
|
<Caption color="uiTextMediumContrast">
|
|
{facility.name}
|
|
</Caption>
|
|
</div>
|
|
)
|
|
})}
|
|
</div>
|
|
<div className={styles.prices}>
|
|
{publicPrice || memberPrice ? (
|
|
<>
|
|
<div className={styles.priceCard}>
|
|
<Caption type="bold">
|
|
{intl.formatMessage({ id: "From" })}
|
|
</Caption>
|
|
{publicPrice && (
|
|
<Subtitle type="two">
|
|
{publicPrice} {currency}
|
|
<Body asChild>
|
|
<span>/{intl.formatMessage({ id: "night" })}</span>
|
|
</Body>
|
|
</Subtitle>
|
|
)}
|
|
{memberPrice && (
|
|
<Subtitle
|
|
type="two"
|
|
color="red"
|
|
className={styles.memberPrice}
|
|
>
|
|
{memberPrice} {currency}
|
|
<Body asChild color="red">
|
|
<span>/{intl.formatMessage({ id: "night" })}</span>
|
|
</Body>
|
|
</Subtitle>
|
|
)}
|
|
</div>
|
|
<Button
|
|
asChild
|
|
theme="base"
|
|
size="small"
|
|
className={styles.button}
|
|
>
|
|
<Link
|
|
href={`${selectRate(lang)}?hotel=${data.operaId}`}
|
|
color="none"
|
|
keepSearchParams
|
|
>
|
|
{intl.formatMessage({ id: "See rooms" })}
|
|
</Link>
|
|
</Button>
|
|
</>
|
|
) : (
|
|
<NoPriceAvailableCard />
|
|
)}
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</dialog>
|
|
)
|
|
}
|