feat: add new cards grid block
This commit is contained in:
@@ -17,7 +17,8 @@ import type {
|
|||||||
import { RTEMarkType } from "@/types/rte/node"
|
import { RTEMarkType } from "@/types/rte/node"
|
||||||
import type { RenderOptions } from "@/types/rte/option"
|
import type { RenderOptions } from "@/types/rte/option"
|
||||||
|
|
||||||
function extractPossibleAttributes(attrs: Attributes) {
|
function extractPossibleAttributes(attrs: Attributes | undefined) {
|
||||||
|
if (!attrs) return {}
|
||||||
const props: Record<string, any> = {}
|
const props: Record<string, any> = {}
|
||||||
if (attrs.id) {
|
if (attrs.id) {
|
||||||
props.id = attrs.id
|
props.id = attrs.id
|
||||||
|
|||||||
@@ -1,28 +0,0 @@
|
|||||||
.container {
|
|
||||||
display: grid;
|
|
||||||
gap: 2.4rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.subtitle {
|
|
||||||
margin: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.titleContainer {
|
|
||||||
display: grid;
|
|
||||||
gap: 0.8rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.cardContainer {
|
|
||||||
display: grid;
|
|
||||||
gap: 1.6rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
@media screen and (min-width: 950px) {
|
|
||||||
.cardContainer {
|
|
||||||
grid-template-columns: 1fr 1fr;
|
|
||||||
}
|
|
||||||
|
|
||||||
.cardWrapper:last-child {
|
|
||||||
grid-column: span 2;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,41 +0,0 @@
|
|||||||
import { _ } from "@/lib/translation"
|
|
||||||
|
|
||||||
import Card from "@/components/TempDesignSystem/Card"
|
|
||||||
import Title from "@/components/Title"
|
|
||||||
|
|
||||||
import styles from "./cardGrid.module.css"
|
|
||||||
|
|
||||||
import { CardGridProps } from "@/types/components/loyalty/blocks"
|
|
||||||
|
|
||||||
export default function CardGrid({ card_grid }: CardGridProps) {
|
|
||||||
return (
|
|
||||||
<section className={styles.container}>
|
|
||||||
<header className={styles.titleContainer}>
|
|
||||||
<Title as="h3" level="h2" weight="semiBold" uppercase>
|
|
||||||
{card_grid.title}
|
|
||||||
</Title>
|
|
||||||
{card_grid.subtitle ? (
|
|
||||||
<Title
|
|
||||||
as="h5"
|
|
||||||
level="h3"
|
|
||||||
weight="regular"
|
|
||||||
className={styles.subtitle}
|
|
||||||
>
|
|
||||||
{card_grid.subtitle}
|
|
||||||
</Title>
|
|
||||||
) : null}
|
|
||||||
</header>
|
|
||||||
<div className={styles.cardContainer}>
|
|
||||||
{card_grid.cards.map((card, i) => (
|
|
||||||
<div className={styles.cardWrapper} key={`${card.title}+${i}`}>
|
|
||||||
<Card
|
|
||||||
subtitle={card.subtitle}
|
|
||||||
title={card.title}
|
|
||||||
link={card.link}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
))}
|
|
||||||
</div>
|
|
||||||
</section>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
4
components/Loyalty/Blocks/CardsGrid/cardsGrid.module.css
Normal file
4
components/Loyalty/Blocks/CardsGrid/cardsGrid.module.css
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
.section {
|
||||||
|
display: grid;
|
||||||
|
gap: 2.4rem;
|
||||||
|
}
|
||||||
44
components/Loyalty/Blocks/CardsGrid/index.tsx
Normal file
44
components/Loyalty/Blocks/CardsGrid/index.tsx
Normal file
@@ -0,0 +1,44 @@
|
|||||||
|
import { _ } from "@/lib/translation"
|
||||||
|
|
||||||
|
import Header from "@/components/MyPages/Blocks/Header"
|
||||||
|
import Card from "@/components/TempDesignSystem/Card"
|
||||||
|
import CardGrid from "@/components/TempDesignSystem/CardGrid"
|
||||||
|
|
||||||
|
import styles from "./cardsGrid.module.css"
|
||||||
|
|
||||||
|
import { CardsGridProps } from "@/types/components/loyalty/blocks"
|
||||||
|
|
||||||
|
export default function CardsGrid({ cards_grid }: CardsGridProps) {
|
||||||
|
return (
|
||||||
|
<section className={styles.section}>
|
||||||
|
<Header title={cards_grid.title} subtitle={cards_grid.preamble} />
|
||||||
|
<CardGrid variant={cards_grid.layout}>
|
||||||
|
{cards_grid.cards.map((card) => (
|
||||||
|
<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 && {
|
||||||
|
href: card.secondaryButton.link.href,
|
||||||
|
title: card.secondaryButton.link.title,
|
||||||
|
openInNewTab: card.secondaryButton.open_in_new_tab,
|
||||||
|
isExternal: card.secondaryButton.isExternal,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
primaryButton={
|
||||||
|
card.primaryButton && {
|
||||||
|
href: card.primaryButton.link.href,
|
||||||
|
title: card.primaryButton.link.title,
|
||||||
|
openInNewTab: card.primaryButton.open_in_new_tab,
|
||||||
|
isExternal: card.primaryButton.isExternal,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
))}
|
||||||
|
</CardGrid>
|
||||||
|
</section>
|
||||||
|
)
|
||||||
|
}
|
||||||
@@ -2,7 +2,7 @@ import JsonToHtml from "@/components/JsonToHtml"
|
|||||||
import DynamicContentBlock from "@/components/Loyalty/Blocks/DynamicContent"
|
import DynamicContentBlock from "@/components/Loyalty/Blocks/DynamicContent"
|
||||||
import Shortcuts from "@/components/MyPages/Blocks/Shortcuts"
|
import Shortcuts from "@/components/MyPages/Blocks/Shortcuts"
|
||||||
|
|
||||||
import CardGrid from "./CardGrid"
|
import CardsGrid from "./CardsGrid"
|
||||||
|
|
||||||
import type { BlocksProps } from "@/types/components/loyalty/blocks"
|
import type { BlocksProps } from "@/types/components/loyalty/blocks"
|
||||||
import { LoyaltyBlocksTypenameEnum } from "@/types/components/loyalty/enums"
|
import { LoyaltyBlocksTypenameEnum } from "@/types/components/loyalty/enums"
|
||||||
@@ -10,8 +10,6 @@ import { LoyaltyBlocksTypenameEnum } from "@/types/components/loyalty/enums"
|
|||||||
export function Blocks({ blocks }: BlocksProps) {
|
export function Blocks({ blocks }: BlocksProps) {
|
||||||
return blocks.map((block) => {
|
return blocks.map((block) => {
|
||||||
switch (block.__typename) {
|
switch (block.__typename) {
|
||||||
case LoyaltyBlocksTypenameEnum.LoyaltyPageBlocksCardGrid:
|
|
||||||
return <CardGrid card_grid={block.card_grid} />
|
|
||||||
case LoyaltyBlocksTypenameEnum.LoyaltyPageBlocksContent:
|
case LoyaltyBlocksTypenameEnum.LoyaltyPageBlocksContent:
|
||||||
return (
|
return (
|
||||||
<section>
|
<section>
|
||||||
@@ -31,6 +29,8 @@ export function Blocks({ blocks }: BlocksProps) {
|
|||||||
subtitle={block.shortcuts.preamble}
|
subtitle={block.shortcuts.preamble}
|
||||||
/>
|
/>
|
||||||
)
|
)
|
||||||
|
case LoyaltyBlocksTypenameEnum.LoyaltyPageBlocksCardsGrid:
|
||||||
|
return <CardsGrid cards_grid={block.cards_grid} />
|
||||||
default:
|
default:
|
||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
|
|||||||
16
components/TempDesignSystem/Card/variants.ts
Normal file
16
components/TempDesignSystem/Card/variants.ts
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
import { cva } from "class-variance-authority"
|
||||||
|
|
||||||
|
import styles from "./card.module.css"
|
||||||
|
|
||||||
|
export const cardVariants = cva(styles.container, {
|
||||||
|
variants: {
|
||||||
|
theme: {
|
||||||
|
one: styles.themeOne,
|
||||||
|
two: styles.themeTwo,
|
||||||
|
three: styles.themeThree,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
defaultVariants: {
|
||||||
|
theme: "one",
|
||||||
|
},
|
||||||
|
})
|
||||||
@@ -37,14 +37,19 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
@media screen and (min-width: 950px) {
|
@media screen and (min-width: 950px) {
|
||||||
.twoColumnGrid {
|
.twoColumnGrid,
|
||||||
|
.twoPlusOne {
|
||||||
grid-template-columns: repeat(2, 1fr);
|
grid-template-columns: repeat(2, 1fr);
|
||||||
}
|
}
|
||||||
|
|
||||||
.treeColumnGrid {
|
.threeColumnGrid {
|
||||||
grid-template-columns: repeat(3, 1fr);
|
grid-template-columns: repeat(3, 1fr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.twoPlusOne > *:last-child {
|
||||||
|
grid-column: span 2;
|
||||||
|
}
|
||||||
|
|
||||||
.carousel {
|
.carousel {
|
||||||
grid-auto-flow: unset;
|
grid-auto-flow: unset;
|
||||||
margin: 0;
|
margin: 0;
|
||||||
|
|||||||
49
lib/graphql/Fragments/Blocks/Card.graphql
Normal file
49
lib/graphql/Fragments/Blocks/Card.graphql
Normal file
@@ -0,0 +1,49 @@
|
|||||||
|
fragment CardBlock on Card {
|
||||||
|
heading
|
||||||
|
body_text
|
||||||
|
background_image
|
||||||
|
scripted_top_title
|
||||||
|
title
|
||||||
|
secondary_button {
|
||||||
|
is_contentstack_link
|
||||||
|
cta_text
|
||||||
|
open_in_new_tab
|
||||||
|
external_link {
|
||||||
|
title
|
||||||
|
href
|
||||||
|
}
|
||||||
|
linkConnection {
|
||||||
|
edges {
|
||||||
|
node {
|
||||||
|
__typename
|
||||||
|
...LoyaltyPageLink
|
||||||
|
...ContentPageLink
|
||||||
|
...AccountPageLink
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
primary_button {
|
||||||
|
is_contentstack_link
|
||||||
|
cta_text
|
||||||
|
open_in_new_tab
|
||||||
|
external_link {
|
||||||
|
title
|
||||||
|
href
|
||||||
|
}
|
||||||
|
linkConnection {
|
||||||
|
edges {
|
||||||
|
node {
|
||||||
|
__typename
|
||||||
|
...LoyaltyPageLink
|
||||||
|
...ContentPageLink
|
||||||
|
...AccountPageLink
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
system {
|
||||||
|
locale
|
||||||
|
uid
|
||||||
|
}
|
||||||
|
}
|
||||||
29
lib/graphql/Fragments/Blocks/Refs/Card.graphql
Normal file
29
lib/graphql/Fragments/Blocks/Refs/Card.graphql
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
fragment CardBlockRef on Card {
|
||||||
|
secondary_button {
|
||||||
|
linkConnection {
|
||||||
|
edges {
|
||||||
|
node {
|
||||||
|
__typename
|
||||||
|
...LoyaltyPageRef
|
||||||
|
...ContentPageRef
|
||||||
|
...AccountPageRef
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
primary_button {
|
||||||
|
linkConnection {
|
||||||
|
edges {
|
||||||
|
node {
|
||||||
|
__typename
|
||||||
|
...LoyaltyPageRef
|
||||||
|
...ContentPageRef
|
||||||
|
...AccountPageRef
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
system {
|
||||||
|
...System
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,4 +1,6 @@
|
|||||||
#import "../Fragments/Image.graphql"
|
#import "../Fragments/Image.graphql"
|
||||||
|
#import "../Fragments/Blocks/Card.graphql"
|
||||||
|
#import "../Fragments/Blocks/Refs/Card.graphql"
|
||||||
#import "../Fragments/PageLink/AccountPageLink.graphql"
|
#import "../Fragments/PageLink/AccountPageLink.graphql"
|
||||||
#import "../Fragments/PageLink/ContentPageLink.graphql"
|
#import "../Fragments/PageLink/ContentPageLink.graphql"
|
||||||
#import "../Fragments/PageLink/LoyaltyPageLink.graphql"
|
#import "../Fragments/PageLink/LoyaltyPageLink.graphql"
|
||||||
@@ -11,8 +13,8 @@
|
|||||||
query GetLoyaltyPage($locale: String!, $uid: String!) {
|
query GetLoyaltyPage($locale: String!, $uid: String!) {
|
||||||
loyalty_page(uid: $uid, locale: $locale) {
|
loyalty_page(uid: $uid, locale: $locale) {
|
||||||
blocks {
|
blocks {
|
||||||
__typename
|
|
||||||
... on LoyaltyPageBlocksShortcuts {
|
... on LoyaltyPageBlocksShortcuts {
|
||||||
|
__typename
|
||||||
shortcuts {
|
shortcuts {
|
||||||
title
|
title
|
||||||
preamble
|
preamble
|
||||||
@@ -22,10 +24,9 @@ query GetLoyaltyPage($locale: String!, $uid: String!) {
|
|||||||
linkConnection {
|
linkConnection {
|
||||||
edges {
|
edges {
|
||||||
node {
|
node {
|
||||||
__typename
|
|
||||||
...AccountPageLink
|
|
||||||
...LoyaltyPageLink
|
...LoyaltyPageLink
|
||||||
...ContentPageLink
|
...ContentPageLink
|
||||||
|
...AccountPageLink
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
totalCount
|
totalCount
|
||||||
@@ -34,6 +35,7 @@ query GetLoyaltyPage($locale: String!, $uid: String!) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
... on LoyaltyPageBlocksDynamicContent {
|
... on LoyaltyPageBlocksDynamicContent {
|
||||||
|
__typename
|
||||||
dynamic_content {
|
dynamic_content {
|
||||||
title
|
title
|
||||||
subtitle
|
subtitle
|
||||||
@@ -52,30 +54,8 @@ query GetLoyaltyPage($locale: String!, $uid: String!) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
... on LoyaltyPageBlocksCardGrid {
|
|
||||||
card_grid {
|
|
||||||
title
|
|
||||||
subtitle
|
|
||||||
cards {
|
|
||||||
referenceConnection {
|
|
||||||
edges {
|
|
||||||
node {
|
|
||||||
__typename
|
|
||||||
...LoyaltyPageLink
|
|
||||||
...ContentPageLink
|
|
||||||
...AccountPageLink
|
|
||||||
}
|
|
||||||
}
|
|
||||||
totalCount
|
|
||||||
}
|
|
||||||
title
|
|
||||||
subtitle
|
|
||||||
open_in_new_tab
|
|
||||||
cta_text
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
... on LoyaltyPageBlocksContent {
|
... on LoyaltyPageBlocksContent {
|
||||||
|
__typename
|
||||||
content {
|
content {
|
||||||
content {
|
content {
|
||||||
json
|
json
|
||||||
@@ -83,7 +63,6 @@ query GetLoyaltyPage($locale: String!, $uid: String!) {
|
|||||||
edges {
|
edges {
|
||||||
node {
|
node {
|
||||||
__typename
|
__typename
|
||||||
...Image
|
|
||||||
...LoyaltyPageLink
|
...LoyaltyPageLink
|
||||||
...ContentPageLink
|
...ContentPageLink
|
||||||
}
|
}
|
||||||
@@ -93,6 +72,22 @@ query GetLoyaltyPage($locale: String!, $uid: String!) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
... on LoyaltyPageBlocksCardsGrid {
|
||||||
|
__typename
|
||||||
|
cards_grid {
|
||||||
|
title
|
||||||
|
preamble
|
||||||
|
layout
|
||||||
|
theme
|
||||||
|
cardConnection(limit: 10) {
|
||||||
|
edges {
|
||||||
|
node {
|
||||||
|
...CardBlock
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
title
|
title
|
||||||
heading
|
heading
|
||||||
@@ -185,23 +180,6 @@ query GetLoyaltyPageRefs($locale: String!, $uid: String!) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
... on LoyaltyPageBlocksCardGrid {
|
|
||||||
__typename
|
|
||||||
card_grid {
|
|
||||||
cards {
|
|
||||||
referenceConnection {
|
|
||||||
edges {
|
|
||||||
node {
|
|
||||||
__typename
|
|
||||||
...AccountPageRef
|
|
||||||
...ContentPageRef
|
|
||||||
...LoyaltyPageRef
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
... on LoyaltyPageBlocksContent {
|
... on LoyaltyPageBlocksContent {
|
||||||
__typename
|
__typename
|
||||||
content {
|
content {
|
||||||
@@ -228,6 +206,18 @@ query GetLoyaltyPageRefs($locale: String!, $uid: String!) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
... on LoyaltyPageBlocksCardsGrid {
|
||||||
|
__typename
|
||||||
|
cards_grid {
|
||||||
|
cardConnection(limit: 10) {
|
||||||
|
edges {
|
||||||
|
node {
|
||||||
|
...CardBlockRef
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
sidebar {
|
sidebar {
|
||||||
... on LoyaltyPageSidebarContent {
|
... on LoyaltyPageSidebarContent {
|
||||||
|
|||||||
@@ -13,37 +13,22 @@ import { PageLinkEnum } from "@/types/requests/pageLinks"
|
|||||||
import { EdgesWithTotalCount } from "@/types/requests/utils/edges"
|
import { EdgesWithTotalCount } from "@/types/requests/utils/edges"
|
||||||
import { RTEDocument } from "@/types/rte/node"
|
import { RTEDocument } from "@/types/rte/node"
|
||||||
|
|
||||||
const loyaltyPageBlockCardGrid = z.object({
|
const pageLink = z.object({
|
||||||
__typename: z.literal(LoyaltyBlocksTypenameEnum.LoyaltyPageBlocksCardGrid),
|
edges: z.array(
|
||||||
card_grid: z.object({
|
z.object({
|
||||||
title: z.string().nullable(),
|
node: z.object({
|
||||||
subtitle: z.string().nullable(),
|
system: z.object({
|
||||||
cards: z.array(
|
uid: z.string(),
|
||||||
z.object({
|
locale: z.nativeEnum(Lang),
|
||||||
title: z.string().nullable(),
|
|
||||||
subtitle: z.string().nullable(),
|
|
||||||
referenceConnection: z.object({
|
|
||||||
edges: z.array(
|
|
||||||
z.object({
|
|
||||||
node: z.object({
|
|
||||||
system: z.object({
|
|
||||||
uid: z.string(),
|
|
||||||
locale: z.nativeEnum(Lang),
|
|
||||||
}),
|
|
||||||
url: z.string(),
|
|
||||||
title: z.string(),
|
|
||||||
__typename: z.string(),
|
|
||||||
}),
|
|
||||||
})
|
|
||||||
),
|
|
||||||
totalCount: z.number(),
|
|
||||||
}),
|
}),
|
||||||
open_in_new_tab: z.boolean(),
|
url: z.string(),
|
||||||
cta_text: z.string().nullable(),
|
title: z.string(),
|
||||||
})
|
__typename: z.string(),
|
||||||
),
|
}),
|
||||||
}),
|
})
|
||||||
|
),
|
||||||
})
|
})
|
||||||
|
|
||||||
const loyaltyPageDynamicContent = z.object({
|
const loyaltyPageDynamicContent = z.object({
|
||||||
__typename: z.literal(
|
__typename: z.literal(
|
||||||
LoyaltyBlocksTypenameEnum.LoyaltyPageBlocksDynamicContent
|
LoyaltyBlocksTypenameEnum.LoyaltyPageBlocksDynamicContent
|
||||||
@@ -93,7 +78,8 @@ const loyaltyPageShortcuts = z.object({
|
|||||||
.object({
|
.object({
|
||||||
original_url: z.string().nullable(),
|
original_url: z.string().nullable(),
|
||||||
})
|
})
|
||||||
.nullable(),
|
.nullable()
|
||||||
|
.optional(),
|
||||||
title: z.string(),
|
title: z.string(),
|
||||||
}),
|
}),
|
||||||
})
|
})
|
||||||
@@ -107,6 +93,59 @@ const loyaltyPageShortcuts = z.object({
|
|||||||
}),
|
}),
|
||||||
})
|
})
|
||||||
|
|
||||||
|
const cardBlock = z.object({
|
||||||
|
heading: z.string().nullable(),
|
||||||
|
body_text: z.string().nullable(),
|
||||||
|
background_image: z.any(),
|
||||||
|
scripted_top_title: z.string().nullable(),
|
||||||
|
primary_button: z
|
||||||
|
.object({
|
||||||
|
is_contentstack_link: z.boolean(),
|
||||||
|
cta_text: z.string().nullable(),
|
||||||
|
open_in_new_tab: z.boolean(),
|
||||||
|
external_link: z.object({
|
||||||
|
title: z.string().nullable(),
|
||||||
|
href: z.string().nullable(),
|
||||||
|
}),
|
||||||
|
linkConnection: pageLink,
|
||||||
|
})
|
||||||
|
.nullable(),
|
||||||
|
secondary_button: z
|
||||||
|
.object({
|
||||||
|
is_contentstack_link: z.boolean(),
|
||||||
|
cta_text: z.string().nullable(),
|
||||||
|
open_in_new_tab: z.boolean().nullable(),
|
||||||
|
external_link: z.object({
|
||||||
|
title: z.string().nullable(),
|
||||||
|
href: z.string().nullable(),
|
||||||
|
}),
|
||||||
|
linkConnection: pageLink,
|
||||||
|
})
|
||||||
|
.nullable(),
|
||||||
|
|
||||||
|
system: z.object({
|
||||||
|
locale: z.nativeEnum(Lang),
|
||||||
|
uid: z.string(),
|
||||||
|
}),
|
||||||
|
})
|
||||||
|
|
||||||
|
const loyaltyPageCards = z.object({
|
||||||
|
__typename: z.literal(LoyaltyBlocksTypenameEnum.LoyaltyPageBlocksCardsGrid),
|
||||||
|
cards_grid: z.object({
|
||||||
|
title: z.string().nullable(),
|
||||||
|
preamble: z.string().nullable(),
|
||||||
|
layout: z.enum(["twoColumnGrid", "threeColumnGrid", "twoPlusOne"]),
|
||||||
|
theme: z.enum(["one", "two", "three"]).nullable(),
|
||||||
|
cardConnection: z.object({
|
||||||
|
edges: z.array(
|
||||||
|
z.object({
|
||||||
|
node: cardBlock,
|
||||||
|
})
|
||||||
|
),
|
||||||
|
}),
|
||||||
|
}),
|
||||||
|
})
|
||||||
|
|
||||||
const loyaltyPageBlockTextContent = z.object({
|
const loyaltyPageBlockTextContent = z.object({
|
||||||
__typename: z.literal(LoyaltyBlocksTypenameEnum.LoyaltyPageBlocksContent),
|
__typename: z.literal(LoyaltyBlocksTypenameEnum.LoyaltyPageBlocksContent),
|
||||||
content: z.object({
|
content: z.object({
|
||||||
@@ -121,10 +160,10 @@ const loyaltyPageBlockTextContent = z.object({
|
|||||||
})
|
})
|
||||||
|
|
||||||
const loyaltyPageBlockItem = z.discriminatedUnion("__typename", [
|
const loyaltyPageBlockItem = z.discriminatedUnion("__typename", [
|
||||||
loyaltyPageBlockCardGrid,
|
|
||||||
loyaltyPageDynamicContent,
|
loyaltyPageDynamicContent,
|
||||||
loyaltyPageBlockTextContent,
|
loyaltyPageBlockTextContent,
|
||||||
loyaltyPageShortcuts,
|
loyaltyPageShortcuts,
|
||||||
|
loyaltyPageCards,
|
||||||
])
|
])
|
||||||
|
|
||||||
const loyaltyPageSidebarTextContent = z.object({
|
const loyaltyPageSidebarTextContent = z.object({
|
||||||
@@ -178,26 +217,6 @@ export const validateLoyaltyPageSchema = z.object({
|
|||||||
})
|
})
|
||||||
|
|
||||||
// Block types
|
// Block types
|
||||||
type CardGridRaw = z.infer<typeof loyaltyPageBlockCardGrid>
|
|
||||||
|
|
||||||
export type CardGridCard = Omit<
|
|
||||||
CardGridRaw["card_grid"]["cards"][number],
|
|
||||||
"referenceConnection"
|
|
||||||
> & {
|
|
||||||
link:
|
|
||||||
| {
|
|
||||||
href: string
|
|
||||||
title: string
|
|
||||||
}
|
|
||||||
| undefined
|
|
||||||
}
|
|
||||||
|
|
||||||
export type CardGrid = Omit<CardGridRaw, "card_grid"> & {
|
|
||||||
card_grid: Omit<CardGridRaw["card_grid"], "cards"> & {
|
|
||||||
cards: CardGridCard[]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
type DynamicContentRaw = z.infer<typeof loyaltyPageDynamicContent>
|
type DynamicContentRaw = z.infer<typeof loyaltyPageDynamicContent>
|
||||||
|
|
||||||
export type DynamicContent = Omit<DynamicContentRaw, "dynamic_content"> & {
|
export type DynamicContent = Omit<DynamicContentRaw, "dynamic_content"> & {
|
||||||
@@ -222,6 +241,43 @@ export interface RteBlockContent extends BlockContentRaw {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type CardsGridRaw = z.infer<typeof loyaltyPageCards>
|
||||||
|
|
||||||
|
export type CardsGrid = Omit<CardsGridRaw, "cards_grid"> & {
|
||||||
|
cards_grid: Omit<CardsGridRaw["cards_grid"], "cardConnection"> & {
|
||||||
|
cards: {
|
||||||
|
system: {
|
||||||
|
locale: Lang
|
||||||
|
uid: string
|
||||||
|
}
|
||||||
|
heading: string | null
|
||||||
|
body_text: string | null
|
||||||
|
scripted_top_title: string | null
|
||||||
|
primaryButton:
|
||||||
|
| {
|
||||||
|
open_in_new_tab: boolean
|
||||||
|
link: {
|
||||||
|
title: string
|
||||||
|
href: string
|
||||||
|
}
|
||||||
|
isExternal: boolean
|
||||||
|
}
|
||||||
|
| undefined
|
||||||
|
secondaryButton:
|
||||||
|
| {
|
||||||
|
open_in_new_tab: boolean
|
||||||
|
link: {
|
||||||
|
title: string
|
||||||
|
href: string
|
||||||
|
}
|
||||||
|
isExternal: boolean
|
||||||
|
}
|
||||||
|
| undefined
|
||||||
|
background_image?: any
|
||||||
|
}[]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
type ShortcutsRaw = z.infer<typeof loyaltyPageShortcuts>
|
type ShortcutsRaw = z.infer<typeof loyaltyPageShortcuts>
|
||||||
|
|
||||||
export type Shortcuts = Omit<ShortcutsRaw, "shortcuts"> & {
|
export type Shortcuts = Omit<ShortcutsRaw, "shortcuts"> & {
|
||||||
@@ -235,7 +291,7 @@ export type Shortcuts = Omit<ShortcutsRaw, "shortcuts"> & {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export type Block = CardGrid | RteBlockContent | DynamicContent | Shortcuts
|
export type Block = RteBlockContent | DynamicContent | Shortcuts | CardsGrid
|
||||||
|
|
||||||
// Sidebar block types
|
// Sidebar block types
|
||||||
type SidebarContentRaw = z.infer<typeof loyaltyPageSidebarTextContent>
|
type SidebarContentRaw = z.infer<typeof loyaltyPageSidebarTextContent>
|
||||||
@@ -275,14 +331,34 @@ const pageConnectionRefs = z.object({
|
|||||||
),
|
),
|
||||||
})
|
})
|
||||||
|
|
||||||
const loyaltyPageBlockCardGridRefs = z.object({
|
const cardBlockRefs = z.object({
|
||||||
__typename: z.literal(LoyaltyBlocksTypenameEnum.LoyaltyPageBlocksCardGrid),
|
primary_button: z
|
||||||
card_grid: z.object({
|
.object({
|
||||||
cards: z.array(
|
linkConnection: pageConnectionRefs,
|
||||||
z.object({
|
})
|
||||||
referenceConnection: pageConnectionRefs,
|
.nullable(),
|
||||||
})
|
secondary_button: z
|
||||||
),
|
.object({
|
||||||
|
linkConnection: pageConnectionRefs,
|
||||||
|
})
|
||||||
|
.nullable(),
|
||||||
|
|
||||||
|
system: z.object({
|
||||||
|
content_type_uid: z.string(),
|
||||||
|
uid: z.string(),
|
||||||
|
}),
|
||||||
|
})
|
||||||
|
|
||||||
|
const loyaltyPageCardsRefs = z.object({
|
||||||
|
__typename: z.literal(LoyaltyBlocksTypenameEnum.LoyaltyPageBlocksCardsGrid),
|
||||||
|
cards_grid: z.object({
|
||||||
|
cardConnection: z.object({
|
||||||
|
edges: z.array(
|
||||||
|
z.object({
|
||||||
|
node: cardBlockRefs,
|
||||||
|
})
|
||||||
|
),
|
||||||
|
}),
|
||||||
}),
|
}),
|
||||||
})
|
})
|
||||||
|
|
||||||
@@ -318,10 +394,10 @@ const loyaltyPageBlockTextContentRefs = z.object({
|
|||||||
})
|
})
|
||||||
|
|
||||||
const loyaltyPageBlocRefsItem = z.discriminatedUnion("__typename", [
|
const loyaltyPageBlocRefsItem = z.discriminatedUnion("__typename", [
|
||||||
loyaltyPageBlockCardGridRefs,
|
|
||||||
loyaltyPageDynamicContentRefs,
|
loyaltyPageDynamicContentRefs,
|
||||||
loyaltyPageBlockTextContentRefs,
|
loyaltyPageBlockTextContentRefs,
|
||||||
loyaltyPageShortcutsRefs,
|
loyaltyPageShortcutsRefs,
|
||||||
|
loyaltyPageCardsRefs,
|
||||||
])
|
])
|
||||||
|
|
||||||
const loyaltyPageSidebarTextContentRef = z.object({
|
const loyaltyPageSidebarTextContentRef = z.object({
|
||||||
|
|||||||
@@ -60,6 +60,8 @@ export const loyaltyPageQueryRouter = router({
|
|||||||
const validatedLoyaltyPageRefs =
|
const validatedLoyaltyPageRefs =
|
||||||
validateLoyaltyPageRefsSchema.safeParse(cleanedData)
|
validateLoyaltyPageRefsSchema.safeParse(cleanedData)
|
||||||
if (!validatedLoyaltyPageRefs.success) {
|
if (!validatedLoyaltyPageRefs.success) {
|
||||||
|
console.error("Bad validation for `GetLoyaltyPageRefs`")
|
||||||
|
console.error(validatedLoyaltyPageRefs.error)
|
||||||
throw internalServerError(validatedLoyaltyPageRefs.error)
|
throw internalServerError(validatedLoyaltyPageRefs.error)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -114,24 +116,6 @@ export const loyaltyPageQueryRouter = router({
|
|||||||
const blocks = validatedLoyaltyPage.data.loyalty_page.blocks
|
const blocks = validatedLoyaltyPage.data.loyalty_page.blocks
|
||||||
? validatedLoyaltyPage.data.loyalty_page.blocks.map((block) => {
|
? validatedLoyaltyPage.data.loyalty_page.blocks.map((block) => {
|
||||||
switch (block.__typename) {
|
switch (block.__typename) {
|
||||||
case LoyaltyBlocksTypenameEnum.LoyaltyPageBlocksCardGrid:
|
|
||||||
return {
|
|
||||||
...block,
|
|
||||||
card_grid: {
|
|
||||||
...block.card_grid,
|
|
||||||
cards: block.card_grid.cards.map((card) => {
|
|
||||||
return {
|
|
||||||
...card,
|
|
||||||
link: card.referenceConnection.totalCount
|
|
||||||
? {
|
|
||||||
href: `/${card.referenceConnection.edges[0].node.system.locale}${card.referenceConnection.edges[0].node.url}`,
|
|
||||||
title: card.cta_text || _("Read more"),
|
|
||||||
}
|
|
||||||
: undefined,
|
|
||||||
}
|
|
||||||
}),
|
|
||||||
},
|
|
||||||
}
|
|
||||||
case LoyaltyBlocksTypenameEnum.LoyaltyPageBlocksDynamicContent:
|
case LoyaltyBlocksTypenameEnum.LoyaltyPageBlocksDynamicContent:
|
||||||
return {
|
return {
|
||||||
...block,
|
...block,
|
||||||
@@ -174,6 +158,70 @@ export const loyaltyPageQueryRouter = router({
|
|||||||
})),
|
})),
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
case LoyaltyBlocksTypenameEnum.LoyaltyPageBlocksCardsGrid:
|
||||||
|
return {
|
||||||
|
...block,
|
||||||
|
cards_grid: {
|
||||||
|
...block.cards_grid,
|
||||||
|
cards: block.cards_grid.cardConnection.edges.map(
|
||||||
|
({ node: card }) => {
|
||||||
|
const primaryButton = card.primary_button
|
||||||
|
? {
|
||||||
|
open_in_new_tab:
|
||||||
|
card.primary_button.open_in_new_tab,
|
||||||
|
link: {
|
||||||
|
title:
|
||||||
|
card.primary_button.cta_text ||
|
||||||
|
(card.primary_button.is_contentstack_link &&
|
||||||
|
card.primary_button.linkConnection.edges.length
|
||||||
|
? card.primary_button.linkConnection.edges[0]
|
||||||
|
.node.title
|
||||||
|
: card.primary_button.external_link.title),
|
||||||
|
href:
|
||||||
|
card.primary_button.is_contentstack_link &&
|
||||||
|
card.primary_button.linkConnection.edges.length
|
||||||
|
? `/${card.primary_button.linkConnection.edges[0].node.system.locale}${card.primary_button.linkConnection.edges[0].node.url}`
|
||||||
|
: card.primary_button.external_link.href,
|
||||||
|
},
|
||||||
|
isExternal:
|
||||||
|
!card.primary_button.is_contentstack_link,
|
||||||
|
}
|
||||||
|
: undefined
|
||||||
|
|
||||||
|
const secondaryButton = card.secondary_button
|
||||||
|
? {
|
||||||
|
open_in_new_tab:
|
||||||
|
card.secondary_button.open_in_new_tab,
|
||||||
|
link: {
|
||||||
|
title:
|
||||||
|
card.secondary_button.cta_text ||
|
||||||
|
(card.secondary_button.is_contentstack_link &&
|
||||||
|
card.secondary_button.linkConnection.edges
|
||||||
|
.length
|
||||||
|
? card.secondary_button.linkConnection
|
||||||
|
.edges[0].node.title
|
||||||
|
: card.secondary_button.external_link.title),
|
||||||
|
href:
|
||||||
|
card.secondary_button.is_contentstack_link &&
|
||||||
|
card.secondary_button.linkConnection.edges
|
||||||
|
.length
|
||||||
|
? `/${card.secondary_button.linkConnection.edges[0].node.system.locale}${card.secondary_button.linkConnection.edges[0].node.url}`
|
||||||
|
: card.secondary_button.external_link.title,
|
||||||
|
},
|
||||||
|
isExternal:
|
||||||
|
!card.secondary_button.is_contentstack_link,
|
||||||
|
}
|
||||||
|
: undefined
|
||||||
|
|
||||||
|
return {
|
||||||
|
...card,
|
||||||
|
primaryButton,
|
||||||
|
secondaryButton,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
),
|
||||||
|
},
|
||||||
|
}
|
||||||
default:
|
default:
|
||||||
return block
|
return block
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -15,12 +15,16 @@ export function getConnections(refs: LoyaltyPageRefsDataRaw) {
|
|||||||
}
|
}
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
case LoyaltyBlocksTypenameEnum.LoyaltyPageBlocksCardGrid: {
|
case LoyaltyBlocksTypenameEnum.LoyaltyPageBlocksCardsGrid: {
|
||||||
item.card_grid.cards.forEach((card) => {
|
connections.push(item.cards_grid.cardConnection)
|
||||||
if (card.referenceConnection.edges.length) {
|
item.cards_grid.cardConnection.edges.forEach((card) => {
|
||||||
connections.push(card.referenceConnection)
|
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
|
||||||
}
|
}
|
||||||
case LoyaltyBlocksTypenameEnum.LoyaltyPageBlocksShortcuts: {
|
case LoyaltyBlocksTypenameEnum.LoyaltyPageBlocksShortcuts: {
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import {
|
import {
|
||||||
Block,
|
Block,
|
||||||
CardGrid,
|
CardsGrid,
|
||||||
DynamicContent,
|
DynamicContent,
|
||||||
RteBlockContent,
|
RteBlockContent,
|
||||||
} from "@/server/routers/contentstack/loyaltyPage/output"
|
} from "@/server/routers/contentstack/loyaltyPage/output"
|
||||||
@@ -17,7 +17,7 @@ export type DynamicComponentProps = {
|
|||||||
component: DynamicContent["dynamic_content"]["component"]
|
component: DynamicContent["dynamic_content"]["component"]
|
||||||
}
|
}
|
||||||
|
|
||||||
export type CardGridProps = Pick<CardGrid, "card_grid">
|
export type CardsGridProps = Pick<CardsGrid, "cards_grid">
|
||||||
|
|
||||||
export type Content = { content: RteBlockContent["content"]["content"] }
|
export type Content = { content: RteBlockContent["content"]["content"] }
|
||||||
|
|
||||||
|
|||||||
@@ -27,7 +27,7 @@ export type LoyaltyComponent = keyof typeof LoyaltyComponentEnum
|
|||||||
|
|
||||||
export enum LoyaltyBlocksTypenameEnum {
|
export enum LoyaltyBlocksTypenameEnum {
|
||||||
LoyaltyPageBlocksDynamicContent = "LoyaltyPageBlocksDynamicContent",
|
LoyaltyPageBlocksDynamicContent = "LoyaltyPageBlocksDynamicContent",
|
||||||
LoyaltyPageBlocksCardGrid = "LoyaltyPageBlocksCardGrid",
|
|
||||||
LoyaltyPageBlocksContent = "LoyaltyPageBlocksContent",
|
LoyaltyPageBlocksContent = "LoyaltyPageBlocksContent",
|
||||||
LoyaltyPageBlocksShortcuts = "LoyaltyPageBlocksShortcuts",
|
LoyaltyPageBlocksShortcuts = "LoyaltyPageBlocksShortcuts",
|
||||||
|
LoyaltyPageBlocksCardsGrid = "LoyaltyPageBlocksCardsGrid",
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user