feat: add JoinLoyalty component
This commit is contained in:
@@ -6,4 +6,5 @@
|
||||
font-family: var(--ff-fira-sans);
|
||||
grid-template-rows: var(--header-height) auto 1fr;
|
||||
min-height: 100dvh;
|
||||
background-color: var(--Brand-Coffee-Subtle);
|
||||
}
|
||||
|
||||
@@ -6,6 +6,13 @@
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.blocks {
|
||||
display: grid;
|
||||
gap: 4.2rem;
|
||||
padding-left: 2rem;
|
||||
padding-right: 2rem;
|
||||
}
|
||||
|
||||
@media screen and (min-width: 950px) {
|
||||
.content {
|
||||
gap: 10rem;
|
||||
@@ -15,4 +22,10 @@
|
||||
padding-right: 2.4rem;
|
||||
padding-top: 5.8rem;
|
||||
}
|
||||
|
||||
.blocks {
|
||||
gap: 6.4rem;
|
||||
padding-left: 0;
|
||||
padding-right: 0;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,6 +6,7 @@ import { LangParams, PageArgs, UriParams } from "@/types/params"
|
||||
import { notFound } from "next/navigation"
|
||||
|
||||
import styles from "./page.module.css"
|
||||
import Sidebar from "@/components/Loyalty/Sidebar"
|
||||
|
||||
export default async function LoyaltyPage({
|
||||
params,
|
||||
@@ -22,13 +23,19 @@ export default async function LoyaltyPage({
|
||||
})
|
||||
|
||||
return (
|
||||
<main className={styles.content}>
|
||||
<aside>{loyaltyPage.sidebar ? <></> : null}</aside>
|
||||
<MaxWidth>
|
||||
<Title>{loyaltyPage.title}</Title>
|
||||
<MaxWidth className={styles.content} tag="main">
|
||||
<aside>
|
||||
{loyaltyPage.sidebar
|
||||
? loyaltyPage.sidebar.map((block, i) => (
|
||||
<Sidebar key={i} block={block} />
|
||||
))
|
||||
: null}
|
||||
</aside>
|
||||
<section className={styles.blocks}>
|
||||
<Title as="h3">{loyaltyPage.title}</Title>
|
||||
<Content content={loyaltyPage.content} />
|
||||
</MaxWidth>
|
||||
</main>
|
||||
</section>
|
||||
</MaxWidth>
|
||||
)
|
||||
} catch (err) {
|
||||
return notFound()
|
||||
|
||||
@@ -29,6 +29,10 @@ function extractPossibleAttributes(attrs: Attributes) {
|
||||
props.className = attrs["class-name"]
|
||||
} else if (attrs.classname) {
|
||||
props.className = attrs.classname
|
||||
} else if (attrs?.style?.["text-align"]) {
|
||||
props.style = {
|
||||
textAlign: attrs?.style?.["text-align"],
|
||||
}
|
||||
}
|
||||
|
||||
return props
|
||||
@@ -250,6 +254,11 @@ export const renderOptions: RenderOptions = {
|
||||
const image = embeds?.[node?.attrs?.["asset-uid"]]
|
||||
if (image.node.__typename === EmbedEnum.SysAsset) {
|
||||
const alt = image?.node?.title ?? node.attrs.alt
|
||||
const alignment = node.attrs?.style?.["text-align"]
|
||||
? {
|
||||
alignSelf: node.attrs?.style?.["text-align"],
|
||||
}
|
||||
: {}
|
||||
return (
|
||||
<Image
|
||||
key={node.uid}
|
||||
@@ -258,6 +267,7 @@ export const renderOptions: RenderOptions = {
|
||||
height={image.node.dimension.height}
|
||||
src={image?.node?.url}
|
||||
width={image.node.dimension.width}
|
||||
style={alignment}
|
||||
/>
|
||||
)
|
||||
}
|
||||
|
||||
8
components/Loyalty/Sidebar/JoinLoyalty/Contact/index.tsx
Normal file
8
components/Loyalty/Sidebar/JoinLoyalty/Contact/index.tsx
Normal file
@@ -0,0 +1,8 @@
|
||||
import { Lang } from "@/constants/languages"
|
||||
import { serverClient } from "@/lib/trpc/server"
|
||||
|
||||
export default function Contact({ lang }: { lang: Lang }) {
|
||||
const data = serverClient().contentstack.contactConfig.get({ lang })
|
||||
|
||||
return <div></div>
|
||||
}
|
||||
37
components/Loyalty/Sidebar/JoinLoyalty/index.tsx
Normal file
37
components/Loyalty/Sidebar/JoinLoyalty/index.tsx
Normal file
@@ -0,0 +1,37 @@
|
||||
import Title from "@/components/Title"
|
||||
import JsonToHtml from "@/components/JsonToHtml"
|
||||
import Button from "@/components/TempDesignSystem/Button"
|
||||
import Link from "@/components/TempDesignSystem/Link"
|
||||
|
||||
import styles from "./joinLoyalty.module.css"
|
||||
|
||||
import type { JoinLoyaltyContact } from "@/types/requests/loyaltyPage"
|
||||
|
||||
export default function JoinLoyaltyContact({
|
||||
block,
|
||||
}: {
|
||||
block: JoinLoyaltyContact["join_loyalty_contact"]
|
||||
}) {
|
||||
return (
|
||||
<div className={styles.container}>
|
||||
<div className={styles.wrapper}>
|
||||
<JsonToHtml
|
||||
embeds={block.body.embedded_itemsConnection.edges}
|
||||
nodes={block.body.json.children}
|
||||
/>
|
||||
<Button intent="primary">
|
||||
<span>{block.login_button_text}</span>
|
||||
</Button>
|
||||
<div className={styles.linkContainer}>
|
||||
<Link href="/login" className={styles.logoutLink}>
|
||||
Already a friend? <br />
|
||||
Click here to log in
|
||||
</Link>
|
||||
</div>
|
||||
</div>
|
||||
<section className={styles.contactContainer}>
|
||||
<Title level="h5">Contact</Title>
|
||||
</section>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
.container {
|
||||
display: grid;
|
||||
font-weight: 600;
|
||||
background-color: var(--Base-Background-Elevated);
|
||||
border-radius: 32px 4px 4px 32px;
|
||||
}
|
||||
|
||||
.wrapper {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
flex-direction: column;
|
||||
gap: 2rem;
|
||||
padding: 4rem 2rem;
|
||||
}
|
||||
|
||||
.logoutLink {
|
||||
text-decoration: none;
|
||||
color: var(--some-black-color, #2e2e2e);
|
||||
font-size: 1.2rem;
|
||||
}
|
||||
|
||||
.linkContainer {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.contactContainer {
|
||||
display: none;
|
||||
}
|
||||
|
||||
@media screen and (min-width: 950px) {
|
||||
.wrapper {
|
||||
gap: 3rem;
|
||||
}
|
||||
|
||||
.contactContainer {
|
||||
display: block;
|
||||
border-top: 0.5px solid var(--Base-Border-Disabled);
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
padding: 3.4rem;
|
||||
}
|
||||
}
|
||||
20
components/Loyalty/Sidebar/index.tsx
Normal file
20
components/Loyalty/Sidebar/index.tsx
Normal file
@@ -0,0 +1,20 @@
|
||||
import JsonToHtml from "@/components/JsonToHtml"
|
||||
import JoinLoyaltyContact from "./JoinLoyalty"
|
||||
|
||||
import { Sidebar, SidebarTypenameEnum } from "@/types/requests/loyaltyPage"
|
||||
|
||||
export default function SidebarLoyalty({ block }: { block: Sidebar }) {
|
||||
switch (block.__typename) {
|
||||
case SidebarTypenameEnum.LoyaltyPageSidebarContent:
|
||||
return (
|
||||
<JsonToHtml
|
||||
embeds={block.content.embedded_itemsConnection.edges}
|
||||
nodes={block.content.json.children}
|
||||
/>
|
||||
)
|
||||
case SidebarTypenameEnum.LoyaltyPageSidebarJoinLoyaltyContact:
|
||||
return <JoinLoyaltyContact block={block.join_loyalty_contact} />
|
||||
default:
|
||||
return null
|
||||
}
|
||||
}
|
||||
37
lib/graphql/Query/ContactConfig.graphql
Normal file
37
lib/graphql/Query/ContactConfig.graphql
Normal file
@@ -0,0 +1,37 @@
|
||||
query GetContactConfig($locale: String!) {
|
||||
all_contact_config(locale: $locale) {
|
||||
items {
|
||||
email {
|
||||
address
|
||||
name
|
||||
}
|
||||
email_loyalty {
|
||||
address
|
||||
name
|
||||
}
|
||||
mailing_address {
|
||||
name
|
||||
street
|
||||
zip
|
||||
country
|
||||
city
|
||||
}
|
||||
phone {
|
||||
number
|
||||
name
|
||||
}
|
||||
phone_loyalty {
|
||||
name
|
||||
number
|
||||
}
|
||||
title
|
||||
visiting_address {
|
||||
country
|
||||
city
|
||||
street
|
||||
zip
|
||||
}
|
||||
}
|
||||
total
|
||||
}
|
||||
}
|
||||
@@ -1,3 +1,5 @@
|
||||
#import "../Fragments/Image.graphql"
|
||||
|
||||
query GetLoyaltyPage($locale: String!, $url: String!) {
|
||||
all_loyalty_page(where: { url: $url, locale: $locale }) {
|
||||
items {
|
||||
@@ -56,12 +58,12 @@ query GetLoyaltyPage($locale: String!, $url: String!) {
|
||||
}
|
||||
title
|
||||
sidebar {
|
||||
... on LoyaltyPageSidebarLoyaltyJoinContact {
|
||||
... on LoyaltyPageSidebarJoinLoyaltyContact {
|
||||
__typename
|
||||
loyalty_join_contact {
|
||||
join_loyalty_contact {
|
||||
title
|
||||
contact {
|
||||
... on LoyaltyPageSidebarLoyaltyJoinContactBlockContactContact {
|
||||
... on LoyaltyPageSidebarJoinLoyaltyContactBlockContactContact {
|
||||
__typename
|
||||
contact {
|
||||
contact_fields
|
||||
@@ -71,19 +73,11 @@ query GetLoyaltyPage($locale: String!, $url: String!) {
|
||||
login_button_text
|
||||
body {
|
||||
json
|
||||
embedded_itemsConnection {
|
||||
embedded_itemsConnection(limit: 30) {
|
||||
edges {
|
||||
node {
|
||||
... on SysAsset {
|
||||
title
|
||||
dimension {
|
||||
width
|
||||
height
|
||||
}
|
||||
file_size
|
||||
filename
|
||||
url
|
||||
}
|
||||
__typename
|
||||
...Image
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -98,16 +92,7 @@ query GetLoyaltyPage($locale: String!, $url: String!) {
|
||||
embedded_itemsConnection {
|
||||
edges {
|
||||
node {
|
||||
... on SysAsset {
|
||||
title
|
||||
url
|
||||
file_size
|
||||
filename
|
||||
dimension {
|
||||
width
|
||||
height
|
||||
}
|
||||
}
|
||||
...Image
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -123,7 +108,6 @@ query GetLoyaltyPage($locale: String!, $url: String!) {
|
||||
title
|
||||
}
|
||||
}
|
||||
original_url
|
||||
seo_metadata {
|
||||
description
|
||||
title
|
||||
|
||||
5
server/routers/contentstack/contactConfig/index.ts
Normal file
5
server/routers/contentstack/contactConfig/index.ts
Normal file
@@ -0,0 +1,5 @@
|
||||
import { mergeRouters } from "@/server/trpc"
|
||||
|
||||
import { contactConfigQueryRouter } from "./query"
|
||||
|
||||
export const contactConfigRouter = mergeRouters(contactConfigQueryRouter)
|
||||
32
server/routers/contentstack/contactConfig/query.ts
Normal file
32
server/routers/contentstack/contactConfig/query.ts
Normal file
@@ -0,0 +1,32 @@
|
||||
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 GetContactConfig from "@/lib/graphql/Query/ContactConfig.graphql"
|
||||
|
||||
import type { GetContactConfigData } from "@/types/requests/contactConfig"
|
||||
|
||||
export const contactConfigQueryRouter = router({
|
||||
get: publicProcedure
|
||||
.input(z.object({ lang: z.nativeEnum(Lang) }))
|
||||
.query(async ({ input }) => {
|
||||
const contactConfig = await request<GetContactConfigData>(
|
||||
GetContactConfig,
|
||||
{
|
||||
locale: input.lang,
|
||||
},
|
||||
{
|
||||
tags: [`contact-config-${input.lang}`],
|
||||
}
|
||||
)
|
||||
|
||||
if (contactConfig.data && contactConfig.data.all_contact_config.total) {
|
||||
return contactConfig.data.all_contact_config.items[0]
|
||||
}
|
||||
|
||||
throw badRequestError()
|
||||
}),
|
||||
})
|
||||
@@ -2,8 +2,10 @@ import { router } from "@/server/trpc"
|
||||
|
||||
import { breadcrumbsRouter } from "./breadcrumbs"
|
||||
import { loyaltyPageRouter } from "./loyaltyPage"
|
||||
import { contactConfigRouter } from "./contactConfig"
|
||||
|
||||
export const contentstackRouter = router({
|
||||
breadcrumbs: breadcrumbsRouter,
|
||||
loyaltyPage: loyaltyPageRouter,
|
||||
contactConfig: contactConfigRouter,
|
||||
})
|
||||
|
||||
@@ -1,16 +1,18 @@
|
||||
import { PageLink } from "./myPages/navigation"
|
||||
import { Edges } from "./utils/edges"
|
||||
import type { AllRequestResponse } from "./utils/all"
|
||||
import type { Typename } from "./utils/typename"
|
||||
import { Edges } from "./utils/edges"
|
||||
import type { RTEDocument } from "../rte/node"
|
||||
import type { Embeds } from "./embeds"
|
||||
import type { ContactField } from "./contactConfig"
|
||||
|
||||
enum SidebarTypenameEnum {
|
||||
LoyaltyPageSidebarLoyaltyJoinContact = "LoyaltyPageSidebarLoyaltyJoinContact",
|
||||
export enum SidebarTypenameEnum {
|
||||
LoyaltyPageSidebarJoinLoyaltyContact = "LoyaltyPageSidebarJoinLoyaltyContact",
|
||||
LoyaltyPageSidebarContent = "LoyaltyPageSidebarContent",
|
||||
}
|
||||
|
||||
export type SidebarTypename = keyof typeof SidebarTypenameEnum
|
||||
|
||||
type SidebarContent = {
|
||||
content: {
|
||||
embedded_itemsConnection: Edges<Embeds>
|
||||
@@ -24,8 +26,8 @@ type Contact = {
|
||||
}
|
||||
}
|
||||
|
||||
type LoyaltyJoinContact = {
|
||||
loyalty_join_contact: {
|
||||
export type JoinLoyaltyContact = {
|
||||
join_loyalty_contact: {
|
||||
title: string
|
||||
contact: Typename<
|
||||
Contact,
|
||||
@@ -42,8 +44,8 @@ type LoyaltyJoinContact = {
|
||||
export type Sidebar =
|
||||
| Typename<SidebarContent, SidebarTypenameEnum.LoyaltyPageSidebarContent>
|
||||
| Typename<
|
||||
LoyaltyJoinContact,
|
||||
SidebarTypenameEnum.LoyaltyPageSidebarLoyaltyJoinContact
|
||||
JoinLoyaltyContact,
|
||||
SidebarTypenameEnum.LoyaltyPageSidebarJoinLoyaltyContact
|
||||
>
|
||||
|
||||
enum ContentBlocks {
|
||||
|
||||
Reference in New Issue
Block a user