refactor: reuse query code for both loyalty and account pages

This commit is contained in:
Matilda Landström
2024-05-27 16:13:44 +02:00
parent 0b694f6a74
commit fb4fbb1cbd
9 changed files with 150 additions and 271 deletions

View File

@@ -1,4 +1,5 @@
import { serverClient } from "@/lib/trpc/server" import { serverClient } from "@/lib/trpc/server"
import { PageTypes } from "@/server/routers/contentstack/breadcrumbs/input"
import { auth } from "@/auth" import { auth } from "@/auth"
import { Blocks } from "@/components/Loyalty/Blocks" import { Blocks } from "@/components/Loyalty/Blocks"
@@ -18,7 +19,7 @@ export default async function LoyaltyPage({ lang }: LangParams) {
return ( return (
<> <>
{session ? <Breadcrumbs b={true} /> : null} {session && <Breadcrumbs pageType={PageTypes.Loyalty} />}
<section className={styles.content}> <section className={styles.content}>
{session ? ( {session ? (
<Sidebar lang={lang} /> <Sidebar lang={lang} />

View File

@@ -1,20 +1,16 @@
import { _ } from "@/lib/translation" import { _ } from "@/lib/translation"
import { serverClient } from "@/lib/trpc/server" import { serverClient } from "@/lib/trpc/server"
import { PageTypes } from "@/server/routers/contentstack/breadcrumbs/input"
import Breadcrumb from "./Breadcrumb" import Breadcrumb from "./Breadcrumb"
import BreadcrumbsWithLink from "./BreadcrumbWithLink" import BreadcrumbsWithLink from "./BreadcrumbWithLink"
import styles from "./breadcrumbs.module.css" import styles from "./breadcrumbs.module.css"
type bool = { export default async function Breadcrumbs({ pageType = PageTypes.Account }) {
b?: Boolean const breadcrumbs = await serverClient().contentstack.breadcrumbs.get({
} pageType,
export default async function Breadcrumbs({ b = false }: bool) { })
let breadcrumbs
if (!b)
breadcrumbs = await serverClient().contentstack.breadcrumbs.getAccountPage()
else
breadcrumbs = await serverClient().contentstack.breadcrumbs.getLoyaltyPage()
return ( return (
<nav className={styles.breadcrumbs}> <nav className={styles.breadcrumbs}>
<ul className={styles.list}> <ul className={styles.list}>

View File

@@ -2,7 +2,7 @@
#import "../Fragments/Refs/Breadcrumbs.graphql" #import "../Fragments/Refs/Breadcrumbs.graphql"
query GetAccountPageBreadcrumbs($locale: String!, $url: String!) { query GetAccountPageBreadcrumbs($locale: String!, $url: String!) {
all_account_page(locale: $locale, where: { url: $url }) { all_page: all_account_page(locale: $locale, where: { url: $url }) {
items { items {
...AccountPageBreadcrumbs ...AccountPageBreadcrumbs
system { system {
@@ -13,7 +13,7 @@ query GetAccountPageBreadcrumbs($locale: String!, $url: String!) {
} }
query GetAccountPageBreadcrumbsRefs($locale: String!, $url: String!) { query GetAccountPageBreadcrumbsRefs($locale: String!, $url: String!) {
all_account_page(locale: $locale, where: { url: $url }) { all_page: all_account_page(locale: $locale, where: { url: $url }) {
items { items {
...AccountPageBreadcrumbsRefs ...AccountPageBreadcrumbsRefs
} }

View File

@@ -2,7 +2,7 @@
#import "../Fragments/Refs/Breadcrumbs.graphql" #import "../Fragments/Refs/Breadcrumbs.graphql"
query GetLoyaltyPageBreadcrumbs($locale: String!, $url: String!) { query GetLoyaltyPageBreadcrumbs($locale: String!, $url: String!) {
all_loyalty_page(locale: $locale, where: { url: $url }) { all_page: all_loyalty_page(locale: $locale, where: { url: $url }) {
items { items {
...LoyaltyPageBreadcrumbs ...LoyaltyPageBreadcrumbs
system { system {
@@ -13,7 +13,7 @@ query GetLoyaltyPageBreadcrumbs($locale: String!, $url: String!) {
} }
query GetLoyaltyPageBreadcrumbsRefs($locale: String!, $url: String!) { query GetLoyaltyPageBreadcrumbsRefs($locale: String!, $url: String!) {
all_loyalty_page(locale: $locale, where: { url: $url }) { all_page: all_loyalty_page(locale: $locale, where: { url: $url }) {
items { items {
...LoyaltyPageBreadcrumbsRefs ...LoyaltyPageBreadcrumbsRefs
} }

View File

@@ -0,0 +1,12 @@
import { z } from "zod"
export enum PageTypes {
Account,
Loyalty,
}
export const PageTypeEnum = z
.object({
pageType: z.nativeEnum(PageTypes),
})
.default({ pageType: PageTypes.Account })

View File

@@ -10,50 +10,26 @@ export const getBreadcrumbsSchema = z.array(
}) })
) )
const validateBreadcrumbs = z.object({ export const validateBreadcrumbsRefsContentstackSchema = z.object({
breadcrumbs: z.object({ all_page: z.object({
title: z.string(),
parentsConnection: z.object({
edges: z.array(
z.object({
node: z.object({
breadcrumbs: z.object({
title: z.string(),
}),
system: z.object({
locale: z.nativeEnum(Lang),
uid: z.string(),
}),
url: z.string(),
}),
})
),
}),
}),
})
const validateBreadcrumbsRefs = z.object({
breadcrumbs: z.object({
parentsConnection: z.object({
edges: z.array(
z.object({
node: z.object({
system: z.object({
content_type_uid: z.string(),
uid: z.string(),
}),
}),
})
),
}),
}),
})
export const validateBreadcrumbsRefsContentstackSchemaAccountPage = z.object({
all_account_page: z.object({
items: z.array( items: z.array(
z.object({ z.object({
web: validateBreadcrumbsRefs, web: z.object({
breadcrumbs: z.object({
parentsConnection: z.object({
edges: z.array(
z.object({
node: z.object({
system: z.object({
content_type_uid: z.string(),
uid: z.string(),
}),
}),
})
),
}),
}),
}),
system: z.object({ system: z.object({
content_type_uid: z.string(), content_type_uid: z.string(),
uid: z.string(), uid: z.string(),
@@ -63,38 +39,31 @@ export const validateBreadcrumbsRefsContentstackSchemaAccountPage = z.object({
}), }),
}) })
export const validateBreadcrumbsContentstackSchemaAccountPage = z.object({ export const validateBreadcrumbsContentstackSchema = z.object({
all_account_page: z.object({ all_page: z.object({
items: z.array( items: z.array(
z.object({ z.object({
web: validateBreadcrumbs, web: z.object({
system: z.object({ breadcrumbs: z.object({
uid: z.string(), title: z.string(),
}), parentsConnection: z.object({
}) edges: z.array(
), z.object({
}), node: z.object({
}) breadcrumbs: z.object({
title: z.string(),
export const validateBreadcrumbsRefsContentstackSchemaLoyaltyPage = z.object({ }),
all_loyalty_page: z.object({ system: z.object({
items: z.array( locale: z.nativeEnum(Lang),
z.object({ uid: z.string(),
web: validateBreadcrumbsRefs, }),
system: z.object({ url: z.string(),
content_type_uid: z.string(), }),
uid: z.string(), })
}), ),
}) }),
), }),
}), }),
})
export const validateBreadcrumbsContentstackSchemaLoyaltyPage = z.object({
all_loyalty_page: z.object({
items: z.array(
z.object({
web: validateBreadcrumbs,
system: z.object({ system: z.object({
uid: z.string(), uid: z.string(),
}), }),

View File

@@ -17,183 +17,107 @@ import {
} from "@/utils/generateTag" } from "@/utils/generateTag"
import { removeMultipleSlashes } from "@/utils/url" import { removeMultipleSlashes } from "@/utils/url"
import { PageTypeEnum, PageTypes } from "./input"
import { import {
getBreadcrumbsSchema, getBreadcrumbsSchema,
validateBreadcrumbsContentstackSchemaAccountPage, validateBreadcrumbsContentstackSchema,
validateBreadcrumbsContentstackSchemaLoyaltyPage, validateBreadcrumbsRefsContentstackSchema,
validateBreadcrumbsRefsContentstackSchemaAccountPage,
validateBreadcrumbsRefsContentstackSchemaLoyaltyPage,
} from "./output" } from "./output"
import { import { affix, getConnections, homeBreadcrumbs } from "./utils"
affix,
getConnectionsAccountPage,
getConnectionsLoyaltyPage,
homeBreadcrumbs,
} from "./utils"
import type { import type {
GetAccountPageBreadcrumbsData, GetMyPagesBreadcrumbsData,
GetAccountPageBreadcrumbsRefsData, GetMyPagesBreadcrumbsRefsData,
GetLoyaltyPageBreadcrumbsData,
GetLoyaltyPageBreadcrumbsRefsData,
} from "@/types/requests/myPages/breadcrumbs" } from "@/types/requests/myPages/breadcrumbs"
export const breadcrumbsQueryRouter = router({ export const breadcrumbsQueryRouter = router({
getAccountPage: contentstackProcedure.query(async ({ ctx }) => { get: contentstackProcedure
const refsResponse = await request<GetAccountPageBreadcrumbsRefsData>( .input(PageTypeEnum)
GetAccountPageBreadcrumbsRefs, .query(async ({ ctx, input }) => {
{ locale: ctx.lang, url: ctx.pathname }, let refsResponse, GetPageBreadcrumbs, GetPageBreadcrumbRefs
{
next: { if (input.pageType == PageTypes.Account) {
tags: [generateRefsResponseTag(ctx.lang, ctx.pathname, affix)], GetPageBreadcrumbs = GetAccountPageBreadcrumbs
}, GetPageBreadcrumbRefs = GetAccountPageBreadcrumbsRefs
} else if (input.pageType == PageTypes.Loyalty) {
GetPageBreadcrumbs = GetLoyaltyPageBreadcrumbs
GetPageBreadcrumbRefs = GetLoyaltyPageBreadcrumbsRefs
} else {
return []
} }
) refsResponse = await request<GetMyPagesBreadcrumbsRefsData>(
if (!refsResponse.data) { GetPageBreadcrumbRefs,
throw notFound(refsResponse) { locale: ctx.lang, url: ctx.pathname },
} {
next: {
const validatedRefsData = tags: [generateRefsResponseTag(ctx.lang, ctx.pathname, affix)],
validateBreadcrumbsRefsContentstackSchemaAccountPage.safeParse( },
refsResponse.data }
) )
if (!validatedRefsData.success) { if (!refsResponse.data) {
throw internalServerError(validatedRefsData.error) throw notFound(refsResponse)
} }
const connections = getConnectionsAccountPage(validatedRefsData.data) const validatedRefsData =
const tags = generateTags(ctx.lang, connections) validateBreadcrumbsRefsContentstackSchema.safeParse(refsResponse.data)
const page = validatedRefsData.data.all_account_page.items[0] if (!validatedRefsData.success) {
tags.push(generateTag(ctx.lang, page.system.uid, affix)) throw internalServerError(validatedRefsData.error)
}
const response = await request<GetAccountPageBreadcrumbsData>( const connections = getConnections(validatedRefsData.data)
GetAccountPageBreadcrumbs, const tags = generateTags(ctx.lang, connections)
{ locale: ctx.lang, url: ctx.pathname }, const page = validatedRefsData.data.all_page.items[0]
{ next: { tags } } tags.push(generateTag(ctx.lang, page.system.uid, affix))
)
if (!response.data) {
throw notFound(response)
}
const validatedBreadcrumbsData = const response = await request<GetMyPagesBreadcrumbsData>(
validateBreadcrumbsContentstackSchemaAccountPage.safeParse(response.data) GetPageBreadcrumbs,
{ locale: ctx.lang, url: ctx.pathname },
{ next: { tags } }
)
if (!response.data) {
throw notFound(response)
}
if (!validatedBreadcrumbsData.success) { const validatedBreadcrumbsData =
throw internalServerError(validatedBreadcrumbsData.error) validateBreadcrumbsContentstackSchema.safeParse(response.data)
}
const parentBreadcrumbs = if (!validatedBreadcrumbsData.success) {
validatedBreadcrumbsData.data.all_account_page.items[0].web.breadcrumbs.parentsConnection.edges.map( throw internalServerError(validatedBreadcrumbsData.error)
}
const parentBreadcrumbs =
validatedBreadcrumbsData.data.all_page.items[0].web.breadcrumbs.parentsConnection.edges.map(
(breadcrumb) => {
return {
href: removeMultipleSlashes(
`/${breadcrumb.node.system.locale}/${breadcrumb.node.url}`
),
title: breadcrumb.node.breadcrumbs.title,
uid: breadcrumb.node.system.uid,
}
}
)
const pageBreadcrumb = validatedBreadcrumbsData.data.all_page.items.map(
(breadcrumb) => { (breadcrumb) => {
return { return {
href: removeMultipleSlashes( title: breadcrumb.web.breadcrumbs.title,
`/${breadcrumb.node.system.locale}/${breadcrumb.node.url}` uid: breadcrumb.system.uid,
),
title: breadcrumb.node.breadcrumbs.title,
uid: breadcrumb.node.system.uid,
} }
} }
) )
const pageBreadcrumb = const breadcrumbs = [
validatedBreadcrumbsData.data.all_account_page.items.map((breadcrumb) => { homeBreadcrumbs[ctx.lang],
return { parentBreadcrumbs,
title: breadcrumb.web.breadcrumbs.title, pageBreadcrumb,
uid: breadcrumb.system.uid, ].flat()
}
})
const breadcrumbs = [ const validatedBreadcrumbs = getBreadcrumbsSchema.safeParse(breadcrumbs)
homeBreadcrumbs[ctx.lang], if (!validatedBreadcrumbs.success) {
parentBreadcrumbs, throw internalServerError(validatedBreadcrumbs.error)
pageBreadcrumb,
].flat()
const validatedBreadcrumbs = getBreadcrumbsSchema.safeParse(breadcrumbs)
if (!validatedBreadcrumbs.success) {
throw internalServerError(validatedBreadcrumbs.error)
}
return validatedBreadcrumbs.data
}),
getLoyaltyPage: contentstackProcedure.query(async ({ ctx }) => {
const refsResponse = await request<GetLoyaltyPageBreadcrumbsRefsData>(
GetLoyaltyPageBreadcrumbsRefs,
{ locale: ctx.lang, url: ctx.pathname },
{
next: {
tags: [generateRefsResponseTag(ctx.lang, ctx.pathname, affix)],
},
} }
)
if (!refsResponse.data) { return validatedBreadcrumbs.data
throw notFound(refsResponse) }),
}
const validatedRefsData =
validateBreadcrumbsRefsContentstackSchemaLoyaltyPage.safeParse(
refsResponse.data
)
if (!validatedRefsData.success) {
throw internalServerError(validatedRefsData.error)
}
const connections = getConnectionsLoyaltyPage(validatedRefsData.data)
const tags = generateTags(ctx.lang, connections)
const page = validatedRefsData.data.all_loyalty_page.items[0]
tags.push(generateTag(ctx.lang, page.system.uid, affix))
const response = await request<GetLoyaltyPageBreadcrumbsData>(
GetLoyaltyPageBreadcrumbs,
{ locale: ctx.lang, url: ctx.pathname },
{ next: { tags } }
)
if (!response.data) {
throw notFound(response)
}
const validatedBreadcrumbsData =
validateBreadcrumbsContentstackSchemaLoyaltyPage.safeParse(response.data)
if (!validatedBreadcrumbsData.success) {
throw internalServerError(validatedBreadcrumbsData.error)
}
const parentBreadcrumbs =
validatedBreadcrumbsData.data.all_loyalty_page.items[0].web.breadcrumbs.parentsConnection.edges.map(
(breadcrumb) => {
return {
href: removeMultipleSlashes(
`/${breadcrumb.node.system.locale}/${breadcrumb.node.url}`
),
title: breadcrumb.node.breadcrumbs.title,
uid: breadcrumb.node.system.uid,
}
}
)
const pageBreadcrumb =
validatedBreadcrumbsData.data.all_loyalty_page.items.map((breadcrumb) => {
return {
title: breadcrumb.web.breadcrumbs.title,
uid: breadcrumb.system.uid,
}
})
const breadcrumbs = [
homeBreadcrumbs[ctx.lang],
parentBreadcrumbs,
pageBreadcrumb,
].flat()
const validatedBreadcrumbs = getBreadcrumbsSchema.safeParse(breadcrumbs)
if (!validatedBreadcrumbs.success) {
throw internalServerError(validatedBreadcrumbs.error)
}
return validatedBreadcrumbs.data
}),
}) })

View File

@@ -1,27 +1,12 @@
import { Lang } from "@/constants/languages" import { Lang } from "@/constants/languages"
import type { import type { GetMyPagesBreadcrumbsRefsData } from "@/types/requests/myPages/breadcrumbs"
GetAccountPageBreadcrumbsRefsData,
GetLoyaltyPageBreadcrumbsRefsData,
} from "@/types/requests/myPages/breadcrumbs"
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"
export function getConnectionsAccountPage( export function getConnections(refs: GetMyPagesBreadcrumbsRefsData) {
refs: GetAccountPageBreadcrumbsRefsData
) {
const connections: Edges<NodeRefs>[] = [] const connections: Edges<NodeRefs>[] = []
refs.all_account_page.items.forEach((ref) => { refs.all_page.items.forEach((ref) => {
connections.push(ref.web.breadcrumbs.parentsConnection)
})
return connections
}
export function getConnectionsLoyaltyPage(
refs: GetLoyaltyPageBreadcrumbsRefsData
) {
const connections: Edges<NodeRefs>[] = []
refs.all_loyalty_page.items.forEach((ref) => {
connections.push(ref.web.breadcrumbs.parentsConnection) connections.push(ref.web.breadcrumbs.parentsConnection)
}) })
return connections return connections

View File

@@ -27,12 +27,8 @@ interface MyPagesBreadcrumbs {
interface AllPageResponse extends AllRequestResponse<MyPagesBreadcrumbs> {} interface AllPageResponse extends AllRequestResponse<MyPagesBreadcrumbs> {}
export interface GetAccountPageBreadcrumbsData { export interface GetMyPagesBreadcrumbsData {
all_account_page: AllPageResponse all_page: AllPageResponse
}
export interface GetLoyaltyPageBreadcrumbsData {
all_loyalty_page: AllPageResponse
} }
interface MyPagesBreadcrumbRefs extends System { interface MyPagesBreadcrumbRefs extends System {
@@ -46,10 +42,6 @@ interface MyPagesBreadcrumbRefs extends System {
interface AllPageRefsResponse interface AllPageRefsResponse
extends AllRequestResponse<MyPagesBreadcrumbRefs> {} extends AllRequestResponse<MyPagesBreadcrumbRefs> {}
export interface GetAccountPageBreadcrumbsRefsData { export interface GetMyPagesBreadcrumbsRefsData {
all_account_page: AllPageRefsResponse all_page: AllPageRefsResponse
}
export interface GetLoyaltyPageBreadcrumbsRefsData {
all_loyalty_page: AllPageRefsResponse
} }