fix: add loyaltyCard
This commit is contained in:
@@ -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);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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>
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -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>
|
||||||
|
|||||||
@@ -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;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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:
|
||||||
|
|||||||
@@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
65
components/TempDesignSystem/LoyaltyCard/index.tsx
Normal file
65
components/TempDesignSystem/LoyaltyCard/index.tsx
Normal 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>
|
||||||
|
)
|
||||||
|
}
|
||||||
@@ -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;
|
||||||
|
}
|
||||||
20
components/TempDesignSystem/LoyaltyCard/loyaltyCard.ts
Normal file
20
components/TempDesignSystem/LoyaltyCard/loyaltyCard.ts
Normal 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 }
|
||||||
|
}
|
||||||
14
components/TempDesignSystem/LoyaltyCard/variants.ts
Normal file
14
components/TempDesignSystem/LoyaltyCard/variants.ts
Normal 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",
|
||||||
|
},
|
||||||
|
})
|
||||||
@@ -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;
|
||||||
|
}
|
||||||
|
|||||||
@@ -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} />
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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",
|
||||||
|
|||||||
28
lib/graphql/Fragments/Blocks/LoyaltyCard.graphql
Normal file
28
lib/graphql/Fragments/Blocks/LoyaltyCard.graphql
Normal 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
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,4 +1,5 @@
|
|||||||
fragment CardBlockRef on Card {
|
fragment CardBlockRef on Card {
|
||||||
|
__typename
|
||||||
secondary_button {
|
secondary_button {
|
||||||
linkConnection {
|
linkConnection {
|
||||||
edges {
|
edges {
|
||||||
|
|||||||
18
lib/graphql/Fragments/Blocks/Refs/LoyaltyCard.graphql
Normal file
18
lib/graphql/Fragments/Blocks/Refs/LoyaltyCard.graphql
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
fragment LoyaltyCardBlockRef on LoyaltyCard {
|
||||||
|
__typename
|
||||||
|
link {
|
||||||
|
linkConnection {
|
||||||
|
edges {
|
||||||
|
node {
|
||||||
|
__typename
|
||||||
|
...LoyaltyPageRef
|
||||||
|
...ContentPageRef
|
||||||
|
...AccountPageRef
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
system {
|
||||||
|
...System
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -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
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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({
|
||||||
|
|||||||
@@ -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,
|
||||||
})
|
})
|
||||||
),
|
),
|
||||||
}),
|
}),
|
||||||
|
|||||||
@@ -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 = {
|
||||||
|
|||||||
@@ -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: {
|
||||||
|
|||||||
@@ -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"] }
|
||||||
|
|
||||||
|
|||||||
@@ -31,3 +31,8 @@ export enum LoyaltyBlocksTypenameEnum {
|
|||||||
LoyaltyPageBlocksShortcuts = "LoyaltyPageBlocksShortcuts",
|
LoyaltyPageBlocksShortcuts = "LoyaltyPageBlocksShortcuts",
|
||||||
LoyaltyPageBlocksCardsGrid = "LoyaltyPageBlocksCardsGrid",
|
LoyaltyPageBlocksCardsGrid = "LoyaltyPageBlocksCardsGrid",
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export enum LoyaltyCardsGridEnum {
|
||||||
|
LoyaltyCard = "LoyaltyCard",
|
||||||
|
Card = "Card",
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user