feat(WEB-131): add loyalty page
This commit is contained in:
@@ -1,7 +1,7 @@
|
|||||||
import CurrentBenefitsBlock from "@/components/MyPages/Blocks/Benefits/CurrentLevel"
|
import CurrentBenefitsBlock from "@/components/MyPages/Blocks/Benefits/CurrentLevel"
|
||||||
import NextLevelBenefitsBlock from "@/components/MyPages/Blocks/Benefits/NextLevel"
|
import NextLevelBenefitsBlock from "@/components/MyPages/Blocks/Benefits/NextLevel"
|
||||||
import Shortcuts from "@/components/MyPages/Blocks/Shortcuts"
|
import Shortcuts from "@/components/MyPages/Blocks/Shortcuts"
|
||||||
import Title from "@/components/MyPages/Title"
|
import Title from "@/components/Title"
|
||||||
|
|
||||||
import { shortcuts } from "./_constants"
|
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 { serverClient } from "@/lib/trpc/server"
|
||||||
|
|
||||||
import Title from "@/components/MyPages/Title"
|
import Title from "@/components/Title"
|
||||||
|
|
||||||
import styles from "./current.module.css"
|
import styles from "./current.module.css"
|
||||||
|
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ import { Lock } from "react-feather"
|
|||||||
|
|
||||||
import { serverClient } from "@/lib/trpc/server"
|
import { serverClient } from "@/lib/trpc/server"
|
||||||
|
|
||||||
import Title from "@/components/MyPages/Title"
|
import Title from "@/components/Title"
|
||||||
import Button from "@/components/TempDesignSystem/Button"
|
import Button from "@/components/TempDesignSystem/Button"
|
||||||
|
|
||||||
import styles from "./next.module.css"
|
import styles from "./next.module.css"
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import Image from "@/components/Image"
|
import Image from "@/components/Image"
|
||||||
import Title from "@/components/MyPages/Title"
|
import Title from "@/components/Title"
|
||||||
|
|
||||||
import styles from "./challenges.module.css"
|
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 Friend from "./Friend"
|
||||||
import Stats from "./Stats"
|
import Stats from "./Stats"
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import Link from "next/link"
|
import Link from "next/link"
|
||||||
|
|
||||||
import Image from "@/components/Image"
|
import Image from "@/components/Image"
|
||||||
import Title from "@/components/MyPages/Title"
|
import Title from "@/components/Title"
|
||||||
|
|
||||||
import styles from "./shortcuts.module.css"
|
import styles from "./shortcuts.module.css"
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import { dt } from "@/lib/dt"
|
import { dt } from "@/lib/dt"
|
||||||
|
|
||||||
import Image from "@/components/Image"
|
import Image from "@/components/Image"
|
||||||
import Title from "@/components/MyPages/Title"
|
import Title from "@/components/Title"
|
||||||
|
|
||||||
import styles from "./stay.module.css"
|
import styles from "./stay.module.css"
|
||||||
|
|
||||||
|
|||||||
@@ -4,9 +4,10 @@ import { LogOut } from "react-feather"
|
|||||||
import { GetNavigationMyPages } from "@/lib/graphql/Query/NavigationMyPages.graphql"
|
import { GetNavigationMyPages } from "@/lib/graphql/Query/NavigationMyPages.graphql"
|
||||||
import { request } from "@/lib/graphql/request"
|
import { request } from "@/lib/graphql/request"
|
||||||
|
|
||||||
|
import Title from "@/components/Title"
|
||||||
import Link from "@/components/TempDesignSystem/Link"
|
import Link from "@/components/TempDesignSystem/Link"
|
||||||
|
|
||||||
import Title from "../Title"
|
|
||||||
import { mapMenuItems } from "./helpers"
|
import { mapMenuItems } from "./helpers"
|
||||||
|
|
||||||
import styles from "./sidebar.module.css"
|
import styles from "./sidebar.module.css"
|
||||||
|
|||||||
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 { router } from "@/server/trpc"
|
||||||
|
|
||||||
import { breadcrumbsRouter } from "./breadcrumbs"
|
import { breadcrumbsRouter } from "./breadcrumbs"
|
||||||
|
import { loyaltyPageRouter } from "./loyaltyPage"
|
||||||
|
|
||||||
export const contentstackRouter = router({
|
export const contentstackRouter = router({
|
||||||
breadcrumbs: breadcrumbsRouter,
|
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"
|
import type { VariantProps } from "class-variance-authority"
|
||||||
|
|
||||||
type HeadingLevel = "h1" | "h2" | "h3" | "h4" | "h5" | "h6"
|
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
|
as?: HeadingLevel
|
||||||
level?: HeadingLevel
|
level?: HeadingLevel
|
||||||
uppercase?: boolean
|
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