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);
|
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 {
|
||||||
|
|||||||
@@ -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>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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,
|
||||||
|
|||||||
@@ -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>
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -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;
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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>
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -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);
|
||||||
|
}
|
||||||
|
|||||||
@@ -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)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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,
|
||||||
|
|||||||
Reference in New Issue
Block a user