feat(WEB-250): overview hero final ui

This commit is contained in:
Simon Emanuelsson
2024-05-24 10:13:24 +02:00
parent f884383c3c
commit 16b817f469
164 changed files with 6262 additions and 990 deletions

View File

@@ -37,6 +37,8 @@ const breadcrumbsRefsItems = z.object({
),
})
export type BreadcrumbsRefsItems = z.infer<typeof breadcrumbsRefsItems>
export const validateMyPagesBreadcrumbsRefsContentstackSchema = z.object({
all_account_page: breadcrumbsRefsItems,
})
@@ -45,37 +47,39 @@ export const validateLoyaltyPageBreadcrumbsRefsContentstackSchema = z.object({
all_loyalty_page: breadcrumbsRefsItems,
})
const breadcrumbsItems = z.object({
items: z.array(
z.object({
web: z.object({
breadcrumbs: z.object({
title: z.string(),
parentsConnection: z.object({
edges: z.array(
z.object({
node: z.object({
web: z.object({
breadcrumbs: z.object({
title: z.string(),
}),
}),
system: z.object({
locale: z.nativeEnum(Lang),
uid: z.string(),
}),
url: z.string(),
const page = z.object({
web: z.object({
breadcrumbs: z.object({
title: z.string(),
parentsConnection: z.object({
edges: z.array(
z.object({
node: z.object({
web: z.object({
breadcrumbs: z.object({
title: z.string(),
}),
})
),
}),
}),
}),
system: z.object({
locale: z.nativeEnum(Lang),
uid: z.string(),
}),
url: z.string(),
}),
})
),
}),
system: z.object({
uid: z.string(),
}),
})
),
}),
}),
system: z.object({
uid: z.string(),
}),
})
export type Page = z.infer<typeof page>
const breadcrumbsItems = z.object({
items: z.array(page),
})
export const validateMyPagesBreadcrumbsContentstackSchema = z.object({

View File

@@ -1,4 +1,3 @@
import { Lang } from "@/constants/languages"
import {
GetLoyaltyPageBreadcrumbs,
GetLoyaltyPageBreadcrumbsRefs,
@@ -7,25 +6,22 @@ import {
GetMyPagesBreadcrumbs,
GetMyPagesBreadcrumbsRefs,
} from "@/lib/graphql/Query/BreadcrumbsMyPages.graphql"
import { request } from "@/lib/graphql/request"
import { internalServerError, notFound } from "@/server/errors/trpc"
import { internalServerError } from "@/server/errors/trpc"
import { contentstackProcedure, router } from "@/server/trpc"
import {
generateRefsResponseTag,
generateTag,
generateTags,
} from "@/utils/generateTag"
import { removeMultipleSlashes } from "@/utils/url"
import {
getBreadcrumbsSchema,
validateLoyaltyPageBreadcrumbsContentstackSchema,
validateLoyaltyPageBreadcrumbsRefsContentstackSchema,
validateMyPagesBreadcrumbsContentstackSchema,
validateMyPagesBreadcrumbsRefsContentstackSchema,
} from "./output"
import { affix, getConnections, homeBreadcrumbs } from "./utils"
import {
getBreadcrumbs,
getRefsResponse,
getResponse,
getTags,
Variables,
} from "./utils"
import type {
GetLoyaltyPageBreadcrumbsData,
@@ -35,23 +31,11 @@ import type {
} from "@/types/requests/myPages/breadcrumbs"
import { PageTypeEnum } from "@/types/requests/pageType"
type fetchBreadcrumbs = {
lang: Lang
pathname: string
}
async function getLoyaltyPageBreadcrumbs({ lang, pathname }: fetchBreadcrumbs) {
const refsResponse = await request<GetLoyaltyPageBreadcrumbsRefsData>(
async function getLoyaltyPageBreadcrumbs(variables: Variables) {
const refsResponse = await getRefsResponse<GetLoyaltyPageBreadcrumbsRefsData>(
GetLoyaltyPageBreadcrumbsRefs,
{ locale: lang, url: pathname },
{
next: {
tags: [generateRefsResponseTag(lang, pathname, affix)],
},
}
variables
)
if (!refsResponse.data) {
throw notFound(refsResponse)
}
const validatedRefsData =
validateLoyaltyPageBreadcrumbsRefsContentstackSchema.safeParse(
@@ -62,19 +46,13 @@ async function getLoyaltyPageBreadcrumbs({ lang, pathname }: fetchBreadcrumbs) {
throw internalServerError(validatedRefsData.error)
}
const connections = getConnections(validatedRefsData.data.all_loyalty_page)
const tags = generateTags(lang, connections)
const page = validatedRefsData.data.all_loyalty_page.items[0]
tags.push(generateTag(lang, page.system.uid, affix))
const tags = getTags(validatedRefsData.data.all_loyalty_page, variables)
const response = await request<GetLoyaltyPageBreadcrumbsData>(
const response = await getResponse<GetLoyaltyPageBreadcrumbsData>(
GetLoyaltyPageBreadcrumbs,
{ locale: lang, url: pathname },
{ next: { tags } }
variables,
tags
)
if (!response.data) {
throw notFound(response)
}
const validatedBreadcrumbsData =
validateLoyaltyPageBreadcrumbsContentstackSchema.safeParse(response.data)
@@ -83,43 +61,17 @@ async function getLoyaltyPageBreadcrumbs({ lang, pathname }: fetchBreadcrumbs) {
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.web.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,
}
})
return [pageBreadcrumb, parentBreadcrumbs]
return getBreadcrumbs(
validatedBreadcrumbsData.data.all_loyalty_page.items[0],
variables.locale
)
}
async function getMyPagesBreadcrumbs({ lang, pathname }: fetchBreadcrumbs) {
const refsResponse = await request<GetMyPagesBreadcrumbsRefsData>(
async function getMyPagesBreadcrumbs(variables: Variables) {
const refsResponse = await getRefsResponse<GetMyPagesBreadcrumbsRefsData>(
GetMyPagesBreadcrumbsRefs,
{ locale: lang, url: pathname },
{
next: {
tags: [generateRefsResponseTag(lang, pathname, affix)],
},
}
variables
)
if (!refsResponse.data) {
throw notFound(refsResponse)
}
const validatedRefsData =
validateMyPagesBreadcrumbsRefsContentstackSchema.safeParse(
@@ -129,19 +81,12 @@ async function getMyPagesBreadcrumbs({ lang, pathname }: fetchBreadcrumbs) {
throw internalServerError(validatedRefsData.error)
}
const connections = getConnections(validatedRefsData.data.all_account_page)
const tags = generateTags(lang, connections)
const page = validatedRefsData.data.all_account_page.items[0]
tags.push(generateTag(lang, page.system.uid, affix))
const response = await request<GetMyPagesBreadcrumbsData>(
const tags = getTags(validatedRefsData.data.all_account_page, variables)
const response = await getResponse<GetMyPagesBreadcrumbsData>(
GetMyPagesBreadcrumbs,
{ locale: lang, url: pathname },
{ next: { tags } }
variables,
tags
)
if (!response.data) {
throw notFound(response)
}
const validatedBreadcrumbsData =
validateMyPagesBreadcrumbsContentstackSchema.safeParse(response.data)
@@ -150,62 +95,26 @@ async function getMyPagesBreadcrumbs({ lang, pathname }: fetchBreadcrumbs) {
throw internalServerError(validatedBreadcrumbsData.error)
}
const parentBreadcrumbs =
validatedBreadcrumbsData.data.all_account_page.items[0].web.breadcrumbs.parentsConnection.edges.map(
(breadcrumb) => {
return {
href: removeMultipleSlashes(
`/${breadcrumb.node.system.locale}/${breadcrumb.node.url}`
),
title: breadcrumb.node.web.breadcrumbs.title,
uid: breadcrumb.node.system.uid,
}
}
)
const pageBreadcrumb =
validatedBreadcrumbsData.data.all_account_page.items.map((breadcrumb) => {
return {
title: breadcrumb.web.breadcrumbs.title,
uid: breadcrumb.system.uid,
}
})
return [pageBreadcrumb, parentBreadcrumbs]
return getBreadcrumbs(
validatedBreadcrumbsData.data.all_account_page.items[0],
variables.locale
)
}
export const breadcrumbsQueryRouter = router({
get: contentstackProcedure.query(async ({ ctx }) => {
let pageBreadcrumb, parentBreadcrumbs
const variables = {
locale: ctx.lang,
url: ctx.pathname,
}
switch (ctx.contentType) {
case PageTypeEnum.accountPage:
;[pageBreadcrumb, parentBreadcrumbs] = await getMyPagesBreadcrumbs({
lang: ctx.lang,
pathname: ctx.pathname,
})
break
return await getMyPagesBreadcrumbs(variables)
case PageTypeEnum.loyaltyPage:
;[pageBreadcrumb, parentBreadcrumbs] = await getLoyaltyPageBreadcrumbs({
lang: ctx.lang,
pathname: ctx.pathname,
})
break
return await getLoyaltyPageBreadcrumbs(variables)
default:
return []
}
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,4 +1,15 @@
import { Lang } from "@/constants/languages"
import { request } from "@/lib/graphql/request"
import { internalServerError, notFound } from "@/server/errors/trpc"
import {
generateRefsResponseTag,
generateTag,
generateTags,
} from "@/utils/generateTag"
import { removeMultipleSlashes } from "@/utils/url"
import { BreadcrumbsRefsItems, getBreadcrumbsSchema,Page } from "./output"
import type { GetBreadcrumbsItems } from "@/types/requests/myPages/breadcrumbs"
import type { Edges } from "@/types/requests/utils/edges"
@@ -47,3 +58,73 @@ export const homeBreadcrumbs = {
uid: "sv",
},
}
export type Variables = {
locale: Lang
url: string
}
export async function getRefsResponse<T>(query: string, variables: Variables) {
const refsResponse = await request<T>(query, variables, {
next: {
tags: [generateRefsResponseTag(variables.locale, variables.url, affix)],
},
})
if (!refsResponse.data) {
throw notFound(refsResponse)
}
return refsResponse
}
export function getTags(page: BreadcrumbsRefsItems, variables: Variables) {
const connections = getConnections(page)
const tags = generateTags(variables.locale, connections)
tags.push(generateTag(variables.locale, page.items[0].system.uid, affix))
return tags
}
export async function getResponse<T>(
query: string,
variables: Variables,
tags: string[]
) {
const response = await request<T>(query, variables, { next: { tags } })
if (!response.data) {
throw notFound(response)
}
return response
}
export function getBreadcrumbs(page: Page, lang: Lang) {
const parentBreadcrumbs = page.web.breadcrumbs.parentsConnection.edges.map(
(breadcrumb) => {
return {
href: removeMultipleSlashes(
`/${breadcrumb.node.system.locale}/${breadcrumb.node.url}`
),
title: breadcrumb.node.web.breadcrumbs.title,
uid: breadcrumb.node.system.uid,
}
}
)
const pageBreadcrumb = {
title: page.web.breadcrumbs.title,
uid: page.system.uid,
}
const breadcrumbs = [
homeBreadcrumbs[lang],
parentBreadcrumbs,
pageBreadcrumb,
].flat()
const validatedBreadcrumbs = getBreadcrumbsSchema.safeParse(breadcrumbs)
if (!validatedBreadcrumbs.success) {
throw internalServerError(validatedBreadcrumbs.error)
}
return validatedBreadcrumbs.data
}

View File

@@ -2,8 +2,8 @@ import { z } from "zod"
export const staysInput = z
.object({
cursor: z.string().optional(),
limit: z.number().min(0).default(6),
cursor: z.number().nullish(),
})
.default({})

View File

@@ -84,7 +84,7 @@ export const userQueryRouter = router({
params.set("limit", limit.toString())
if (cursor) {
params.set("offset", cursor.toString())
params.set("offset", cursor)
}
const apiResponse = await api.get(
@@ -111,6 +111,7 @@ export const userQueryRouter = router({
}
const apiJson = await apiResponse.json()
const verifiedData = getStaysSchema.safeParse(apiJson)
if (!verifiedData.success) {
throw internalServerError(verifiedData.error)
@@ -118,7 +119,7 @@ export const userQueryRouter = router({
const nextCursor =
verifiedData.data.links &&
verifiedData.data.links.offset < verifiedData.data.links.totalCount
verifiedData.data.links.offset < verifiedData.data.links.totalCount
? verifiedData.data.links.offset
: undefined
@@ -137,7 +138,7 @@ export const userQueryRouter = router({
params.set("limit", limit.toString())
if (cursor) {
params.set("offset", cursor.toString())
params.set("offset", cursor)
}
const apiResponse = await api.get(
@@ -171,7 +172,7 @@ export const userQueryRouter = router({
const nextCursor =
verifiedData.data.links &&
verifiedData.data.links.offset < verifiedData.data.links.totalCount
verifiedData.data.links.offset < verifiedData.data.links.totalCount
? verifiedData.data.links.offset
: undefined
@@ -235,7 +236,7 @@ export const userQueryRouter = router({
const nextCursor =
verifiedData.data.links &&
verifiedData.data.links.offset < verifiedData.data.links.totalCount
verifiedData.data.links.offset < verifiedData.data.links.totalCount
? verifiedData.data.links.offset
: undefined