feat: add included param to hotel call, fetch room data, setup schema, use in hotelpage

This commit is contained in:
Chuma McPhoy
2024-07-10 13:41:39 +02:00
parent f71d0a07d5
commit 0697c8d9ef
15 changed files with 191 additions and 162 deletions

View File

@@ -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>
)
}

View File

@@ -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>
)

View File

@@ -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);
}

View File

@@ -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}`
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>
)
}

View File

@@ -0,0 +1,5 @@
import { RoomData } from "@/types/hotel"
export type RoomsProps = {
rooms: RoomData[]
}

View File

@@ -12,7 +12,6 @@
@media screen and (min-width: 1367px) {
.pageContainer {
gap: var(--Spacing-x3);
padding: var(--Spacing-x9) var(--Spacing-x5);
}
.introContainer {

View File

@@ -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,
},
]