Merged in feat/SW-1001-multiple-activity-cards (pull request #1191)

Feat(SW-1001): Multiple activity cards on hotel page

* chore(SW-1001): render all activity cards

* chore(SW-1001): add sidepeek CTA text to CS

* feat(SW-1001): add slug from CS


Approved-by: Erik Tiekstra
Approved-by: Fredrik Thorsson
This commit is contained in:
Matilda Landström
2025-01-21 10:25:55 +00:00
parent d02dc51dcc
commit 554b73696d
15 changed files with 36 additions and 23 deletions

View File

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

View File

@@ -16,9 +16,9 @@ import type {
export default async function Facilities({
facilities,
activitiesCard,
amenities,
healthFacilities,
activitiesCards,
}: FacilitiesProps) {
const intl = await getIntl()
@@ -56,7 +56,12 @@ export default async function Facilities({
facilitiesCardGrid={cardGrid}
/>
))}
{activitiesCard && <ActivitiesCardGrid {...activitiesCard} />}
{activitiesCards.map((card) => (
<ActivitiesCardGrid
key={card.upcoming_activities_card.contentPage.href}
{...card.upcoming_activities_card}
/>
))}
</SectionContainer>
)
}

View File

@@ -13,20 +13,22 @@ import type { ActivitiesSidePeekProps } from "@/types/components/hotelPage/sidep
export default async function ActivitiesSidePeek({
contentPage,
sidepeekCTA,
sidepeekSlug,
}: ActivitiesSidePeekProps) {
const lang = getLang()
const intl = await getIntl()
const { href, preamble } = contentPage
return (
<SidePeek
contentKey={activities[lang]}
contentKey={sidepeekSlug}
title={intl.formatMessage({ id: "Activities" })}
>
<Preamble>{preamble}</Preamble>
<div className={styles.buttonContainer}>
<Button theme="base" intent="secondary" asChild>
<Link href={href} color="burgundy" weight="bold">
{intl.formatMessage({ id: "Show activities calendar" })}
{sidepeekCTA}
</Link>
</Button>
</div>

View File

@@ -85,7 +85,7 @@ export default async function HotelPage({ hotelId }: HotelPageProps) {
const images = gallery?.smallerImages
const description = hotelContent.texts.descriptions.medium
const { spaPage, activitiesCard } = content
const { spaPage, activitiesCards } = content
const facilities: Facility[] = [
{
@@ -140,7 +140,7 @@ export default async function HotelPage({ hotelId }: HotelPageProps) {
</header>
<TabNavigation
restaurantTitle={getRestaurantHeading(detailedFacilities)}
hasActivities={!!activitiesCard}
hasActivities={activitiesCards.length > 0}
hasFAQ={!!faq.accordions.length}
/>
@@ -173,7 +173,7 @@ export default async function HotelPage({ hotelId }: HotelPageProps) {
<Rooms rooms={roomCategories} preamble={hotelRoomElevatorPitchText} />
<Facilities
facilities={facilities}
activitiesCard={activitiesCard?.upcoming_activities_card}
activitiesCards={activitiesCards}
amenities={detailedFacilities}
healthFacilities={healthFacilities}
/>
@@ -220,11 +220,14 @@ export default async function HotelPage({ hotelId }: HotelPageProps) {
spaPage={spaPage?.spa_page}
/>
<RestaurantBarSidePeek restaurants={restaurants} />
{activitiesCard && (
{activitiesCards.map((card) => (
<ActivitiesSidePeek
contentPage={activitiesCard.upcoming_activities_card.contentPage}
key={card.upcoming_activities_card.heading}
contentPage={card.upcoming_activities_card.contentPage}
sidepeekCTA={card.upcoming_activities_card.sidepeekCtaText}
sidepeekSlug={card.upcoming_activities_card.sidepeekSlug}
/>
)}
))}
<MeetingsAndConferencesSidePeek
meetingFacilities={conferencesAndMeetings}
descriptions={hotelContent.texts.meetingDescription}

View File

@@ -404,7 +404,6 @@
"Select your language": "Vælg dit sprog",
"Shopping": "Shopping",
"Shopping & Dining": "Shopping & Spisning",
"Show activities calendar": "Vis aktivitetskalender",
"Show all amenities": "Vis alle faciliteter",
"Show less": "Vis mindre",
"Show less rooms": "Vise færre rum",

View File

@@ -403,7 +403,6 @@
"Select your language": "Wählen Sie Ihre Sprache",
"Shopping": "Einkaufen",
"Shopping & Dining": "Einkaufen & Essen",
"Show activities calendar": "Aktivitätenkalender anzeigen",
"Show all amenities": "Alle Annehmlichkeiten anzeigen",
"Show less": "Weniger anzeigen",
"Show less rooms": "Weniger Zimmer anzeigen",

View File

@@ -444,7 +444,6 @@
"Select your language": "Select your language",
"Shopping": "Shopping",
"Shopping & Dining": "Shopping & Dining",
"Show activities calendar": "Show activities calendar",
"Show all amenities": "Show all amenities",
"Show less": "Show less",
"Show less rooms": "Show less rooms",

View File

@@ -405,7 +405,6 @@
"Select your language": "Valitse kieli",
"Shopping": "Ostokset",
"Shopping & Dining": "Ostokset & Ravintolat",
"Show activities calendar": "Näytä aktiviteettikalenteri",
"Show all amenities": "Näytä kaikki mukavuudet",
"Show less": "Näytä vähemmän",
"Show less rooms": "Näytä vähemmän huoneita",

View File

@@ -403,7 +403,6 @@
"Select your language": "Velg språk",
"Shopping": "Shopping",
"Shopping & Dining": "Shopping & Spisesteder",
"Show activities calendar": "Vis aktivitetskalender",
"Show all amenities": "Vis alle fasiliteter",
"Show less": "Vis mindre",
"Show less rooms": "Vise færre rom",

View File

@@ -403,7 +403,6 @@
"Select your language": "Välj ditt språk",
"Shopping": "Shopping",
"Shopping & Dining": "Shopping & Mat",
"Show activities calendar": "Visa aktivitetskalender",
"Show all amenities": "Visa alla bekvämligheter",
"Show less": "Visa mindre",
"Show less rooms": "Visa färre rum",

View File

@@ -41,9 +41,11 @@ query GetHotelPage($locale: String!, $uid: String!) {
upcoming_activities_card {
background_image
cta_text
sidepeek_cta_text
heading
body_text
scripted_title
sidepeek_slug
hotel_page_activities_content_pageConnection {
edges {
node {

View File

@@ -41,11 +41,12 @@ export const hotelPageSchema = z.object({
.nullable()
.transform((data) => {
let spaPage: SpaPage | undefined
let activitiesCard: ActivitiesCard | undefined
let activitiesCards: ActivitiesCard[] = []
data?.map((block) => {
switch (block.typename) {
case HotelPageEnum.ContentStack.blocks.ActivitiesCard:
activitiesCard = block
activitiesCards.push(block)
break
case HotelPageEnum.ContentStack.blocks.SpaPage:
spaPage = block
@@ -54,7 +55,7 @@ export const hotelPageSchema = z.object({
break
}
})
return { spaPage, activitiesCard }
return { spaPage, activitiesCards }
}),
faq: hotelFaqSchema,
hotel_page_id: z.string(),

View File

@@ -18,8 +18,10 @@ export const activitiesCardSchema = z.object({
background_image: tempImageVaultAssetSchema,
body_text: z.string(),
cta_text: z.string(),
sidepeek_cta_text: z.string(),
heading: z.string(),
scripted_title: z.string().optional(),
sidepeek_slug: z.string(),
hotel_page_activities_content_pageConnection: z.object({
edges: z.array(
z.object({
@@ -53,6 +55,8 @@ export const activitiesCardSchema = z.object({
bodyText: data.body_text,
contentPage,
ctaText: data.cta_text,
sidepeekCtaText: data.sidepeek_cta_text,
sidepeekSlug: data.sidepeek_slug,
heading: data.heading,
scriptedTopTitle: data.scripted_title,
}

View File

@@ -1,10 +1,10 @@
import type { Amenities, Facility, HealthFacilities } from "@/types/hotel"
import type { ActivityCard } from "@/types/trpc/routers/contentstack/hotelPage"
import type { ActivitiesCard } from "@/types/trpc/routers/contentstack/hotelPage"
import type { CardProps } from "@/components/TempDesignSystem/Card/card"
export type FacilitiesProps = {
facilities: Facility[]
activitiesCard?: ActivityCard
activitiesCards: ActivitiesCard[]
amenities: Amenities
healthFacilities: HealthFacilities
}

View File

@@ -3,4 +3,6 @@ export type ActivitiesSidePeekProps = {
href: string
preamble: string
}
sidepeekCTA: string
sidepeekSlug: string
}