feat: Add tab navigation to hotel page

This commit is contained in:
Chuma McPhoy
2024-07-18 00:40:49 +02:00
parent 9b0ee16282
commit ebe79c43e0
14 changed files with 145 additions and 20 deletions

View File

@@ -108,6 +108,7 @@ html,
body { body {
margin: 0; margin: 0;
padding: 0; padding: 0;
scroll-behavior: smooth;
} }
body { body {

View File

@@ -3,6 +3,7 @@ import { serverClient } from "@/lib/trpc/server"
import AmenitiesList from "./AmenitiesList" import AmenitiesList from "./AmenitiesList"
import IntroSection from "./IntroSection" import IntroSection from "./IntroSection"
import { Rooms } from "./Rooms" import { Rooms } from "./Rooms"
import TabNavigation from "./TabNavigation"
import styles from "./hotelPage.module.css" import styles from "./hotelPage.module.css"
@@ -23,18 +24,21 @@ export default async function HotelPage({ lang }: LangParams) {
}) })
return ( return (
<main className={styles.pageContainer}> <div className={styles.pageContainer}>
<div className={styles.introContainer}> <TabNavigation />
<IntroSection <main className={styles.mainSection}>
hotelName={attributes.name} <div className={styles.introContainer}>
hotelDescription={attributes.hotelContent.texts.descriptions.short} <IntroSection
location={attributes.location} hotelName={attributes.name}
address={attributes.address} hotelDescription={attributes.hotelContent.texts.descriptions.short}
tripAdvisor={attributes.ratings.tripAdvisor} location={attributes.location}
/> address={attributes.address}
<AmenitiesList detailedFacilities={attributes.detailedFacilities} /> tripAdvisor={attributes.ratings.tripAdvisor}
</div> />
<Rooms rooms={roomCategories} /> <AmenitiesList detailedFacilities={attributes.detailedFacilities} />
</main> </div>
<Rooms rooms={roomCategories} />
</main>
</div>
) )
} }

View File

@@ -30,10 +30,10 @@ export async function Rooms({ rooms }: RoomsProps) {
.sort((a, b) => a.sortOrder - b.sortOrder) .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. .slice(0, 3) //TODO: Remove this and render all rooms once we've implemented "show more" logic in SW-203.
return ( return (
<SectionContainer> <SectionContainer id="rooms-section">
<SectionHeader <SectionHeader
textTransform="uppercase" textTransform="uppercase"
title={formatMessage({ id: "hotelPages.rooms.title" })} title={formatMessage({ id: "Rooms" })}
subtitle={null} subtitle={null}
/> />
<Grids.Stackable> <Grids.Stackable>

View File

@@ -0,0 +1,44 @@
"use client"
import { useIntl } from "react-intl"
import Link from "@/components/TempDesignSystem/Link"
import useHash from "@/hooks/useHash"
import { HotelHashValues } from "./types"
import styles from "./tabNavigation.module.css"
export default function TabNavigation() {
const hash = useHash()
const { formatMessage } = useIntl()
const hotelTabLinks: { href: HotelHashValues; text: string }[] = [
{ href: "#overview", text: "Overview" },
{ href: "#rooms-section", text: "Rooms" },
{ href: "#restaurant-and-bar", text: "Restaurant & Bar" },
{ href: "#meetings-and-conferences", text: "Meetings & Conferences" },
{ href: "#wellness-and-exercise", text: "Wellness & Exercise" },
{ href: "#activities", text: "Activities" },
{ href: "#faq", text: "FAQ" },
]
return (
<nav className={styles.tabsContainer}>
{hotelTabLinks.map((link) => {
const isActive =
hash === link.href || (hash === "" && link.href === "#overview")
console.log("isActive", isActive, "hash", hash, "link.href", link.href)
return (
<Link
key={link.href}
href={link.href}
active={isActive}
variant="tab"
color="burgundy"
textDecoration="none"
>
{formatMessage({ id: link.text })}
</Link>
)
})}
</nav>
)
}

View File

@@ -0,0 +1,11 @@
.tabsContainer {
display: flex;
overflow-x: auto;
white-space: nowrap;
gap: var(--Spacing-x4);
background: var(--Base-Surface-Subtle-Normal);
justify-content: flex-start;
padding-left: var(--Spacing-x4);
padding-right: var(--Spacing-x3);
border-bottom: 1px solid var(--Base-Border-Subtle);
}

View File

@@ -0,0 +1,8 @@
export type HotelHashValues =
| "#overview"
| "#rooms-section"
| "#restaurant-and-bar"
| "#meetings-and-conferences"
| "#wellness-and-exercise"
| "#activities"
| "#faq"

View File

@@ -1,4 +1,13 @@
.pageContainer { .pageContainer {
overflow-x: auto;
}
.pageContainer > * {
padding-left: var(--Spacing-x4);
padding-right: var(--Spacing-x3);
}
.mainSection {
display: grid; display: grid;
gap: var(--Spacing-x9); gap: var(--Spacing-x9);
padding: var(--Spacing-x5) var(--Spacing-x3) var(--Spacing-x4); padding: var(--Spacing-x5) var(--Spacing-x3) var(--Spacing-x4);
@@ -11,9 +20,14 @@
} }
@media screen and (min-width: 1367px) { @media screen and (min-width: 1367px) {
.pageContainer { .pageContainer > *:not(nav) {
padding: var(--Spacing-x9) var(--Spacing-x5); padding: var(--Spacing-x9) var(--Spacing-x5);
} }
.pageContainer > nav {
padding-left: var(--Spacing-x5);
padding-right: var(--Spacing-x5);
}
.introContainer { .introContainer {
display: grid; display: grid;
/* use justify-content: space between once we have the map component*/ /* use justify-content: space between once we have the map component*/

View File

@@ -8,7 +8,7 @@ import styles from "./breadcrumbs.module.css"
export default async function Breadcrumbs() { export default async function Breadcrumbs() {
const breadcrumbs = await serverClient().contentstack.breadcrumbs.get() const breadcrumbs = await serverClient().contentstack.breadcrumbs.get()
if (!breadcrumbs) { if (!breadcrumbs || breadcrumbs.length === 0) {
return null return null
} }
const homeBreadcrumb = breadcrumbs.shift() const homeBreadcrumb = breadcrumbs.shift()

View File

@@ -10,6 +10,7 @@ import { linkVariants } from "./variants"
import type { LinkProps } from "./link" import type { LinkProps } from "./link"
export default function Link({ export default function Link({
active,
className, className,
color, color,
href, href,
@@ -23,10 +24,12 @@ export default function Link({
...props ...props
}: LinkProps) { }: LinkProps) {
const currentPageSlug = usePathname() const currentPageSlug = usePathname()
let isActive = currentPageSlug === href let isActive = active || currentPageSlug === href
if (partialMatch && !isActive) { if (partialMatch && !isActive) {
isActive = currentPageSlug === href isActive = currentPageSlug === href
} }
const classNames = linkVariants({ const classNames = linkVariants({
active: isActive, active: isActive,
className, className,

View File

@@ -93,6 +93,17 @@
background-color: var(--Scandic-Peach-20); background-color: var(--Scandic-Peach-20);
} }
.tab {
font-family: var(--typography-Body-Regular-fontFamily);
padding: var(--Spacing-x2) var(--Spacing-x0);
color: var(--Base-Text-High-contrast);
text-decoration: none;
}
.tab.active {
border-bottom: 2px solid var(--Scandic-Brand-Burgundy);
}
.black { .black {
color: #000; color: #000;
} }

View File

@@ -31,6 +31,7 @@ export const linkVariants = cva(styles.link, {
myPageMobileDropdown: styles.myPageMobileDropdown, myPageMobileDropdown: styles.myPageMobileDropdown,
shortcut: styles.shortcut, shortcut: styles.shortcut,
sidebar: styles.sidebar, sidebar: styles.sidebar,
tab: styles.tab,
}, },
}, },
defaultVariants: { defaultVariants: {

22
hooks/useHash.tsx Normal file
View File

@@ -0,0 +1,22 @@
"use client"
import { useParams } from "next/navigation"
import { useEffect, useState } from "react"
const getHash = () =>
typeof window !== "undefined" ? window.location.hash : undefined
const useHash = () => {
const [isClient, setIsClient] = useState(false)
const [hash, setHash] = useState(getHash())
const params = useParams()
useEffect(() => {
setIsClient(true)
setHash(getHash())
}, [params])
return isClient ? hash : null
}
export default useHash

View File

@@ -1,5 +1,6 @@
{ {
"A photo of the room": "A photo of the room", "A photo of the room": "A photo of the room",
"Activities": "Activities",
"Add new card": "Add new card", "Add new card": "Add new card",
"Address": "Address", "Address": "Address",
"All our beds are from Bliss, allowing you to adjust the firmness for your perfect comfort.": "All our beds are from Bliss, allowing you to adjust the firmness for your perfect comfort.", "All our beds are from Bliss, allowing you to adjust the firmness for your perfect comfort.": "All our beds are from Bliss, allowing you to adjust the firmness for your perfect comfort.",
@@ -44,12 +45,12 @@
"Email": "Email", "Email": "Email",
"There are no transactions to display": "There are no transactions to display", "There are no transactions to display": "There are no transactions to display",
"Explore all levels and benefits": "Explore all levels and benefits", "Explore all levels and benefits": "Explore all levels and benefits",
"FAQ": "FAQ",
"Find booking": "Find booking", "Find booking": "Find booking",
"Flexibility": "Flexibility", "Flexibility": "Flexibility",
"From": "From", "From": "From",
"Get inspired": "Get inspired", "Get inspired": "Get inspired",
"Go back to overview": "Go back to overview", "Go back to overview": "Go back to overview",
"hotelPages.rooms.title": "Rooms",
"hotelPages.rooms.roomCard.person": "person", "hotelPages.rooms.roomCard.person": "person",
"hotelPages.rooms.roomCard.persons": "persons", "hotelPages.rooms.roomCard.persons": "persons",
"hotelPages.rooms.roomCard.seeRoomDetails": "See room details", "hotelPages.rooms.roomCard.seeRoomDetails": "See room details",
@@ -63,6 +64,7 @@
"Log in": "Log in", "Log in": "Log in",
"Log in here": "Log in here", "Log in here": "Log in here",
"Log out": "Log out", "Log out": "Log out",
"Meetings & Conferences": "Meetings & Conferences",
"Members": "Members", "Members": "Members",
"Membership cards": "Membership cards", "Membership cards": "Membership cards",
"Membership ID": "Membership ID", "Membership ID": "Membership ID",
@@ -85,6 +87,7 @@
"On your journey": "On your journey", "On your journey": "On your journey",
"Open": "Open", "Open": "Open",
"or": "or", "or": "or",
"Overview": "Overview",
"Password": "Password", "Password": "Password",
"Phone": "Phone", "Phone": "Phone",
"Phone is required": "Phone is required", "Phone is required": "Phone is required",
@@ -98,7 +101,9 @@
"Previous victories": "Previous victories", "Previous victories": "Previous victories",
"Read more": "Read more", "Read more": "Read more",
"Read more about the hotel": "Read more about the hotel", "Read more about the hotel": "Read more about the hotel",
"Restaurant & Bar": "Restaurant & Bar",
"Retype new password": "Retype new password", "Retype new password": "Retype new password",
"Rooms": "Rooms",
"Save": "Save", "Save": "Save",
"Select a country": "Select a country", "Select a country": "Select a country",
"Select country of residence": "Select country of residence", "Select country of residence": "Select country of residence",
@@ -121,6 +126,7 @@
"Welcome": "Welcome", "Welcome": "Welcome",
"Visiting address": "Visiting address", "Visiting address": "Visiting address",
"Welcome to": "Welcome to", "Welcome to": "Welcome to",
"Wellness & Exercise": "Wellness & Exercise",
"Where should you go next?": "Where should you go next?", "Where should you go next?": "Where should you go next?",
"Which room class suits you the best?": "Which room class suits you the best?", "Which room class suits you the best?": "Which room class suits you the best?",
"Year": "Year", "Year": "Year",

View File

@@ -51,7 +51,6 @@
"Highest level": "Högsta nivå", "Highest level": "Högsta nivå",
"How do you want to sleep?": "Hur vill du sova?", "How do you want to sleep?": "Hur vill du sova?",
"How it works": "Hur det fungerar", "How it works": "Hur det fungerar",
"hotelPages.rooms.title": "Rum",
"hotelPages.rooms.roomCard.person": "person", "hotelPages.rooms.roomCard.person": "person",
"hotelPages.rooms.roomCard.persons": "personer", "hotelPages.rooms.roomCard.persons": "personer",
"hotelPages.rooms.roomCard.seeRoomDetails": "Se rumsdetaljer", "hotelPages.rooms.roomCard.seeRoomDetails": "Se rumsdetaljer",
@@ -98,6 +97,7 @@
"Read more": "Läs mer", "Read more": "Läs mer",
"Read more about the hotel": "Läs mer om hotellet", "Read more about the hotel": "Läs mer om hotellet",
"Retype new password": "Upprepa nytt lösenord", "Retype new password": "Upprepa nytt lösenord",
"Rooms": "Rum",
"Save": "Spara", "Save": "Spara",
"Select a country": "Välj ett land", "Select a country": "Välj ett land",
"Select country of residence": "Välj bosättningsland", "Select country of residence": "Välj bosättningsland",