feat(SW-3061): Added block for all campaigns
Approved-by: Matilda Landström
This commit is contained in:
@@ -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);
|
||||||
|
}
|
||||||
|
}
|
||||||
80
apps/scandic-web/components/Blocks/AllCampaigns/index.tsx
Normal file
80
apps/scandic-web/components/Blocks/AllCampaigns/index.tsx
Normal file
@@ -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 (
|
||||||
|
<section className={styles.allCampaignsSection}>
|
||||||
|
<header className={styles.header}>
|
||||||
|
<Typography variant="Title/md">
|
||||||
|
<h3 className={styles.heading}>{heading}</h3>
|
||||||
|
</Typography>
|
||||||
|
{preamble ? (
|
||||||
|
<Typography variant="Body/Paragraph/mdRegular">
|
||||||
|
<p className={styles.preamble}>{preamble}</p>
|
||||||
|
</Typography>
|
||||||
|
) : null}
|
||||||
|
</header>
|
||||||
|
<ul className={styles.cardsList}>
|
||||||
|
{cards.map(({ url, image, heading, text }) => (
|
||||||
|
<li key={url} className={styles.listItem}>
|
||||||
|
<ContentCard
|
||||||
|
heading={heading}
|
||||||
|
image={image}
|
||||||
|
bodyText={text || ""}
|
||||||
|
link={{ href: url }}
|
||||||
|
/>
|
||||||
|
</li>
|
||||||
|
))}
|
||||||
|
</ul>
|
||||||
|
<Carousel className={styles.carousel}>
|
||||||
|
<CarouselContent>
|
||||||
|
{cards.map(({ url, heading, text, image }) => (
|
||||||
|
<CarouselItem key={url}>
|
||||||
|
<ContentCard
|
||||||
|
heading={heading}
|
||||||
|
image={image}
|
||||||
|
bodyText={text || ""}
|
||||||
|
link={{ href: url }}
|
||||||
|
/>
|
||||||
|
</CarouselItem>
|
||||||
|
))}
|
||||||
|
</CarouselContent>
|
||||||
|
<CarouselPrevious className={styles.navigationButton} />
|
||||||
|
<CarouselNext className={styles.navigationButton} />
|
||||||
|
<CarouselDots />
|
||||||
|
</Carousel>
|
||||||
|
</section>
|
||||||
|
)
|
||||||
|
}
|
||||||
@@ -1,5 +1,6 @@
|
|||||||
import { BlocksEnums } from "@scandic-hotels/trpc/types/blocksEnum"
|
import { BlocksEnums } from "@scandic-hotels/trpc/types/blocksEnum"
|
||||||
|
|
||||||
|
import AllCampaigns from "@/components/Blocks/AllCampaigns"
|
||||||
import CampaignHotelListing from "@/components/Blocks/CampaignHotelListing"
|
import CampaignHotelListing from "@/components/Blocks/CampaignHotelListing"
|
||||||
import CarouselCards from "@/components/Blocks/CarouselCards"
|
import CarouselCards from "@/components/Blocks/CarouselCards"
|
||||||
|
|
||||||
@@ -26,6 +27,15 @@ export default function Blocks({ blocks }: BlocksProps) {
|
|||||||
visibleCountDesktop={3}
|
visibleCountDesktop={3}
|
||||||
/>
|
/>
|
||||||
)
|
)
|
||||||
|
case BlocksEnums.block.CampaignOverviewPageAllCampaigns:
|
||||||
|
return (
|
||||||
|
<AllCampaigns
|
||||||
|
key={block.all_campaigns.heading}
|
||||||
|
heading={block.all_campaigns.heading}
|
||||||
|
preamble={block.all_campaigns.preamble}
|
||||||
|
cards={block.all_campaigns.cards}
|
||||||
|
/>
|
||||||
|
)
|
||||||
default:
|
default:
|
||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -3,6 +3,7 @@
|
|||||||
#import "../../Fragments/CampaignOverviewPage/NavigationLinks.graphql"
|
#import "../../Fragments/CampaignOverviewPage/NavigationLinks.graphql"
|
||||||
#import "../../Fragments/CampaignOverviewPage/TopCampaign.graphql"
|
#import "../../Fragments/CampaignOverviewPage/TopCampaign.graphql"
|
||||||
|
|
||||||
|
#import "../../Fragments/Blocks/AllCampaigns.graphql"
|
||||||
#import "../../Fragments/Blocks/CarouselCards.graphql"
|
#import "../../Fragments/Blocks/CarouselCards.graphql"
|
||||||
#import "../../Fragments/Blocks/HotelListing.graphql"
|
#import "../../Fragments/Blocks/HotelListing.graphql"
|
||||||
|
|
||||||
@@ -23,6 +24,7 @@ query GetCampaignOverviewPage($locale: String!, $uid: String!) {
|
|||||||
}
|
}
|
||||||
blocks {
|
blocks {
|
||||||
__typename
|
__typename
|
||||||
|
...AllCampaigns
|
||||||
...CarouselCards_CampaignOverviewPage
|
...CarouselCards_CampaignOverviewPage
|
||||||
...HotelListing_CampaignOverviewPage
|
...HotelListing_CampaignOverviewPage
|
||||||
}
|
}
|
||||||
@@ -52,6 +54,7 @@ query GetCampaignOverviewPageRefs($locale: String!, $uid: String!) {
|
|||||||
blocks {
|
blocks {
|
||||||
__typename
|
__typename
|
||||||
...CarouselCards_CampaignOverviewPageRefs
|
...CarouselCards_CampaignOverviewPageRefs
|
||||||
|
...AllCampaignsRefs
|
||||||
}
|
}
|
||||||
system {
|
system {
|
||||||
...System
|
...System
|
||||||
|
|||||||
@@ -8,6 +8,10 @@ import {
|
|||||||
heroSchema,
|
heroSchema,
|
||||||
includedHotelsSchema,
|
includedHotelsSchema,
|
||||||
} from "../campaignPage/output"
|
} from "../campaignPage/output"
|
||||||
|
import {
|
||||||
|
allCampaignsRefsSchema,
|
||||||
|
allCampaignsSchema,
|
||||||
|
} from "../schemas/blocks/allCampaigns"
|
||||||
import {
|
import {
|
||||||
carouselCardsRefsSchema,
|
carouselCardsRefsSchema,
|
||||||
carouselCardsSchema,
|
carouselCardsSchema,
|
||||||
@@ -71,6 +75,14 @@ const campaignOverviewPageCarouselCards = z
|
|||||||
})
|
})
|
||||||
.merge(carouselCardsSchema)
|
.merge(carouselCardsSchema)
|
||||||
|
|
||||||
|
const campaignOverviewPageAllCampaigns = z
|
||||||
|
.object({
|
||||||
|
__typename: z.literal(
|
||||||
|
CampaignOverviewPageEnum.ContentStack.blocks.AllCampaigns
|
||||||
|
),
|
||||||
|
})
|
||||||
|
.merge(allCampaignsSchema)
|
||||||
|
|
||||||
export const campaignOverviewPageHotelListing = z
|
export const campaignOverviewPageHotelListing = z
|
||||||
.object({
|
.object({
|
||||||
__typename: z.literal(
|
__typename: z.literal(
|
||||||
@@ -80,6 +92,7 @@ export const campaignOverviewPageHotelListing = z
|
|||||||
.merge(campaignOverviewPageHotelListingSchema)
|
.merge(campaignOverviewPageHotelListingSchema)
|
||||||
|
|
||||||
export const blocksSchema = z.discriminatedUnion("__typename", [
|
export const blocksSchema = z.discriminatedUnion("__typename", [
|
||||||
|
campaignOverviewPageAllCampaigns,
|
||||||
campaignOverviewPageCarouselCards,
|
campaignOverviewPageCarouselCards,
|
||||||
campaignOverviewPageHotelListing,
|
campaignOverviewPageHotelListing,
|
||||||
])
|
])
|
||||||
@@ -134,7 +147,16 @@ const campaignOverviewPageCarouselCardsRef = z
|
|||||||
})
|
})
|
||||||
.merge(carouselCardsRefsSchema)
|
.merge(carouselCardsRefsSchema)
|
||||||
|
|
||||||
|
const campaignOverviewPageAllCampaignsRef = z
|
||||||
|
.object({
|
||||||
|
__typename: z.literal(
|
||||||
|
CampaignOverviewPageEnum.ContentStack.blocks.AllCampaigns
|
||||||
|
),
|
||||||
|
})
|
||||||
|
.merge(allCampaignsRefsSchema)
|
||||||
|
|
||||||
const blockRefsSchema = z.discriminatedUnion("__typename", [
|
const blockRefsSchema = z.discriminatedUnion("__typename", [
|
||||||
|
campaignOverviewPageAllCampaignsRef,
|
||||||
campaignOverviewPageCarouselCardsRef,
|
campaignOverviewPageCarouselCardsRef,
|
||||||
])
|
])
|
||||||
|
|
||||||
|
|||||||
@@ -45,6 +45,12 @@ export function getConnections({
|
|||||||
})
|
})
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
case CampaignOverviewPageEnum.ContentStack.blocks.AllCampaigns: {
|
||||||
|
block.all_campaigns.campaignsConnection.edges.forEach(({ node }) => {
|
||||||
|
connections.push(node.system)
|
||||||
|
})
|
||||||
|
break
|
||||||
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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,
|
||||||
|
})
|
||||||
|
),
|
||||||
|
}),
|
||||||
|
}),
|
||||||
|
})
|
||||||
@@ -8,6 +8,7 @@ export namespace BlocksEnums {
|
|||||||
DynamicContent = "DynamicContent",
|
DynamicContent = "DynamicContent",
|
||||||
FullWidthCampaign = "FullWidthCampaign",
|
FullWidthCampaign = "FullWidthCampaign",
|
||||||
CampaignOverviewPageHotelListing = "CampaignOverviewPageHotelListing",
|
CampaignOverviewPageHotelListing = "CampaignOverviewPageHotelListing",
|
||||||
|
CampaignOverviewPageAllCampaigns = "CampaignOverviewPageAllCampaigns",
|
||||||
CampaignPageHotelListing = "CampaignPageHotelListing",
|
CampaignPageHotelListing = "CampaignPageHotelListing",
|
||||||
ContentPageHotelListing = "ContentPageHotelListing",
|
ContentPageHotelListing = "ContentPageHotelListing",
|
||||||
JoinScandicFriends = "JoinScandicFriends",
|
JoinScandicFriends = "JoinScandicFriends",
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ export namespace CampaignOverviewPageEnum {
|
|||||||
export const enum blocks {
|
export const enum blocks {
|
||||||
CarouselCards = "CampaignOverviewPageBlocksCarouselCards",
|
CarouselCards = "CampaignOverviewPageBlocksCarouselCards",
|
||||||
HotelListing = "CampaignOverviewPageBlocksHotelListing",
|
HotelListing = "CampaignOverviewPageBlocksHotelListing",
|
||||||
|
AllCampaigns = "CampaignOverviewPageBlocksAllCampaigns",
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user