fix(SW-239): make contents in sidepeek component render serverside for seo
This commit is contained in:
@@ -1,8 +1,6 @@
|
|||||||
import { mapFacilityToIcon } from "@/components/ContentType/HotelPage/data"
|
import { mapFacilityToIcon } from "@/components/ContentType/HotelPage/data"
|
||||||
import { ChevronRightIcon } from "@/components/Icons"
|
import { ChevronRightIcon } from "@/components/Icons"
|
||||||
import Link from "@/components/TempDesignSystem/Link"
|
import Link from "@/components/TempDesignSystem/Link"
|
||||||
import SidePeekContainer from "@/components/TempDesignSystem/SidePeek/Container"
|
|
||||||
import SidePeekContent from "@/components/TempDesignSystem/SidePeek/Content"
|
|
||||||
import { generateSidePeekLink } from "@/components/TempDesignSystem/SidePeek/data"
|
import { generateSidePeekLink } from "@/components/TempDesignSystem/SidePeek/data"
|
||||||
import Body from "@/components/TempDesignSystem/Text/Body"
|
import Body from "@/components/TempDesignSystem/Text/Body"
|
||||||
import Subtitle from "@/components/TempDesignSystem/Text/Subtitle"
|
import Subtitle from "@/components/TempDesignSystem/Text/Subtitle"
|
||||||
@@ -22,6 +20,7 @@ export default async function AmenitiesList({
|
|||||||
const sortedAmenities = detailedFacilities
|
const sortedAmenities = detailedFacilities
|
||||||
.sort((a, b) => b.sortOrder - a.sortOrder)
|
.sort((a, b) => b.sortOrder - a.sortOrder)
|
||||||
.slice(0, 5)
|
.slice(0, 5)
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<section className={styles.amenitiesContainer}>
|
<section className={styles.amenitiesContainer}>
|
||||||
<Subtitle type="two" color="black">
|
<Subtitle type="two" color="black">
|
||||||
@@ -42,14 +41,6 @@ export default async function AmenitiesList({
|
|||||||
{formatMessage({ id: "Show all amenities" })}
|
{formatMessage({ id: "Show all amenities" })}
|
||||||
<ChevronRightIcon />
|
<ChevronRightIcon />
|
||||||
</Link>
|
</Link>
|
||||||
<SidePeekContainer>
|
|
||||||
<SidePeekContent
|
|
||||||
contentKey={"amenities"}
|
|
||||||
title={formatMessage({ id: "Amenities" })}
|
|
||||||
>
|
|
||||||
{/* TODO: Render amenities as per the design. */}
|
|
||||||
</SidePeekContent>
|
|
||||||
</SidePeekContainer>
|
|
||||||
</section>
|
</section>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,9 @@
|
|||||||
import { serverClient } from "@/lib/trpc/server"
|
import { serverClient } from "@/lib/trpc/server"
|
||||||
|
|
||||||
import { getLang } from "@/i18n/serverContext"
|
import { getLang } from "@/i18n/serverContext"
|
||||||
|
import SidePeekContainer from "@/components/TempDesignSystem/SidePeek/Container"
|
||||||
|
import SidePeekContent from "@/components/TempDesignSystem/SidePeek/Content"
|
||||||
|
import { getIntl } from "@/i18n"
|
||||||
|
|
||||||
import AmenitiesList from "./AmenitiesList"
|
import AmenitiesList from "./AmenitiesList"
|
||||||
import IntroSection from "./IntroSection"
|
import IntroSection from "./IntroSection"
|
||||||
@@ -23,6 +26,8 @@ export default async function HotelPage() {
|
|||||||
include: ["RoomCategories"],
|
include: ["RoomCategories"],
|
||||||
})
|
})
|
||||||
|
|
||||||
|
const { formatMessage } = await getIntl()
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={styles.pageContainer}>
|
<div className={styles.pageContainer}>
|
||||||
<TabNavigation />
|
<TabNavigation />
|
||||||
@@ -35,6 +40,21 @@ export default async function HotelPage() {
|
|||||||
address={attributes.address}
|
address={attributes.address}
|
||||||
tripAdvisor={attributes.ratings.tripAdvisor}
|
tripAdvisor={attributes.ratings.tripAdvisor}
|
||||||
/>
|
/>
|
||||||
|
<SidePeekContainer>
|
||||||
|
<SidePeekContent
|
||||||
|
contentKey={"amenities"}
|
||||||
|
title={formatMessage({ id: "Amenities" })}
|
||||||
|
>
|
||||||
|
{/* TODO: Render amenities as per the design. */}
|
||||||
|
Read more about the amenities here
|
||||||
|
</SidePeekContent>
|
||||||
|
<SidePeekContent
|
||||||
|
contentKey={"about"}
|
||||||
|
title={formatMessage({ id: "About the hotel" })}
|
||||||
|
>
|
||||||
|
Some additional information about the hotel
|
||||||
|
</SidePeekContent>
|
||||||
|
</SidePeekContainer>
|
||||||
<AmenitiesList detailedFacilities={attributes.detailedFacilities} />
|
<AmenitiesList detailedFacilities={attributes.detailedFacilities} />
|
||||||
</div>
|
</div>
|
||||||
<Rooms rooms={roomCategories} />
|
<Rooms rooms={roomCategories} />
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
import ArrowRight from "@/components/Icons/ArrowRight"
|
import ArrowRight from "@/components/Icons/ArrowRight"
|
||||||
import TripAdvisorIcon from "@/components/Icons/TripAdvisor"
|
import TripAdvisorIcon from "@/components/Icons/TripAdvisor"
|
||||||
import Link from "@/components/TempDesignSystem/Link"
|
import Link from "@/components/TempDesignSystem/Link"
|
||||||
|
import { generateSidePeekLink } from "@/components/TempDesignSystem/SidePeek/data"
|
||||||
import BiroScript from "@/components/TempDesignSystem/Text/BiroScript"
|
import BiroScript from "@/components/TempDesignSystem/Text/BiroScript"
|
||||||
import Body from "@/components/TempDesignSystem/Text/Body"
|
import Body from "@/components/TempDesignSystem/Text/Body"
|
||||||
import Preamble from "@/components/TempDesignSystem/Text/Preamble"
|
import Preamble from "@/components/TempDesignSystem/Text/Preamble"
|
||||||
@@ -31,6 +32,7 @@ export default async function IntroSection({
|
|||||||
{ id: "Tripadvisor reviews" },
|
{ id: "Tripadvisor reviews" },
|
||||||
{ rating: tripAdvisor.rating, count: tripAdvisor.numberOfReviews }
|
{ rating: tripAdvisor.rating, count: tripAdvisor.numberOfReviews }
|
||||||
)
|
)
|
||||||
|
const aboutTheHotelLink = generateSidePeekLink("about")
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<section className={styles.introSection}>
|
<section className={styles.introSection}>
|
||||||
@@ -58,13 +60,11 @@ export default async function IntroSection({
|
|||||||
<Preamble>{hotelDescription}</Preamble>
|
<Preamble>{hotelDescription}</Preamble>
|
||||||
<Link
|
<Link
|
||||||
className={styles.introLink}
|
className={styles.introLink}
|
||||||
target="_blank"
|
|
||||||
color="peach80"
|
color="peach80"
|
||||||
textDecoration="underline"
|
textDecoration="underline"
|
||||||
variant="icon"
|
variant="icon"
|
||||||
href="#"
|
href={aboutTheHotelLink}
|
||||||
>
|
>
|
||||||
{/*TODO: Ask content team where this should link to. */}
|
|
||||||
{formatMessage({ id: "Read more about the hotel" })}
|
{formatMessage({ id: "Read more about the hotel" })}
|
||||||
<ArrowRight color="peach80" />
|
<ArrowRight color="peach80" />
|
||||||
</Link>
|
</Link>
|
||||||
|
|||||||
@@ -13,7 +13,6 @@ import styles from "./content.module.css"
|
|||||||
export default function Content({
|
export default function Content({
|
||||||
title,
|
title,
|
||||||
children,
|
children,
|
||||||
contentKey,
|
|
||||||
isActive = false,
|
isActive = false,
|
||||||
onClose,
|
onClose,
|
||||||
}: PropsWithChildren<SidePeekContentProps>) {
|
}: PropsWithChildren<SidePeekContentProps>) {
|
||||||
|
|||||||
@@ -1,7 +1,13 @@
|
|||||||
"use client"
|
"use client"
|
||||||
|
|
||||||
|
import { useIsSSR } from "@react-aria/ssr"
|
||||||
import { Children, cloneElement, PropsWithChildren } from "react"
|
import { Children, cloneElement, PropsWithChildren } from "react"
|
||||||
import { Dialog, DialogTrigger, Modal } from "react-aria-components"
|
import {
|
||||||
|
Dialog,
|
||||||
|
DialogTrigger,
|
||||||
|
Modal,
|
||||||
|
ModalOverlay,
|
||||||
|
} from "react-aria-components"
|
||||||
|
|
||||||
import { SidePeekProps } from "./types"
|
import { SidePeekProps } from "./types"
|
||||||
|
|
||||||
@@ -12,25 +18,31 @@ export default function SidePeek({
|
|||||||
onClose,
|
onClose,
|
||||||
activeContent,
|
activeContent,
|
||||||
}: PropsWithChildren<SidePeekProps>) {
|
}: PropsWithChildren<SidePeekProps>) {
|
||||||
return (
|
const isSSR = useIsSSR()
|
||||||
|
return isSSR ? (
|
||||||
|
<div>{children}</div>
|
||||||
|
) : (
|
||||||
<DialogTrigger>
|
<DialogTrigger>
|
||||||
<Modal
|
<ModalOverlay
|
||||||
className={styles.sidePeek}
|
className={styles.overlay}
|
||||||
isOpen={!!activeContent}
|
isOpen={!!activeContent}
|
||||||
onOpenChange={onClose}
|
onOpenChange={onClose}
|
||||||
|
isDismissable
|
||||||
>
|
>
|
||||||
<Dialog className={styles.dialog}>
|
<Modal className={styles.sidePeek}>
|
||||||
{({ close }) => (
|
<Dialog className={styles.dialog}>
|
||||||
<>
|
{({ close }) => (
|
||||||
{Children.map(children, (child) => {
|
<>
|
||||||
return cloneElement(child as React.ReactElement, {
|
{Children.map(children, (child) => {
|
||||||
onClose: close,
|
return cloneElement(child as React.ReactElement, {
|
||||||
})
|
onClose: close,
|
||||||
})}
|
})
|
||||||
</>
|
})}
|
||||||
)}
|
</>
|
||||||
</Dialog>
|
)}
|
||||||
</Modal>
|
</Dialog>
|
||||||
|
</Modal>
|
||||||
|
</ModalOverlay>
|
||||||
</DialogTrigger>
|
</DialogTrigger>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -22,6 +22,14 @@
|
|||||||
height: 100%;
|
height: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.overlay {
|
||||||
|
position: absolute;
|
||||||
|
top: 70.047px;
|
||||||
|
bottom: 0;
|
||||||
|
left: 0;
|
||||||
|
right: 0;
|
||||||
|
z-index: 99;
|
||||||
|
}
|
||||||
@keyframes slide-in {
|
@keyframes slide-in {
|
||||||
from {
|
from {
|
||||||
right: -600px;
|
right: -600px;
|
||||||
@@ -56,4 +64,7 @@
|
|||||||
.sidePeek[data-exiting] {
|
.sidePeek[data-exiting] {
|
||||||
animation: slide-in 250ms reverse;
|
animation: slide-in 250ms reverse;
|
||||||
}
|
}
|
||||||
|
.overlay {
|
||||||
|
top: 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
export type SidePeekContentKey = "amenities" | "read_more_about_the_hotel"
|
export type SidePeekContentKey = string
|
||||||
|
|
||||||
export type SidePeekProps = {
|
export type SidePeekProps = {
|
||||||
activeContent: string | null
|
activeContent: string | null
|
||||||
|
|||||||
1722
package-lock.json
generated
1722
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@@ -31,6 +31,7 @@
|
|||||||
"@hookform/resolvers": "^3.3.4",
|
"@hookform/resolvers": "^3.3.4",
|
||||||
"@netlify/plugin-nextjs": "^5.1.1",
|
"@netlify/plugin-nextjs": "^5.1.1",
|
||||||
"@radix-ui/react-slot": "^1.0.2",
|
"@radix-ui/react-slot": "^1.0.2",
|
||||||
|
"@react-aria/ssr": "^3.9.5",
|
||||||
"@scandic-hotels/design-system": "git+https://x-token-auth:$DESIGN_SYSTEM_ACCESS_TOKEN@bitbucket.org/scandic-swap/design-system.git#v0.1.0-rc.8",
|
"@scandic-hotels/design-system": "git+https://x-token-auth:$DESIGN_SYSTEM_ACCESS_TOKEN@bitbucket.org/scandic-swap/design-system.git#v0.1.0-rc.8",
|
||||||
"@t3-oss/env-nextjs": "^0.9.2",
|
"@t3-oss/env-nextjs": "^0.9.2",
|
||||||
"@tanstack/react-query": "^5.28.6",
|
"@tanstack/react-query": "^5.28.6",
|
||||||
|
|||||||
Reference in New Issue
Block a user