refactor: 'Report' template schema correction

This commit is contained in:
Suraj Jha 2026-04-09 21:46:31 +05:45
parent c6dd188753
commit e77b674bf1
No known key found for this signature in database
GPG key ID: 5AC6C16355CE2C14
12 changed files with 122 additions and 122 deletions

View file

@ -7,21 +7,21 @@ import { ResponsiveContainer } from "recharts";
import { FlexibleReportChart, flexibleChartDataSchema } from "./flexibleReportChart";
const InsightItemSchema = z.object({
title: z.string().min(3).max(12).meta({
description: "Short insight title shown next to the icon.",
title: z.string().min(3).max(80).meta({
description: "Bullet point title shown next to the icon.",
}),
description: z.string().min(20).max(40).meta({
description: "Supporting text shown below the insight title.",
description: z.string().min(20).max(120).meta({
description: "Bullet point description shown below the title.",
}),
});
export const slideLayoutId = "data-analysis-bar-slide";
export const slideLayoutName = "Data Analysis Bar Slide";
export const slideLayoutId = "bar-chart-with-bullet-list-title-description-icon-slide";
export const slideLayoutName = "Bar Chart with Bullet List with Title Description Icon Slide";
export const slideLayoutDescription =
"A slide with a title at the top, a vertical list of three analysis points on the left, and a bar chart on the right. Each analysis point contains a small icon badge, a short title, and a supporting description.";
"A slide with a title at the top, a vertical list of three bullet points with icon, title and description on the left, and a bar chart on the right.";
export const Schema = z.object({
title: z.string().min(3).max(28).default("Data Analysis").meta({
title: z.string().min(3).max(80).default("Data Analysis").meta({
description: "Slide title shown at the top-left.",
}),
itemIcon: z
@ -40,7 +40,7 @@ export const Schema = z.object({
}),
items: z
.array(InsightItemSchema)
.min(1)
.max(3)
.default([
{ title: "Title 1", description: "Ut enim ad minima veniam, quis." },
@ -63,7 +63,7 @@ export const Schema = z.object({
],
}),
legendLabel: z.string().min(3).max(32).default("Traditional Workflow").meta({
legendLabel: z.string().min(3).max(50).default("Traditional Workflow").meta({
description: "Legend label shown below the chart.",
}),
});

View file

@ -6,14 +6,14 @@ import { ResponsiveContainer } from "recharts";
import { FlexibleReportChart, flexibleChartDataSchema } from "./flexibleReportChart";
export const slideLayoutId = "data-analysis-insight-bar-slide";
export const slideLayoutName = "Data Analysis Insight Bar Slide";
export const slideLayoutId = "title-description-chart-slide";
export const slideLayoutName = "Title Description Chart Slide";
export const slideLayoutDescription =
"A slide with a title at the top, a single featured insight block on the left containing an icon badge and a paragraph, and a chart on the right with a legend below it.";
"A slide with a title at the top, description text in left and chart in the right.";
export const Schema = z.object({
title: z.string().min(3).max(12).default("Data Analysis").meta({
title: z.string().min(3).max(80).default("Data Analysis").meta({
description: "Slide title shown at the top-left.",
}),
insightIcon: z
@ -32,13 +32,13 @@ export const Schema = z.object({
}),
insightBody: z
.string()
.min(80)
.min(30)
.max(320)
.default(
"Ut enim ad minima veniam, quis nostrum exercitationem ullam corporis suscipit laboriosam, nisi ut alut enim ad minima veniam, quis. Ut enim ad minima veniam, quis nostrum exercitationem ullam corporis suscipit laboriosam, nisi ut alut enim ad minima veniam, quis"
)
.meta({
description: "Featured insight paragraph shown in the left content area.",
description: "Description text shown in the left content area.",
}),
chartData: flexibleChartDataSchema.default({
type: "line-dual",

View file

@ -19,18 +19,18 @@ const MetricSchema = z.object({
});
const StatColumnSchema = z.object({
metrics: z.array(MetricSchema).min(2).max(2).meta({
metrics: z.array(MetricSchema).min(0).max(2).meta({
description: "Two stacked metrics shown in one stat card.",
}),
});
export const slideLayoutId = "data-analysis-line-stats-slide";
export const slideLayoutName = "Data Analysis Line Stats Slide";
export const slideLayoutId = "title-chart-metrics-cards-slide";
export const slideLayoutName = "Title Chart with Metrics Cards Slide";
export const slideLayoutDescription =
"A slide with a title at the top, a two-series line chart in the left content area, and two tall metric cards arranged side by side on the right. Each metric card contains two stacked metric blocks.";
"A slide with a title at the top, chart in the left content area, and optional metric cards arranged side by side on the right.";
export const Schema = z.object({
title: z.string().min(3).max(12).default("Data Analysis").meta({
title: z.string().min(3).max(80).default("Data Analysis").meta({
description: "Slide title shown at the top-left.",
}),
seriesALabel: z.string().min(3).max(20).default("Category A").meta({
@ -56,7 +56,7 @@ export const Schema = z.object({
}),
statColumns: z
.array(StatColumnSchema)
.min(2)
.min(1)
.max(2)
.default([
{
@ -73,7 +73,7 @@ export const Schema = z.object({
},
])
.meta({
description: "Two stat cards shown on the right side of the slide.",
description: "Stat/metric cards shown on the right side of the slide.",
}),
});

View file

@ -10,10 +10,10 @@ const AnalysisItemSchema = z.object({
}),
});
export const slideLayoutId = "data-analysis-list-slide";
export const slideLayoutName = "Data Analysis List Slide";
export const slideLayoutId = "bullet-list-with-icon-title-description-slide";
export const slideLayoutName = "Bullet List with Icon Title Description Slide";
export const slideLayoutDescription =
"A slide with a title at the top and a two-column list of analysis points underneath. Each point contains a small circular icon badge, a short title on the same row, and a supporting description directly below.";
"A slide with a title at the top and a two-column list of bullets points underneath. Each point contains a small circular icon badge, a short title on the same row, and a supporting description directly below.";
export const Schema = z.object({
title: z.string().min(3).max(12).default("Data Analysis").meta({
@ -42,7 +42,7 @@ export const Schema = z.object({
{ title: "Title 5", description: "Ut enim ad minima veniam, quis." },
])
.meta({
description: "Six analysis items distributed across two columns.",
description: "List of points contains a title and description.",
}),
});

View file

@ -1,18 +1,26 @@
import * as z from "zod";
export const Schema = z.object({
title: z.string().min(1).max(12).default("Company's "),
subtitle: z.string().min(1).max(15).default("Report"),
name: z.string().min(1).max(10).default("John Doe"),
position: z.string().min(1).max(20).default("Company Name | Strategy, Content, growth"),
titleFirstLine: z.string().min(1).max(12).default("Company's ").meta({
description: "First half of title or heading",
}),
titleSecondLine: z.string().min(1).max(12).default("Annual Report").meta({
description: "Second half of title or heading",
}),
name: z.string().min(1).max(10).optional().default("John Doe").meta({
description: "Name of the presenter/individual/company/organization.",
}),
position: z.string().min(1).max(20).default("Company Name | Strategy, Content, growth").meta({
description: "Position or role of the presenter or address of the company/organization.",
}),
})
export type SchemaType = z.infer<typeof Schema>;
export const slideLayoutId = "intro-slide";
export const slideLayoutName = "Intro Slide";
export const slideLayoutName = "Intro/Cover Slide";
export const slideLayoutDescription =
"A report cover slide with decorative corner accents, a centered two-line title section, a divider directly beneath the title, and a presenter information block below the divider containing a name line and a supporting role or company line.";
"A cover/intro slide with a two-line title section, a divider directly beneath the title, and a presenter information block below the divider containing a name line and a supporting role or company line.";
const IntroSlide = ({ data }: { data: Partial<SchemaType> }) => {
const { title, subtitle, name, position } = data;
const { titleFirstLine, titleSecondLine, name, position } = data;
return (
<div
@ -36,13 +44,13 @@ const IntroSlide = ({ data }: { data: Partial<SchemaType> }) => {
className="text-[#232223] text-[133px] italic text-center font-bold capitalize tracking-[-2.8px]"
style={{ color: "var(--background-text,#232223)" }}
>
{title}
{titleFirstLine}
</h1>
<p
className="text-[#232223] text-[93px] text-center font-medium capitalize tracking-[-2.8px]"
style={{ color: "var(--background-text,#232223)" }}
>
{subtitle}
{titleSecondLine}
</p>
</div>
<div

View file

@ -5,10 +5,10 @@ const MetricSchema = z.object({
value: z.string().min(1).max(6).meta({
description: "Primary metric value shown in the card.",
}),
label: z.string().min(3).max(10).optional().meta({
label: z.string().min(0).max(10).optional().meta({
description: "Short metric label shown below the value.",
}),
description: z.string().min(6).max(20).optional().meta({
description: z.string().min(0).max(20).optional().meta({
description: "Supporting text shown below the label.",
}),
});
@ -19,10 +19,10 @@ const StatColumnSchema = z.object({
}),
});
export const slideLayoutId = "introduction-stats-slide";
export const slideLayoutName = "Introduction Stats Slide";
export const slideLayoutId = "metrics-slide";
export const slideLayoutName = "Metrics Slide";
export const slideLayoutDescription =
"A slide with a title and explanatory text on the left, a bulleted list underneath the text, and two tall metric cards placed side by side on the right. Each metric card contains two stacked metric blocks.";
"A slide with a title and explanatory text on the left, an optional bulleted list underneath the text, and metric cards on the right. Each metric card contains two stacked metric blocks.";
export const Schema = z.object({
title: z.string().min(3).max(12).default("Introduction").meta({
@ -34,9 +34,9 @@ export const Schema = z.object({
description: "Primary paragraph shown below the title.",
}),
bullets: z
.array(z.string().max(35))
.array(z.string().max(100))
.max(4)
.optional()
.default([
"Ut enim ad minima veniam, quis nostrum",
"Exercitationem ullam corporis suscipit",
@ -44,7 +44,7 @@ export const Schema = z.object({
"exercitationem ullam corporis suscipit",
])
.meta({
description: "Bullet list shown in the lower-left area.",
description: "Optional bullet list shown after the description if required.",
}),
statColumns: z
.array(StatColumnSchema)

View file

@ -1,13 +1,13 @@
import * as z from "zod";
const MilestoneItemSchema = z.object({
stepNumber: z.string().min(2).max(4).meta({
bulletNumber: z.string().min(2).max(4).meta({
description: "Short milestone number such as 01 or 05.",
}),
heading: z.string().min(3).max(10).meta({
heading: z.string().min(3).max(30).meta({
description: "Heading displayed below the milestone marker.",
}),
description: z.string().min(20).max(50).meta({
description: z.string().min(10).max(80).meta({
description: "Supporting milestone description shown under the heading.",
}),
});
@ -26,37 +26,37 @@ export const Schema = z.object({
}),
items: z
.array(MilestoneItemSchema)
.min(5)
.min(1)
.max(5)
.default([
{
stepNumber: "01",
bulletNumber: "01",
heading: "Heading",
description: "Lorem ipsum dolor sit amet, consectetur adipiscing elit.",
},
{
stepNumber: "02",
bulletNumber: "02",
heading: "Heading",
description: "Lorem ipsum dolor sit amet, consectetur adipiscing elit.",
},
{
stepNumber: "03",
bulletNumber: "03",
heading: "Heading",
description: "Lorem ipsum dolor sit amet, consectetur adipiscing elit.",
},
{
stepNumber: "04",
bulletNumber: "04",
heading: "Heading",
description: "Lorem ipsum dolor sit amet, consectetur adipiscing elit.",
},
{
stepNumber: "05",
bulletNumber: "05",
heading: "Heading",
description: "Lorem ipsum dolor sit amet, consectetur adipiscing elit.",
},
])
.meta({
description: "Five milestone entries rendered across the slide.",
description: "Bullet with title and description.",
}),
});
@ -110,7 +110,7 @@ const MilestoneSlide = ({ data }: { data: Partial<SchemaType> }) => {
className={`${isActive ? "text-white" : "text-[#157CFF]"} text-[42px] font-medium tracking-[0.18em]`}
style={{ color: isActive ? "var(--primary-text,#ffffff)" : "var(--primary-color,#157CFF)" }}
>
{item.stepNumber}
{item.bulletNumber}
</span>
</div>
@ -130,8 +130,6 @@ const MilestoneSlide = ({ data }: { data: Partial<SchemaType> }) => {
);
})}
</div>
</div>
</div>
);

View file

@ -5,10 +5,10 @@ const MetricSchema = z.object({
value: z.string().min(1).max(6).meta({
description: "Primary metric value shown in the pill.",
}),
label: z.string().max(10).optional().meta({
label: z.string().max(20).optional().meta({
description: "Short label shown below the metric value.",
}),
description: z.string().min(6).max(20).optional().meta({
description: z.string().min(6).max(50).optional().meta({
description: "Supporting metric description shown below the label.",
}),
});
@ -19,18 +19,18 @@ const MetricColumnSchema = z.object({
}),
});
export const slideLayoutId = "performance-snapshot-slide";
export const slideLayoutName = "Performance Snapshot Slide";
export const slideLayoutId = "title-metrics-slide";
export const slideLayoutName = "Title Metrics Slide";
export const slideLayoutDescription =
"A slide with a title at the top and three tall metric cards arranged horizontally below it. Each card can contain one or two stacked metric blocks, and each block includes a main value, a label, and a supporting description.";
"A slide with a title at the top and tall metric cards arranged horizontally below it. Each card can contain one or two stacked metric blocks, and each block includes a main value, a label, and a supporting description.";
export const Schema = z.object({
title: z.string().min(3).max(12).default("Performance Snapshot").meta({
title: z.string().min(3).max(80).default("Performance Snapshot").meta({
description: "Slide title shown at the top-left.",
}),
columns: z
.array(MetricColumnSchema)
.min(2)
.min(1)
.max(4)
.default([
{
@ -50,12 +50,7 @@ export const Schema = z.object({
{ value: "25K", label: "Students", description: "Ut enim ad minima" },
{ value: "25K", label: "Students", description: "Ut enim ad minima" },
],
},
{
metrics: [
{ value: "25K", label: "Students", description: "Ut enim ad minima" },
],
},
}
])
.meta({
description: "Three metric columns displayed beneath the title.",
@ -77,8 +72,6 @@ function StatPill({
metrics: StatMetric[];
}) {
return (
<div
className=" h-[438px] w-[248px] overflow-hidden rounded-[127px] bg-[#157CFF] px-[28px] py-[74px] text-center text-white"
@ -148,7 +141,7 @@ const PerformanceSnapshotSlide = ({ data }: { data: Partial<SchemaType> }) => {
</h2>
</div>
<div className="mt-[44px] flex justify-start gap-[33px] pl-[94px]">
<div className="mt-[44px] flex justify-center gap-[33px]">
{columns?.map((column, index) => (
<StatPill
key={`snapshot-column-${index}`}

View file

@ -13,21 +13,21 @@ const ServiceItemSchema = z.object({
}).meta({
description: "Icon used for service circles.",
}),
heading: z.string().min(3).max(18).meta({
heading: z.string().min(3).max(30).meta({
description: "Heading shown below the service icon.",
}),
description: z.string().min(20).max(50).meta({
description: z.string().min(20).max(60).meta({
description: "Supporting description below the service heading.",
}),
});
export const slideLayoutId = "services-slide";
export const slideLayoutName = "Services Slide";
export const slideLayoutId = "title-workflow-with-title-description-slide";
export const slideLayoutName = "Title Workflow with Title Description Slide";
export const slideLayoutDescription =
"A slide with a title and a three-step horizontal service flow. Each step contains a circular icon area, a heading, and a description placed underneath. Directional connectors between the circles indicate sequence, and the activeIndex field determines which step is emphasized.";
"A slide with a title and a horizontal flow. Each step contains a circular icon area, a heading, and a description placed underneath. Directional connectors between the circles indicate sequence, and the activeIndex field determines which step is emphasized.";
export const Schema = z.object({
title: z.string().min(3).max(12).default("Services").meta({
title: z.string().min(3).max(50).default("Services").meta({
description: "Slide title shown at the top-left.",
}),
@ -36,7 +36,7 @@ export const Schema = z.object({
}),
items: z
.array(ServiceItemSchema)
.min(3)
.min(1)
.max(5)
.default([
{

View file

@ -1,26 +1,26 @@
import * as z from "zod";
export const slideLayoutId = "report-solution-slide";
export const slideLayoutName = "Report Solution Slide";
export const slideLayoutId = "title-image-bullet-cards-slide";
export const slideLayoutName = "Title Image Bullet Cards Slide";
export const slideLayoutDescription =
"A solution slide with a title at the top and a main content area below. The content area supports two structural modes controlled by the showImage boolean: when true, it places one image panel on the left and two numbered content cards on the right; when false, it removes the image and displays three numbered content cards arranged across the content area. Each card contains a short step label and a descriptive text block.";
"A slide with optional image on the left and cards with bullet on the right.";
const CardSchema = z.object({
stepNumber: z.string().min(2).max(4).meta({
description: "Short card step number such as 01, 02, or 03.",
bulletNumber: z.string().min(2).max(4).meta({
description: "Short description step number starting from 01...",
}),
description: z.string().min(20).max(50).meta({
description: "Card body copy displayed inside the feature pill.",
description: z.string().min(10).max(80).meta({
description: "Bullet point description shown inside the card.",
}),
});
export const Schema = z.object({
title: z.string().min(3).max(12).default("Solution").meta({
title: z.string().min(3).max(30).default("Solution").meta({
description: "Slide heading shown in the top-left corner.",
}),
showImage: z.boolean().default(true).meta({
description: "Controls whether the image is shown beside the cards.",
description: "Whether the image should be shown.",
}),
featureImage: z.object({
__image_url__: z.string().default("https://presenton-public.s3.ap-southeast-1.amazonaws.com/static/images/placeholder.jpg"),
@ -34,19 +34,19 @@ export const Schema = z.object({
}),
cards: z
.array(CardSchema)
.min(3)
.min(1)
.max(3)
.default([
{
stepNumber: "01",
bulletNumber: "01",
description: "Lorem ipsum dolor sit amet, consectetur adipiscing elit.",
},
{
stepNumber: "02",
bulletNumber: "02",
description: "Lorem ipsum dolor sit amet, consectetur adipiscing elit.",
},
{
stepNumber: "03",
bulletNumber: "03",
description: "Lorem ipsum dolor sit amet, consectetur adipiscing elit.",
},
])
@ -130,8 +130,8 @@ const SolutionSlide = ({ data }: SolutionSlideProps) => {
<div className="flex gap-[40px]">
{visibleCards?.map((card, index) => (
<SolutionCard
key={`${card.stepNumber}-${index}`}
stepNumber={card.stepNumber}
key={`${card.bulletNumber}-${index}`}
stepNumber={card.bulletNumber}
description={card.description}
/>
))}
@ -141,8 +141,8 @@ const SolutionSlide = ({ data }: SolutionSlideProps) => {
<div className="flex justify-center gap-[44px] pt-[6px]">
{visibleCards?.map((card, index) => (
<SolutionCard
key={`${card.stepNumber}-${index}`}
stepNumber={card.stepNumber}
key={`${card.bulletNumber}-${index}`}
stepNumber={card.bulletNumber}
description={card.description}
/>
))}

View file

@ -2,11 +2,11 @@ import * as z from "zod";
const MemberSchema = z.object({
title: z.string().min(2).max(12).meta({
description: "Short role or title shown above the member name.",
subtext: z.string().min(2).max(40).meta({
description: "Subtext for the image.",
}),
name: z.string().min(2).max(20).meta({
description: "Member name shown at the bottom of the card.",
title: z.string().min(2).max(40).meta({
description: "Title/name/subject for the image",
}),
image: z.object({
__image_url__: z.string().default("https://presenton-public.s3.ap-southeast-1.amazonaws.com/static/images/placeholder.jpg"),
@ -17,10 +17,10 @@ const MemberSchema = z.object({
}),
});
export const slideLayoutId = "team-slide";
export const slideLayoutName = "Team Slide";
export const slideLayoutId = "horizontal-height-spanning-images-with-title-slide";
export const slideLayoutName = "Horizontal Height Spanning Images with Title Slide";
export const slideLayoutDescription =
"A team slide made of five vertical portrait cards placed side by side from edge to edge. Each card uses a full-height image background with a content overlay at the bottom containing a short title line and a larger name line.";
"A slide of portrait cards placed side by side from edge to edge. Each card uses a full-height image background with a content overlay at the bottom containing a short subtext line and a larger title line.";
export const Schema = z.object({
members: z
@ -29,40 +29,40 @@ export const Schema = z.object({
.max(5)
.default([
{
title: "Title",
name: "Lanny LA",
subtext: "Title",
title: "Lanny LA",
image: {
__image_url__: "https://presenton-public.s3.ap-southeast-1.amazonaws.com/static/images/placeholder.jpg",
__image_prompt__: "Professional portrait of a male team member",
},
},
{
title: "Title",
name: "Lanny LA",
subtext: "Title",
title: "Lanny LA",
image: {
__image_url__: "https://presenton-public.s3.ap-southeast-1.amazonaws.com/static/images/placeholder.jpg",
__image_prompt__: "Professional portrait of a female team member",
},
},
{
title: "Title",
name: "Lanny LA",
subtext: "Title",
title: "Lanny LA",
image: {
__image_url__: "https://presenton-public.s3.ap-southeast-1.amazonaws.com/static/images/placeholder.jpg",
__image_prompt__: "Professional portrait of a business manager",
},
},
{
title: "Title",
name: "Lanny LA",
subtext: "Title",
title: "Lanny LA",
image: {
__image_url__: "https://presenton-public.s3.ap-southeast-1.amazonaws.com/static/images/placeholder.jpg",
__image_prompt__: "Professional portrait of a senior employee",
},
},
{
title: "Title",
name: "Lanny LA",
subtext: "Title",
title: "Lanny LA",
image: {
__image_url__: "https://presenton-public.s3.ap-southeast-1.amazonaws.com/static/images/placeholder.jpg",
__image_prompt__: "Professional portrait of a young executive",
@ -70,7 +70,7 @@ export const Schema = z.object({
},
])
.meta({
description: "Five team members rendered as portrait cards.",
description: "List of team members shown as portrait cards. Each member contains a title, subtext, and image.",
}),
});

View file

@ -1,14 +1,14 @@
import * as z from "zod";
export const slideLayoutId = "introduction-image-slide";
export const slideLayoutName = "Introduction Image Slide";
export const slideLayoutId = "title-description-image-slide";
export const slideLayoutName = "Title Description Image Slide";
export const slideLayoutDescription =
"A slide with a title at the top-left, a paragraph block beneath the title, a short bulleted list in the lower-left area, and a large supporting image anchored on the right side of the slide.";
"A slide with a title at the top-left, a paragraph block beneath the title, a large supporting image anchored on the right side of the slide.";
export const Schema = z.object({
title: z.string().min(3).max(12).default("Introduction").meta({
description: "Slide title shown at the top-left.",
description: "Title/heading of the slide",
}),
body: z.string().max(250).default(
"Ut enim ad minima veniam, quis nostrum exercitationem ullam corporis suscipit laboriosam, nisi ut alut enim ad minima veniam, quis. Ut enim ad minima veniam, quis nostrum exercitationem ullam corporis suscipit laboriosam, nisi ut alut enim ad minima veniam, quis"
@ -16,9 +16,10 @@ export const Schema = z.object({
description: "Primary paragraph shown under the title.",
}),
bullets: z
.array(z.string().max(35))
.array(z.string().max(100))
.min(0)
.max(4)
.optional()
.default([
"Ut enim ad minima veniam, quis nostrum",
"Exercitationem ullam corporis suscipit",
@ -26,7 +27,7 @@ export const Schema = z.object({
"exercitationem ullam corporis suscipit",
])
.meta({
description: "Bullet list shown in the lower-left area.",
description: "Optional bullet list shown after the description if required.",
}),
featureImage: z.object({
__image_url__: z.string(),