fix(SW-2758): Using ?s queryparameter again to handle sidepeeks on hotel pages
Approved-by: Matilda Landström
This commit is contained in:
@@ -7,6 +7,7 @@
|
||||
gap: var(--Spacing-x-one-and-half);
|
||||
height: fit-content;
|
||||
width: min(100%, 300px);
|
||||
justify-items: start;
|
||||
}
|
||||
|
||||
.amenityItemList {
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import { MaterialIcon } from "@scandic-hotels/design-system/Icons/MaterialIcon"
|
||||
import { Typography } from "@scandic-hotels/design-system/Typography"
|
||||
|
||||
import ButtonLink from "@/components/ButtonLink"
|
||||
import { FacilityToIcon } from "@/components/ContentType/HotelPage/data"
|
||||
import Link from "@/components/TempDesignSystem/Link"
|
||||
import { getIntl } from "@/i18n"
|
||||
|
||||
import styles from "./amenitiesList.module.css"
|
||||
@@ -48,19 +48,17 @@ export default async function AmenitiesList({
|
||||
)
|
||||
})}
|
||||
</div>
|
||||
<Link
|
||||
<ButtonLink
|
||||
href={`?s=${SidepeekSlugs.amenities}`}
|
||||
variant="Text"
|
||||
typography="Body/Paragraph/mdBold"
|
||||
scroll={false}
|
||||
href={`#s-${SidepeekSlugs.amenities}`}
|
||||
color="burgundy"
|
||||
variant="icon"
|
||||
weight="bold"
|
||||
className={styles.showAllAmenities}
|
||||
>
|
||||
{intl.formatMessage({
|
||||
defaultMessage: "See all amenities",
|
||||
})}
|
||||
<MaterialIcon icon="chevron_right" size={20} color="CurrentColor" />
|
||||
</Link>
|
||||
<MaterialIcon icon="chevron_right" size={24} color="CurrentColor" />
|
||||
</ButtonLink>
|
||||
</section>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -15,7 +15,7 @@ export default function ActivitiesCardGrid(activitiesCard: ActivityCard) {
|
||||
theme: hasImage ? "image" : "primaryDark",
|
||||
primaryButton: hasImage
|
||||
? {
|
||||
href: `#s-${activitiesCard.sidepeekSlug}`,
|
||||
href: `?s=${activitiesCard.sidepeekSlug}`,
|
||||
title: activitiesCard.ctaText,
|
||||
isExternal: false,
|
||||
scrollOnClick: false,
|
||||
@@ -24,7 +24,7 @@ export default function ActivitiesCardGrid(activitiesCard: ActivityCard) {
|
||||
secondaryButton: hasImage
|
||||
? undefined
|
||||
: {
|
||||
href: `#s-${activitiesCard.sidepeekSlug}`,
|
||||
href: `?s=${activitiesCard.sidepeekSlug}`,
|
||||
title: activitiesCard.ctaText,
|
||||
isExternal: false,
|
||||
scrollOnClick: false,
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { MaterialIcon } from "@scandic-hotels/design-system/Icons/MaterialIcon"
|
||||
import { Typography } from "@scandic-hotels/design-system/Typography"
|
||||
|
||||
import Link from "@/components/TempDesignSystem/Link"
|
||||
import ButtonLink from "@/components/ButtonLink"
|
||||
import { getIntl } from "@/i18n"
|
||||
import { getSingleDecimal } from "@/utils/numberFormatting"
|
||||
|
||||
@@ -56,24 +56,17 @@ export default async function IntroSection({
|
||||
<Typography variant="Body/Lead text">
|
||||
<p>{hotelDescription}</p>
|
||||
</Typography>
|
||||
<Link
|
||||
className={styles.introLink}
|
||||
color="burgundy"
|
||||
variant="icon"
|
||||
weight="bold"
|
||||
href={`#s-${SidepeekSlugs.about}`}
|
||||
<ButtonLink
|
||||
href={`?s=${SidepeekSlugs.about}`}
|
||||
variant="Text"
|
||||
typography="Body/Paragraph/mdBold"
|
||||
scroll={false}
|
||||
>
|
||||
{intl.formatMessage({
|
||||
defaultMessage: "Read more",
|
||||
})}
|
||||
<MaterialIcon
|
||||
icon="chevron_right"
|
||||
size={20}
|
||||
color="CurrentColor"
|
||||
className={styles.introLink}
|
||||
/>
|
||||
</Link>
|
||||
<MaterialIcon icon="chevron_right" size={24} color="CurrentColor" />
|
||||
</ButtonLink>
|
||||
</div>
|
||||
</section>
|
||||
)
|
||||
|
||||
@@ -1,19 +1,20 @@
|
||||
.introSection {
|
||||
display: grid;
|
||||
gap: var(--Spacing-x2);
|
||||
gap: var(--Space-x2);
|
||||
position: relative;
|
||||
max-width: var(--hotel-page-intro-section-width);
|
||||
}
|
||||
|
||||
.mainContent {
|
||||
display: grid;
|
||||
gap: var(--Spacing-x1);
|
||||
gap: var(--Space-x1);
|
||||
justify-items: start;
|
||||
}
|
||||
|
||||
.subtitleContent {
|
||||
display: grid;
|
||||
gap: var(--Spacing-x-one-and-half);
|
||||
gap: var(--Space-x05);
|
||||
justify-items: start;
|
||||
}
|
||||
|
||||
.title {
|
||||
@@ -31,10 +32,5 @@
|
||||
|
||||
.titleContainer {
|
||||
display: grid;
|
||||
gap: var(--Spacing-x2);
|
||||
}
|
||||
|
||||
.introLink {
|
||||
text-decoration-color: var(--Scandic-Peach-80);
|
||||
width: fit-content;
|
||||
gap: var(--Space-x2);
|
||||
}
|
||||
|
||||
@@ -1,14 +1,12 @@
|
||||
"use client"
|
||||
|
||||
import Link from "next/link"
|
||||
import { useIntl } from "react-intl"
|
||||
|
||||
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 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 { getRoomNameAsParam } from "../../utils"
|
||||
@@ -46,36 +44,36 @@ export function RoomCard({ room }: RoomCardProps) {
|
||||
</div>
|
||||
<div className={styles.content}>
|
||||
<div className={styles.innerContent}>
|
||||
<Subtitle
|
||||
textTransform="capitalize"
|
||||
textAlign="center"
|
||||
type="one"
|
||||
color="black"
|
||||
>
|
||||
{name}
|
||||
</Subtitle>
|
||||
<Body color="grey">
|
||||
{intl.formatMessage(
|
||||
{
|
||||
defaultMessage:
|
||||
"{size} ({max, plural, one {{range} guest} other {{range} guests}})",
|
||||
},
|
||||
{
|
||||
size,
|
||||
max: totalOccupancy.max,
|
||||
range: totalOccupancy.range,
|
||||
}
|
||||
)}
|
||||
</Body>
|
||||
<Typography variant="Title/Subtitle/lg">
|
||||
<h3>{name}</h3>
|
||||
</Typography>
|
||||
<Typography variant="Body/Paragraph/mdRegular">
|
||||
<p className={styles.roomSize}>
|
||||
{intl.formatMessage(
|
||||
{
|
||||
defaultMessage:
|
||||
"{size} ({max, plural, one {{range} guest} other {{range} guests}})",
|
||||
},
|
||||
{
|
||||
size,
|
||||
max: totalOccupancy.max,
|
||||
range: totalOccupancy.range,
|
||||
}
|
||||
)}
|
||||
</p>
|
||||
</Typography>
|
||||
</div>
|
||||
<Button intent="text" type="button" size="medium" theme="base" asChild>
|
||||
<Link scroll={false} href={`#s-room-${getRoomNameAsParam(name)}`}>
|
||||
{intl.formatMessage({
|
||||
defaultMessage: "See room details",
|
||||
})}
|
||||
<MaterialIcon icon="chevron_right" size={20} color="CurrentColor" />
|
||||
</Link>
|
||||
</Button>
|
||||
<ButtonLink
|
||||
href={`?s=room-${getRoomNameAsParam(name)}`}
|
||||
variant="Text"
|
||||
typography="Body/Paragraph/mdBold"
|
||||
scroll={false}
|
||||
>
|
||||
{intl.formatMessage({
|
||||
defaultMessage: "See room details",
|
||||
})}
|
||||
<MaterialIcon icon="chevron_right" size={24} color="CurrentColor" />
|
||||
</ButtonLink>
|
||||
</div>
|
||||
</article>
|
||||
)
|
||||
|
||||
@@ -1,25 +1,30 @@
|
||||
.roomCard {
|
||||
border-radius: var(--Corner-radius-md);
|
||||
background-color: var(--UI-Opacity-White-100);
|
||||
border: 1px solid var(--Base-Border-Subtle);
|
||||
background-color: var(--Surface-Primary-Default);
|
||||
border: 1px solid var(--Border-Default);
|
||||
display: grid;
|
||||
overflow: hidden;
|
||||
color: var(--Text-Default);
|
||||
}
|
||||
|
||||
.content {
|
||||
display: grid;
|
||||
justify-items: center;
|
||||
gap: var(--Spacing-x-one-and-half);
|
||||
padding: var(--Spacing-x2);
|
||||
gap: var(--Space-x05);
|
||||
padding: var(--Space-x2);
|
||||
}
|
||||
|
||||
.innerContent {
|
||||
display: grid;
|
||||
justify-items: center;
|
||||
gap: var(--Spacing-x1);
|
||||
gap: var(--Space-x1);
|
||||
}
|
||||
|
||||
.imageContainer {
|
||||
position: relative;
|
||||
height: 200px;
|
||||
}
|
||||
|
||||
.roomSize {
|
||||
color: var(--Text-Tertiary);
|
||||
}
|
||||
|
||||
@@ -1,9 +1,7 @@
|
||||
"use client"
|
||||
import { useRouter } from "next/navigation"
|
||||
import { usePathname, useRouter, useSearchParams } from "next/navigation"
|
||||
import { createContext, useEffect, useState } from "react"
|
||||
|
||||
import useHash from "@/hooks/useHash"
|
||||
|
||||
interface SidepeekProviderProps extends React.PropsWithChildren {
|
||||
onOpen?: (sidePeek: string) => void
|
||||
}
|
||||
@@ -20,16 +18,15 @@ export default function SidePeekProvider({
|
||||
onOpen,
|
||||
}: SidepeekProviderProps) {
|
||||
const router = useRouter()
|
||||
const hash = useHash()
|
||||
const pathname = usePathname()
|
||||
const searchParams = useSearchParams()
|
||||
const [activeSidePeek, setActiveSidePeek] = useState<string | null>(null)
|
||||
|
||||
useEffect(() => {
|
||||
if (hash?.startsWith("s-")) {
|
||||
setActiveSidePeek(hash.slice(2))
|
||||
} else {
|
||||
setActiveSidePeek(null)
|
||||
const sidePeekParam = searchParams.get("s")
|
||||
if (sidePeekParam !== activeSidePeek) {
|
||||
setActiveSidePeek(sidePeekParam)
|
||||
}
|
||||
}, [hash, setActiveSidePeek])
|
||||
}, [searchParams, activeSidePeek])
|
||||
|
||||
useEffect(() => {
|
||||
if (activeSidePeek && onOpen) {
|
||||
@@ -39,7 +36,9 @@ export default function SidePeekProvider({
|
||||
|
||||
function handleClose(isOpen: boolean) {
|
||||
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)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -83,7 +83,7 @@ function setCardProps(
|
||||
heading,
|
||||
scriptedTopTitle,
|
||||
secondaryButton: {
|
||||
href: `#s-${slug}`,
|
||||
href: `?s=${slug}`,
|
||||
title: buttonText,
|
||||
isExternal: false,
|
||||
scrollOnClick: false,
|
||||
|
||||
Reference in New Issue
Block a user