refactor: infer types from zod validation

This commit is contained in:
Christel Westerberg
2024-04-29 09:53:54 +02:00
parent 00f30811cf
commit 49b7aa89f8
18 changed files with 418 additions and 217 deletions

View File

@@ -35,16 +35,9 @@ export default function CardGrid({ card_grid }: CardGridProps) {
} }
function CardWrapper({ card }: CardProps) { function CardWrapper({ card }: CardProps) {
const link = card.referenceConnection.edges.length
? {
href: card.referenceConnection.edges[0].node.url,
title: _("Read more"),
}
: undefined
return ( return (
<div className={styles.cardWrapper}> <div className={styles.cardWrapper}>
<Card subtitle={card.subtitle} title={card.title} link={link} /> <Card subtitle={card.subtitle} title={card.title} link={card.link} />
</div> </div>
) )
} }

View File

@@ -7,13 +7,13 @@ import OverviewTable from "./OverviewTable"
import styles from "./dynamicContent.module.css" import styles from "./dynamicContent.module.css"
import { DynamicContentProps } from "@/types/components/loyalty/blocks" import type {
import { DynamicComponentProps,
LoyaltyComponent, DynamicContentProps,
LoyaltyComponentEnum, } from "@/types/components/loyalty/blocks"
} from "@/types/requests/loyaltyPage" import { LoyaltyComponentEnum } from "@/types/requests/loyaltyPage"
function DynamicComponentBlock({ component }: { component: LoyaltyComponent }) { function DynamicComponentBlock({ component }: DynamicComponentProps) {
switch (component) { switch (component) {
case LoyaltyComponentEnum.how_it_works: case LoyaltyComponentEnum.how_it_works:
return <HowItWorks /> return <HowItWorks />
@@ -30,9 +30,6 @@ function DynamicComponentBlock({ component }: { component: LoyaltyComponent }) {
export default function DynamicContent({ export default function DynamicContent({
dynamicContent, dynamicContent,
}: DynamicContentProps) { }: DynamicContentProps) {
const link = dynamicContent.link.pageConnection.edges.length
? dynamicContent.link.pageConnection.edges[0].node.url
: null
return ( return (
<section className={styles.container}> <section className={styles.container}>
<header> <header>
@@ -48,11 +45,11 @@ export default function DynamicContent({
{dynamicContent.title} {dynamicContent.title}
</Title> </Title>
)} )}
{link && ( {dynamicContent.link ? (
<Link className={styles.link} href={link}> <Link className={styles.link} href={dynamicContent.link.href}>
{dynamicContent.link.text} {dynamicContent.link.text}
</Link> </Link>
)} ) : null}
</div> </div>
{dynamicContent.subtitle && ( {dynamicContent.subtitle && (
<Title <Title

View File

@@ -3,12 +3,10 @@ import DynamicContentBlock from "@/components/Loyalty/Blocks/DynamicContent"
import CardGrid from "./CardGrid" import CardGrid from "./CardGrid"
import { import type { BlocksProps } from "@/types/components/loyalty/blocks"
Blocks as BlocksType, import { LoyaltyBlocksTypenameEnum } from "@/types/requests/loyaltyPage"
LoyaltyBlocksTypenameEnum,
} from "@/types/requests/loyaltyPage"
export function Blocks({ blocks }: { blocks: BlocksType[] }) { export function Blocks({ blocks }: BlocksProps) {
return blocks.map((block) => { return blocks.map((block) => {
switch (block.__typename) { switch (block.__typename) {
case LoyaltyBlocksTypenameEnum.LoyaltyPageBlocksCardGrid: case LoyaltyBlocksTypenameEnum.LoyaltyPageBlocksCardGrid:
@@ -16,8 +14,8 @@ export function Blocks({ blocks }: { blocks: BlocksType[] }) {
case LoyaltyBlocksTypenameEnum.LoyaltyPageBlocksContent: case LoyaltyBlocksTypenameEnum.LoyaltyPageBlocksContent:
return ( return (
<JsonToHtml <JsonToHtml
nodes={block.content.json.children} nodes={block.content.content.json.children}
embeds={block.content.embedded_itemsConnection.edges} embeds={block.content.content.embedded_itemsConnection.edges}
/> />
) )
case LoyaltyBlocksTypenameEnum.LoyaltyPageBlocksDynamicContent: case LoyaltyBlocksTypenameEnum.LoyaltyPageBlocksDynamicContent:

View File

@@ -1,9 +1,10 @@
import { Lang } from "@/constants/languages"
import { serverClient } from "@/lib/trpc/server" import { serverClient } from "@/lib/trpc/server"
import { getValueFromContactConfig } from "@/utils/contactConfig" import { getValueFromContactConfig } from "@/utils/contactConfig"
import styles from "./contactRow.module.css" import styles from "./contactRow.module.css"
import { Lang } from "@/constants/languages"
import type { ContactFields } from "@/types/requests/contactConfig" import type { ContactFields } from "@/types/requests/contactConfig"
export default async function ContactRow({ export default async function ContactRow({
@@ -16,6 +17,11 @@ export default async function ContactRow({
}) })
const val = getValueFromContactConfig(contact.contact_field, data) const val = getValueFromContactConfig(contact.contact_field, data)
if (!val) {
return null
}
return ( return (
<div className={styles.container}> <div className={styles.container}>
<h4 className={styles.title}>{contact.display_text}</h4> <h4 className={styles.title}>{contact.display_text}</h4>

View File

@@ -1,20 +1,28 @@
import { _ } from "@/lib/translation"
import Title from "@/components/Title" import Title from "@/components/Title"
import ContactRow from "./ContactRow" import ContactRow from "./ContactRow"
import styles from "./contact.module.css" import styles from "./contact.module.css"
import { JoinLoyaltyContactTypenameEnum } from "@/types/requests/loyaltyPage"
import type { ContactProps } from "@/types/components/loyalty/sidebar" import type { ContactProps } from "@/types/components/loyalty/sidebar"
import { JoinLoyaltyContactTypenameEnum } from "@/types/requests/loyaltyPage"
export default async function Contact({ contactBlock }: ContactProps) { export default async function Contact({ contactBlock }: ContactProps) {
return ( return (
<div className={styles.contactContainer}> <div className={styles.contactContainer}>
<Title level="h5">Contact us</Title> <Title level="h5">{_("Contact us")}</Title>
<section> <section>
{contactBlock.map(({ contact, __typename }) => { {contactBlock.map(({ contact, __typename }, i) => {
switch (__typename) { switch (__typename) {
case JoinLoyaltyContactTypenameEnum.LoyaltyPageSidebarJoinLoyaltyContactBlockContactContact: case JoinLoyaltyContactTypenameEnum.LoyaltyPageSidebarJoinLoyaltyContactBlockContactContact:
return <ContactRow contact={contact} /> return (
<ContactRow
key={`${contact.display_text}-i`}
contact={contact}
/>
)
default: default:
return null return null
} }

View File

@@ -9,13 +9,9 @@ import Contact from "./Contact"
import styles from "./joinLoyalty.module.css" import styles from "./joinLoyalty.module.css"
import type { JoinLoyaltyContact } from "@/types/requests/loyaltyPage" import type { JoinLoyaltyContactProps } from "@/types/components/loyalty/sidebar"
export default function JoinLoyaltyContact({ export default function JoinLoyaltyContact({ block }: JoinLoyaltyContactProps) {
block,
}: {
block: JoinLoyaltyContact["join_loyalty_contact"]
}) {
return ( return (
<div className={styles.container}> <div className={styles.container}>
<div className={styles.wrapper}> <div className={styles.wrapper}>

View File

@@ -2,15 +2,16 @@ import JsonToHtml from "@/components/JsonToHtml"
import JoinLoyaltyContact from "./JoinLoyalty" import JoinLoyaltyContact from "./JoinLoyalty"
import { Sidebar, SidebarTypenameEnum } from "@/types/requests/loyaltyPage" import { SidebarProps } from "@/types/components/loyalty/sidebar"
import { SidebarTypenameEnum } from "@/types/requests/loyaltyPage"
export default function SidebarLoyalty({ block }: { block: Sidebar }) { export default function SidebarLoyalty({ block }: SidebarProps) {
switch (block.__typename) { switch (block.__typename) {
case SidebarTypenameEnum.LoyaltyPageSidebarContent: case SidebarTypenameEnum.LoyaltyPageSidebarContent:
return ( return (
<JsonToHtml <JsonToHtml
embeds={block.content.embedded_itemsConnection.edges} embeds={block.content.content.embedded_itemsConnection.edges}
nodes={block.content.json.children} nodes={block.content.content.json.children}
/> />
) )
case SidebarTypenameEnum.LoyaltyPageSidebarJoinLoyaltyContact: case SidebarTypenameEnum.LoyaltyPageSidebarJoinLoyaltyContact:

View File

@@ -22,6 +22,7 @@ query GetLoyaltyPage($locale: String!, $url: String!) {
...LoyaltyPageLink ...LoyaltyPageLink
} }
} }
totalCount
} }
} }
} }
@@ -41,9 +42,11 @@ query GetLoyaltyPage($locale: String!, $url: String!) {
...AccountPageLink ...AccountPageLink
} }
} }
totalCount
} }
title title
subtitle subtitle
open_in_new_tab
} }
} }
} }
@@ -55,16 +58,11 @@ query GetLoyaltyPage($locale: String!, $url: String!) {
embedded_itemsConnection { embedded_itemsConnection {
edges { edges {
node { node {
... on SysAsset { __typename
title ...Image
url
dimension {
width
height
}
}
} }
} }
totalCount
} }
} }
} }
@@ -86,7 +84,6 @@ query GetLoyaltyPage($locale: String!, $url: String!) {
} }
} }
} }
login_button_text
} }
} }
... on LoyaltyPageSidebarContent { ... on LoyaltyPageSidebarContent {
@@ -101,6 +98,7 @@ query GetLoyaltyPage($locale: String!, $url: String!) {
...Image ...Image
} }
} }
totalCount
} }
} }
} }

View File

@@ -0,0 +1,208 @@
import { z } from "zod"
import { Embeds } from "@/types/requests/embeds"
import {
JoinLoyaltyContactTypenameEnum,
LoyaltyBlocksTypenameEnum,
LoyaltyComponentEnum,
SidebarTypenameEnum,
} from "@/types/requests/loyaltyPage"
import { Edges } from "@/types/requests/utils/edges"
import { RTEDocument } from "@/types/rte/node"
const loyaltyPageBlockCardGrid = z.object({
__typename: z.literal(LoyaltyBlocksTypenameEnum.LoyaltyPageBlocksCardGrid),
card_grid: z.object({
title: z.string().optional(),
subtitle: z.string().optional(),
cards: z.array(
z.object({
title: z.string().optional(),
subtitle: z.string().optional(),
referenceConnection: z.object({
edges: z.array(
z.object({
node: z.object({
system: z.object({
uid: z.string(),
}),
url: z.string(),
title: z.string(),
__typename: z.string(),
}),
})
),
totalCount: z.number(),
}),
open_in_new_tab: z.boolean(),
})
),
}),
})
const loyaltyPageDynamicContent = z.object({
__typename: z.literal(
LoyaltyBlocksTypenameEnum.LoyaltyPageBlocksDynamicContent
),
dynamic_content: z.object({
title: z.string().optional(),
subtitle: z.string().optional(),
component: z.nativeEnum(LoyaltyComponentEnum),
link: z.object({
text: z.string().optional(),
pageConnection: z.object({
edges: z.array(
z.object({
node: z.object({
system: z.object({
uid: z.string(),
}),
url: z.string(),
title: z.string(),
}),
})
),
totalCount: z.number(),
}),
}),
}),
})
const loyaltyPageBlockTextContent = z.object({
__typename: z.literal(LoyaltyBlocksTypenameEnum.LoyaltyPageBlocksContent),
content: z.object({
content: z.object({
embedded_itemsConnection: z.object({
edges: z.array(z.any()),
totalCount: z.number(),
}),
json: z.any(),
}),
}),
})
const loyaltyPageBlockItem = z.discriminatedUnion("__typename", [
loyaltyPageBlockCardGrid,
loyaltyPageDynamicContent,
loyaltyPageBlockTextContent,
])
const loyaltyPageSidebarTextContent = z.object({
__typename: z.literal(SidebarTypenameEnum.LoyaltyPageSidebarContent),
content: z.object({
content: z.object({
embedded_itemsConnection: z.object({
edges: z.array(z.any()),
totalCount: z.number(),
}),
json: z.any(),
}),
}),
})
const loyaltyPageJoinLoyaltyContact = z.object({
__typename: z.literal(
SidebarTypenameEnum.LoyaltyPageSidebarJoinLoyaltyContact
),
join_loyalty_contact: z.object({
title: z.string().optional(),
preamble: z.string().optional(),
contact: z.array(
z.object({
__typename: z.literal(
JoinLoyaltyContactTypenameEnum.LoyaltyPageSidebarJoinLoyaltyContactBlockContactContact
),
contact: z.object({
display_text: z.string().optional(),
contact_field: z.string(),
}),
})
),
}),
})
const loyaltyPageSidebarItem = z.discriminatedUnion("__typename", [
loyaltyPageSidebarTextContent,
loyaltyPageJoinLoyaltyContact,
])
export const validateLoyaltyPageSchema = z.object({
all_loyalty_page: z.object({
items: z.array(
z.object({
title: z.string(),
blocks: z.array(loyaltyPageBlockItem),
sidebar: z.array(loyaltyPageSidebarItem),
})
),
}),
})
// 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>
export type DynamicContent = Omit<DynamicContentRaw, "dynamic_content"> & {
dynamic_content: Omit<DynamicContentRaw["dynamic_content"], "link"> & {
link:
| {
href: string
title: string
text?: string
}
| undefined
}
}
type BlockContentRaw = z.infer<typeof loyaltyPageBlockTextContent>
export interface RteBlockContent extends BlockContentRaw {
content: {
content: {
json: RTEDocument
embedded_itemsConnection: Edges<Embeds>
}
}
}
export type Block = CardGrid | RteBlockContent | DynamicContent
// Sidebar block types
type SidebarContentRaw = z.infer<typeof loyaltyPageSidebarTextContent>
export type RteSidebarContent = Omit<SidebarContentRaw, "content"> & {
content: {
content: {
json: RTEDocument
embedded_itemsConnection: Edges<Embeds>
}
}
}
export type JoinLoyaltyContact = z.infer<typeof loyaltyPageJoinLoyaltyContact>
export type Sidebar = JoinLoyaltyContact | RteSidebarContent
type LoyaltyPageDataRaw = z.infer<typeof validateLoyaltyPageSchema>
type LoyaltyPageRaw = LoyaltyPageDataRaw["all_loyalty_page"]["items"][0]
export type LoyaltyPage = Omit<LoyaltyPageRaw, "blocks" | "sidebar"> & {
blocks: Block[]
sidebar: Sidebar[]
}

View File

@@ -1,33 +1,132 @@
import { z } from "zod" import GetLoyaltyPage from "@/lib/graphql/Query/LoyaltyPage.graphql"
import { request } from "@/lib/graphql/request"
import { badRequestError } from "@/server/errors/trpc" import { badRequestError } from "@/server/errors/trpc"
import { publicProcedure, router } from "@/server/trpc" import { publicProcedure, router } from "@/server/trpc"
import { request } from "@/lib/graphql/request"
import { Lang } from "@/constants/languages"
import GetLoyaltyPage from "@/lib/graphql/Query/LoyaltyPage.graphql" import { getLoyaltyPageInput } from "./input"
import { type LoyaltyPage, validateLoyaltyPageSchema } from "./output"
import type { GetLoyaltyPageData } from "@/types/requests/loyaltyPage" import { Embeds } from "@/types/requests/embeds"
import {
LoyaltyBlocksTypenameEnum,
SidebarTypenameEnum,
} from "@/types/requests/loyaltyPage"
import { Edges } from "@/types/requests/utils/edges"
import { RTEDocument } from "@/types/rte/node"
export const loyaltyPageQueryRouter = router({ export const loyaltyPageQueryRouter = router({
get: publicProcedure get: publicProcedure.input(getLoyaltyPageInput).query(async ({ input }) => {
.input(z.object({ uri: z.string(), lang: z.nativeEnum(Lang) })) try {
.query(async ({ input }) => { const loyaltyPageRes = await request<LoyaltyPage>(GetLoyaltyPage, {
const loyaltyPage = await request<GetLoyaltyPageData>( locale: input.locale,
GetLoyaltyPage, url: input.href,
{ })
locale: input.lang,
url: input.uri,
},
{
tags: [`${input.uri}-${input.lang}`],
}
)
if (loyaltyPage.data && loyaltyPage.data.all_loyalty_page.items.length) { if (!loyaltyPageRes.data) {
return loyaltyPage.data.all_loyalty_page.items[0] throw badRequestError()
} }
const validatedLoyaltyPage = validateLoyaltyPageSchema.safeParse(
loyaltyPageRes.data
)
if (!validatedLoyaltyPage.success) {
throw badRequestError()
}
const sidebar =
validatedLoyaltyPage.data.all_loyalty_page.items[0].sidebar.map(
(block) => {
if (
block.__typename == SidebarTypenameEnum.LoyaltyPageSidebarContent
) {
return {
...block,
content: {
content: {
json: block.content.content.json as RTEDocument,
embedded_itemsConnection: block.content.content
.embedded_itemsConnection as Edges<Embeds>,
},
},
}
} else {
return block
}
}
)
const blocks =
validatedLoyaltyPage.data.all_loyalty_page.items[0].blocks.map(
(block) => {
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 > 0
? {
href: card.referenceConnection.edges[0].node
.url,
title:
card.referenceConnection.edges[0].node.title,
}
: undefined,
}
}),
},
}
case LoyaltyBlocksTypenameEnum.LoyaltyPageBlocksDynamicContent:
return {
...block,
dynamic_content: {
...block.dynamic_content,
link:
block.dynamic_content.link.pageConnection.totalCount > 0
? {
text: block.dynamic_content.link.text,
href: block.dynamic_content.link.pageConnection
.edges[0].node.url,
title:
block.dynamic_content.link.pageConnection.edges[0]
.node.title,
}
: undefined,
},
}
case LoyaltyBlocksTypenameEnum.LoyaltyPageBlocksContent:
return {
...block,
content: {
content: {
json: block.content.content.json as RTEDocument,
embedded_itemsConnection: block.content.content
.embedded_itemsConnection as Edges<Embeds>,
},
},
}
default:
return block
}
}
)
const loyaltyPage = {
...validatedLoyaltyPage.data.all_loyalty_page.items[0],
blocks,
sidebar,
} as LoyaltyPage
return loyaltyPage
} catch (error) {
console.info(`Get Loyalty Page Error`)
console.error(error)
throw badRequestError() throw badRequestError()
}), }
}),
}) })

View File

@@ -1,8 +1,7 @@
import type { RTENode } from "../rte/node"
import type { Node } from "@/types/requests/utils/edges"
import type { RenderOptions } from "../rte/option"
import type { Embeds } from "@/types/requests/embeds" import type { Embeds } from "@/types/requests/embeds"
import type { Node } from "@/types/requests/utils/edges"
import type { RTENode } from "../rte/node"
import type { RenderOptions } from "../rte/option"
export type JsonToHtmlProps = { export type JsonToHtmlProps = {
embeds: Node<Embeds>[] embeds: Node<Embeds>[]

View File

@@ -1,38 +1,28 @@
import { Embeds } from "@/types/requests/embeds" import {
import { DynamicContentBlock } from "@/types/requests/loyaltyPage" Block,
import { PageLink } from "@/types/requests/myPages/navigation" CardGrid,
import { Edges } from "@/types/requests/utils/edges" CardGridCard,
import { RTEDocument } from "@/types/rte/node" DynamicContent,
RteBlockContent,
} from "@/server/routers/contentstack/loyaltyPage/output"
export type BlocksProps = {
blocks: Block[]
}
export type DynamicContentProps = { export type DynamicContentProps = {
dynamicContent: DynamicContentBlock["dynamic_content"] dynamicContent: DynamicContent["dynamic_content"]
} }
type Card = { export type DynamicComponentProps = {
referenceConnection: Edges<PageLink> component: DynamicContent["dynamic_content"]["component"]
title?: string
subtitle?: string
open_in_new_tab: boolean
} }
export type CardProps = { card: Card } export type CardProps = { card: CardGridCard }
export type CardGrid = { export type CardGridProps = Pick<CardGrid, "card_grid">
card_grid: {
title?: string
subtitle?: string
cards: Card[]
}
}
export type CardGridProps = CardGrid export type Content = { content: RteBlockContent["content"]["content"] }
export type Content = {
content: {
embedded_itemsConnection: Edges<Embeds>
json: RTEDocument
}
}
export type LevelCardProps = { export type LevelCardProps = {
level: { level: {

View File

@@ -1,20 +1,16 @@
import { ContactFields } from "@/types/requests/contactConfig" import {
import { Embeds } from "@/types/requests/embeds" JoinLoyaltyContact,
import { JoinLoyaltyContactContact } from "@/types/requests/loyaltyPage" Sidebar,
import { Edges } from "@/types/requests/utils/edges" } from "@/server/routers/contentstack/loyaltyPage/output"
import { RTEDocument } from "@/types/rte/node"
export type SidebarContent = { export type SidebarProps = {
content: { block: Sidebar
embedded_itemsConnection: Edges<Embeds>
json: RTEDocument
}
} }
export type Contact = { export type JoinLoyaltyContactProps = {
contact: ContactFields block: JoinLoyaltyContact["join_loyalty_contact"]
} }
export type ContactProps = { export type ContactProps = {
contactBlock: JoinLoyaltyContactContact[] contactBlock: JoinLoyaltyContact["join_loyalty_contact"]["contact"]
} }

View File

@@ -4,7 +4,7 @@ export type Image = {
height: number height: number
width: number width: number
} }
metadata: JSON metadata: JSON | null
system: { system: {
uid: string uid: string
} }

View File

@@ -47,28 +47,7 @@ export type GetContactConfigData = {
all_contact_config: AllRequestResponse<ContactConfig> all_contact_config: AllRequestResponse<ContactConfig>
} }
// Utility types that extract the possible strings of ContactConfigField,
// Which is all the dot notated values of ContactConfig (for example: 'email.name')
// From: https://stackoverflow.com/questions/47057649/typescript-string-dot-notation-of-nested-object#47058976
type PathsToStringProps<T> = T extends string
? []
: {
[K in Extract<keyof T, string>]: [K, ...PathsToStringProps<T[K]>]
}[Extract<keyof T, string>]
type Join<T extends string[], D extends string> = T extends []
? never
: T extends [infer F]
? F
: T extends [infer F, ...infer R]
? F extends string
? `${F}${D}${Join<Extract<R, string[]>, D>}`
: never
: string
export type ContactConfigField = Join<PathsToStringProps<ContactConfig>, ".">
export type ContactFields = { export type ContactFields = {
display_text?: string display_text?: string
contact_field: ContactConfigField contact_field: string
} }

View File

@@ -1,9 +1,4 @@
import { CardGrid, Content } from "../components/loyalty/blocks" import type { JoinLoyaltyContact } from "@/server/routers/contentstack/loyaltyPage/output"
import { Contact, SidebarContent } from "../components/loyalty/sidebar"
import { PageLink } from "./myPages/navigation"
import { Edges } from "./utils/edges"
import type { AllRequestResponse } from "./utils/all"
import type { Typename } from "./utils/typename" import type { Typename } from "./utils/typename"
export enum JoinLoyaltyContactTypenameEnum { export enum JoinLoyaltyContactTypenameEnum {
@@ -11,18 +6,10 @@ export enum JoinLoyaltyContactTypenameEnum {
} }
export type JoinLoyaltyContactContact = Typename< export type JoinLoyaltyContactContact = Typename<
Contact, JoinLoyaltyContact["join_loyalty_contact"],
JoinLoyaltyContactTypenameEnum.LoyaltyPageSidebarJoinLoyaltyContactBlockContactContact JoinLoyaltyContactTypenameEnum.LoyaltyPageSidebarJoinLoyaltyContactBlockContactContact
> >
export type JoinLoyaltyContact = {
join_loyalty_contact: {
title?: string
preamble?: string
contact: JoinLoyaltyContactContact[]
}
}
export enum SidebarTypenameEnum { export enum SidebarTypenameEnum {
LoyaltyPageSidebarJoinLoyaltyContact = "LoyaltyPageSidebarJoinLoyaltyContact", LoyaltyPageSidebarJoinLoyaltyContact = "LoyaltyPageSidebarJoinLoyaltyContact",
LoyaltyPageSidebarContent = "LoyaltyPageSidebarContent", LoyaltyPageSidebarContent = "LoyaltyPageSidebarContent",
@@ -30,13 +17,6 @@ export enum SidebarTypenameEnum {
export type SidebarTypename = keyof typeof SidebarTypenameEnum export type SidebarTypename = keyof typeof SidebarTypenameEnum
export type Sidebar =
| Typename<SidebarContent, SidebarTypenameEnum.LoyaltyPageSidebarContent>
| Typename<
JoinLoyaltyContact,
SidebarTypenameEnum.LoyaltyPageSidebarJoinLoyaltyContact
>
export enum LoyaltyComponentEnum { export enum LoyaltyComponentEnum {
loyalty_levels = "loyalty_levels", loyalty_levels = "loyalty_levels",
how_it_works = "how_it_works", how_it_works = "how_it_works",
@@ -45,57 +25,8 @@ export enum LoyaltyComponentEnum {
export type LoyaltyComponent = keyof typeof LoyaltyComponentEnum export type LoyaltyComponent = keyof typeof LoyaltyComponentEnum
export type DynamicContentBlock = {
dynamic_content: {
title?: string
subtitle?: string
component: LoyaltyComponent
link: {
text?: string
pageConnection: Edges<PageLink>
}
}
}
export enum LoyaltyBlocksTypenameEnum { export enum LoyaltyBlocksTypenameEnum {
LoyaltyPageBlocksDynamicContent = "LoyaltyPageBlocksDynamicContent", LoyaltyPageBlocksDynamicContent = "LoyaltyPageBlocksDynamicContent",
LoyaltyPageBlocksCardGrid = "LoyaltyPageBlocksCardGrid", LoyaltyPageBlocksCardGrid = "LoyaltyPageBlocksCardGrid",
LoyaltyPageBlocksContent = "LoyaltyPageBlocksContent", LoyaltyPageBlocksContent = "LoyaltyPageBlocksContent",
} }
export type Blocks =
| Typename<CardGrid, LoyaltyBlocksTypenameEnum.LoyaltyPageBlocksCardGrid>
| Typename<
DynamicContentBlock,
LoyaltyBlocksTypenameEnum.LoyaltyPageBlocksDynamicContent
>
| Typename<Content, LoyaltyBlocksTypenameEnum.LoyaltyPageBlocksContent>
export type Breadcrumb = {
href: string
title: string
}
export type Breadcrumbs = {
parents: Breadcrumb[]
title: string
}
export type LoyaltyPage = {
sidebar: Sidebar[]
blocks: Blocks[]
web: {
breadcrumbs: Breadcrumbs
}
system: {
created_at: string
uid: string
updated_at: string
}
title: string
url: string
}
export type GetLoyaltyPageData = {
all_loyalty_page: AllRequestResponse<LoyaltyPage>
}

View File

@@ -1,11 +1,12 @@
import { RTETypeEnum } from "./enums" import { RTETypeEnum } from "./enums"
import type { EmbedByUid } from "../components/jsontohtml"
import type { import type {
Attributes, Attributes,
RTEAnchorAttrs, RTEAnchorAttrs,
RTEAssetAttrs, RTEAssetAttrs,
RTELinkAttrs, RTELinkAttrs,
} from "./attrs" } from "./attrs"
import type { EmbedByUid } from "../components/jsontohtml"
import type { RenderOptions } from "./option" import type { RenderOptions } from "./option"
export interface RTEDefaultNode { export interface RTEDefaultNode {

View File

@@ -1,18 +1,19 @@
import { import {
ContactConfig, ContactConfig,
ContactConfigField,
ContactFieldGroups, ContactFieldGroups,
} from "@/types/requests/contactConfig" } from "@/types/requests/contactConfig"
export function getValueFromContactConfig( export function getValueFromContactConfig(
keyStrings: ContactConfigField, keyString: string,
data: ContactConfig data: ContactConfig
): string | undefined { ): string | undefined {
const [groupName, key] = keyStrings.split(".") as [ const [groupName, key] = keyString.split(".") as [
ContactFieldGroups, ContactFieldGroups,
keyof ContactConfig[ContactFieldGroups], keyof ContactConfig[ContactFieldGroups],
] ]
const fieldGroup = data[groupName] if (data[groupName]) {
const fieldGroup = data[groupName]
return fieldGroup[key] return fieldGroup[key]
}
} }