fix: add loyaltyCard

This commit is contained in:
Christel Westerberg
2024-06-28 11:21:09 +02:00
parent 5be118d9e5
commit 323df671d8
23 changed files with 467 additions and 106 deletions

View File

@@ -8,7 +8,7 @@
.blocks { .blocks {
display: grid; display: grid;
gap: var(--Spacing-x5); gap: var(--Spacing-x7);
padding-left: var(--Spacing-x2); padding-left: var(--Spacing-x2);
padding-right: var(--Spacing-x2); padding-right: var(--Spacing-x2);
} }
@@ -29,6 +29,7 @@
} }
.blocks { .blocks {
gap: var(--Spacing-x9);
padding-left: var(--Spacing-x0); padding-left: var(--Spacing-x0);
padding-right: var(--Spacing-x0); padding-right: var(--Spacing-x0);
} }

View File

@@ -2,25 +2,50 @@ import SectionContainer from "@/components/Section/Container"
import Header from "@/components/Section/Header" import Header from "@/components/Section/Header"
import Card from "@/components/TempDesignSystem/Card" import Card from "@/components/TempDesignSystem/Card"
import Grids from "@/components/TempDesignSystem/Grids" import Grids from "@/components/TempDesignSystem/Grids"
import LoyaltyCard from "@/components/TempDesignSystem/LoyaltyCard"
import { CardsGridProps } from "@/types/components/loyalty/blocks" import { CardsGridProps } from "@/types/components/loyalty/blocks"
import { LoyaltyCardsGridEnum } from "@/types/components/loyalty/enums"
export default function CardsGrid({ cards_grid }: CardsGridProps) { export default function CardsGrid({
cards_grid,
firstItem = false,
}: CardsGridProps) {
return ( return (
<SectionContainer> <SectionContainer>
<Header title={cards_grid.title} subtitle={cards_grid.preamble} /> <Header
title={cards_grid.title}
subtitle={cards_grid.preamble}
topTitle={firstItem}
/>
<Grids.Stackable> <Grids.Stackable>
{cards_grid.cards.map((card) => ( {cards_grid.cards.map((card) => {
<Card switch (card.__typename) {
theme={cards_grid.theme || "one"} case LoyaltyCardsGridEnum.LoyaltyCard:
key={card.system.uid} return (
scriptedTopTitle={card.scripted_top_title} <LoyaltyCard
heading={card.heading} key={card.system.uid}
bodyText={card.body_text} image={card.image}
secondaryButton={card.secondaryButton} heading={card.heading}
primaryButton={card.primaryButton} bodyText={card.body_text}
/> link={card.link}
))} />
)
case LoyaltyCardsGridEnum.Card: {
return (
<Card
theme={cards_grid.theme || "one"}
key={card.system.uid}
scriptedTopTitle={card.scripted_top_title}
heading={card.heading}
bodyText={card.body_text}
secondaryButton={card.secondaryButton}
primaryButton={card.primaryButton}
/>
)
}
}
})}
</Grids.Stackable> </Grids.Stackable>
</SectionContainer> </SectionContainer>
) )

View File

@@ -16,7 +16,7 @@ import {
TrueFriend, TrueFriend,
} from "@/components/Levels" } from "@/components/Levels"
import BiroScript from "@/components/TempDesignSystem/Text/BiroScript" import BiroScript from "@/components/TempDesignSystem/Text/BiroScript"
import Footnote from "@/components/TempDesignSystem/Text/Footnote" import Caption from "@/components/TempDesignSystem/Text/Caption"
import Title from "@/components/TempDesignSystem/Text/Title" import Title from "@/components/TempDesignSystem/Text/Title"
import levelsData from "./data" import levelsData from "./data"
@@ -97,7 +97,8 @@ function LevelCard({ formatMessage, lang, level }: LevelCardProps) {
</Title> </Title>
<div className={styles.textContainer}> <div className={styles.textContainer}>
{level.benefits.map((benefit) => ( {level.benefits.map((benefit) => (
<Footnote <Caption
className={styles.levelText}
key={benefit.title} key={benefit.title}
textAlign="center" textAlign="center"
color="textMediumContrast" color="textMediumContrast"
@@ -107,7 +108,7 @@ function LevelCard({ formatMessage, lang, level }: LevelCardProps) {
color="primaryLightOnSurfaceAccent" color="primaryLightOnSurfaceAccent"
/> />
{benefit.title} {benefit.title}
</Footnote> </Caption>
))} ))}
</div> </div>
</article> </article>

View File

@@ -20,9 +20,9 @@
display: grid; display: grid;
gap: var(--Spacing-x2); gap: var(--Spacing-x2);
min-height: 280px; min-height: 280px;
justify-content: center;
justify-items: center; justify-items: center;
padding: var(--Spacing-x5) var(--Spacing-x1); padding: var(--Spacing-x5) var(--Spacing-x1);
grid-template-rows: auto auto 1fr;
} }
.textContainer { .textContainer {
@@ -34,6 +34,10 @@
justify-content: center; justify-content: center;
} }
.levelText {
margin: 0;
}
.checkIcon { .checkIcon {
vertical-align: middle; vertical-align: middle;
} }

View File

@@ -43,6 +43,7 @@ export function Blocks({ blocks }: BlocksProps) {
<CardsGrid <CardsGrid
cards_grid={block.cards_grid} cards_grid={block.cards_grid}
key={`${block.cards_grid.title}-${idx}`} key={`${block.cards_grid.title}-${idx}`}
firstItem={firstItem}
/> />
) )
default: default:

View File

@@ -1,11 +1,15 @@
.aside { .aside {
align-content: flex-start; display: none;
display: grid;
gap: var(--Spacing-x4);
} }
@media screen and (max-width: 1366px) { .content {
.content { padding: var(--Spacing-x0) var(--Spacing-x2);
padding: var(--Spacing-x0) var(--Spacing-x2); }
@media screen and (min-width: 1366px) {
.aside {
align-content: flex-start;
display: grid;
gap: var(--Spacing-x4);
} }
} }

View File

@@ -0,0 +1,65 @@
import ArrowRight from "@/components/Icons/ArrowRight"
import Image from "@/components/Image"
import Link from "@/components/TempDesignSystem/Link"
import Body from "@/components/TempDesignSystem/Text/Body"
import Title from "@/components/TempDesignSystem/Text/Title"
import { loyaltyCardVariants } from "./variants"
import styles from "./loyaltyCard.module.css"
import type { LoyaltyCardProps } from "./loyaltyCard"
export default function LoyaltyCard({
link,
image,
heading,
bodyText,
theme = "white",
className,
}: LoyaltyCardProps) {
return (
<article
className={loyaltyCardVariants({
className,
theme,
})}
>
{image ? (
<section>
<Image
src={image.url}
width={180}
height={160}
className={styles.image}
alt={image.meta.alt || image.title}
/>
</section>
) : null}
<Title as="h5" level="h3" textAlign="center">
{heading}
</Title>
{bodyText ? (
<Body textAlign="center" color="red">
{bodyText}
</Body>
) : null}
<div className={styles.buttonContainer}>
{link ? (
<span className={styles.linkWrapper}>
<ArrowRight color="burgundy" className={styles.icon} />
<Link
className={styles.link}
color="burgundy"
href={link.href}
target={link.openInNewTab ? "_blank" : undefined}
variant="myPage"
>
{link.title}
</Link>
</span>
) : null}
</div>
</article>
)
}

View File

@@ -0,0 +1,43 @@
.container {
align-items: center;
display: grid;
border-radius: var(--Corner-radius-xLarge);
gap: var(--Spacing-x2);
height: 480px;
justify-content: space-between;
margin-right: var(--Spacing-x2);
padding: var(--Spacing-x4) var(--Spacing-x3);
text-align: center;
width: 100%;
}
.image {
object-fit: contain;
height: 160px;
width: auto;
}
.white {
background-color: var(--Main-Grey-White);
}
.buttonContainer {
display: flex;
gap: var(--Spacing-x1);
justify-content: center;
}
.linkWrapper {
display: flex;
align-items: baseline;
gap: var(--Spacing-x-half);
}
.link {
display: flex;
align-items: center;
}
.icon {
align-self: center;
}

View File

@@ -0,0 +1,20 @@
import { loyaltyCardVariants } from "./variants"
import type { VariantProps } from "class-variance-authority"
import { ImageVaultAsset } from "@/types/components/imageVaultImage"
export interface LoyaltyCardProps
extends React.HTMLAttributes<HTMLDivElement>,
VariantProps<typeof loyaltyCardVariants> {
link?: {
href: string
title: string
openInNewTab?: boolean
isExternal: boolean
}
image?: ImageVaultAsset
heading?: string | null
bodyText?: string | null
backgroundImage?: { url: string }
}

View File

@@ -0,0 +1,14 @@
import { cva } from "class-variance-authority"
import styles from "./loyaltyCard.module.css"
export const loyaltyCardVariants = cva(styles.container, {
variants: {
theme: {
white: styles.white,
},
},
defaultVariants: {
theme: "white",
},
})

View File

@@ -36,3 +36,15 @@
.pale { .pale {
color: var(--Scandic-Brand-Pale-Peach); color: var(--Scandic-Brand-Pale-Peach);
} }
.textMediumContrast {
color: var(--Base-Text-UI-Medium-contrast);
}
.center {
text-align: center;
}
.left {
text-align: left;
}

View File

@@ -9,19 +9,21 @@ export default function Caption({
className = "", className = "",
color, color,
fontOnly = false, fontOnly = false,
textAlign,
textTransform, textTransform,
...props ...props
}: CaptionProps) { }: CaptionProps) {
const Comp = asChild ? Slot : "p" const Comp = asChild ? Slot : "p"
const classNames = fontOnly const classNames = fontOnly
? fontOnlycaptionVariants({ ? fontOnlycaptionVariants({
className, className,
textTransform, textTransform,
}) })
: captionVariants({ : captionVariants({
className, className,
color, color,
textTransform, textTransform,
}) textAlign,
})
return <Comp className={classNames} {...props} /> return <Comp className={classNames} {...props} />
} }

View File

@@ -8,11 +8,16 @@ const config = {
black: styles.black, black: styles.black,
burgundy: styles.burgundy, burgundy: styles.burgundy,
pale: styles.pale, pale: styles.pale,
textMediumContrast: styles.textMediumContrast,
}, },
textTransform: { textTransform: {
bold: styles.bold, bold: styles.bold,
regular: styles.regular, regular: styles.regular,
}, },
textAlign: {
center: styles.center,
left: styles.left,
},
}, },
defaultVariants: { defaultVariants: {
color: "black", color: "black",

View File

@@ -0,0 +1,28 @@
fragment LoyaltyCardBlock on LoyaltyCard {
heading
body_text
image
title
link {
cta_text
open_in_new_tab
external_link {
title
href
}
linkConnection {
edges {
node {
__typename
...LoyaltyPageLink
...ContentPageLink
...AccountPageLink
}
}
}
}
system {
locale
uid
}
}

View File

@@ -1,4 +1,5 @@
fragment CardBlockRef on Card { fragment CardBlockRef on Card {
__typename
secondary_button { secondary_button {
linkConnection { linkConnection {
edges { edges {

View File

@@ -0,0 +1,18 @@
fragment LoyaltyCardBlockRef on LoyaltyCard {
__typename
link {
linkConnection {
edges {
node {
__typename
...LoyaltyPageRef
...ContentPageRef
...AccountPageRef
}
}
}
}
system {
...System
}
}

View File

@@ -1,6 +1,10 @@
#import "../Fragments/Image.graphql" #import "../Fragments/Image.graphql"
#import "../Fragments/Blocks/Card.graphql" #import "../Fragments/Blocks/Card.graphql"
#import "../Fragments/Blocks/LoyaltyCard.graphql"
#import "../Fragments/Blocks/Refs/Card.graphql" #import "../Fragments/Blocks/Refs/Card.graphql"
#import "../Fragments/Blocks/Refs/LoyaltyCard.graphql"
#import "../Fragments/LoyaltyPage/Breadcrumbs.graphql" #import "../Fragments/LoyaltyPage/Breadcrumbs.graphql"
#import "../Fragments/PageLink/AccountPageLink.graphql" #import "../Fragments/PageLink/AccountPageLink.graphql"
#import "../Fragments/PageLink/ContentPageLink.graphql" #import "../Fragments/PageLink/ContentPageLink.graphql"
@@ -83,7 +87,9 @@ query GetLoyaltyPage($locale: String!, $uid: String!) {
cardConnection(limit: 10) { cardConnection(limit: 10) {
edges { edges {
node { node {
__typename
...CardBlock ...CardBlock
...LoyaltyCardBlock
} }
} }
} }
@@ -104,6 +110,7 @@ query GetLoyaltyPage($locale: String!, $uid: String!) {
contact { contact {
display_text display_text
contact_field contact_field
footnote
} }
} }
} }
@@ -206,6 +213,7 @@ query GetLoyaltyPageRefs($locale: String!, $uid: String!) {
edges { edges {
node { node {
...CardBlockRef ...CardBlockRef
...LoyaltyCardBlockRef
} }
} }
} }

View File

@@ -59,6 +59,7 @@ export type ContactConfig = ContactConfigData["all_contact_config"]["items"][0]
export type ContactFields = { export type ContactFields = {
display_text: string | null display_text: string | null
contact_field: string contact_field: string
footnote: string | null
} }
export const validateHeaderConfigSchema = z.object({ export const validateHeaderConfigSchema = z.object({

View File

@@ -2,9 +2,11 @@ import { z } from "zod"
import { Lang } from "@/constants/languages" import { Lang } from "@/constants/languages"
import { ImageVaultAsset } from "@/types/components/imageVaultImage"
import { import {
JoinLoyaltyContactTypenameEnum, JoinLoyaltyContactTypenameEnum,
LoyaltyBlocksTypenameEnum, LoyaltyBlocksTypenameEnum,
LoyaltyCardsGridEnum,
LoyaltyComponentEnum, LoyaltyComponentEnum,
SidebarTypenameEnum, SidebarTypenameEnum,
} from "@/types/components/loyalty/enums" } from "@/types/components/loyalty/enums"
@@ -47,6 +49,7 @@ const loyaltyPageShortcuts = z.object({
}) })
const cardBlock = z.object({ const cardBlock = z.object({
__typename: z.literal(LoyaltyCardsGridEnum.Card),
heading: z.string().nullable(), heading: z.string().nullable(),
body_text: z.string().nullable(), body_text: z.string().nullable(),
background_image: z.any(), background_image: z.any(),
@@ -73,6 +76,30 @@ const cardBlock = z.object({
}), }),
}) })
const loyaltyCardBlock = z.object({
__typename: z.literal(LoyaltyCardsGridEnum.LoyaltyCard),
heading: z.string().nullable(),
body_text: z.string().nullable(),
image: z.any(),
link: z
.object({
openInNewTab: z.boolean(),
title: z.string(),
href: z.string(),
isExternal: z.boolean(),
})
.optional(),
system: z.object({
locale: z.nativeEnum(Lang),
uid: z.string(),
}),
})
const loyaltyPageCardsItems = z.discriminatedUnion("__typename", [
loyaltyCardBlock,
cardBlock,
])
const loyaltyPageCards = z.object({ const loyaltyPageCards = z.object({
__typename: z.literal(LoyaltyBlocksTypenameEnum.LoyaltyPageBlocksCardsGrid), __typename: z.literal(LoyaltyBlocksTypenameEnum.LoyaltyPageBlocksCardsGrid),
cards_grid: z.object({ cards_grid: z.object({
@@ -80,7 +107,7 @@ const loyaltyPageCards = z.object({
preamble: z.string().nullable(), preamble: z.string().nullable(),
layout: z.enum(["twoColumnGrid", "threeColumnGrid", "twoPlusOne"]), layout: z.enum(["twoColumnGrid", "threeColumnGrid", "twoPlusOne"]),
theme: z.enum(["one", "two", "three"]).nullable(), theme: z.enum(["one", "two", "three"]).nullable(),
cards: z.array(cardBlock), cards: z.array(loyaltyPageCardsItems),
}), }),
}) })
@@ -132,6 +159,7 @@ const loyaltyPageJoinLoyaltyContact = z.object({
contact: z.object({ contact: z.object({
display_text: z.string().nullable(), display_text: z.string().nullable(),
contact_field: z.string(), contact_field: z.string(),
footnote: z.string().nullable(),
}), }),
}) })
), ),
@@ -151,7 +179,6 @@ export const validateLoyaltyPageSchema = z.object({
}) })
// Block types // Block types
export type DynamicContent = z.infer<typeof loyaltyPageDynamicContent> export type DynamicContent = z.infer<typeof loyaltyPageDynamicContent>
type BlockContentRaw = z.infer<typeof loyaltyPageBlockTextContent> type BlockContentRaw = z.infer<typeof loyaltyPageBlockTextContent>
@@ -164,11 +191,25 @@ export interface RteBlockContent extends BlockContentRaw {
} }
} }
type LoyaltyCardRaw = z.infer<typeof loyaltyCardBlock>
type LoyaltyCard = Omit<LoyaltyCardRaw, "image"> & {
image?: ImageVaultAsset
}
type CardRaw = z.infer<typeof cardBlock>
type Card = Omit<CardRaw, "background_image"> & {
backgroundImage?: ImageVaultAsset
}
type CardsGridRaw = z.infer<typeof loyaltyPageCards> type CardsGridRaw = z.infer<typeof loyaltyPageCards>
export type CardsRaw = CardsGridRaw["cards_grid"]["cards"][number] export type CardsGrid = Omit<CardsGridRaw, "cards"> & {
cards: (LoyaltyCard | Card)[]
}
export type CardsGrid = z.infer<typeof loyaltyPageCards> export type CardsRaw = CardsGrid["cards_grid"]["cards"][number]
export type Shortcuts = z.infer<typeof loyaltyPageShortcuts> export type Shortcuts = z.infer<typeof loyaltyPageShortcuts>
@@ -210,6 +251,7 @@ const pageConnectionRefs = z.object({
}) })
const cardBlockRefs = z.object({ const cardBlockRefs = z.object({
__typename: z.literal(LoyaltyCardsGridEnum.Card),
primary_button: z primary_button: z
.object({ .object({
linkConnection: pageConnectionRefs, linkConnection: pageConnectionRefs,
@@ -227,13 +269,32 @@ const cardBlockRefs = z.object({
}), }),
}) })
const loyaltyCardBlockRefs = z.object({
__typename: z.literal(LoyaltyCardsGridEnum.LoyaltyCard),
link: z
.object({
linkConnection: pageConnectionRefs,
})
.nullable(),
system: z.object({
content_type_uid: z.string(),
uid: z.string(),
}),
})
const cardGridCardsRef = z.discriminatedUnion("__typename", [
loyaltyCardBlockRefs,
cardBlockRefs,
])
const loyaltyPageCardsRefs = z.object({ const loyaltyPageCardsRefs = z.object({
__typename: z.literal(LoyaltyBlocksTypenameEnum.LoyaltyPageBlocksCardsGrid), __typename: z.literal(LoyaltyBlocksTypenameEnum.LoyaltyPageBlocksCardsGrid),
cards_grid: z.object({ cards_grid: z.object({
cardConnection: z.object({ cardConnection: z.object({
edges: z.array( edges: z.array(
z.object({ z.object({
node: cardBlockRefs, node: cardGridCardsRef,
}) })
), ),
}), }),

View File

@@ -11,6 +11,7 @@ import {
generateTag, generateTag,
generateTags, generateTags,
} from "@/utils/generateTag" } from "@/utils/generateTag"
import { insertResponseToImageVaultAsset } from "@/utils/imageVault"
import { removeMultipleSlashes } from "@/utils/url" import { removeMultipleSlashes } from "@/utils/url"
import { removeEmptyObjects } from "../../utils" import { removeEmptyObjects } from "../../utils"
@@ -22,7 +23,17 @@ import {
} from "./output" } from "./output"
import { getConnections } from "./utils" import { getConnections } from "./utils"
import { LoyaltyBlocksTypenameEnum } from "@/types/components/loyalty/enums" import { InsertResponse } from "@/types/components/imageVaultImage"
import {
LoyaltyBlocksTypenameEnum,
LoyaltyCardsGridEnum,
} from "@/types/components/loyalty/enums"
function makeImageVaultImage(image: any) {
return image && !!Object.keys(image).length
? insertResponseToImageVaultAsset(image as InsertResponse)
: undefined
}
function makeButtonObject(button: any) { function makeButtonObject(button: any) {
return { return {
@@ -35,9 +46,9 @@ function makeButtonObject(button: any) {
href: href:
button.is_contentstack_link && button.linkConnection.edges.length button.is_contentstack_link && button.linkConnection.edges.length
? button.linkConnection.edges[0].node.web?.original_url || ? button.linkConnection.edges[0].node.web?.original_url ||
removeMultipleSlashes( removeMultipleSlashes(
`/${button.linkConnection.edges[0].node.system.locale}/${button.linkConnection.edges[0].node.url}` `/${button.linkConnection.edges[0].node.system.locale}/${button.linkConnection.edges[0].node.url}`
) )
: button.external_link.href, : button.external_link.href,
isExternal: !button.is_contentstack_link, isExternal: !button.is_contentstack_link,
} }
@@ -96,66 +107,82 @@ export const loyaltyPageQueryRouter = router({
const blocks = response.data.loyalty_page.blocks const blocks = response.data.loyalty_page.blocks
? response.data.loyalty_page.blocks.map((block: any) => { ? response.data.loyalty_page.blocks.map((block: any) => {
switch (block.__typename) { switch (block.__typename) {
case LoyaltyBlocksTypenameEnum.LoyaltyPageBlocksDynamicContent: case LoyaltyBlocksTypenameEnum.LoyaltyPageBlocksDynamicContent:
return { return {
...block, ...block,
dynamic_content: { dynamic_content: {
...block.dynamic_content, ...block.dynamic_content,
link: block.dynamic_content.link.pageConnection.edges.length link: block.dynamic_content.link.pageConnection.edges.length
? { ? {
text: block.dynamic_content.link.text, text: block.dynamic_content.link.text,
href: removeMultipleSlashes( href: removeMultipleSlashes(
`/${block.dynamic_content.link.pageConnection.edges[0].node.system.locale}/${block.dynamic_content.link.pageConnection.edges[0].node.url}` `/${block.dynamic_content.link.pageConnection.edges[0].node.system.locale}/${block.dynamic_content.link.pageConnection.edges[0].node.url}`
), ),
title: title:
block.dynamic_content.link.pageConnection.edges[0] block.dynamic_content.link.pageConnection.edges[0]
.node.title, .node.title,
} }
: undefined, : undefined,
}, },
} }
case LoyaltyBlocksTypenameEnum.LoyaltyPageBlocksShortcuts: case LoyaltyBlocksTypenameEnum.LoyaltyPageBlocksShortcuts:
return { return {
...block, ...block,
shortcuts: { shortcuts: {
...block.shortcuts, ...block.shortcuts,
shortcuts: block.shortcuts.shortcuts.map((shortcut: any) => ({ shortcuts: block.shortcuts.shortcuts.map((shortcut: any) => ({
text: shortcut.text, text: shortcut.text,
openInNewTab: shortcut.open_in_new_tab, openInNewTab: shortcut.open_in_new_tab,
...shortcut.linkConnection.edges[0].node, ...shortcut.linkConnection.edges[0].node,
url: url:
shortcut.linkConnection.edges[0].node.web?.original_url || shortcut.linkConnection.edges[0].node.web?.original_url ||
removeMultipleSlashes( removeMultipleSlashes(
`/${shortcut.linkConnection.edges[0].node.system.locale}/${shortcut.linkConnection.edges[0].node.url}` `/${shortcut.linkConnection.edges[0].node.system.locale}/${shortcut.linkConnection.edges[0].node.url}`
), ),
})), })),
}, },
} }
case LoyaltyBlocksTypenameEnum.LoyaltyPageBlocksCardsGrid: case LoyaltyBlocksTypenameEnum.LoyaltyPageBlocksCardsGrid:
return { return {
...block, ...block,
cards_grid: { cards_grid: {
...block.cards_grid, ...block.cards_grid,
cards: block.cards_grid.cardConnection.edges.map( cards: block.cards_grid.cardConnection.edges.map(
({ node: card }: { node: any }) => { ({ node: card }: { node: any }) => {
return { switch (card.__typename) {
...card, case LoyaltyCardsGridEnum.LoyaltyCard:
primaryButton: card.has_primary_button return {
? makeButtonObject(card.primary_button) ...card,
: undefined, image: makeImageVaultImage(card.image),
secondaryButton: card.has_secondary_button link: makeButtonObject({
? makeButtonObject(card.secondary_button) ...card.link,
: undefined, is_contentstack_link:
!!card.link.linkConnection.edges.length,
}),
}
case LoyaltyCardsGridEnum.Card:
return {
...card,
backgroundImage: makeImageVaultImage(
card.background_image
),
primaryButton: card.has_primary_button
? makeButtonObject(card.primary_button)
: undefined,
secondaryButton: card.has_secondary_button
? makeButtonObject(card.secondary_button)
: undefined,
}
}
} }
} ),
), },
}, }
} default:
default: return block
return block }
} })
})
: null : null
const loyaltyPage = { const loyaltyPage = {

View File

@@ -1,6 +1,9 @@
import { LoyaltyPageRefsDataRaw } from "./output" import { LoyaltyPageRefsDataRaw } from "./output"
import { LoyaltyBlocksTypenameEnum } from "@/types/components/loyalty/enums" import {
LoyaltyBlocksTypenameEnum,
LoyaltyCardsGridEnum,
} from "@/types/components/loyalty/enums"
import type { Edges } from "@/types/requests/utils/edges" import type { Edges } from "@/types/requests/utils/edges"
import type { NodeRefs } from "@/types/requests/utils/refs" import type { NodeRefs } from "@/types/requests/utils/refs"
@@ -18,13 +21,23 @@ export function getConnections(refs: LoyaltyPageRefsDataRaw) {
case LoyaltyBlocksTypenameEnum.LoyaltyPageBlocksCardsGrid: { case LoyaltyBlocksTypenameEnum.LoyaltyPageBlocksCardsGrid: {
connections.push(item.cards_grid.cardConnection) connections.push(item.cards_grid.cardConnection)
item.cards_grid.cardConnection.edges.forEach((card) => { item.cards_grid.cardConnection.edges.forEach((card) => {
if (card.node.primary_button) { switch (card.node.__typename) {
connections.push(card.node.primary_button?.linkConnection) case LoyaltyCardsGridEnum.LoyaltyCard: {
} else if (card.node.secondary_button) { if (card.node.link) {
connections.push(card.node.secondary_button?.linkConnection) connections.push(card.node.link?.linkConnection)
}
break
}
case LoyaltyCardsGridEnum.Card: {
if (card.node.primary_button) {
connections.push(card.node.primary_button?.linkConnection)
} else if (card.node.secondary_button) {
connections.push(card.node.secondary_button?.linkConnection)
}
break
}
} }
}) })
break break
} }
case LoyaltyBlocksTypenameEnum.LoyaltyPageBlocksShortcuts: { case LoyaltyBlocksTypenameEnum.LoyaltyPageBlocksShortcuts: {

View File

@@ -24,7 +24,9 @@ export type DynamicComponentProps = {
component: DynamicContent["dynamic_content"]["component"] component: DynamicContent["dynamic_content"]["component"]
} }
export type CardsGridProps = Pick<CardsGrid, "cards_grid"> export type CardsGridProps = Pick<CardsGrid, "cards_grid"> & {
firstItem?: boolean
}
export type Content = { content: RteBlockContent["content"]["content"] } export type Content = { content: RteBlockContent["content"]["content"] }

View File

@@ -31,3 +31,8 @@ export enum LoyaltyBlocksTypenameEnum {
LoyaltyPageBlocksShortcuts = "LoyaltyPageBlocksShortcuts", LoyaltyPageBlocksShortcuts = "LoyaltyPageBlocksShortcuts",
LoyaltyPageBlocksCardsGrid = "LoyaltyPageBlocksCardsGrid", LoyaltyPageBlocksCardsGrid = "LoyaltyPageBlocksCardsGrid",
} }
export enum LoyaltyCardsGridEnum {
LoyaltyCard = "LoyaltyCard",
Card = "Card",
}