Merged in SW-1382-start-page-offers-section (pull request #1221)
SW-1382 start page offers section * feat(SW-1382): Add InfoCard component to CardsGrid and StartPage * feat(SW-1382): Add dynamic image positioning for InfoCard in CardsGrid * refactor(SW-1382): Update InfoCard data transformation and prop naming * fix(SW-1382): Add flex display to InfoCard image container Approved-by: Christian Andolf Approved-by: Erik Tiekstra
This commit is contained in:
@@ -1,3 +1,4 @@
|
|||||||
|
import InfoCard from "@/components/ContentType/StartPage/InfoCard"
|
||||||
import SectionContainer from "@/components/Section/Container"
|
import SectionContainer from "@/components/Section/Container"
|
||||||
import SectionHeader from "@/components/Section/Header"
|
import SectionHeader from "@/components/Section/Header"
|
||||||
import Card from "@/components/TempDesignSystem/Card"
|
import Card from "@/components/TempDesignSystem/Card"
|
||||||
@@ -37,7 +38,7 @@ export default function CardsGrid({
|
|||||||
topTitle={firstItem}
|
topTitle={firstItem}
|
||||||
/>
|
/>
|
||||||
<Grids.Stackable columns={columns}>
|
<Grids.Stackable columns={columns}>
|
||||||
{cards_grid.cards.map((card) => {
|
{cards_grid.cards.map((card, index) => {
|
||||||
switch (card.__typename) {
|
switch (card.__typename) {
|
||||||
case CardsGridEnum.cards.Card:
|
case CardsGridEnum.cards.Card:
|
||||||
return (
|
return (
|
||||||
@@ -55,6 +56,19 @@ export default function CardsGrid({
|
|||||||
imageGradient
|
imageGradient
|
||||||
/>
|
/>
|
||||||
)
|
)
|
||||||
|
case CardsGridEnum.cards.InfoCard:
|
||||||
|
return (
|
||||||
|
<InfoCard
|
||||||
|
key={card.system.uid}
|
||||||
|
scriptedTopTitle={card.scriptedTopTitle}
|
||||||
|
heading={card.heading}
|
||||||
|
bodyText={card.bodyText}
|
||||||
|
image={card.image}
|
||||||
|
primaryButton={card.primaryButton}
|
||||||
|
secondaryButton={card.secondaryButton}
|
||||||
|
imagePosition={index % 2 === 0 ? "right" : "left"}
|
||||||
|
/>
|
||||||
|
)
|
||||||
case CardsGridEnum.cards.TeaserCard:
|
case CardsGridEnum.cards.TeaserCard:
|
||||||
return (
|
return (
|
||||||
<TeaserCard
|
<TeaserCard
|
||||||
|
|||||||
46
components/ContentType/StartPage/InfoCard/index.tsx
Normal file
46
components/ContentType/StartPage/InfoCard/index.tsx
Normal file
@@ -0,0 +1,46 @@
|
|||||||
|
import Image from "@/components/Image"
|
||||||
|
import Card from "@/components/TempDesignSystem/Card"
|
||||||
|
|
||||||
|
import styles from "./infoCard.module.css"
|
||||||
|
|
||||||
|
import type { InfoCardProps } from "@/types/components/blocks/infoCard"
|
||||||
|
|
||||||
|
export default function InfoCard({
|
||||||
|
scriptedTopTitle,
|
||||||
|
heading,
|
||||||
|
bodyText,
|
||||||
|
image,
|
||||||
|
primaryButton,
|
||||||
|
secondaryButton,
|
||||||
|
theme = "one",
|
||||||
|
imagePosition = "right",
|
||||||
|
}: InfoCardProps) {
|
||||||
|
return (
|
||||||
|
<article className={styles.container}>
|
||||||
|
{image ? (
|
||||||
|
<div
|
||||||
|
className={`${styles.imageContainer} ${styles[`image-${imagePosition}`]}`}
|
||||||
|
>
|
||||||
|
<Image
|
||||||
|
src={image.url}
|
||||||
|
alt={image.title}
|
||||||
|
sizes="(min-width: 768px) 724px, 358px"
|
||||||
|
width={358}
|
||||||
|
height={179}
|
||||||
|
focalPoint={image.focalPoint}
|
||||||
|
className={styles.image}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
) : null}
|
||||||
|
<Card
|
||||||
|
scriptedTopTitle={scriptedTopTitle}
|
||||||
|
heading={heading}
|
||||||
|
bodyText={bodyText}
|
||||||
|
primaryButton={primaryButton}
|
||||||
|
secondaryButton={secondaryButton}
|
||||||
|
className={styles.card}
|
||||||
|
theme={theme}
|
||||||
|
/>
|
||||||
|
</article>
|
||||||
|
)
|
||||||
|
}
|
||||||
@@ -0,0 +1,47 @@
|
|||||||
|
.container {
|
||||||
|
display: grid;
|
||||||
|
gap: var(--Spacing-x-quarter);
|
||||||
|
}
|
||||||
|
|
||||||
|
.image {
|
||||||
|
object-fit: cover;
|
||||||
|
overflow: hidden;
|
||||||
|
width: 100%;
|
||||||
|
height: 179px; /* Exact mobile height from Figma */
|
||||||
|
border-radius: var(--Corner-radius-Medium);
|
||||||
|
}
|
||||||
|
|
||||||
|
.imageContainer {
|
||||||
|
display: flex;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (min-width: 768px) {
|
||||||
|
.container:has(.imageContainer) {
|
||||||
|
gap: var(--Spacing-x2);
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.container:not(:has(.imageContainer)) {
|
||||||
|
grid-template-columns: 1fr;
|
||||||
|
}
|
||||||
|
|
||||||
|
.container:has(.image-right) {
|
||||||
|
grid-template-columns: 456px 1fr;
|
||||||
|
}
|
||||||
|
|
||||||
|
.container:has(.image-left) {
|
||||||
|
grid-template-columns: 1fr 456px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.image-right {
|
||||||
|
order: 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
.image-left {
|
||||||
|
order: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.image {
|
||||||
|
height: 320px; /* Desktop height from Figma */
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -2,6 +2,7 @@ import { Suspense } from "react"
|
|||||||
|
|
||||||
import { getStartPage } from "@/lib/trpc/memoizedRequests"
|
import { getStartPage } from "@/lib/trpc/memoizedRequests"
|
||||||
|
|
||||||
|
import Blocks from "@/components/Blocks"
|
||||||
import Image from "@/components/Image"
|
import Image from "@/components/Image"
|
||||||
import PageContainer from "@/components/PageContainer"
|
import PageContainer from "@/components/PageContainer"
|
||||||
import Title from "@/components/TempDesignSystem/Text/Title"
|
import Title from "@/components/TempDesignSystem/Text/Title"
|
||||||
@@ -15,7 +16,7 @@ export default async function StartPage() {
|
|||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
|
|
||||||
const { header } = content.startPage
|
const { header, blocks } = content.startPage
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<PageContainer>
|
<PageContainer>
|
||||||
@@ -41,12 +42,15 @@ export default async function StartPage() {
|
|||||||
/>
|
/>
|
||||||
) : null}
|
) : null}
|
||||||
</header>
|
</header>
|
||||||
<details
|
<main className={styles.main}>
|
||||||
style={{ maxWidth: "100vw", overflow: "hidden", padding: "1rem 0" }}
|
<details
|
||||||
>
|
style={{ maxWidth: "100vw", overflow: "hidden", padding: "1rem 0" }}
|
||||||
<summary>JSON data</summary>
|
>
|
||||||
<pre>{JSON.stringify(content, null, 2)}</pre>
|
<summary>JSON data</summary>
|
||||||
</details>
|
<pre>{JSON.stringify(content, null, 2)}</pre>
|
||||||
|
</details>
|
||||||
|
{blocks ? <Blocks blocks={blocks} /> : null}
|
||||||
|
</main>
|
||||||
<Suspense fallback={null}>
|
<Suspense fallback={null}>
|
||||||
<TrackingSDK pageData={content.tracking} />
|
<TrackingSDK pageData={content.tracking} />
|
||||||
</Suspense>
|
</Suspense>
|
||||||
|
|||||||
@@ -37,3 +37,12 @@
|
|||||||
.topImage {
|
.topImage {
|
||||||
max-width: 100%;
|
max-width: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.main {
|
||||||
|
display: grid;
|
||||||
|
width: 100%;
|
||||||
|
gap: var(--Spacing-x6);
|
||||||
|
margin: 0 auto;
|
||||||
|
max-width: var(--max-width-content);
|
||||||
|
padding: var(--Spacing-x4) 0;
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,8 +1,10 @@
|
|||||||
#import "./Card.graphql"
|
#import "./Card.graphql"
|
||||||
|
#import "./InfoCard.graphql"
|
||||||
#import "./LoyaltyCard.graphql"
|
#import "./LoyaltyCard.graphql"
|
||||||
#import "./TeaserCard.graphql"
|
#import "./TeaserCard.graphql"
|
||||||
|
|
||||||
#import "./Refs/Card.graphql"
|
#import "./Refs/Card.graphql"
|
||||||
|
#import "./Refs/InfoCard.graphql"
|
||||||
#import "./Refs/LoyaltyCard.graphql"
|
#import "./Refs/LoyaltyCard.graphql"
|
||||||
#import "./Refs/TeaserCard.graphql"
|
#import "./Refs/TeaserCard.graphql"
|
||||||
|
|
||||||
@@ -17,6 +19,7 @@ fragment CardsGrid_ContentPage on ContentPageBlocksCardsGrid {
|
|||||||
node {
|
node {
|
||||||
__typename
|
__typename
|
||||||
...CardBlock
|
...CardBlock
|
||||||
|
...InfoCardBlock
|
||||||
...LoyaltyCardBlock
|
...LoyaltyCardBlock
|
||||||
...TeaserCardBlock
|
...TeaserCardBlock
|
||||||
}
|
}
|
||||||
@@ -32,6 +35,7 @@ fragment CardsGrid_ContentPageRefs on ContentPageBlocksCardsGrid {
|
|||||||
node {
|
node {
|
||||||
__typename
|
__typename
|
||||||
...CardBlockRef
|
...CardBlockRef
|
||||||
|
...InfoCardBlockRef
|
||||||
...LoyaltyCardBlockRef
|
...LoyaltyCardBlockRef
|
||||||
...TeaserCardBlockRef
|
...TeaserCardBlockRef
|
||||||
}
|
}
|
||||||
@@ -103,3 +107,37 @@ fragment CardsGrid_LoyaltyPageRefs on LoyaltyPageBlocksCardsGrid {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fragment CardsGrid_StartPage on StartPageBlocksCardsGrid {
|
||||||
|
cards_grid {
|
||||||
|
layout
|
||||||
|
preamble
|
||||||
|
theme
|
||||||
|
title
|
||||||
|
cardConnection(limit: 10) {
|
||||||
|
edges {
|
||||||
|
node {
|
||||||
|
__typename
|
||||||
|
...CardBlock
|
||||||
|
...TeaserCardBlock
|
||||||
|
...InfoCardBlock
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fragment CardsGrid_StartPageRefs on StartPageBlocksCardsGrid {
|
||||||
|
cards_grid {
|
||||||
|
cardConnection(limit: 10) {
|
||||||
|
edges {
|
||||||
|
node {
|
||||||
|
__typename
|
||||||
|
...CardBlockRef
|
||||||
|
...TeaserCardBlockRef
|
||||||
|
...InfoCardBlockRef
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
73
lib/graphql/Fragments/Blocks/InfoCard.graphql
Normal file
73
lib/graphql/Fragments/Blocks/InfoCard.graphql
Normal file
@@ -0,0 +1,73 @@
|
|||||||
|
#import "../System.graphql"
|
||||||
|
|
||||||
|
#import "../PageLink/AccountPageLink.graphql"
|
||||||
|
#import "../PageLink/CollectionPageLink.graphql"
|
||||||
|
#import "../PageLink/ContentPageLink.graphql"
|
||||||
|
#import "../PageLink/DestinationCityPageLink.graphql"
|
||||||
|
#import "../PageLink/DestinationCountryPageLink.graphql"
|
||||||
|
#import "../PageLink/DestinationOverviewPageLink.graphql"
|
||||||
|
#import "../PageLink/HotelPageLink.graphql"
|
||||||
|
#import "../PageLink/LoyaltyPageLink.graphql"
|
||||||
|
#import "../PageLink/StartPageLink.graphql"
|
||||||
|
|
||||||
|
fragment InfoCardBlock on InfoCard {
|
||||||
|
scripted_top_title
|
||||||
|
heading
|
||||||
|
body_text
|
||||||
|
image
|
||||||
|
title
|
||||||
|
|
||||||
|
primary_button {
|
||||||
|
is_contentstack_link
|
||||||
|
cta_text
|
||||||
|
open_in_new_tab
|
||||||
|
external_link {
|
||||||
|
title
|
||||||
|
href
|
||||||
|
}
|
||||||
|
linkConnection {
|
||||||
|
edges {
|
||||||
|
node {
|
||||||
|
__typename
|
||||||
|
...AccountPageLink
|
||||||
|
...CollectionPageLink
|
||||||
|
...ContentPageLink
|
||||||
|
...DestinationCityPageLink
|
||||||
|
...DestinationCountryPageLink
|
||||||
|
...DestinationOverviewPageLink
|
||||||
|
...HotelPageLink
|
||||||
|
...LoyaltyPageLink
|
||||||
|
...StartPageLink
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
secondary_button {
|
||||||
|
is_contentstack_link
|
||||||
|
cta_text
|
||||||
|
open_in_new_tab
|
||||||
|
external_link {
|
||||||
|
title
|
||||||
|
href
|
||||||
|
}
|
||||||
|
linkConnection {
|
||||||
|
edges {
|
||||||
|
node {
|
||||||
|
__typename
|
||||||
|
...AccountPageLink
|
||||||
|
...CollectionPageLink
|
||||||
|
...ContentPageLink
|
||||||
|
...DestinationCityPageLink
|
||||||
|
...DestinationCountryPageLink
|
||||||
|
...DestinationOverviewPageLink
|
||||||
|
...HotelPageLink
|
||||||
|
...LoyaltyPageLink
|
||||||
|
...StartPageLink
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
system {
|
||||||
|
...System
|
||||||
|
}
|
||||||
|
}
|
||||||
51
lib/graphql/Fragments/Blocks/Refs/InfoCard.graphql
Normal file
51
lib/graphql/Fragments/Blocks/Refs/InfoCard.graphql
Normal file
@@ -0,0 +1,51 @@
|
|||||||
|
#import "../../AccountPage/Ref.graphql"
|
||||||
|
#import "../../CollectionPage/Ref.graphql"
|
||||||
|
#import "../../ContentPage/Ref.graphql"
|
||||||
|
#import "../../DestinationCityPage/Ref.graphql"
|
||||||
|
#import "../../DestinationCountryPage/Ref.graphql"
|
||||||
|
#import "../../DestinationOverviewPage/Ref.graphql"
|
||||||
|
#import "../../HotelPage/Ref.graphql"
|
||||||
|
#import "../../LoyaltyPage/Ref.graphql"
|
||||||
|
#import "../../StartPage/Ref.graphql"
|
||||||
|
|
||||||
|
fragment InfoCardBlockRef on InfoCard {
|
||||||
|
secondary_button {
|
||||||
|
linkConnection {
|
||||||
|
edges {
|
||||||
|
node {
|
||||||
|
__typename
|
||||||
|
...AccountPageRef
|
||||||
|
...CollectionPageRef
|
||||||
|
...ContentPageRef
|
||||||
|
...DestinationCityPageRef
|
||||||
|
...DestinationCountryPageRef
|
||||||
|
...DestinationOverviewPageRef
|
||||||
|
...HotelPageRef
|
||||||
|
...LoyaltyPageRef
|
||||||
|
...StartPageRef
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
primary_button {
|
||||||
|
linkConnection {
|
||||||
|
edges {
|
||||||
|
node {
|
||||||
|
__typename
|
||||||
|
...AccountPageRef
|
||||||
|
...CollectionPageRef
|
||||||
|
...ContentPageRef
|
||||||
|
...DestinationCityPageRef
|
||||||
|
...DestinationCountryPageRef
|
||||||
|
...DestinationOverviewPageRef
|
||||||
|
...HotelPageRef
|
||||||
|
...LoyaltyPageRef
|
||||||
|
...StartPageRef
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
system {
|
||||||
|
...System
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,4 +1,5 @@
|
|||||||
#import "../../Fragments/System.graphql"
|
#import "../../Fragments/System.graphql"
|
||||||
|
#import "../../Fragments/Blocks/CardsGrid.graphql"
|
||||||
|
|
||||||
query GetStartPage($locale: String!, $uid: String!) {
|
query GetStartPage($locale: String!, $uid: String!) {
|
||||||
start_page(uid: $uid, locale: $locale) {
|
start_page(uid: $uid, locale: $locale) {
|
||||||
@@ -13,6 +14,10 @@ query GetStartPage($locale: String!, $uid: String!) {
|
|||||||
created_at
|
created_at
|
||||||
updated_at
|
updated_at
|
||||||
}
|
}
|
||||||
|
blocks {
|
||||||
|
__typename
|
||||||
|
...CardsGrid_StartPage
|
||||||
|
}
|
||||||
}
|
}
|
||||||
trackingProps: start_page(locale: "en", uid: $uid) {
|
trackingProps: start_page(locale: "en", uid: $uid) {
|
||||||
url
|
url
|
||||||
@@ -21,6 +26,10 @@ query GetStartPage($locale: String!, $uid: String!) {
|
|||||||
|
|
||||||
query GetStartPageRefs($locale: String!, $uid: String!) {
|
query GetStartPageRefs($locale: String!, $uid: String!) {
|
||||||
start_page(locale: $locale, uid: $uid) {
|
start_page(locale: $locale, uid: $uid) {
|
||||||
|
blocks {
|
||||||
|
__typename
|
||||||
|
...CardsGrid_StartPageRefs
|
||||||
|
}
|
||||||
system {
|
system {
|
||||||
...System
|
...System
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -157,6 +157,34 @@ const loyaltyCardBlockSchema = z.object({
|
|||||||
title: z.string().optional(),
|
title: z.string().optional(),
|
||||||
})
|
})
|
||||||
|
|
||||||
|
export const infoCardBlockSchema = z.object({
|
||||||
|
__typename: z.literal(CardsGridEnum.cards.InfoCard),
|
||||||
|
scripted_top_title: z.string().optional(),
|
||||||
|
heading: z.string().optional().default(""),
|
||||||
|
body_text: z.string().optional().default(""),
|
||||||
|
image: tempImageVaultAssetSchema,
|
||||||
|
title: z.string().optional(),
|
||||||
|
primary_button: buttonSchema.optional().nullable(),
|
||||||
|
secondary_button: buttonSchema.optional().nullable(),
|
||||||
|
system: systemSchema,
|
||||||
|
})
|
||||||
|
|
||||||
|
export function transformInfoCardBlock(card: typeof infoCardBlockSchema._type) {
|
||||||
|
return {
|
||||||
|
__typename: card.__typename,
|
||||||
|
scriptedTopTitle: card.scripted_top_title,
|
||||||
|
heading: card.heading,
|
||||||
|
bodyText: card.body_text,
|
||||||
|
image: card.image,
|
||||||
|
title: card.title,
|
||||||
|
primaryButton: card.primary_button?.href ? card.primary_button : undefined,
|
||||||
|
secondaryButton: card.secondary_button?.href
|
||||||
|
? card.secondary_button
|
||||||
|
: undefined,
|
||||||
|
system: card.system,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
export const cardsGridSchema = z.object({
|
export const cardsGridSchema = z.object({
|
||||||
typename: z
|
typename: z
|
||||||
.literal(BlocksEnums.block.CardsGrid)
|
.literal(BlocksEnums.block.CardsGrid)
|
||||||
@@ -171,6 +199,7 @@ export const cardsGridSchema = z.object({
|
|||||||
cardBlockSchema,
|
cardBlockSchema,
|
||||||
loyaltyCardBlockSchema,
|
loyaltyCardBlockSchema,
|
||||||
teaserCardBlockSchema,
|
teaserCardBlockSchema,
|
||||||
|
infoCardBlockSchema,
|
||||||
]),
|
]),
|
||||||
})
|
})
|
||||||
),
|
),
|
||||||
@@ -191,6 +220,8 @@ export const cardsGridSchema = z.object({
|
|||||||
return transformCardBlock(card.node)
|
return transformCardBlock(card.node)
|
||||||
} else if (card.node.__typename === CardsGridEnum.cards.TeaserCard) {
|
} else if (card.node.__typename === CardsGridEnum.cards.TeaserCard) {
|
||||||
return transformTeaserCardBlock(card.node)
|
return transformTeaserCardBlock(card.node)
|
||||||
|
} else if (card.node.__typename === CardsGridEnum.cards.InfoCard) {
|
||||||
|
return transformInfoCardBlock(card.node)
|
||||||
} else {
|
} else {
|
||||||
return {
|
return {
|
||||||
__typename: card.node.__typename,
|
__typename: card.node.__typename,
|
||||||
@@ -218,6 +249,7 @@ export function transformCardBlockRefs(
|
|||||||
card:
|
card:
|
||||||
| typeof cardBlockRefsSchema._type
|
| typeof cardBlockRefsSchema._type
|
||||||
| typeof teaserCardBlockRefsSchema._type
|
| typeof teaserCardBlockRefsSchema._type
|
||||||
|
| typeof infoCardBlockRefsSchema._type
|
||||||
) {
|
) {
|
||||||
const cards = [card.system]
|
const cards = [card.system]
|
||||||
if (card.primary_button) {
|
if (card.primary_button) {
|
||||||
@@ -242,6 +274,13 @@ export const teaserCardBlockRefsSchema = z.object({
|
|||||||
system: systemSchema,
|
system: systemSchema,
|
||||||
})
|
})
|
||||||
|
|
||||||
|
export const infoCardBlockRefsSchema = z.object({
|
||||||
|
__typename: z.literal(CardsGridEnum.cards.InfoCard),
|
||||||
|
primary_button: linkConnectionRefsSchema,
|
||||||
|
secondary_button: linkConnectionRefsSchema,
|
||||||
|
system: systemSchema,
|
||||||
|
})
|
||||||
|
|
||||||
export const cardGridRefsSchema = z.object({
|
export const cardGridRefsSchema = z.object({
|
||||||
cards_grid: z
|
cards_grid: z
|
||||||
.object({
|
.object({
|
||||||
@@ -252,6 +291,7 @@ export const cardGridRefsSchema = z.object({
|
|||||||
cardBlockRefsSchema,
|
cardBlockRefsSchema,
|
||||||
loyaltyCardBlockRefsSchema,
|
loyaltyCardBlockRefsSchema,
|
||||||
teaserCardBlockRefsSchema,
|
teaserCardBlockRefsSchema,
|
||||||
|
infoCardBlockRefsSchema,
|
||||||
]),
|
]),
|
||||||
})
|
})
|
||||||
),
|
),
|
||||||
@@ -262,7 +302,8 @@ export const cardGridRefsSchema = z.object({
|
|||||||
.map(({ node }) => {
|
.map(({ node }) => {
|
||||||
if (
|
if (
|
||||||
node.__typename === CardsGridEnum.cards.Card ||
|
node.__typename === CardsGridEnum.cards.Card ||
|
||||||
node.__typename === CardsGridEnum.cards.TeaserCard
|
node.__typename === CardsGridEnum.cards.TeaserCard ||
|
||||||
|
node.__typename === CardsGridEnum.cards.InfoCard
|
||||||
) {
|
) {
|
||||||
return transformCardBlockRefs(node)
|
return transformCardBlockRefs(node)
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@@ -136,6 +136,7 @@ export const imageVaultAssetTransformedSchema = imageVaultAssetSchema.transform(
|
|||||||
)
|
)
|
||||||
|
|
||||||
export const tempImageVaultAssetSchema = imageVaultAssetSchema
|
export const tempImageVaultAssetSchema = imageVaultAssetSchema
|
||||||
|
.nullable()
|
||||||
.optional()
|
.optional()
|
||||||
.or(
|
.or(
|
||||||
// Temp since there is a bug in Contentstack
|
// Temp since there is a bug in Contentstack
|
||||||
|
|||||||
@@ -1,10 +1,27 @@
|
|||||||
import { z } from "zod"
|
import { z } from "zod"
|
||||||
|
|
||||||
|
import { discriminatedUnionArray } from "@/lib/discriminatedUnion"
|
||||||
|
|
||||||
|
import {
|
||||||
|
cardGridRefsSchema,
|
||||||
|
cardsGridSchema,
|
||||||
|
} from "../schemas/blocks/cardsGrid"
|
||||||
import { tempImageVaultAssetSchema } from "../schemas/imageVault"
|
import { tempImageVaultAssetSchema } from "../schemas/imageVault"
|
||||||
import { systemSchema } from "../schemas/system"
|
import { systemSchema } from "../schemas/system"
|
||||||
|
|
||||||
|
import { StartPageEnum } from "@/types/enums/startPage"
|
||||||
|
|
||||||
|
export const startPageCards = z
|
||||||
|
.object({
|
||||||
|
__typename: z.literal(StartPageEnum.ContentStack.blocks.CardsGrid),
|
||||||
|
})
|
||||||
|
.merge(cardsGridSchema)
|
||||||
|
|
||||||
|
export const blocksSchema = z.discriminatedUnion("__typename", [startPageCards])
|
||||||
|
|
||||||
export const startPageSchema = z.object({
|
export const startPageSchema = z.object({
|
||||||
start_page: z.object({
|
start_page: z.object({
|
||||||
|
blocks: discriminatedUnionArray(blocksSchema.options).nullable(),
|
||||||
title: z.string(),
|
title: z.string(),
|
||||||
header: z.object({
|
header: z.object({
|
||||||
heading: z.string(),
|
heading: z.string(),
|
||||||
@@ -23,8 +40,19 @@ export const startPageSchema = z.object({
|
|||||||
})
|
})
|
||||||
|
|
||||||
/** REFS */
|
/** REFS */
|
||||||
|
const startPageCardsRefs = z
|
||||||
|
.object({
|
||||||
|
__typename: z.literal(StartPageEnum.ContentStack.blocks.CardsGrid),
|
||||||
|
})
|
||||||
|
.merge(cardGridRefsSchema)
|
||||||
|
|
||||||
|
const startPageBlockRefsItem = z.discriminatedUnion("__typename", [
|
||||||
|
startPageCardsRefs,
|
||||||
|
])
|
||||||
|
|
||||||
export const startPageRefsSchema = z.object({
|
export const startPageRefsSchema = z.object({
|
||||||
start_page: z.object({
|
start_page: z.object({
|
||||||
|
blocks: discriminatedUnionArray(startPageBlockRefsItem.options).nullable(),
|
||||||
system: systemSchema,
|
system: systemSchema,
|
||||||
}),
|
}),
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -2,12 +2,14 @@ import type { Block as AccountPageBlock } from "@/types/trpc/routers/contentstac
|
|||||||
import type { Block as CollectionPageBlock } from "@/types/trpc/routers/contentstack/collectionPage"
|
import type { Block as CollectionPageBlock } from "@/types/trpc/routers/contentstack/collectionPage"
|
||||||
import type { Block as ContentPageBlock } from "@/types/trpc/routers/contentstack/contentPage"
|
import type { Block as ContentPageBlock } from "@/types/trpc/routers/contentstack/contentPage"
|
||||||
import type { Block as LoyaltyPageBlock } from "@/types/trpc/routers/contentstack/loyaltyPage"
|
import type { Block as LoyaltyPageBlock } from "@/types/trpc/routers/contentstack/loyaltyPage"
|
||||||
|
import type { Block as StartPageBlock } from "@/types/trpc/routers/contentstack/startPage"
|
||||||
|
|
||||||
export type Blocks =
|
export type Blocks =
|
||||||
| AccountPageBlock
|
| AccountPageBlock
|
||||||
| CollectionPageBlock
|
| CollectionPageBlock
|
||||||
| ContentPageBlock
|
| ContentPageBlock
|
||||||
| LoyaltyPageBlock
|
| LoyaltyPageBlock
|
||||||
|
| StartPageBlock
|
||||||
|
|
||||||
export interface BlocksProps {
|
export interface BlocksProps {
|
||||||
blocks: Blocks[]
|
blocks: Blocks[]
|
||||||
|
|||||||
22
types/components/blocks/infoCard.ts
Normal file
22
types/components/blocks/infoCard.ts
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
import type { VariantProps } from "class-variance-authority"
|
||||||
|
|
||||||
|
import type { ImageVaultAsset } from "@/types/components/imageVault"
|
||||||
|
import type { CardProps } from "@/components/TempDesignSystem/Card/card"
|
||||||
|
import type { cardVariants } from "@/components/TempDesignSystem/Card/variants"
|
||||||
|
|
||||||
|
type CardTheme = Exclude<
|
||||||
|
NonNullable<VariantProps<typeof cardVariants>["theme"]>,
|
||||||
|
"image"
|
||||||
|
>
|
||||||
|
|
||||||
|
export interface InfoCardProps {
|
||||||
|
scriptedTopTitle?: string
|
||||||
|
heading: string
|
||||||
|
bodyText: string
|
||||||
|
image?: ImageVaultAsset
|
||||||
|
imagePosition?: "left" | "right"
|
||||||
|
primaryButton?: CardProps["primaryButton"]
|
||||||
|
secondaryButton?: CardProps["secondaryButton"]
|
||||||
|
theme?: CardTheme
|
||||||
|
className?: string
|
||||||
|
}
|
||||||
@@ -3,6 +3,7 @@ export namespace CardsGridEnum {
|
|||||||
Card = "Card",
|
Card = "Card",
|
||||||
LoyaltyCard = "LoyaltyCard",
|
LoyaltyCard = "LoyaltyCard",
|
||||||
TeaserCard = "TeaserCard",
|
TeaserCard = "TeaserCard",
|
||||||
|
InfoCard = "InfoCard",
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
7
types/enums/startPage.ts
Normal file
7
types/enums/startPage.ts
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
export namespace StartPageEnum {
|
||||||
|
export namespace ContentStack {
|
||||||
|
export const enum blocks {
|
||||||
|
CardsGrid = "StartPageBlocksCardsGrid",
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,6 +1,7 @@
|
|||||||
import type { z } from "zod"
|
import type { z } from "zod"
|
||||||
|
|
||||||
import type {
|
import type {
|
||||||
|
blocksSchema,
|
||||||
startPageRefsSchema,
|
startPageRefsSchema,
|
||||||
startPageSchema,
|
startPageSchema,
|
||||||
} from "@/server/routers/contentstack/startPage/output"
|
} from "@/server/routers/contentstack/startPage/output"
|
||||||
@@ -12,3 +13,5 @@ export interface GetStartPageRefsSchema
|
|||||||
extends z.input<typeof startPageRefsSchema> {}
|
extends z.input<typeof startPageRefsSchema> {}
|
||||||
|
|
||||||
export interface StartPageRefs extends z.output<typeof startPageRefsSchema> {}
|
export interface StartPageRefs extends z.output<typeof startPageRefsSchema> {}
|
||||||
|
|
||||||
|
export type Block = z.output<typeof blocksSchema>
|
||||||
|
|||||||
Reference in New Issue
Block a user