feat: Add AmenitiesList and IntroSection components to Hotel Page
This commit is contained in:
@@ -0,0 +1,18 @@
|
||||
.amenitiesContainer {
|
||||
display: grid;
|
||||
gap: var(--Spacing-x-one-and-half);
|
||||
height: fit-content;
|
||||
}
|
||||
|
||||
.showAllButton {
|
||||
padding: var(--Spacing-x-one-and-half) var(--Spacing-x0) !important;
|
||||
}
|
||||
|
||||
@media screen and (min-width: 1367px) {
|
||||
.amenitiesContainer {
|
||||
background-color: var(--Scandic-Beige-10);
|
||||
padding: var(--Spacing-x3) var(--Spacing-x3) var(--Spacing-x-one-and-half)
|
||||
var(--Spacing-x3);
|
||||
border-radius: var(--Corner-radius-Large);
|
||||
}
|
||||
}
|
||||
39
components/ContentType/HotelPage/AmenitiesList/index.tsx
Normal file
39
components/ContentType/HotelPage/AmenitiesList/index.tsx
Normal file
@@ -0,0 +1,39 @@
|
||||
import { ChevronRightIcon } from "@/components/Icons"
|
||||
import Button from "@/components/TempDesignSystem/Button"
|
||||
import Body from "@/components/TempDesignSystem/Text/Body"
|
||||
import Subtitle from "@/components/TempDesignSystem/Text/Subtitle"
|
||||
|
||||
import styles from "./amenitiesList.module.css"
|
||||
|
||||
import { HotelData } from "@/types/hotel"
|
||||
|
||||
export default function AmenitiesList({
|
||||
detailedFacilities,
|
||||
}: {
|
||||
detailedFacilities: HotelData["data"]["attributes"]["detailedFacilities"]
|
||||
}) {
|
||||
const sortedAmenities = detailedFacilities
|
||||
.sort((a, b) => b.sortOrder - a.sortOrder)
|
||||
.slice(0, 5)
|
||||
return (
|
||||
<section className={styles.amenitiesContainer}>
|
||||
<Subtitle color="black">At the hotel</Subtitle>
|
||||
<div>
|
||||
{sortedAmenities.map((facility, index) => (
|
||||
<Body color="textMediumContrast" key={facility.id}>
|
||||
{facility.name}
|
||||
</Body>
|
||||
))}
|
||||
</div>
|
||||
<Button
|
||||
className={styles.showAllButton}
|
||||
theme="base"
|
||||
variant="icon"
|
||||
intent="text"
|
||||
>
|
||||
Show all amenities
|
||||
<ChevronRightIcon />
|
||||
</Button>
|
||||
</section>
|
||||
)
|
||||
}
|
||||
@@ -1,6 +1,7 @@
|
||||
import { serverClient } from "@/lib/trpc/server"
|
||||
|
||||
import Title from "@/components/TempDesignSystem/Text/Title"
|
||||
import AmenitiesList from "./AmenitiesList"
|
||||
import IntroSection from "./IntroSection"
|
||||
|
||||
import styles from "./hotelPage.module.css"
|
||||
|
||||
@@ -18,9 +19,23 @@ export default async function HotelPage({ lang }: LangParams) {
|
||||
hotelId: hotelPageIdentifierData.hotel_page_id,
|
||||
language: lang,
|
||||
})
|
||||
|
||||
return (
|
||||
<section className={styles.content}>
|
||||
<Title>{hotelPageData.data.attributes.name}</Title>
|
||||
</section>
|
||||
<main className={styles.pageContainer}>
|
||||
<div className={styles.introContainer}>
|
||||
<IntroSection
|
||||
hotelName={hotelPageData.data.attributes.name}
|
||||
hotelDescription={
|
||||
hotelPageData.data.attributes.hotelContent.texts.descriptions.short
|
||||
}
|
||||
location={hotelPageData.data.attributes.location}
|
||||
address={hotelPageData.data.attributes.address}
|
||||
tripAdvisor={hotelPageData.data.attributes.ratings.tripAdvisor}
|
||||
/>
|
||||
<AmenitiesList
|
||||
detailedFacilities={hotelPageData.data.attributes.detailedFacilities}
|
||||
/>
|
||||
</div>
|
||||
</main>
|
||||
)
|
||||
}
|
||||
|
||||
73
components/ContentType/HotelPage/IntroSection/index.tsx
Normal file
73
components/ContentType/HotelPage/IntroSection/index.tsx
Normal file
@@ -0,0 +1,73 @@
|
||||
import ArrowRight from "@/components/Icons/ArrowRight"
|
||||
import TripAdvisorIcon from "@/components/Icons/TripAdvisor"
|
||||
import Link from "@/components/TempDesignSystem/Link"
|
||||
import BiroScript from "@/components/TempDesignSystem/Text/BiroScript"
|
||||
import Body from "@/components/TempDesignSystem/Text/Body"
|
||||
import Subtitle from "@/components/TempDesignSystem/Text/Subtitle"
|
||||
import Title from "@/components/TempDesignSystem/Text/Title"
|
||||
import { getIntl } from "@/i18n"
|
||||
|
||||
import styles from "./introSection.module.css"
|
||||
|
||||
import { HotelAddress, HotelData, HotelLocation } from "@/types/hotel"
|
||||
|
||||
export default async function IntroSection({
|
||||
hotelName,
|
||||
hotelDescription,
|
||||
location,
|
||||
address,
|
||||
tripAdvisor,
|
||||
}: {
|
||||
hotelName: HotelData["data"]["attributes"]["name"]
|
||||
hotelDescription: HotelData["data"]["attributes"]["hotelContent"]["texts"]["descriptions"]["short"]
|
||||
location: HotelLocation
|
||||
address: HotelAddress
|
||||
tripAdvisor: HotelData["data"]["attributes"]["ratings"]["tripAdvisor"]
|
||||
}) {
|
||||
const intl = await getIntl()
|
||||
const { formatMessage } = intl
|
||||
const { streetAddress, city } = address
|
||||
const { distanceToCentre } = location
|
||||
const formattedDistanceText = formatMessage(
|
||||
{ id: "Distance to city centre" },
|
||||
{ number: distanceToCentre }
|
||||
)
|
||||
const formattedLocationText = `${streetAddress}, ${city} (${formattedDistanceText})`
|
||||
const formattedTripAdvisorText = `${tripAdvisor.rating} (${tripAdvisor.numberOfReviews} reviews on tripadvisor)`
|
||||
|
||||
return (
|
||||
<section className={styles.introSection}>
|
||||
<BiroScript className={styles.welcomeLabel} color="red">
|
||||
{formatMessage({ id: "Welcome to" })}:
|
||||
</BiroScript>
|
||||
<div className={styles.mainContent}>
|
||||
<Title level="h2">{hotelName}</Title>
|
||||
<Body color="textMediumContrast">{formattedLocationText}</Body>
|
||||
<Link
|
||||
className={styles.introLink}
|
||||
target="_blank"
|
||||
variant="icon"
|
||||
color="peach80"
|
||||
href={tripAdvisor.webUrl}
|
||||
>
|
||||
<TripAdvisorIcon color="peach80" />
|
||||
{formattedTripAdvisorText}
|
||||
</Link>
|
||||
</div>
|
||||
<div className={styles.subtitleContent}>
|
||||
<Subtitle color="black">{hotelDescription}</Subtitle>
|
||||
<Link
|
||||
className={styles.introLink}
|
||||
target="_blank"
|
||||
color="peach80"
|
||||
variant="icon"
|
||||
href="#"
|
||||
>
|
||||
{/*TODO: Ask content team where this should link to. */}
|
||||
Read more about the hotel
|
||||
<ArrowRight color="peach80" />
|
||||
</Link>
|
||||
</div>
|
||||
</section>
|
||||
)
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
.introSection {
|
||||
margin-top: var(--Spacing-x3);
|
||||
display: grid;
|
||||
gap: var(--Spacing-x3);
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.mainContent {
|
||||
display: grid;
|
||||
gap: var(--Spacing-x1);
|
||||
}
|
||||
|
||||
.subtitleContent {
|
||||
display: grid;
|
||||
gap: var(--Spacing-x-one-and-half);
|
||||
}
|
||||
|
||||
.welcomeLabel {
|
||||
/* TODO: Update and use absolute position. */
|
||||
transform: rotate(-3.378deg) translate(0px, -15px);
|
||||
}
|
||||
|
||||
.introLink {
|
||||
text-decoration: underline !important;
|
||||
text-decoration-color: var(--Scandic-Peach-80);
|
||||
width: fit-content;
|
||||
}
|
||||
@@ -1,11 +1,23 @@
|
||||
.content {
|
||||
.pageContainer {
|
||||
display: grid;
|
||||
gap: var(--Spacing-x4);
|
||||
gap: var(--Spacing-x9);
|
||||
padding: var(--Spacing-x3) var(--Spacing-x3) var(--Spacing-x4);
|
||||
}
|
||||
|
||||
.introContainer {
|
||||
display: grid;
|
||||
grid-template-columns: 1fr;
|
||||
gap: var(--Spacing-x4);
|
||||
}
|
||||
|
||||
@media screen and (min-width: 1367px) {
|
||||
.content {
|
||||
.pageContainer {
|
||||
gap: var(--Spacing-x3);
|
||||
padding-left: var(--Spacing-x5);
|
||||
}
|
||||
.introContainer {
|
||||
display: grid;
|
||||
gap: 105px;
|
||||
grid-template-columns: 607px 340px;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user