Feat/SW-451 ui hotel card * feat(SW-451): initial design * feat(SW-451): add gallery icon and responsive design for mobile * feat(SW-451): refactor name, add routing to sidepeek * feat(SW-451): add updated design * feat(SW-451): add tripadvisor chip * feat(SW-451): fix gallery icon * feat(SW-451): fix additional falsy value check * feat(SW-451): fix import type * feat(SW-451): remove galleryIcon until image data exists * feat(SW-451): fix css styling * feat(SW-451): add new design for mobile * feat(SW-451): add translation * feat(SW-451): change css to mobile first * feat(SW-451): change div to article Approved-by: Matilda Landström
121 lines
4.0 KiB
TypeScript
121 lines
4.0 KiB
TypeScript
"use client"
|
|
|
|
import { useState } from "react"
|
|
import { useIntl } from "react-intl"
|
|
|
|
import { ChevronRightIcon } from "@/components/Icons"
|
|
import Accordion from "@/components/TempDesignSystem/Accordion"
|
|
import AccordionItem from "@/components/TempDesignSystem/Accordion/AccordionItem"
|
|
import Button from "@/components/TempDesignSystem/Button"
|
|
import SidePeek from "@/components/TempDesignSystem/SidePeek"
|
|
import Body from "@/components/TempDesignSystem/Text/Body"
|
|
import Subtitle from "@/components/TempDesignSystem/Text/Subtitle"
|
|
|
|
import Contact from "../Contact"
|
|
|
|
import styles from "./readMore.module.css"
|
|
|
|
import {
|
|
DetailedAmenity,
|
|
ParkingProps,
|
|
ReadMoreProps,
|
|
} from "@/types/components/hotelReservation/selectHotel/selectHotel"
|
|
import { Hotel } from "@/types/hotel"
|
|
|
|
function getAmenitiesList(hotel: Hotel) {
|
|
const detailedAmenities: DetailedAmenity[] = Object.entries(
|
|
hotel.hotelFacts.hotelFacilityDetail
|
|
).map(([key, value]) => ({ name: key, ...value }))
|
|
|
|
// Remove Parking facilities since parking accordion is based on hotel.parking
|
|
const simpleAmenities = hotel.detailedFacilities.filter(
|
|
(facility) => !facility.name.startsWith("Parking")
|
|
)
|
|
return [...detailedAmenities, ...simpleAmenities]
|
|
}
|
|
|
|
export default function ReadMore({ label, hotel, hotelId }: ReadMoreProps) {
|
|
const intl = useIntl()
|
|
|
|
const [sidePeekOpen, setSidePeekOpen] = useState(false)
|
|
|
|
const amenitiesList = getAmenitiesList(hotel)
|
|
return (
|
|
<>
|
|
<Button
|
|
onPress={() => {
|
|
setSidePeekOpen(true)
|
|
}}
|
|
intent="text"
|
|
theme="base"
|
|
wrapping
|
|
className={styles.detailsButton}
|
|
>
|
|
{label}
|
|
<ChevronRightIcon color="burgundy" />
|
|
</Button>
|
|
<SidePeek
|
|
title={hotel.name}
|
|
isOpen={sidePeekOpen}
|
|
contentKey={`${hotelId}`}
|
|
handleClose={() => {
|
|
setSidePeekOpen(false)
|
|
}}
|
|
>
|
|
<div className={styles.content}>
|
|
<Subtitle>
|
|
{intl.formatMessage({ id: "Practical information" })}
|
|
</Subtitle>
|
|
<Contact hotel={hotel} />
|
|
<Accordion>
|
|
{/* parking */}
|
|
{hotel.parking.length ? (
|
|
<AccordionItem title={intl.formatMessage({ id: "Parking" })}>
|
|
{hotel.parking.map((p) => (
|
|
<Parking key={p.name} parking={p} />
|
|
))}
|
|
</AccordionItem>
|
|
) : null}
|
|
<AccordionItem title={intl.formatMessage({ id: "Accessibility" })}>
|
|
TODO: What content should be in the accessibility section?
|
|
</AccordionItem>
|
|
{amenitiesList.map((amenity) => {
|
|
return "description" in amenity ? (
|
|
<AccordionItem key={amenity.name} title={amenity.heading}>
|
|
{amenity.description}
|
|
</AccordionItem>
|
|
) : (
|
|
<div key={amenity.id} className={styles.amenity}>
|
|
{amenity.name}
|
|
</div>
|
|
)
|
|
})}
|
|
</Accordion>
|
|
{/* TODO: handle linking to Hotel Page */}
|
|
<Button theme={"base"}>To the hotel</Button>
|
|
</div>
|
|
</SidePeek>
|
|
</>
|
|
)
|
|
}
|
|
|
|
function Parking({ parking }: ParkingProps) {
|
|
const intl = useIntl()
|
|
return (
|
|
<div>
|
|
<Body>{`${intl.formatMessage({ id: parking.type })} (${parking.name})`}</Body>
|
|
<ul className={styles.list}>
|
|
<li>
|
|
{`${intl.formatMessage({
|
|
id: "Number of charging points for electric cars",
|
|
})}: ${parking.numberOfChargingSpaces}`}
|
|
</li>
|
|
<li>{`${intl.formatMessage({ id: "Parking can be reserved in advance" })}: ${parking.canMakeReservation ? intl.formatMessage({ id: "Yes" }) : intl.formatMessage({ id: "No" })}`}</li>
|
|
<li>{`${intl.formatMessage({ id: "Number of parking spots" })}: ${parking.numberOfParkingSpots}`}</li>
|
|
<li>{`${intl.formatMessage({ id: "Distance to hotel" })}: ${parking.distanceToHotel}`}</li>
|
|
<li>{`${intl.formatMessage({ id: "Address" })}: ${parking.address}`}</li>
|
|
</ul>
|
|
</div>
|
|
)
|
|
}
|