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 SectionHeader from "@/components/Section/Header"
|
||||
import Card from "@/components/TempDesignSystem/Card"
|
||||
@@ -37,7 +38,7 @@ export default function CardsGrid({
|
||||
topTitle={firstItem}
|
||||
/>
|
||||
<Grids.Stackable columns={columns}>
|
||||
{cards_grid.cards.map((card) => {
|
||||
{cards_grid.cards.map((card, index) => {
|
||||
switch (card.__typename) {
|
||||
case CardsGridEnum.cards.Card:
|
||||
return (
|
||||
@@ -55,6 +56,19 @@ export default function CardsGrid({
|
||||
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:
|
||||
return (
|
||||
<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 Blocks from "@/components/Blocks"
|
||||
import Image from "@/components/Image"
|
||||
import PageContainer from "@/components/PageContainer"
|
||||
import Title from "@/components/TempDesignSystem/Text/Title"
|
||||
@@ -15,7 +16,7 @@ export default async function StartPage() {
|
||||
return null
|
||||
}
|
||||
|
||||
const { header } = content.startPage
|
||||
const { header, blocks } = content.startPage
|
||||
|
||||
return (
|
||||
<PageContainer>
|
||||
@@ -41,12 +42,15 @@ export default async function StartPage() {
|
||||
/>
|
||||
) : null}
|
||||
</header>
|
||||
<details
|
||||
style={{ maxWidth: "100vw", overflow: "hidden", padding: "1rem 0" }}
|
||||
>
|
||||
<summary>JSON data</summary>
|
||||
<pre>{JSON.stringify(content, null, 2)}</pre>
|
||||
</details>
|
||||
<main className={styles.main}>
|
||||
<details
|
||||
style={{ maxWidth: "100vw", overflow: "hidden", padding: "1rem 0" }}
|
||||
>
|
||||
<summary>JSON data</summary>
|
||||
<pre>{JSON.stringify(content, null, 2)}</pre>
|
||||
</details>
|
||||
{blocks ? <Blocks blocks={blocks} /> : null}
|
||||
</main>
|
||||
<Suspense fallback={null}>
|
||||
<TrackingSDK pageData={content.tracking} />
|
||||
</Suspense>
|
||||
|
||||
@@ -37,3 +37,12 @@
|
||||
.topImage {
|
||||
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 "./InfoCard.graphql"
|
||||
#import "./LoyaltyCard.graphql"
|
||||
#import "./TeaserCard.graphql"
|
||||
|
||||
#import "./Refs/Card.graphql"
|
||||
#import "./Refs/InfoCard.graphql"
|
||||
#import "./Refs/LoyaltyCard.graphql"
|
||||
#import "./Refs/TeaserCard.graphql"
|
||||
|
||||
@@ -17,6 +19,7 @@ fragment CardsGrid_ContentPage on ContentPageBlocksCardsGrid {
|
||||
node {
|
||||
__typename
|
||||
...CardBlock
|
||||
...InfoCardBlock
|
||||
...LoyaltyCardBlock
|
||||
...TeaserCardBlock
|
||||
}
|
||||
@@ -32,6 +35,7 @@ fragment CardsGrid_ContentPageRefs on ContentPageBlocksCardsGrid {
|
||||
node {
|
||||
__typename
|
||||
...CardBlockRef
|
||||
...InfoCardBlockRef
|
||||
...LoyaltyCardBlockRef
|
||||
...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/Blocks/CardsGrid.graphql"
|
||||
|
||||
query GetStartPage($locale: String!, $uid: String!) {
|
||||
start_page(uid: $uid, locale: $locale) {
|
||||
@@ -13,6 +14,10 @@ query GetStartPage($locale: String!, $uid: String!) {
|
||||
created_at
|
||||
updated_at
|
||||
}
|
||||
blocks {
|
||||
__typename
|
||||
...CardsGrid_StartPage
|
||||
}
|
||||
}
|
||||
trackingProps: start_page(locale: "en", uid: $uid) {
|
||||
url
|
||||
@@ -21,6 +26,10 @@ query GetStartPage($locale: String!, $uid: String!) {
|
||||
|
||||
query GetStartPageRefs($locale: String!, $uid: String!) {
|
||||
start_page(locale: $locale, uid: $uid) {
|
||||
blocks {
|
||||
__typename
|
||||
...CardsGrid_StartPageRefs
|
||||
}
|
||||
system {
|
||||
...System
|
||||
}
|
||||
|
||||
@@ -157,6 +157,34 @@ const loyaltyCardBlockSchema = z.object({
|
||||
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({
|
||||
typename: z
|
||||
.literal(BlocksEnums.block.CardsGrid)
|
||||
@@ -171,6 +199,7 @@ export const cardsGridSchema = z.object({
|
||||
cardBlockSchema,
|
||||
loyaltyCardBlockSchema,
|
||||
teaserCardBlockSchema,
|
||||
infoCardBlockSchema,
|
||||
]),
|
||||
})
|
||||
),
|
||||
@@ -191,6 +220,8 @@ export const cardsGridSchema = z.object({
|
||||
return transformCardBlock(card.node)
|
||||
} else if (card.node.__typename === CardsGridEnum.cards.TeaserCard) {
|
||||
return transformTeaserCardBlock(card.node)
|
||||
} else if (card.node.__typename === CardsGridEnum.cards.InfoCard) {
|
||||
return transformInfoCardBlock(card.node)
|
||||
} else {
|
||||
return {
|
||||
__typename: card.node.__typename,
|
||||
@@ -218,6 +249,7 @@ export function transformCardBlockRefs(
|
||||
card:
|
||||
| typeof cardBlockRefsSchema._type
|
||||
| typeof teaserCardBlockRefsSchema._type
|
||||
| typeof infoCardBlockRefsSchema._type
|
||||
) {
|
||||
const cards = [card.system]
|
||||
if (card.primary_button) {
|
||||
@@ -242,6 +274,13 @@ export const teaserCardBlockRefsSchema = z.object({
|
||||
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({
|
||||
cards_grid: z
|
||||
.object({
|
||||
@@ -252,6 +291,7 @@ export const cardGridRefsSchema = z.object({
|
||||
cardBlockRefsSchema,
|
||||
loyaltyCardBlockRefsSchema,
|
||||
teaserCardBlockRefsSchema,
|
||||
infoCardBlockRefsSchema,
|
||||
]),
|
||||
})
|
||||
),
|
||||
@@ -262,7 +302,8 @@ export const cardGridRefsSchema = z.object({
|
||||
.map(({ node }) => {
|
||||
if (
|
||||
node.__typename === CardsGridEnum.cards.Card ||
|
||||
node.__typename === CardsGridEnum.cards.TeaserCard
|
||||
node.__typename === CardsGridEnum.cards.TeaserCard ||
|
||||
node.__typename === CardsGridEnum.cards.InfoCard
|
||||
) {
|
||||
return transformCardBlockRefs(node)
|
||||
} else {
|
||||
|
||||
@@ -136,6 +136,7 @@ export const imageVaultAssetTransformedSchema = imageVaultAssetSchema.transform(
|
||||
)
|
||||
|
||||
export const tempImageVaultAssetSchema = imageVaultAssetSchema
|
||||
.nullable()
|
||||
.optional()
|
||||
.or(
|
||||
// Temp since there is a bug in Contentstack
|
||||
|
||||
@@ -1,10 +1,27 @@
|
||||
import { z } from "zod"
|
||||
|
||||
import { discriminatedUnionArray } from "@/lib/discriminatedUnion"
|
||||
|
||||
import {
|
||||
cardGridRefsSchema,
|
||||
cardsGridSchema,
|
||||
} from "../schemas/blocks/cardsGrid"
|
||||
import { tempImageVaultAssetSchema } from "../schemas/imageVault"
|
||||
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({
|
||||
start_page: z.object({
|
||||
blocks: discriminatedUnionArray(blocksSchema.options).nullable(),
|
||||
title: z.string(),
|
||||
header: z.object({
|
||||
heading: z.string(),
|
||||
@@ -23,8 +40,19 @@ export const startPageSchema = z.object({
|
||||
})
|
||||
|
||||
/** 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({
|
||||
start_page: z.object({
|
||||
blocks: discriminatedUnionArray(startPageBlockRefsItem.options).nullable(),
|
||||
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 ContentPageBlock } from "@/types/trpc/routers/contentstack/contentPage"
|
||||
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 =
|
||||
| AccountPageBlock
|
||||
| CollectionPageBlock
|
||||
| ContentPageBlock
|
||||
| LoyaltyPageBlock
|
||||
| StartPageBlock
|
||||
|
||||
export interface BlocksProps {
|
||||
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",
|
||||
LoyaltyCard = "LoyaltyCard",
|
||||
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 {
|
||||
blocksSchema,
|
||||
startPageRefsSchema,
|
||||
startPageSchema,
|
||||
} from "@/server/routers/contentstack/startPage/output"
|
||||
@@ -12,3 +13,5 @@ export interface GetStartPageRefsSchema
|
||||
extends z.input<typeof startPageRefsSchema> {}
|
||||
|
||||
export interface StartPageRefs extends z.output<typeof startPageRefsSchema> {}
|
||||
|
||||
export type Block = z.output<typeof blocksSchema>
|
||||
|
||||
Reference in New Issue
Block a user