feat: add JoinLoyalty component

This commit is contained in:
Christel Westerberg
2024-04-19 13:11:02 +02:00
parent b57665ce62
commit 3a0c8610dc
15 changed files with 238 additions and 38 deletions

View File

@@ -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);
}

View File

@@ -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;
}
}

View File

@@ -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()

View File

@@ -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}
/>
)
}

View 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>
}

View 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>
)
}

View File

@@ -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;
}
}

View 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
}
}

View 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
}
}

View File

@@ -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

View File

@@ -0,0 +1,5 @@
import { mergeRouters } from "@/server/trpc"
import { contactConfigQueryRouter } from "./query"
export const contactConfigRouter = mergeRouters(contactConfigQueryRouter)

View 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()
}),
})

View File

@@ -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,
})

View File

@@ -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 {