feat: add included param to hotel call, fetch room data, setup schema, use in hotelpage
This commit is contained in:
@@ -4,7 +4,6 @@ import AmenitiesList from "./AmenitiesList"
|
||||
import IntroSection from "./IntroSection"
|
||||
|
||||
import { Rooms } from "./Rooms"
|
||||
import { MOCK_ROOMS } from "./tempHotelPageData"
|
||||
|
||||
import styles from "./hotelPage.module.css"
|
||||
|
||||
@@ -18,11 +17,11 @@ export default async function HotelPage({ lang }: LangParams) {
|
||||
return null
|
||||
}
|
||||
|
||||
const attributes = await serverClient().hotel.getHotel({
|
||||
const { attributes, roomCategories } = await serverClient().hotel.getHotel({
|
||||
hotelId: hotelPageIdentifierData.hotel_page_id,
|
||||
language: lang,
|
||||
include: ["RoomCategories"],
|
||||
})
|
||||
const rooms = MOCK_ROOMS
|
||||
|
||||
return (
|
||||
<main className={styles.pageContainer}>
|
||||
@@ -36,7 +35,7 @@ export default async function HotelPage({ lang }: LangParams) {
|
||||
/>
|
||||
<AmenitiesList detailedFacilities={attributes.detailedFacilities} />
|
||||
</div>
|
||||
<Rooms rooms={rooms} />
|
||||
<Rooms rooms={roomCategories} />
|
||||
</main>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -4,6 +4,7 @@ import { useIntl } from "react-intl"
|
||||
|
||||
import { ImageIcon } from "@/components/Icons"
|
||||
import Image from "@/components/Image"
|
||||
import Link from "@/components/TempDesignSystem/Link"
|
||||
import Body from "@/components/TempDesignSystem/Text/Body"
|
||||
import Title from "@/components/TempDesignSystem/Text/Title"
|
||||
|
||||
@@ -43,12 +44,14 @@ export function RoomCard({
|
||||
<ImageIcon color="white" />
|
||||
{images.length}
|
||||
</span>
|
||||
{/*NOTE: images from the test API are hosted on test3.scandichotels.com,
|
||||
which can't be accessed unless on Scandic's Wifi or using Citrix. */}
|
||||
<Image
|
||||
className={styles.image}
|
||||
src={mainImage.src}
|
||||
alt={mainImage.alt}
|
||||
height={mainImage.height}
|
||||
width={mainImage.width}
|
||||
src={mainImage.imageSizes.large}
|
||||
alt={mainImage.metaData.altText}
|
||||
height={200}
|
||||
width={300}
|
||||
/>
|
||||
</button>
|
||||
<div className={styles.content}>
|
||||
@@ -58,9 +61,14 @@ export function RoomCard({
|
||||
</Title>
|
||||
<Body color="grey">{subtitle}</Body>
|
||||
</div>
|
||||
<button className={styles.cta} onClick={handleRoomCtaClick}>
|
||||
{formatMessage({ id: "View room" })}
|
||||
</button>
|
||||
<Link
|
||||
href="#"
|
||||
color="peach80"
|
||||
variant="underscored"
|
||||
onClick={handleRoomCtaClick}
|
||||
>
|
||||
{formatMessage({ id: "hotelPages.rooms.roomCard.seeRoomDetails" })}
|
||||
</Link>
|
||||
</div>
|
||||
</article>
|
||||
)
|
||||
|
||||
@@ -65,22 +65,3 @@
|
||||
.subtitle {
|
||||
color: var(--UI-Text-Placeholder);
|
||||
}
|
||||
|
||||
.cta {
|
||||
background-color: transparent;
|
||||
border-width: 0;
|
||||
cursor: pointer;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: var(--Spacing-x-half);
|
||||
color: var(--Base-Text-Medium-contrast);
|
||||
font-family: var(--typography-Body-Bold-fontFamily);
|
||||
font-size: var(--typography-Body-Bold-fontSize);
|
||||
font-weight: 600;
|
||||
text-decoration: underline;
|
||||
}
|
||||
.cta:hover {
|
||||
color: var(--Base-Text-High-contrast);
|
||||
}
|
||||
|
||||
@@ -1,31 +1,54 @@
|
||||
import SectionContainer from "@/components/Section/Container"
|
||||
import SectionHeader from "@/components/Section/Header"
|
||||
import { getIntl } from "@/i18n"
|
||||
|
||||
import { RoomCard } from "./RoomCard"
|
||||
import { RoomsProps } from "./types"
|
||||
|
||||
import styles from "./rooms.module.css"
|
||||
|
||||
import { RoomsProps } from "@/types/components/hotelPage/rooms"
|
||||
export async function Rooms({ rooms }: RoomsProps) {
|
||||
const { formatMessage } = await getIntl()
|
||||
const mappedRooms = rooms
|
||||
.map((room) => {
|
||||
const size = `${room.attributes.roomSize.min} - ${room.attributes.roomSize.max} m²`
|
||||
const personLabel =
|
||||
room.attributes.occupancy.total === 1
|
||||
? formatMessage({ id: "hotelPages.rooms.roomCard.person" })
|
||||
: formatMessage({ id: "hotelPages.rooms.roomCard.persons" })
|
||||
|
||||
export function Rooms({ rooms }: RoomsProps) {
|
||||
// TODO: Typings should be adjusted to match the actual data structure
|
||||
const mappedRooms = rooms.map((room) => ({
|
||||
id: room.id,
|
||||
images: room.images,
|
||||
title: room.title,
|
||||
subtitle: room.subtitle,
|
||||
popularChoice: room.popularChoice,
|
||||
}))
|
||||
const subtitle = `${size} (${room.attributes.occupancy.total} ${personLabel})`
|
||||
|
||||
return {
|
||||
id: room.id,
|
||||
images: room.attributes.content.images,
|
||||
title: room.attributes.name,
|
||||
subtitle: subtitle,
|
||||
sortOrder: room.attributes.sortOrder,
|
||||
popularChoice: null,
|
||||
}
|
||||
})
|
||||
.sort((a, b) => a.sortOrder - b.sortOrder)
|
||||
.slice(0, 3) //TODO: Remove this and render all rooms once we've implemented "show more" logic in SW-203.
|
||||
return (
|
||||
<section className={styles.cardContainer}>
|
||||
{mappedRooms.map(({ id, images, title, subtitle, popularChoice }) => (
|
||||
<RoomCard
|
||||
key={id}
|
||||
id={id}
|
||||
images={images}
|
||||
title={title}
|
||||
subtitle={subtitle}
|
||||
badgeTextTransKey={popularChoice ? "Popular choice" : null}
|
||||
/>
|
||||
))}
|
||||
</section>
|
||||
<SectionContainer>
|
||||
<SectionHeader
|
||||
textTransform="uppercase"
|
||||
title={formatMessage({ id: "hotelPages.rooms.title" })}
|
||||
subtitle={null}
|
||||
/>
|
||||
<section className={styles.cardContainer}>
|
||||
{mappedRooms.map(({ id, images, title, subtitle, popularChoice }) => (
|
||||
<RoomCard
|
||||
key={id}
|
||||
id={id}
|
||||
images={images}
|
||||
title={title}
|
||||
subtitle={subtitle}
|
||||
badgeTextTransKey={popularChoice ? "Popular choice" : null}
|
||||
/>
|
||||
))}
|
||||
</section>
|
||||
</SectionContainer>
|
||||
)
|
||||
}
|
||||
|
||||
5
components/ContentType/HotelPage/Rooms/types.ts
Normal file
5
components/ContentType/HotelPage/Rooms/types.ts
Normal file
@@ -0,0 +1,5 @@
|
||||
import { RoomData } from "@/types/hotel"
|
||||
|
||||
export type RoomsProps = {
|
||||
rooms: RoomData[]
|
||||
}
|
||||
@@ -12,7 +12,6 @@
|
||||
|
||||
@media screen and (min-width: 1367px) {
|
||||
.pageContainer {
|
||||
gap: var(--Spacing-x3);
|
||||
padding: var(--Spacing-x9) var(--Spacing-x5);
|
||||
}
|
||||
.introContainer {
|
||||
|
||||
@@ -1,82 +0,0 @@
|
||||
import { RoomsProps } from "../../../types/components/hotelPage/rooms"
|
||||
|
||||
export const MOCK_ROOMS: RoomsProps["rooms"] = [
|
||||
{
|
||||
id: "1",
|
||||
title: "Cabin",
|
||||
subtitle: "15 - 20 m² (2 personer)",
|
||||
images: [
|
||||
{
|
||||
src: "https://placehold.co/300x200",
|
||||
alt: "Placeholder image",
|
||||
width: 300,
|
||||
height: 200,
|
||||
},
|
||||
{
|
||||
src: "https://placehold.co/300x200",
|
||||
alt: "Placeholder image",
|
||||
width: 300,
|
||||
height: 200,
|
||||
},
|
||||
],
|
||||
popularChoice: false,
|
||||
},
|
||||
{
|
||||
id: "2",
|
||||
title: "Standard",
|
||||
subtitle: "15 - 20 m² (2 personer)",
|
||||
images: [
|
||||
{
|
||||
src: "https://placehold.co/300x200",
|
||||
alt: "Placeholder image",
|
||||
width: 300,
|
||||
height: 200,
|
||||
},
|
||||
{
|
||||
src: "https://placehold.co/300x200",
|
||||
alt: "Placeholder image",
|
||||
width: 300,
|
||||
height: 200,
|
||||
},
|
||||
{
|
||||
src: "https://placehold.co/300x200",
|
||||
alt: "Placeholder image",
|
||||
width: 300,
|
||||
height: 200,
|
||||
},
|
||||
],
|
||||
popularChoice: true,
|
||||
},
|
||||
{
|
||||
id: "3",
|
||||
title: "Superior",
|
||||
subtitle: "15 m² (2 personer)",
|
||||
images: [
|
||||
{
|
||||
src: "https://placehold.co/300x200",
|
||||
alt: "Placeholder image",
|
||||
width: 300,
|
||||
height: 200,
|
||||
},
|
||||
{
|
||||
src: "https://placehold.co/300x200",
|
||||
alt: "Placeholder image",
|
||||
width: 300,
|
||||
height: 200,
|
||||
},
|
||||
{
|
||||
src: "https://placehold.co/300x200",
|
||||
alt: "Placeholder image",
|
||||
width: 300,
|
||||
height: 200,
|
||||
},
|
||||
{
|
||||
src: "https://placehold.co/300x200",
|
||||
alt: "Placeholder image",
|
||||
width: 300,
|
||||
height: 200,
|
||||
},
|
||||
],
|
||||
popularChoice: false,
|
||||
},
|
||||
]
|
||||
Reference in New Issue
Block a user