fix(SW-2758): Using ?s queryparameter again to handle sidepeeks on hotel pages

Approved-by: Matilda Landström
This commit is contained in:
Erik Tiekstra
2025-05-26 09:09:52 +00:00
parent 532f45a79c
commit c963891ca7
10 changed files with 74 additions and 84 deletions

View File

@@ -7,6 +7,7 @@
gap: var(--Spacing-x-one-and-half); gap: var(--Spacing-x-one-and-half);
height: fit-content; height: fit-content;
width: min(100%, 300px); width: min(100%, 300px);
justify-items: start;
} }
.amenityItemList { .amenityItemList {

View File

@@ -1,8 +1,8 @@
import { MaterialIcon } from "@scandic-hotels/design-system/Icons/MaterialIcon" import { MaterialIcon } from "@scandic-hotels/design-system/Icons/MaterialIcon"
import { Typography } from "@scandic-hotels/design-system/Typography" import { Typography } from "@scandic-hotels/design-system/Typography"
import ButtonLink from "@/components/ButtonLink"
import { FacilityToIcon } from "@/components/ContentType/HotelPage/data" import { FacilityToIcon } from "@/components/ContentType/HotelPage/data"
import Link from "@/components/TempDesignSystem/Link"
import { getIntl } from "@/i18n" import { getIntl } from "@/i18n"
import styles from "./amenitiesList.module.css" import styles from "./amenitiesList.module.css"
@@ -48,19 +48,17 @@ export default async function AmenitiesList({
) )
})} })}
</div> </div>
<Link <ButtonLink
href={`?s=${SidepeekSlugs.amenities}`}
variant="Text"
typography="Body/Paragraph/mdBold"
scroll={false} scroll={false}
href={`#s-${SidepeekSlugs.amenities}`}
color="burgundy"
variant="icon"
weight="bold"
className={styles.showAllAmenities}
> >
{intl.formatMessage({ {intl.formatMessage({
defaultMessage: "See all amenities", defaultMessage: "See all amenities",
})} })}
<MaterialIcon icon="chevron_right" size={20} color="CurrentColor" /> <MaterialIcon icon="chevron_right" size={24} color="CurrentColor" />
</Link> </ButtonLink>
</section> </section>
) )
} }

View File

@@ -15,7 +15,7 @@ export default function ActivitiesCardGrid(activitiesCard: ActivityCard) {
theme: hasImage ? "image" : "primaryDark", theme: hasImage ? "image" : "primaryDark",
primaryButton: hasImage primaryButton: hasImage
? { ? {
href: `#s-${activitiesCard.sidepeekSlug}`, href: `?s=${activitiesCard.sidepeekSlug}`,
title: activitiesCard.ctaText, title: activitiesCard.ctaText,
isExternal: false, isExternal: false,
scrollOnClick: false, scrollOnClick: false,
@@ -24,7 +24,7 @@ export default function ActivitiesCardGrid(activitiesCard: ActivityCard) {
secondaryButton: hasImage secondaryButton: hasImage
? undefined ? undefined
: { : {
href: `#s-${activitiesCard.sidepeekSlug}`, href: `?s=${activitiesCard.sidepeekSlug}`,
title: activitiesCard.ctaText, title: activitiesCard.ctaText,
isExternal: false, isExternal: false,
scrollOnClick: false, scrollOnClick: false,

View File

@@ -1,7 +1,7 @@
import { MaterialIcon } from "@scandic-hotels/design-system/Icons/MaterialIcon" import { MaterialIcon } from "@scandic-hotels/design-system/Icons/MaterialIcon"
import { Typography } from "@scandic-hotels/design-system/Typography" import { Typography } from "@scandic-hotels/design-system/Typography"
import Link from "@/components/TempDesignSystem/Link" import ButtonLink from "@/components/ButtonLink"
import { getIntl } from "@/i18n" import { getIntl } from "@/i18n"
import { getSingleDecimal } from "@/utils/numberFormatting" import { getSingleDecimal } from "@/utils/numberFormatting"
@@ -56,24 +56,17 @@ export default async function IntroSection({
<Typography variant="Body/Lead text"> <Typography variant="Body/Lead text">
<p>{hotelDescription}</p> <p>{hotelDescription}</p>
</Typography> </Typography>
<Link <ButtonLink
className={styles.introLink} href={`?s=${SidepeekSlugs.about}`}
color="burgundy" variant="Text"
variant="icon" typography="Body/Paragraph/mdBold"
weight="bold"
href={`#s-${SidepeekSlugs.about}`}
scroll={false} scroll={false}
> >
{intl.formatMessage({ {intl.formatMessage({
defaultMessage: "Read more", defaultMessage: "Read more",
})} })}
<MaterialIcon <MaterialIcon icon="chevron_right" size={24} color="CurrentColor" />
icon="chevron_right" </ButtonLink>
size={20}
color="CurrentColor"
className={styles.introLink}
/>
</Link>
</div> </div>
</section> </section>
) )

View File

@@ -1,19 +1,20 @@
.introSection { .introSection {
display: grid; display: grid;
gap: var(--Spacing-x2); gap: var(--Space-x2);
position: relative; position: relative;
max-width: var(--hotel-page-intro-section-width); max-width: var(--hotel-page-intro-section-width);
} }
.mainContent { .mainContent {
display: grid; display: grid;
gap: var(--Spacing-x1); gap: var(--Space-x1);
justify-items: start; justify-items: start;
} }
.subtitleContent { .subtitleContent {
display: grid; display: grid;
gap: var(--Spacing-x-one-and-half); gap: var(--Space-x05);
justify-items: start;
} }
.title { .title {
@@ -31,10 +32,5 @@
.titleContainer { .titleContainer {
display: grid; display: grid;
gap: var(--Spacing-x2); gap: var(--Space-x2);
}
.introLink {
text-decoration-color: var(--Scandic-Peach-80);
width: fit-content;
} }

View File

@@ -1,14 +1,12 @@
"use client" "use client"
import Link from "next/link"
import { useIntl } from "react-intl" import { useIntl } from "react-intl"
import { MaterialIcon } from "@scandic-hotels/design-system/Icons/MaterialIcon" import { MaterialIcon } from "@scandic-hotels/design-system/Icons/MaterialIcon"
import { Typography } from "@scandic-hotels/design-system/Typography"
import ButtonLink from "@/components/ButtonLink"
import ImageGallery from "@/components/ImageGallery" import ImageGallery from "@/components/ImageGallery"
import Button from "@/components/TempDesignSystem/Button"
import Body from "@/components/TempDesignSystem/Text/Body"
import Subtitle from "@/components/TempDesignSystem/Text/Subtitle"
import { mapApiImagesToGalleryImages } from "@/utils/imageGallery" import { mapApiImagesToGalleryImages } from "@/utils/imageGallery"
import { getRoomNameAsParam } from "../../utils" import { getRoomNameAsParam } from "../../utils"
@@ -46,36 +44,36 @@ export function RoomCard({ room }: RoomCardProps) {
</div> </div>
<div className={styles.content}> <div className={styles.content}>
<div className={styles.innerContent}> <div className={styles.innerContent}>
<Subtitle <Typography variant="Title/Subtitle/lg">
textTransform="capitalize" <h3>{name}</h3>
textAlign="center" </Typography>
type="one" <Typography variant="Body/Paragraph/mdRegular">
color="black" <p className={styles.roomSize}>
> {intl.formatMessage(
{name} {
</Subtitle> defaultMessage:
<Body color="grey"> "{size} ({max, plural, one {{range} guest} other {{range} guests}})",
{intl.formatMessage( },
{ {
defaultMessage: size,
"{size} ({max, plural, one {{range} guest} other {{range} guests}})", max: totalOccupancy.max,
}, range: totalOccupancy.range,
{ }
size, )}
max: totalOccupancy.max, </p>
range: totalOccupancy.range, </Typography>
}
)}
</Body>
</div> </div>
<Button intent="text" type="button" size="medium" theme="base" asChild> <ButtonLink
<Link scroll={false} href={`#s-room-${getRoomNameAsParam(name)}`}> href={`?s=room-${getRoomNameAsParam(name)}`}
{intl.formatMessage({ variant="Text"
defaultMessage: "See room details", typography="Body/Paragraph/mdBold"
})} scroll={false}
<MaterialIcon icon="chevron_right" size={20} color="CurrentColor" /> >
</Link> {intl.formatMessage({
</Button> defaultMessage: "See room details",
})}
<MaterialIcon icon="chevron_right" size={24} color="CurrentColor" />
</ButtonLink>
</div> </div>
</article> </article>
) )

View File

@@ -1,25 +1,30 @@
.roomCard { .roomCard {
border-radius: var(--Corner-radius-md); border-radius: var(--Corner-radius-md);
background-color: var(--UI-Opacity-White-100); background-color: var(--Surface-Primary-Default);
border: 1px solid var(--Base-Border-Subtle); border: 1px solid var(--Border-Default);
display: grid; display: grid;
overflow: hidden; overflow: hidden;
color: var(--Text-Default);
} }
.content { .content {
display: grid; display: grid;
justify-items: center; justify-items: center;
gap: var(--Spacing-x-one-and-half); gap: var(--Space-x05);
padding: var(--Spacing-x2); padding: var(--Space-x2);
} }
.innerContent { .innerContent {
display: grid; display: grid;
justify-items: center; justify-items: center;
gap: var(--Spacing-x1); gap: var(--Space-x1);
} }
.imageContainer { .imageContainer {
position: relative; position: relative;
height: 200px; height: 200px;
} }
.roomSize {
color: var(--Text-Tertiary);
}

View File

@@ -1,9 +1,7 @@
"use client" "use client"
import { useRouter } from "next/navigation" import { usePathname, useRouter, useSearchParams } from "next/navigation"
import { createContext, useEffect, useState } from "react" import { createContext, useEffect, useState } from "react"
import useHash from "@/hooks/useHash"
interface SidepeekProviderProps extends React.PropsWithChildren { interface SidepeekProviderProps extends React.PropsWithChildren {
onOpen?: (sidePeek: string) => void onOpen?: (sidePeek: string) => void
} }
@@ -20,16 +18,15 @@ export default function SidePeekProvider({
onOpen, onOpen,
}: SidepeekProviderProps) { }: SidepeekProviderProps) {
const router = useRouter() const router = useRouter()
const hash = useHash() const pathname = usePathname()
const searchParams = useSearchParams()
const [activeSidePeek, setActiveSidePeek] = useState<string | null>(null) const [activeSidePeek, setActiveSidePeek] = useState<string | null>(null)
useEffect(() => { useEffect(() => {
if (hash?.startsWith("s-")) { const sidePeekParam = searchParams.get("s")
setActiveSidePeek(hash.slice(2)) if (sidePeekParam !== activeSidePeek) {
} else { setActiveSidePeek(sidePeekParam)
setActiveSidePeek(null)
} }
}, [hash, setActiveSidePeek]) }, [searchParams, activeSidePeek])
useEffect(() => { useEffect(() => {
if (activeSidePeek && onOpen) { if (activeSidePeek && onOpen) {
@@ -39,7 +36,9 @@ export default function SidePeekProvider({
function handleClose(isOpen: boolean) { function handleClose(isOpen: boolean) {
if (!isOpen) { if (!isOpen) {
router.push(window.location.pathname, { scroll: false }) const nextSearchParams = new URLSearchParams(searchParams.toString())
nextSearchParams.delete("s")
router.push(`${pathname}?${nextSearchParams}`, { scroll: false })
setActiveSidePeek(null) setActiveSidePeek(null)
} }
} }

View File

@@ -83,7 +83,7 @@ function setCardProps(
heading, heading,
scriptedTopTitle, scriptedTopTitle,
secondaryButton: { secondaryButton: {
href: `#s-${slug}`, href: `?s=${slug}`,
title: buttonText, title: buttonText,
isExternal: false, isExternal: false,
scrollOnClick: false, scrollOnClick: false,