diff --git a/apps/scandic-web/components/Blocks/AllCampaigns/allCampaigns.module.css b/apps/scandic-web/components/Blocks/AllCampaigns/allCampaigns.module.css new file mode 100644 index 000000000..d676ec5b5 --- /dev/null +++ b/apps/scandic-web/components/Blocks/AllCampaigns/allCampaigns.module.css @@ -0,0 +1,35 @@ +.allCampaignsSection { + display: grid; + gap: var(--Space-x3); +} + +.header { + display: grid; + gap: var(--Space-x15); +} + +.heading { + color: var(--Text-Heading); +} + +.cardsList { + list-style: none; + display: none; +} + +@media screen and (min-width: 768px) { + .carousel { + display: none; + } + .cardsList { + display: grid; + grid-template-columns: repeat(2, 1fr); + gap: var(--Space-x4) var(--Space-x1); + } +} + +@media screen and (min-width: 1024px) { + .cardsList { + grid-template-columns: repeat(3, 1fr); + } +} diff --git a/apps/scandic-web/components/Blocks/AllCampaigns/index.tsx b/apps/scandic-web/components/Blocks/AllCampaigns/index.tsx new file mode 100644 index 000000000..ca2d4df8d --- /dev/null +++ b/apps/scandic-web/components/Blocks/AllCampaigns/index.tsx @@ -0,0 +1,80 @@ +import { Typography } from "@scandic-hotels/design-system/Typography" + +import { Carousel } from "@/components/Carousel" +import { CarouselContent } from "@/components/Carousel/CarouselContent" +import { CarouselDots } from "@/components/Carousel/CarouselDots" +import { CarouselItem } from "@/components/Carousel/CarouselItem" +import { + CarouselNext, + CarouselPrevious, +} from "@/components/Carousel/CarouselNavigation" +import ContentCard from "@/components/ContentCard" + +import styles from "./allCampaigns.module.css" + +import type { ImageVaultAsset } from "@scandic-hotels/trpc/types/imageVault" + +interface AllCampaignsProps { + heading: string + preamble?: string | null + cards: { + url: string + heading: string + text: string | null + image: ImageVaultAsset + }[] +} + +export default function AllCampaigns({ + heading, + preamble, + cards, +}: AllCampaignsProps) { + if (!cards.length) { + return null + } + + return ( +
+
+ +

{heading}

+
+ {preamble ? ( + +

{preamble}

+
+ ) : null} +
+ + + + {cards.map(({ url, heading, text, image }) => ( + + + + ))} + + + + + +
+ ) +} diff --git a/apps/scandic-web/components/ContentType/CampaignOverviewPage/Blocks/index.tsx b/apps/scandic-web/components/ContentType/CampaignOverviewPage/Blocks/index.tsx index b05b2e140..f0308865f 100644 --- a/apps/scandic-web/components/ContentType/CampaignOverviewPage/Blocks/index.tsx +++ b/apps/scandic-web/components/ContentType/CampaignOverviewPage/Blocks/index.tsx @@ -1,5 +1,6 @@ import { BlocksEnums } from "@scandic-hotels/trpc/types/blocksEnum" +import AllCampaigns from "@/components/Blocks/AllCampaigns" import CampaignHotelListing from "@/components/Blocks/CampaignHotelListing" import CarouselCards from "@/components/Blocks/CarouselCards" @@ -26,6 +27,15 @@ export default function Blocks({ blocks }: BlocksProps) { visibleCountDesktop={3} /> ) + case BlocksEnums.block.CampaignOverviewPageAllCampaigns: + return ( + + ) default: return null } diff --git a/packages/trpc/lib/graphql/Fragments/Blocks/AllCampaigns.graphql b/packages/trpc/lib/graphql/Fragments/Blocks/AllCampaigns.graphql new file mode 100644 index 000000000..53b13236a --- /dev/null +++ b/packages/trpc/lib/graphql/Fragments/Blocks/AllCampaigns.graphql @@ -0,0 +1,38 @@ +#import "../CampaignPage/Ref.graphql" + +fragment AllCampaigns on CampaignOverviewPageBlocksAllCampaigns { + all_campaigns { + heading + preamble + campaignsConnection { + edges { + node { + ... on CampaignPage { + url + card_content { + heading + image + text + } + system { + locale + } + } + } + } + } + } +} + +fragment AllCampaignsRefs on CampaignOverviewPageBlocksAllCampaigns { + all_campaigns { + campaignsConnection { + edges { + node { + __typename + ...CampaignPageRef + } + } + } + } +} diff --git a/packages/trpc/lib/graphql/Query/CampaignOverviewPage/CampaignOverviewPage.graphql b/packages/trpc/lib/graphql/Query/CampaignOverviewPage/CampaignOverviewPage.graphql index 93586dc11..ca5079793 100644 --- a/packages/trpc/lib/graphql/Query/CampaignOverviewPage/CampaignOverviewPage.graphql +++ b/packages/trpc/lib/graphql/Query/CampaignOverviewPage/CampaignOverviewPage.graphql @@ -3,6 +3,7 @@ #import "../../Fragments/CampaignOverviewPage/NavigationLinks.graphql" #import "../../Fragments/CampaignOverviewPage/TopCampaign.graphql" +#import "../../Fragments/Blocks/AllCampaigns.graphql" #import "../../Fragments/Blocks/CarouselCards.graphql" #import "../../Fragments/Blocks/HotelListing.graphql" @@ -23,6 +24,7 @@ query GetCampaignOverviewPage($locale: String!, $uid: String!) { } blocks { __typename + ...AllCampaigns ...CarouselCards_CampaignOverviewPage ...HotelListing_CampaignOverviewPage } @@ -52,6 +54,7 @@ query GetCampaignOverviewPageRefs($locale: String!, $uid: String!) { blocks { __typename ...CarouselCards_CampaignOverviewPageRefs + ...AllCampaignsRefs } system { ...System diff --git a/packages/trpc/lib/routers/contentstack/campaignOverviewPage/output.ts b/packages/trpc/lib/routers/contentstack/campaignOverviewPage/output.ts index 9a5c7bc9c..9ef5e3e74 100644 --- a/packages/trpc/lib/routers/contentstack/campaignOverviewPage/output.ts +++ b/packages/trpc/lib/routers/contentstack/campaignOverviewPage/output.ts @@ -8,6 +8,10 @@ import { heroSchema, includedHotelsSchema, } from "../campaignPage/output" +import { + allCampaignsRefsSchema, + allCampaignsSchema, +} from "../schemas/blocks/allCampaigns" import { carouselCardsRefsSchema, carouselCardsSchema, @@ -71,6 +75,14 @@ const campaignOverviewPageCarouselCards = z }) .merge(carouselCardsSchema) +const campaignOverviewPageAllCampaigns = z + .object({ + __typename: z.literal( + CampaignOverviewPageEnum.ContentStack.blocks.AllCampaigns + ), + }) + .merge(allCampaignsSchema) + export const campaignOverviewPageHotelListing = z .object({ __typename: z.literal( @@ -80,6 +92,7 @@ export const campaignOverviewPageHotelListing = z .merge(campaignOverviewPageHotelListingSchema) export const blocksSchema = z.discriminatedUnion("__typename", [ + campaignOverviewPageAllCampaigns, campaignOverviewPageCarouselCards, campaignOverviewPageHotelListing, ]) @@ -134,7 +147,16 @@ const campaignOverviewPageCarouselCardsRef = z }) .merge(carouselCardsRefsSchema) +const campaignOverviewPageAllCampaignsRef = z + .object({ + __typename: z.literal( + CampaignOverviewPageEnum.ContentStack.blocks.AllCampaigns + ), + }) + .merge(allCampaignsRefsSchema) + const blockRefsSchema = z.discriminatedUnion("__typename", [ + campaignOverviewPageAllCampaignsRef, campaignOverviewPageCarouselCardsRef, ]) diff --git a/packages/trpc/lib/routers/contentstack/campaignOverviewPage/utils.ts b/packages/trpc/lib/routers/contentstack/campaignOverviewPage/utils.ts index dc830334f..d46d27842 100644 --- a/packages/trpc/lib/routers/contentstack/campaignOverviewPage/utils.ts +++ b/packages/trpc/lib/routers/contentstack/campaignOverviewPage/utils.ts @@ -45,6 +45,12 @@ export function getConnections({ }) break } + case CampaignOverviewPageEnum.ContentStack.blocks.AllCampaigns: { + block.all_campaigns.campaignsConnection.edges.forEach(({ node }) => { + connections.push(node.system) + }) + break + } } }) } diff --git a/packages/trpc/lib/routers/contentstack/schemas/blocks/allCampaigns.ts b/packages/trpc/lib/routers/contentstack/schemas/blocks/allCampaigns.ts new file mode 100644 index 000000000..c756e8081 --- /dev/null +++ b/packages/trpc/lib/routers/contentstack/schemas/blocks/allCampaigns.ts @@ -0,0 +1,80 @@ +import { z } from "zod" + +import { removeMultipleSlashes } from "@scandic-hotels/common/utils/url" + +import { BlocksEnums } from "../../../../types/blocksEnum" +import { tempImageVaultAssetSchema } from "../imageVault" +import { campaignPageRefSchema } from "../pageLinks" + +export const campaignPageCardSchema = z.object({ + image: tempImageVaultAssetSchema, + heading: z.string(), + text: z.string(), +}) + +export const allCampaignsSchema = z.object({ + typename: z + .literal(BlocksEnums.block.CampaignOverviewPageAllCampaigns) + .optional() + .default(BlocksEnums.block.CampaignOverviewPageAllCampaigns), + all_campaigns: z + .object({ + heading: z.string(), + preamble: z.string().nullish(), + campaignsConnection: z.object({ + edges: z + .array( + z.object({ + node: z.object({ + url: z.string(), + card_content: z + .object({ + image: tempImageVaultAssetSchema, + heading: z.string().nullish(), + text: z.string().nullish(), + }) + .nullish(), + system: z.object({ + locale: z.string(), + }), + }), + }) + ) + .transform((data) => { + const mappedCards = data.map(({ node }) => { + const { url, card_content } = node + if (url && card_content?.image && card_content?.heading) { + return { + url: removeMultipleSlashes(`/${node.system.locale}/${url}`), + heading: card_content.heading, + image: card_content.image, + text: card_content.text ?? null, + } + } + + return null + }) + + return mappedCards.filter((card) => !!card) + }), + }), + }) + .transform((data) => { + return { + ...data, + cards: data.campaignsConnection.edges, + } + }), +}) + +export const allCampaignsRefsSchema = z.object({ + all_campaigns: z.object({ + campaignsConnection: z.object({ + edges: z.array( + z.object({ + node: campaignPageRefSchema, + }) + ), + }), + }), +}) diff --git a/packages/trpc/lib/types/blocksEnum.ts b/packages/trpc/lib/types/blocksEnum.ts index 5807dbb06..b0eb5c8eb 100644 --- a/packages/trpc/lib/types/blocksEnum.ts +++ b/packages/trpc/lib/types/blocksEnum.ts @@ -8,6 +8,7 @@ export namespace BlocksEnums { DynamicContent = "DynamicContent", FullWidthCampaign = "FullWidthCampaign", CampaignOverviewPageHotelListing = "CampaignOverviewPageHotelListing", + CampaignOverviewPageAllCampaigns = "CampaignOverviewPageAllCampaigns", CampaignPageHotelListing = "CampaignPageHotelListing", ContentPageHotelListing = "ContentPageHotelListing", JoinScandicFriends = "JoinScandicFriends", diff --git a/packages/trpc/lib/types/campaignOverviewPageEnum.ts b/packages/trpc/lib/types/campaignOverviewPageEnum.ts index 75f442971..0d9e1c6f3 100644 --- a/packages/trpc/lib/types/campaignOverviewPageEnum.ts +++ b/packages/trpc/lib/types/campaignOverviewPageEnum.ts @@ -3,6 +3,7 @@ export namespace CampaignOverviewPageEnum { export const enum blocks { CarouselCards = "CampaignOverviewPageBlocksCarouselCards", HotelListing = "CampaignOverviewPageBlocksHotelListing", + AllCampaigns = "CampaignOverviewPageBlocksAllCampaigns", } } }