feat(WEB-131): add loyalty page
This commit is contained in:
@@ -1,7 +1,7 @@
|
||||
import CurrentBenefitsBlock from "@/components/MyPages/Blocks/Benefits/CurrentLevel"
|
||||
import NextLevelBenefitsBlock from "@/components/MyPages/Blocks/Benefits/NextLevel"
|
||||
import Shortcuts from "@/components/MyPages/Blocks/Shortcuts"
|
||||
import Title from "@/components/MyPages/Title"
|
||||
import Title from "@/components/Title"
|
||||
|
||||
import { shortcuts } from "./_constants"
|
||||
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
.layout {
|
||||
--max-width: 101.4rem;
|
||||
--header-height: 4.5rem;
|
||||
|
||||
display: grid;
|
||||
font-family: var(--ff-fira-sans);
|
||||
grid-template-rows: var(--header-height) auto 1fr;
|
||||
min-height: 100dvh;
|
||||
}
|
||||
21
app/[lang]/(live)/(public)/loyalty-page/layout.tsx
Normal file
21
app/[lang]/(live)/(public)/loyalty-page/layout.tsx
Normal file
@@ -0,0 +1,21 @@
|
||||
import { firaMono, firaSans } from "@/app/[lang]/(live)/fonts"
|
||||
|
||||
import Header from "@/components/MyPages/Header"
|
||||
|
||||
import styles from "./layout.module.css"
|
||||
|
||||
import type { MyPagesLayoutProps } from "@/types/components/myPages/layout"
|
||||
|
||||
export default async function LoyaltyPagesLayout({
|
||||
children,
|
||||
params,
|
||||
}: React.PropsWithChildren<MyPagesLayoutProps>) {
|
||||
return (
|
||||
<div
|
||||
className={`${firaMono.variable} ${firaSans.variable} ${styles.layout}`}
|
||||
>
|
||||
<Header lang={params.lang} />
|
||||
{children}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
18
app/[lang]/(live)/(public)/loyalty-page/page.module.css
Normal file
18
app/[lang]/(live)/(public)/loyalty-page/page.module.css
Normal file
@@ -0,0 +1,18 @@
|
||||
.content {
|
||||
display: grid;
|
||||
padding-bottom: 7.7rem;
|
||||
padding-left: 0;
|
||||
padding-right: 0;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
@media screen and (min-width: 950px) {
|
||||
.content {
|
||||
gap: 10rem;
|
||||
grid-template-columns: 25rem 1fr;
|
||||
padding-bottom: 17.5rem;
|
||||
padding-left: 2.4rem;
|
||||
padding-right: 2.4rem;
|
||||
padding-top: 5.8rem;
|
||||
}
|
||||
}
|
||||
40
app/[lang]/(live)/(public)/loyalty-page/page.tsx
Normal file
40
app/[lang]/(live)/(public)/loyalty-page/page.tsx
Normal file
@@ -0,0 +1,40 @@
|
||||
import Title from "@/components/Title"
|
||||
import MaxWidth from "@/components/MaxWidth"
|
||||
|
||||
import { serverClient } from "@/lib/trpc/server"
|
||||
import { LangParams, PageArgs, UriParams } from "@/types/params"
|
||||
import { notFound } from "next/navigation"
|
||||
|
||||
import styles from "./page.module.css"
|
||||
|
||||
export default async function LoyaltyPage({
|
||||
params,
|
||||
searchParams,
|
||||
}: PageArgs<LangParams, UriParams>) {
|
||||
try {
|
||||
if (!searchParams.uri) {
|
||||
throw new Error("Bad URI")
|
||||
}
|
||||
|
||||
const loyaltyPage = await serverClient().contentstack.loyaltyPage.get({
|
||||
uri: searchParams.uri,
|
||||
lang: params.lang,
|
||||
})
|
||||
|
||||
return (
|
||||
<main className={styles.content}>
|
||||
<aside>{loyaltyPage.sidebar ? <></> : null}</aside>
|
||||
<MaxWidth>
|
||||
<Title>{loyaltyPage.title}</Title>
|
||||
<Content content={loyaltyPage.content} />
|
||||
</MaxWidth>
|
||||
</main>
|
||||
)
|
||||
} catch (err) {
|
||||
return notFound()
|
||||
}
|
||||
}
|
||||
|
||||
function Content(content: any) {
|
||||
return <></>
|
||||
}
|
||||
@@ -2,7 +2,7 @@ import Link from "next/link"
|
||||
|
||||
import { serverClient } from "@/lib/trpc/server"
|
||||
|
||||
import Title from "@/components/MyPages/Title"
|
||||
import Title from "@/components/Title"
|
||||
|
||||
import styles from "./current.module.css"
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@ import { Lock } from "react-feather"
|
||||
|
||||
import { serverClient } from "@/lib/trpc/server"
|
||||
|
||||
import Title from "@/components/MyPages/Title"
|
||||
import Title from "@/components/Title"
|
||||
import Button from "@/components/TempDesignSystem/Button"
|
||||
|
||||
import styles from "./next.module.css"
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import Image from "@/components/Image"
|
||||
import Title from "@/components/MyPages/Title"
|
||||
import Title from "@/components/Title"
|
||||
|
||||
import styles from "./challenges.module.css"
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import Title from "@/components/MyPages/Title"
|
||||
import Title from "@/components/Title"
|
||||
|
||||
import Friend from "./Friend"
|
||||
import Stats from "./Stats"
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import Link from "next/link"
|
||||
|
||||
import Image from "@/components/Image"
|
||||
import Title from "@/components/MyPages/Title"
|
||||
import Title from "@/components/Title"
|
||||
|
||||
import styles from "./shortcuts.module.css"
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { dt } from "@/lib/dt"
|
||||
|
||||
import Image from "@/components/Image"
|
||||
import Title from "@/components/MyPages/Title"
|
||||
import Title from "@/components/Title"
|
||||
|
||||
import styles from "./stay.module.css"
|
||||
|
||||
|
||||
@@ -4,9 +4,10 @@ import { LogOut } from "react-feather"
|
||||
import { GetNavigationMyPages } from "@/lib/graphql/Query/NavigationMyPages.graphql"
|
||||
import { request } from "@/lib/graphql/request"
|
||||
|
||||
import Title from "@/components/Title"
|
||||
import Link from "@/components/TempDesignSystem/Link"
|
||||
|
||||
import Title from "../Title"
|
||||
|
||||
import { mapMenuItems } from "./helpers"
|
||||
|
||||
import styles from "./sidebar.module.css"
|
||||
|
||||
@@ -82,4 +82,4 @@
|
||||
font-size: var(--typography-Title5-Desktop-fontSize);
|
||||
line-height: var(--typography-Title5-Desktop-lineHeight);
|
||||
}
|
||||
}
|
||||
}
|
||||
140
lib/graphql/Query/LoyaltyPage.graphql
Normal file
140
lib/graphql/Query/LoyaltyPage.graphql
Normal file
@@ -0,0 +1,140 @@
|
||||
query GetLoyaltyPage($locale: String!, $url: String!) {
|
||||
all_loyalty_page(where: { url: $url, locale: $locale }) {
|
||||
items {
|
||||
content {
|
||||
... on LoyaltyPageContentLoyaltyLevels {
|
||||
__typename
|
||||
loyalty_levels {
|
||||
heading
|
||||
sub_heading
|
||||
level_card {
|
||||
loyalty_level
|
||||
}
|
||||
}
|
||||
}
|
||||
... on LoyaltyPageContentCardGrid {
|
||||
__typename
|
||||
card_grid {
|
||||
heading
|
||||
subheading
|
||||
cards {
|
||||
referenceConnection {
|
||||
edges {
|
||||
node {
|
||||
... on LoyaltyPage {
|
||||
url
|
||||
}
|
||||
... on ContentPage {
|
||||
web {
|
||||
url
|
||||
}
|
||||
}
|
||||
... on AccountPage {
|
||||
url
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
heading
|
||||
subheading
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
title
|
||||
sidebar {
|
||||
... on LoyaltyPageSidebarLoyaltyJoinContact {
|
||||
__typename
|
||||
loyalty_join_contact {
|
||||
title
|
||||
contact {
|
||||
... on LoyaltyPageSidebarLoyaltyJoinContactBlockContactContact {
|
||||
__typename
|
||||
contact {
|
||||
contact_fields
|
||||
}
|
||||
}
|
||||
}
|
||||
login_button_text
|
||||
body {
|
||||
json
|
||||
embedded_itemsConnection {
|
||||
edges {
|
||||
node {
|
||||
... on SysAsset {
|
||||
title
|
||||
dimension {
|
||||
width
|
||||
height
|
||||
}
|
||||
file_size
|
||||
filename
|
||||
url
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
... on LoyaltyPageSidebarContent {
|
||||
__typename
|
||||
content {
|
||||
content {
|
||||
json
|
||||
embedded_itemsConnection {
|
||||
edges {
|
||||
node {
|
||||
... on SysAsset {
|
||||
title
|
||||
url
|
||||
file_size
|
||||
filename
|
||||
dimension {
|
||||
width
|
||||
height
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
web {
|
||||
breadcrumbs {
|
||||
title
|
||||
parents {
|
||||
href
|
||||
title
|
||||
}
|
||||
}
|
||||
original_url
|
||||
seo_metadata {
|
||||
description
|
||||
title
|
||||
imageConnection {
|
||||
edges {
|
||||
node {
|
||||
file_size
|
||||
filename
|
||||
dimension {
|
||||
height
|
||||
width
|
||||
}
|
||||
url
|
||||
title
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
system {
|
||||
uid
|
||||
created_at
|
||||
updated_at
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,7 +1,9 @@
|
||||
import { router } from "@/server/trpc"
|
||||
|
||||
import { breadcrumbsRouter } from "./breadcrumbs"
|
||||
import { loyaltyPageRouter } from "./loyaltyPage"
|
||||
|
||||
export const contentstackRouter = router({
|
||||
breadcrumbs: breadcrumbsRouter,
|
||||
loyaltyPage: loyaltyPageRouter,
|
||||
})
|
||||
|
||||
5
server/routers/contentstack/loyaltyPage/index.tsx
Normal file
5
server/routers/contentstack/loyaltyPage/index.tsx
Normal file
@@ -0,0 +1,5 @@
|
||||
import { mergeRouters } from "@/server/trpc"
|
||||
|
||||
import { loyaltyPageQueryRouter } from "./query"
|
||||
|
||||
export const loyaltyPageRouter = mergeRouters(loyaltyPageQueryRouter)
|
||||
33
server/routers/contentstack/loyaltyPage/query.ts
Normal file
33
server/routers/contentstack/loyaltyPage/query.ts
Normal file
@@ -0,0 +1,33 @@
|
||||
import { z } from "zod"
|
||||
|
||||
import { badRequestError } from "@/server/errors/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 type { GetLoyaltyPageData } from "@/types/requests/loyaltyPage"
|
||||
|
||||
export const loyaltyPageQueryRouter = router({
|
||||
get: publicProcedure
|
||||
.input(z.object({ uri: z.string(), lang: z.nativeEnum(Lang) }))
|
||||
.query(async ({ input }) => {
|
||||
const loyaltyPage = await request<GetLoyaltyPageData>(
|
||||
GetLoyaltyPage,
|
||||
{
|
||||
locale: input.lang,
|
||||
url: input.uri,
|
||||
},
|
||||
{
|
||||
tags: [`${input.uri}-${input.lang}`],
|
||||
}
|
||||
)
|
||||
|
||||
if (loyaltyPage.data && loyaltyPage.data.all_loyalty_page.items.length) {
|
||||
return loyaltyPage.data.all_loyalty_page.items[0]
|
||||
}
|
||||
|
||||
throw badRequestError()
|
||||
}),
|
||||
})
|
||||
@@ -1,10 +1,12 @@
|
||||
import { headingVariants } from "@/components/MyPages/Title/variants"
|
||||
import { headingVariants } from "@/components/Title/variants"
|
||||
|
||||
import type { VariantProps } from "class-variance-authority"
|
||||
|
||||
type HeadingLevel = "h1" | "h2" | "h3" | "h4" | "h5" | "h6"
|
||||
|
||||
export interface HeadingProps extends React.HTMLAttributes<HTMLHeadingElement>, VariantProps<typeof headingVariants> {
|
||||
export interface HeadingProps
|
||||
extends React.HTMLAttributes<HTMLHeadingElement>,
|
||||
VariantProps<typeof headingVariants> {
|
||||
as?: HeadingLevel
|
||||
level?: HeadingLevel
|
||||
uppercase?: boolean
|
||||
|
||||
104
types/requests/loyaltyPage.ts
Normal file
104
types/requests/loyaltyPage.ts
Normal file
@@ -0,0 +1,104 @@
|
||||
import type { AllRequestResponse } from "./utils/all"
|
||||
import type { Typename } from "./utils/typename"
|
||||
|
||||
enum SidebarTypenameEnum {
|
||||
LoyaltyPageSidebarLoyaltyJoinContact = "LoyaltyPageSidebarLoyaltyJoinContact",
|
||||
LoyaltyPageSidebarContent = "LoyaltyPageSidebarContent",
|
||||
}
|
||||
|
||||
type SidebarContent = {}
|
||||
|
||||
type JoinContact = {}
|
||||
|
||||
export type Sidebar =
|
||||
| Typename<SidebarContent, SidebarTypenameEnum.LoyaltyPageSidebarContent>
|
||||
| Typename<
|
||||
JoinContact,
|
||||
SidebarTypenameEnum.LoyaltyPageSidebarLoyaltyJoinContact
|
||||
>
|
||||
|
||||
enum ContentBlocks {
|
||||
LoyaltyPageContentLoyaltyLevels = "LoyaltyPageContentLoyaltyLevels",
|
||||
LoyaltyPageContentCardGrid = "LoyaltyPageContentCardGrid",
|
||||
}
|
||||
|
||||
enum LinkedPageConnection {
|
||||
LoyaltyPage = "LoyaltyPage",
|
||||
ContentPage = "ContentPage",
|
||||
AccountPage = "AccountPage",
|
||||
}
|
||||
|
||||
type ContentPageLink = {
|
||||
web: { url: string }
|
||||
}
|
||||
type LoyaltyPageLink = {
|
||||
url: string
|
||||
}
|
||||
|
||||
type AccountPageLink = {
|
||||
url: string
|
||||
}
|
||||
|
||||
type LinkedPage =
|
||||
| Typename<ContentPageLink, LinkedPageConnection.ContentPage>
|
||||
| Typename<LoyaltyPageLink, ContentBlocks.LoyaltyPageContentLoyaltyLevels>
|
||||
| Typename<AccountPageLink, ContentBlocks.LoyaltyPageContentLoyaltyLevels>
|
||||
|
||||
type CardGrid = {
|
||||
card_grid: {
|
||||
heading: string
|
||||
subheading: string
|
||||
cards: {
|
||||
referenceConnection: {
|
||||
edges: {
|
||||
node: LinkedPage
|
||||
}
|
||||
}
|
||||
heading: string
|
||||
subheading: string
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
type LoyaltyLevels = {
|
||||
loyalty_levels: {
|
||||
heading: string
|
||||
sub_heading?: string
|
||||
level_card: {
|
||||
loyalty_level: number
|
||||
}[]
|
||||
}
|
||||
}
|
||||
|
||||
export type Content =
|
||||
| Typename<CardGrid, ContentBlocks.LoyaltyPageContentCardGrid>
|
||||
| Typename<LoyaltyLevels, ContentBlocks.LoyaltyPageContentLoyaltyLevels>
|
||||
|
||||
export type Breadcrumb = {
|
||||
href: string
|
||||
title: string
|
||||
}
|
||||
|
||||
export type Breadcrumbs = {
|
||||
parents: Breadcrumb[]
|
||||
title: string
|
||||
}
|
||||
|
||||
export type LoyaltyPage = {
|
||||
sidebar: Sidebar[]
|
||||
content: Content[]
|
||||
web: {
|
||||
breadcrumbs: Breadcrumbs
|
||||
}
|
||||
system: {
|
||||
created_at: string
|
||||
uid: string
|
||||
updated_at: string
|
||||
}
|
||||
title: string
|
||||
url: string
|
||||
}
|
||||
|
||||
export type GetLoyaltyPageData = {
|
||||
all_loyalty_page: AllRequestResponse<LoyaltyPage>
|
||||
}
|
||||
Reference in New Issue
Block a user