diff --git a/electron/servers/nextjs/app/globals.css b/electron/servers/nextjs/app/globals.css index 137382cc..aa9e7d95 100644 --- a/electron/servers/nextjs/app/globals.css +++ b/electron/servers/nextjs/app/globals.css @@ -84,7 +84,7 @@ strong { @font-face { font-family: 'Times New Roman'; - src: url('https: //presenton-public.s3.ap-southeast-1.amazonaws.com/static/fonts/times.ttf') format('truetype'); + src: url('https://presenton-public.s3.ap-southeast-1.amazonaws.com/static/fonts/times.ttf') format('truetype'); font-style: normal; font-display: swap; @@ -92,7 +92,7 @@ strong { @font-face { font-family: 'Helvetica Neue'; - src: url('https: //presenton-public.s3.ap-southeast-1.amazonaws.com/static/fonts/HelveticaNeueBold.otf') format('truetype'); + src: url('https://presenton-public.s3.ap-southeast-1.amazonaws.com/static/fonts/HelveticaNeue-Bold.otf') format('truetype'); font-weight: 600; font-style: normal; font-display: swap; @@ -100,7 +100,7 @@ strong { @font-face { font-family: 'Helvetica Neue'; - src: url('https: //presenton-public.s3.ap-southeast-1.amazonaws.com/static/fonts/HelveticaNeueMedium.otf') format('truetype'); + src: url('https://presenton-public.s3.ap-southeast-1.amazonaws.com/static/fonts/HelveticaNeue-Medium.otf') format('truetype'); font-weight: 500; font-style: normal; font-display: swap; @@ -108,7 +108,7 @@ strong { @font-face { font-family: 'Helvetica Neue'; - src: url('https: //presenton-public.s3.ap-southeast-1.amazonaws.com/static/fonts/HelveticaNeueRoman.otf') format('truetype'); + src: url('https://presenton-public.s3.ap-southeast-1.amazonaws.com/static/fonts/HelveticaNeue-Roman.otf') format('truetype'); font-weight: 400; font-style: normal; font-display: swap; diff --git a/electron/servers/nextjs/app/presentation-templates/Education/EducationAboutSlide.tsx b/electron/servers/nextjs/app/presentation-templates/Education/EducationAboutSlide.tsx index 4bb11c5d..72402f2c 100644 --- a/electron/servers/nextjs/app/presentation-templates/Education/EducationAboutSlide.tsx +++ b/electron/servers/nextjs/app/presentation-templates/Education/EducationAboutSlide.tsx @@ -1,22 +1,22 @@ import * as z from "zod"; -export const slideLayoutId = "education-about-slide"; -export const slideLayoutName = "Education About Slide"; +export const slideLayoutId = "about-slide"; +export const slideLayoutName = "About Slide"; export const slideLayoutDescription = - "A left text column with company introduction and a right-side visual grid made from one repeated image and tinted text panels."; + "A left text column with company/instructor/presenter/institute name and title introduction and a right-side visual grid made from one repeated image and tinted text panels."; export const Schema = z.object({ - companyName: z.string().min(3).max(22).default("Company Name").meta({ + name: z.string().min(3).max(22).default("Company Name").meta({ description: "Main heading in the left content column.", }), - intro: z.string().min(40).max(120).default( + intro: z.string().min(40).max(100).default( "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do eiusmod tempor incididunt ut labore et." ).meta({ description: "Bold intro text shown beneath the company heading.", }), body: z.string().min(120).max(280).default( - "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi." + "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat." ).meta({ description: "Body paragraph in the left content section.", }), @@ -28,23 +28,23 @@ export const Schema = z.object({ }), topFeatureImage: z.object({ __image_url__: z.string().default("https://images.unsplash.com/photo-1521737604893-d14cc237f11d?auto=format&fit=crop&w=1200&q=80"), - __image_prompt__: z.string().min(10).max(200).default("Office team collaboration"), + __image_prompt__: z.string().default("Office team collaboration"), }).default({ __image_url__: "https://images.unsplash.com/photo-1521737604893-d14cc237f11d?auto=format&fit=crop&w=1200&q=80", __image_prompt__: "Office team collaboration", }).meta({ - description: "Single image reused in the right-side visual grid.", + description: "Single image reused in the top right-side visual grid.", }), bottomFeatureImage: z.object({ __image_url__: z.string().default("https://images.unsplash.com/photo-1521737604893-d14cc237f11d?auto=format&fit=crop&w=1200&q=80"), - __image_prompt__: z.string().min(10).max(200).default("Office team collaboration"), + __image_prompt__: z.string().default("Office team collaboration"), }).default({ __image_url__: "https://images.unsplash.com/photo-1521737604893-d14cc237f11d?auto=format&fit=crop&w=1200&q=80", __image_prompt__: "Office team collaboration", }).meta({ - description: "Single image reused in the right-side visual grid.", + description: "Single image reused in the bottom right-side visual grid.", }), }); @@ -66,7 +66,7 @@ const EducationAboutSlide = ({ data }: { data: Partial }) => {

- {data.companyName} + {data.name}

{data.intro} diff --git a/electron/servers/nextjs/app/presentation-templates/Education/EducationContentSplitSlide.tsx b/electron/servers/nextjs/app/presentation-templates/Education/EducationContentSplitSlide.tsx index e12bb2a3..8be4223e 100644 --- a/electron/servers/nextjs/app/presentation-templates/Education/EducationContentSplitSlide.tsx +++ b/electron/servers/nextjs/app/presentation-templates/Education/EducationContentSplitSlide.tsx @@ -1,39 +1,50 @@ import * as z from "zod"; -export const slideLayoutId = "education-content-split-slide"; -export const slideLayoutName = "Education Content Split Slide"; +export const slideLayoutId = "content-split-slide"; +export const slideLayoutName = "Content Split Slide"; export const slideLayoutDescription = "A left collage built from one repeated image and a right content block containing heading, tagline, and paragraph text."; export const Schema = z.object({ - heading: z.string().min(3).max(16).default("Heading").meta({ + heading: z.string().max(24).default("Heading").meta({ description: "Main right-side heading.", }), - tagline: z.string().min(3).max(12).default("TAGLINE").meta({ + tagline: z.string().max(12).default("TAGLINE").meta({ description: "Small uppercase label shown under the heading.", }), - body: z.string().min(80).max(300).default( - "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat." + body: z.string().max(300).default( + "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat." ).meta({ description: "Main descriptive paragraph on the right side.", }), - collageImage: z.object({ + images: z.array(z.object({ __image_url__: z.string().default("https://images.unsplash.com/photo-1521737604893-d14cc237f11d?auto=format&fit=crop&w=1200&q=80"), - __image_prompt__: z.string().min(10).max(200).default("Business team around a laptop"), - }).default({ + __image_prompt__: z.string().default("Business team around a laptop"), + })).min(1).max(3).default([{ __image_url__: "https://images.unsplash.com/photo-1521737604893-d14cc237f11d?auto=format&fit=crop&w=1200&q=80", __image_prompt__: "Business team around a laptop", - }).meta({ - description: "Single image reused to create the left collage composition.", + }, + { + __image_url__: + "https://images.unsplash.com/photo-1521737604893-d14cc237f11d?auto=format&fit=crop&w=1200&q=80", + __image_prompt__: "Business team around a laptop", + }, + { + __image_url__: + "https://images.unsplash.com/photo-1521737604893-d14cc237f11d?auto=format&fit=crop&w=1200&q=80", + __image_prompt__: "Business team around a laptop", + }, + ]).meta({ + description: "Array of images reused to create the left collage composition.", }), }); export type SchemaType = z.infer; const EducationContentSplitSlide = ({ data }: { data: Partial }) => { - const { heading, tagline, body, collageImage } = data; + const { heading, tagline, body, images } = data; return (

}) =>
{collageImage?.__image_prompt__}
{collageImage?.__image_prompt__}
{collageImage?.__image_prompt__}
diff --git a/electron/servers/nextjs/app/presentation-templates/Education/EducationCoverSlide.tsx b/electron/servers/nextjs/app/presentation-templates/Education/EducationCoverSlide.tsx index d081716c..d8a1fa2a 100644 --- a/electron/servers/nextjs/app/presentation-templates/Education/EducationCoverSlide.tsx +++ b/electron/servers/nextjs/app/presentation-templates/Education/EducationCoverSlide.tsx @@ -1,21 +1,21 @@ import * as z from "zod"; -export const slideLayoutId = "education-cover-slide"; -export const slideLayoutName = "Education Cover Slide"; +export const slideLayoutId = "cover-slide"; +export const slideLayoutName = "Cover Slide"; export const slideLayoutDescription = - "A full-bleed cover slide with a single background image, a strong violet overlay, and centered company/title text."; + "A full-bleed cover slide with a single background image, a strong violet overlay, and centered company/instructor/presenter/institute name and title text."; export const Schema = z.object({ - companyName: z.string().min(3).max(24).default("COMPANY NAME").meta({ - description: "Small uppercase company label shown above the main title.", + name: z.string().min(3).max(16).optional().default("COMPANY NAME").meta({ + description: "Company/instructor/presenter/institute name label shown above the main title.", }), title: z.string().min(6).max(32).default("PowerPoint Template").meta({ description: "Main centered title of the cover slide.", }), backgroundImage: z.object({ __image_url__: z.string().default("https://images.unsplash.com/photo-1486406146926-c627a92ad1ab?auto=format&fit=crop&w=1920&q=80"), - __image_prompt__: z.string().min(10).max(200).default("City business district buildings"), + __image_prompt__: z.string().default("City business district buildings"), }).default({ __image_url__: "https://images.unsplash.com/photo-1486406146926-c627a92ad1ab?auto=format&fit=crop&w=1920&q=80", @@ -28,7 +28,7 @@ export const Schema = z.object({ export type SchemaType = z.infer; const EducationCoverSlide = ({ data }: { data: Partial }) => { - const { companyName, title, backgroundImage } = data; + const { name, title, backgroundImage } = data; return (
}) => { className="relative z-10 flex h-full flex-col items-center justify-center text-center" style={{ color: "var(--primary-text,#ffffff)" }} > -

{companyName}

-

+ {name &&

{name}

+ }

{title}

diff --git a/electron/servers/nextjs/app/presentation-templates/Education/EducationImageGallerySlide.tsx b/electron/servers/nextjs/app/presentation-templates/Education/EducationImageGallerySlide.tsx index 1d520d10..2423dfe7 100644 --- a/electron/servers/nextjs/app/presentation-templates/Education/EducationImageGallerySlide.tsx +++ b/electron/servers/nextjs/app/presentation-templates/Education/EducationImageGallerySlide.tsx @@ -1,17 +1,17 @@ import * as z from "zod"; -export const slideLayoutId = "education-image-gallery-slide"; -export const slideLayoutName = "Education Image Gallery Slide"; +export const slideLayoutId = "image-gallery-slide"; +export const slideLayoutName = "Image Gallery Slide"; export const slideLayoutDescription = - "A slide with a left image collage (one repeated image) and right text block for gallery heading and description."; + "A slide with a left image gallery and right text block for gallery heading and description."; export const Schema = z.object({ - title: z.string().min(3).max(16).default("Image Gallery").meta({ + title: z.string().max(24).default("Image Gallery").meta({ description: "Heading on the right side.", }), - body: z.string().min(70).max(200).default( - "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris." + body: z.string().max(300).default( + "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat." ).meta({ description: "Supporting paragraph shown below the heading.", }), diff --git a/electron/servers/nextjs/app/presentation-templates/Education/EducationReportChartSlide.tsx b/electron/servers/nextjs/app/presentation-templates/Education/EducationReportChartSlide.tsx index 3a75cfae..51532365 100644 --- a/electron/servers/nextjs/app/presentation-templates/Education/EducationReportChartSlide.tsx +++ b/electron/servers/nextjs/app/presentation-templates/Education/EducationReportChartSlide.tsx @@ -5,10 +5,10 @@ import EducationChartPrimitives, { type EducationChartType, } from "./EducationChartPrimitives"; -export const slideLayoutId = "education-report-chart-slide"; -export const slideLayoutName = "Education Report Chart Slide"; +export const slideLayoutId = "report-chart-slide"; +export const slideLayoutName = "Report Chart Slide"; export const slideLayoutDescription = - "A split education report slide with one unified schema that supports multiple Recharts chart types in the right panel."; + "A left text column with a report title, body, footnote and a right-side chart."; const ChartTypeSchema = z.enum([ "bar", @@ -25,7 +25,7 @@ const SimpleDataSchema = z.object({ name: z.string().min(1).max(20).meta({ description: "Simple chart category label.", }), - value: z.number().min(-100000).max(100000).meta({ + value: z.number().meta({ description: "Simple chart numeric value.", }), }); @@ -71,7 +71,7 @@ const UnifiedChartDataSchema = z.union([ ]); export const Schema = z.object({ - title: z.string().min(3).max(20).default("Report").meta({ + title: z.string().max(24).default("Report").meta({ description: "Left-side report title.", }), body: z.string().min(80).max(260).default( diff --git a/electron/servers/nextjs/app/presentation-templates/Education/EducationServicesSplitSlide.tsx b/electron/servers/nextjs/app/presentation-templates/Education/EducationServicesSplitSlide.tsx index d491e193..634a4ac4 100644 --- a/electron/servers/nextjs/app/presentation-templates/Education/EducationServicesSplitSlide.tsx +++ b/electron/servers/nextjs/app/presentation-templates/Education/EducationServicesSplitSlide.tsx @@ -1,13 +1,13 @@ import * as z from "zod"; -export const slideLayoutId = "education-services-split-slide"; -export const slideLayoutName = "Education Services Split Slide"; +export const slideLayoutId = "services-split-slide"; +export const slideLayoutName = "Services Split Slide"; export const slideLayoutDescription = - "A services layout with left heading, one repeated image column, and two stacked service description blocks on the right."; + "A left text column with a heading, one image column, and stacked service description blocks on the right side."; const ServiceSchema = z.object({ - serviceImage: z.object({ + image: z.object({ __image_url__: z.string(), __image_prompt__: z.string(), }).default({ @@ -15,30 +15,30 @@ const ServiceSchema = z.object({ "https://images.unsplash.com/photo-1521737604893-d14cc237f11d?auto=format&fit=crop&w=1200&q=80", __image_prompt__: "Team meeting image reused across two rows", }).meta({ - description: "Single image reused in the middle column.", + description: "Single image in the middle column.", }), heading: z.string().min(3).max(18).meta({ - description: "Service heading shown in the right column.", + description: "Heading shown in the right column.", }), tagline: z.string().min(3).max(12).meta({ - description: "Short label under each service heading.", + description: "Short label under each heading.", }), body: z.string().max(40).meta({ - description: "Service description paragraph.", + description: "Description paragraph shown below the heading and tagline.", }), }); export const Schema = z.object({ - title: z.string().min(4).max(12).default("Services").meta({ + title: z.string().max(16).default("Services").meta({ description: "Main slide title shown on the left.", }), sections: z .array(ServiceSchema) - .min(2) + .min(1) .max(4) .default([ { - serviceImage: { + image: { __image_url__: "https://images.unsplash.com/photo-1521737604893-d14cc237f11d?auto=format&fit=crop&w=1200&q=80", __image_prompt__: "Team meeting image reused across two rows", @@ -48,7 +48,7 @@ export const Schema = z.object({ body: "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do eiusmod tempor.", }, { - serviceImage: { + image: { __image_url__: "https://images.unsplash.com/photo-1521737604893-d14cc237f11d?auto=format&fit=crop&w=1200&q=80", __image_prompt__: "Team meeting image reused across two rows", @@ -58,7 +58,7 @@ export const Schema = z.object({ body: "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do eiusmod tempor.", }, { - serviceImage: { + image: { __image_url__: "https://images.unsplash.com/photo-1521737604893-d14cc237f11d?auto=format&fit=crop&w=1200&q=80", __image_prompt__: "Team meeting image reused across two rows", @@ -68,7 +68,7 @@ export const Schema = z.object({ body: "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do eiusmod tempor.", }, { - serviceImage: { + image: { __image_url__: "https://images.unsplash.com/photo-1521737604893-d14cc237f11d?auto=format&fit=crop&w=1200&q=80", __image_prompt__: "Team meeting image reused across two rows", @@ -128,8 +128,8 @@ const EducationServicesSplitSlide = ({ data }: { data: Partial }) => > {section.serviceImage.__image_prompt__}
diff --git a/electron/servers/nextjs/app/presentation-templates/Education/EducationStatisticsGridSlide.tsx b/electron/servers/nextjs/app/presentation-templates/Education/EducationStatisticsGridSlide.tsx index eefd401e..46ac18a1 100644 --- a/electron/servers/nextjs/app/presentation-templates/Education/EducationStatisticsGridSlide.tsx +++ b/electron/servers/nextjs/app/presentation-templates/Education/EducationStatisticsGridSlide.tsx @@ -1,27 +1,27 @@ import * as z from "zod"; -export const slideLayoutId = "education-statistics-grid-slide"; -export const slideLayoutName = "Education Statistics Grid Slide"; +export const slideLayoutId = "statistics-grid-slide"; +export const slideLayoutName = "Statistics Grid Slide"; export const slideLayoutDescription = - "A two-column layout with a left title block and a right 2x4 grid of statistics cards, using one subtle background image texture."; + "A left text column with a title, description and a right-side grid of statistics cards,value and label each in a card"; const StatisticSchema = z.object({ - value: z.string().min(1).max(8).meta({ - description: "Main metric value shown at the top of one card. with max 8 characters", + value: z.string().max(8).meta({ + description: "Main metric value shown at the top of one card.", }), - label: z.string().min(3).max(20).meta({ - description: "Label shown under the value. with max 20 characters", + label: z.string().max(20).meta({ + description: "Label shown under the value.", }), }); export const Schema = z.object({ - title: z.string().min(4).max(14).default("Statistics").meta({ - description: "Main title shown in the left column. with max 14 characters", + title: z.string().max(16).default("Statistics").meta({ + description: "Main title shown in the left column.", }), - description: z.string().min(40).max(120).default( - "Lorem ipsum dolor sit amet, consectetur adipiscing elit. with max 120 characters" + description: z.string().max(160).default( + "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Lorem ipsum dolor sit amet, consectetur adipiscing elit." ).meta({ - description: "Supporting line shown under the left title. with max 120 characters", + description: "Supporting line shown under the left title.", }), stats: z .array(StatisticSchema) @@ -38,7 +38,7 @@ export const Schema = z.object({ { value: "20", label: "Merchandising Team" }, ]) .meta({ - description: "Eight statistic cards. with max 8 cards", + description: "statistic cards, with value and label each in a card", }), }); @@ -58,10 +58,8 @@ const EducationStatisticsGridSlide = ({ data }: { data: Partial }) = fontFamily: "var(--body-font-family,'Times New Roman')", }} > - -
-
+

{data.title} @@ -89,22 +87,7 @@ const EducationStatisticsGridSlide = ({ data }: { data: Partial }) = ))}

} - {/* {stats && stats?.length > 4 && stats?.length <= 8 &&
- {stats?.map((stat, index) => ( -
-

- {stat.value} -

-

- {stat.label} -

-
- ))} -
} */} + {data.stats && data.stats?.length > 4 && data.stats?.length <= 8 && (() => { const rightArray = data.stats?.slice(0, Math.floor(data.stats?.length / 2)); @@ -112,7 +95,7 @@ const EducationStatisticsGridSlide = ({ data }: { data: Partial }) = return (
-
+
{leftArray?.map((stat: any, index: number) => (
}) = className="px-[52px] pt-[22px] h-full" style={{ backgroundColor: index % 2 === 0 ? 'var(--card-color,#5C0FD908)' : 'var(--card-color,white)' }} > -

+

{stat?.value}

@@ -129,9 +112,7 @@ const EducationStatisticsGridSlide = ({ data }: { data: Partial }) =

))}
- - -
+
{rightArray?.map((stat: any, index: number) => (
}) = className="px-[52px] pt-[22px] h-full" style={{ backgroundColor: index % 2 === 1 ? 'var(--card-color,#5C0FD908)' : 'var(--card-color,white)' }} > -

+

{stat.value}

diff --git a/electron/servers/nextjs/app/presentation-templates/Education/EducationTableOfContentsSlide.tsx b/electron/servers/nextjs/app/presentation-templates/Education/EducationTableOfContentsSlide.tsx index f7d900b2..9204630b 100644 --- a/electron/servers/nextjs/app/presentation-templates/Education/EducationTableOfContentsSlide.tsx +++ b/electron/servers/nextjs/app/presentation-templates/Education/EducationTableOfContentsSlide.tsx @@ -1,8 +1,8 @@ import * as z from "zod"; -export const slideLayoutId = "education-table-of-contents-slide"; -export const slideLayoutName = "Education Table Of Contents Slide"; +export const slideLayoutId = "table-of-contents-slide"; +export const slideLayoutName = "Table Of Contents Slide"; export const slideLayoutDescription = "A split layout with a left title panel and a right list of numbered sections, with one subtle background image overlay."; @@ -16,28 +16,27 @@ const TocItemSchema = z.object({ }); export const Schema = z.object({ - titleLine1: z.string().min(4).max(12).default("Table of").meta({ - description: "First line of the left-side heading.", - }), - titleLine2: z.string().min(4).max(12).default("Contents").meta({ - description: "Second line of the left-side heading.", + title: z.string().min(6).max(32).default("Table of Contents").meta({ + description: "Main centered title of the table of contents slide.", }), items: z .array(TocItemSchema) - .min(8) - .max(8) + .min(1) + .max(10) .default([ - { number: "03", label: "ABOUT" }, - { number: "04", label: "TIMELINE" }, - { number: "05", label: "GROUP OF COMPANIES" }, - { number: "06", label: "SERVICES" }, - { number: "07", label: "IMAGE GALLERY" }, - { number: "08", label: "STATISTICS" }, - { number: "09", label: "REPORT" }, - { number: "10", label: "CONCLUSION" }, + { number: "01", label: "ABOUT" }, + { number: "02", label: "TIMELINE" }, + { number: "03", label: "GROUP OF COMPANIES" }, + { number: "04", label: "SERVICES" }, + { number: "05", label: "IMAGE GALLERY" }, + { number: "06", label: "STATISTICS" }, + { number: "07", label: "REPORT" }, + { number: "08", label: "CONCLUSION" }, + { number: "09", label: "QUESTIONS" }, + { number: "10", label: "CONTACT" }, ]) .meta({ - description: "Eight table-of-content entries listed on the right.", + description: "table-of-content entries listed on the right.", }), }); @@ -59,9 +58,7 @@ const EducationTableOfContentsSlide = ({ data }: { data: Partial })

- {data.titleLine1} -
- {data.titleLine2} + {data.title}

diff --git a/electron/servers/nextjs/app/presentation-templates/Education/EducationTimelineSlide.tsx b/electron/servers/nextjs/app/presentation-templates/Education/EducationTimelineSlide.tsx index 86b1fcc8..85777e53 100644 --- a/electron/servers/nextjs/app/presentation-templates/Education/EducationTimelineSlide.tsx +++ b/electron/servers/nextjs/app/presentation-templates/Education/EducationTimelineSlide.tsx @@ -1,16 +1,16 @@ import * as z from "zod"; -export const slideLayoutId = "education-timeline-slide"; -export const slideLayoutName = "Education Timeline Slide"; +export const slideLayoutId = "timeline-slide"; +export const slideLayoutName = "Timeline Slide"; export const slideLayoutDescription = - "A timeline slide with a title, a horizontal progress line, and year-based milestones with short descriptions."; + "A slide with a title, a horizontal progress line, and short heading and description pairs."; const MilestoneSchema = z.object({ - year: z.string().min(4).max(6).meta({ - description: "Year label displayed under each timeline marker.", + heading: z.string().max(6).meta({ + description: "Heading displayed under each timeline marker.", }), - description: z.string().min(20).max(50).meta({ - description: "Short text shown under each year label.", + description: z.string().max(50).meta({ + description: "Short text shown under each heading. with max 50 characters", }), }); @@ -20,20 +20,17 @@ export const Schema = z.object({ }), milestones: z .array(MilestoneSchema) - .min(6) + .min(2) .max(12) .default([ - { year: "2022", description: "Lorem ipsum dolor sit amet, consectetur adipiscing elit." }, - { year: "1994", description: "Lorem ipsum dolor sit amet, consectetur adipiscing elit." }, - { year: "1993", description: "Lorem ipsum dolor sit amet, consectetur adipiscing elit." }, - { year: "1991", description: "Lorem ipsum dolor sit amet, consectetur adipiscing elit." }, - { year: "1991", description: "Lorem ipsum dolor sit amet, consectetur adipiscing elit." }, - { year: "1988", description: "Lorem ipsum dolor sit amet, consectetur adipiscing elit. " }, - { year: "1988", description: "Lorem ipsum dolor sit amet, consectetur adipiscing elit." }, - { year: "1988", description: "Lorem ipsum dolor sit amet, consectetur adipiscing elit." }, - { year: "1988", description: "Lorem ipsum dolor sit amet, consectetur adipiscing elit." }, - { year: "1988", description: "Lorem ipsum dolor sit amet, consectetur adipiscing elit." }, - { year: "1988", description: "Lorem ipsum dolor sit amet, consectetur adipiscing elit." }, + { heading: "2022", description: "Lorem ipsum dolor sit amet, consectetur adipiscing elit." }, + { heading: "1994", description: "Lorem ipsum dolor sit amet, consectetur adipiscing elit." }, + { heading: "1993", description: "Lorem ipsum dolor sit amet, consectetur adipiscing elit." }, + { heading: "1991", description: "Lorem ipsum dolor sit amet, consectetur adipiscing elit." }, + { heading: "1991", description: "Lorem ipsum dolor sit amet, consectetur adipiscing elit." }, + { heading: "1988", description: "Lorem ipsum dolor sit amet, consectetur adipiscing elit. " }, + { heading: "1988", description: "Lorem ipsum dolor sit amet, consectetur adipiscing elit." }, + { heading: "1988", description: "Lorem ipsum dolor sit amet, consectetur adipiscing elit." }, ]) .meta({ description: "Timeline milestones displayed left to right.", @@ -50,7 +47,7 @@ const EducationTimelineSlide = ({ data }: { data: Partial }) => { return (
+
{milestones.map((milestone: any, index: number) => ( -
+
{index !== milestones.length - 1 &&
}

- {milestone.year} + {milestone.heading}

{milestone.description} @@ -130,7 +127,7 @@ function TimelineMoreThanSix({ style={{ gridTemplateColumns: `repeat(${topItems.length}, minmax(0, 1fr))` }} > {topItems.map((milestone: any, index: number) => ( -

+
@@ -139,7 +136,7 @@ function TimelineMoreThanSix({

- {milestone.year} + {milestone.heading}

{milestone.description} @@ -162,7 +159,7 @@ function TimelineMoreThanSix({ if (!item) return

; return ( -
+
{/* {colIndex === 0 &&
} */}
@@ -171,7 +168,7 @@ function TimelineMoreThanSix({

- {item.year} + {item.heading}

{item.description} diff --git a/electron/servers/nextjs/app/presentation-templates/ProductOverview/BusinessChallengesCardsSlide.tsx b/electron/servers/nextjs/app/presentation-templates/ProductOverview/BusinessChallengesCardsSlide.tsx index 2d3e2191..f0e05180 100644 --- a/electron/servers/nextjs/app/presentation-templates/ProductOverview/BusinessChallengesCardsSlide.tsx +++ b/electron/servers/nextjs/app/presentation-templates/ProductOverview/BusinessChallengesCardsSlide.tsx @@ -2,16 +2,16 @@ import * as z from "zod"; -export const slideLayoutId = "product-overview-business-challenges-cards-slide"; -export const slideLayoutName = "Product Overview Business Challenges Cards Slide"; +export const slideLayoutId = "title-description-with-cards-text-slide"; +export const slideLayoutName = "Title Description with Cards to Text Slide"; export const slideLayoutDescription = - "A business challenges slide with headline and tagline on the left, a large supporting image in the top-right area, and three vertical detail cards across the lower center-right section."; + "A slide with a title on top and a description below, and a content section containing cards of text."; const CardSchema = z.object({ - heading: z.string().min(4).max(12).meta({ + heading: z.string().max(16).meta({ description: "Card heading for one challenge column.", }), - body: z.string().max(40).meta({ + body: z.string().max(45).meta({ description: "Card body copy for one challenge column.", }), dark: z.boolean().default(false).meta({ @@ -20,13 +20,13 @@ const CardSchema = z.object({ }); export const Schema = z.object({ - title: z.string().min(8).max(24).default("Business Challenges").meta({ - description: "Main slide title.", + title: z.string().min(8).max(16).default("Business Challenges").meta({ + description: "Main slide title. Max 16 characters.", }), - taglineLabel: z.string().min(3).max(10).default("TAGLINE").meta({ + taglineLabel: z.string().max(16).default("TAGLINE").meta({ description: "Short label above the left-side paragraph.", }), - taglineBody: z.string().max(80).default( + taglineBody: z.string().max(100).default( "Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea." ).meta({ description: "Supporting paragraph on the left side.", @@ -76,13 +76,13 @@ const BusinessChallengesCardsSlide = ({ data }: { data: Partial }) = <>

-
+

; const BusinessChallengesGridSlide = ({ data }: { data: Partial }) => { - const { title, challenges } = data; + const { title, blocks } = data; return ( <>
}) => className="grid grid-cols-2 justify-between items-center flex-1 gap-y-[63px] px-[84px] py-[70px] gap-x-[63px]" style={{ backgroundColor: "var(--primary-color,#15342D)" }} > - {challenges?.map((challenge, index) => ( + {blocks?.map((block, index) => (

- {challenge.heading} + {block.heading}

- {challenge.body} + {block.body}

))} diff --git a/electron/servers/nextjs/app/presentation-templates/ProductOverview/ComparisonChartSlide.tsx b/electron/servers/nextjs/app/presentation-templates/ProductOverview/ComparisonChartSlide.tsx index a2ac164a..aad81772 100644 --- a/electron/servers/nextjs/app/presentation-templates/ProductOverview/ComparisonChartSlide.tsx +++ b/electron/servers/nextjs/app/presentation-templates/ProductOverview/ComparisonChartSlide.tsx @@ -1,25 +1,52 @@ import * as z from "zod"; -export const slideLayoutId = "product-overview-comparison-chart-slide"; -export const slideLayoutName = "Product Overview Comparison Chart Slide"; +export const slideLayoutId = "title-description-with-table-slide"; +export const slideLayoutName = "Title Description with Table Slide"; export const slideLayoutDescription = - "A comparison table slide with a headline, short description, four column headers, and three data rows using check, cross, or empty cells."; + "A slide with a title on top and a description below, and a content section containing a table with column headers and rows of text content."; const CellStatusSchema = z.enum(["check", "cross", "empty"]); -const RowSchema = z.object({ - label: z.string().min(4).max(18).meta({ +const GeneralRowSchema = z.object({ + label: z.string().max(18).meta({ description: "Row heading shown in the first column.", }), - cell1: CellStatusSchema.default("check"), - cell2: CellStatusSchema.default("empty"), - cell3: CellStatusSchema.default("check"), - cell4: CellStatusSchema.default("empty"), + cells: z.array(CellStatusSchema).min(1).max(8).meta({ + description: "Status cells aligned with the table columns.", + }), }); +const LegacyRowSchema = z.object({ + label: z.string().max(18).meta({ + description: "Row heading shown in the first column.", + }), + cell1: CellStatusSchema.optional(), + cell2: CellStatusSchema.optional(), + cell3: CellStatusSchema.optional(), + cell4: CellStatusSchema.optional(), +}); + +const RowSchema = z.union([GeneralRowSchema, LegacyRowSchema]); + +const DEFAULT_COLUMNS = ["HEADING 1", "HEADING 2", "HEADING 3", "HEADING 4"]; +const DEFAULT_ROWS: z.infer[] = [ + { + label: "HEADING 1", + cells: ["check", "cross", "check", "cross"], + }, + { + label: "HEADING 1", + cells: ["check", "empty", "check", "empty"], + }, + { + label: "HEADING 2", + cells: ["check", "check", "check", "check"], + }, +]; + export const Schema = z.object({ - title: z.string().min(8).max(20).default("Comparison Chart").meta({ + title: z.string().max(14).default("Comparison Chart").meta({ description: "Main heading shown above the table.", }), subtitle: z.string().max(80).default( @@ -28,42 +55,23 @@ export const Schema = z.object({ description: "Short subtitle shown under the main heading.", }), columns: z - .array(z.string().min(4).max(18)) - .min(4) + .array(z.string().max(18)) + .min(1) .max(4) - .default(["HEADING 1", "HEADING 1", "HEADING 2", "HEADING 3"]) + .default(DEFAULT_COLUMNS) .meta({ - description: "Four table column headings.", + description: "Table column headings.", }), + highlightedColumnIndex: z.number().int().min(1).max(8).default(4).meta({ + description: "1-based column index for the dark highlighted table header.", + }), rows: z .array(RowSchema) - + .min(1) .max(3) - .default([ - { - label: "HEADING 1", - cell1: "check", - cell2: "cross", - cell3: "check", - cell4: "cross", - }, - { - label: "HEADING 1", - cell1: "check", - cell2: "empty", - cell3: "check", - cell4: "empty", - }, - { - label: "HEADING 2", - cell1: "check", - cell2: "check", - cell3: "check", - cell4: "check", - }, - ]) + .default(DEFAULT_ROWS) .meta({ - description: "Three table rows with status indicators.", + description: "Table rows with status indicators. Prefer the `cells` array format.", }), checkIcon: z.object({ __icon_url__: z.string(), @@ -88,6 +96,7 @@ export const Schema = z.object({ }); export type SchemaType = z.infer; +type CellStatus = z.infer; function StatusIcon({ status, @@ -114,13 +123,46 @@ function StatusIcon({ } const ComparisonChartSlide = ({ data }: { data: Partial }) => { - const { title, subtitle, columns, rows, checkIcon, crossIcon } = data; + const { + title, + subtitle, + columns, + highlightedColumnIndex, + rows, + checkIcon, + crossIcon, + } = data; + const safeColumns = columns && columns.length > 0 ? columns : DEFAULT_COLUMNS; + const resolvedHighlightedColumnIndex = + highlightedColumnIndex && + highlightedColumnIndex >= 1 && + highlightedColumnIndex <= safeColumns.length + ? highlightedColumnIndex + : Math.min(4, safeColumns.length); + const safeRows = rows && rows.length > 0 ? rows : DEFAULT_ROWS; + const normalizedRows = safeRows.map((row) => { + const rowCells = + "cells" in row + ? row.cells + : [row.cell1, row.cell2, row.cell3, row.cell4].filter( + (cell): cell is CellStatus => typeof cell !== "undefined" + ); + + return { + label: row.label, + cells: Array.from( + { length: safeColumns.length }, + (_, cellIndex) => rowCells[cellIndex] ?? "empty" + ), + }; + }); + const tableGridColumns = `220px repeat(${safeColumns.length}, minmax(0, 1fr))`; return ( <>
}) => {

-
+
-
- {columns?.map((column, index) => ( +
+ {safeColumns.map((column, index) => (
}) => { ))}
- {rows?.map((row, index) => { - const cells: ("check" | "cross" | "empty")[] = [ - row.cell1, - row.cell2, - row.cell3, - row.cell4, - ]; - + {normalizedRows.map((row, index) => { return (
}) => { {row.label}
- {cells?.map((status, cellIndex) => ( + {row.cells.map((status, cellIndex) => (
[] = [ + { + cells: [ + "Lorem ipsum dolor sit.", + "Lorem ipsum dolor sit.", + "Lorem ipsum dolor sit.", + "Lorem ipsum dolor sit.", + ], + }, + { + cells: [ + "Lorem ipsum dolor sit.", + "Lorem ipsum dolor sit.", + "Lorem ipsum dolor sit.", + "Lorem ipsum dolor sit.", + ], + }, + { + cells: [ + "Lorem ipsum dolor sit.", + "Lorem ipsum dolor sit.", + "Lorem ipsum dolor sit.", + "Lorem ipsum dolor sit.", + ], + }, +]; + export const Schema = z.object({ - title: z.string().min(8).max(20).default("Comparison Chart").meta({ + title: z.string().max(14).default("Comparison Chart").meta({ description: "Main heading shown above the table.", }), subtitle: z @@ -34,41 +66,23 @@ export const Schema = z.object({ description: "Short subtitle shown under the main heading.", }), columns: z - .array(z.string().max(10)) - .max(4) - .default(["HEADING 1", "HEADING 1", "HEADING 2", "HEADING 3"]) + .array(z.string().max(20)) + .min(1) + .max(8) + .default(DEFAULT_COLUMNS) .meta({ - description: "Four table column headings.", + description: "Table column headings.", }), - highlightedHeaderIndex: z.number().int().min(1).max(4).default(4).meta({ + highlightedHeaderIndex: z.number().int().min(1).max(8).default(4).meta({ description: "1-based column index for the dark highlighted table header.", }), rows: z .array(RowSchema) - .min(3) - .max(3) - .default([ - { - cell1: "Lorem ipsum dolor sit.", - cell2: "Lorem ipsum dolor sit.", - cell3: "Lorem ipsum dolor sit.", - cell4: "Lorem ipsum dolor sit.", - }, - { - cell1: "Lorem ipsum dolor sit.", - cell2: "Lorem ipsum dolor sit.", - cell3: "Lorem ipsum dolor sit.", - cell4: "Lorem ipsum dolor sit.", - }, - { - cell1: "Lorem ipsum dolor sit.", - cell2: "Lorem ipsum dolor sit.", - cell3: "Lorem ipsum dolor sit.", - cell4: "Lorem ipsum dolor sit.", - }, - ]) + .min(1) + .max(6) + .default(DEFAULT_ROWS) .meta({ - description: "Three table rows of text content.", + description: "Table rows of text content. Prefer the `cells` array format.", }), }); @@ -76,12 +90,33 @@ export type SchemaType = z.infer; const ComparisonTableWithTextSlide = ({ data }: { data: Partial }) => { const { title, subtitle, columns, highlightedHeaderIndex, rows } = data; + const safeColumns = columns && columns.length > 0 ? columns : DEFAULT_COLUMNS; + const resolvedHighlightedHeaderIndex = + highlightedHeaderIndex && + highlightedHeaderIndex >= 1 && + highlightedHeaderIndex <= safeColumns.length + ? highlightedHeaderIndex + : Math.min(4, safeColumns.length); + const safeRows = rows && rows.length > 0 ? rows : DEFAULT_ROWS; + const normalizedRows = safeRows.map((row) => { + const rowCells = + "cells" in row + ? row.cells + : [row.cell1, row.cell2, row.cell3, row.cell4].filter( + (cell): cell is string => typeof cell === "string" + ); + + return Array.from( + { length: safeColumns.length }, + (_, cellIndex) => rowCells[cellIndex] ?? "" + ); + }); return ( <>
}) = > - {columns?.map((column, index) => { - const isHighlighted = index + 1 === highlightedHeaderIndex; + {safeColumns.map((column, index) => { + const isHighlighted = index + 1 === resolvedHighlightedHeaderIndex; return ( }) = - {rows?.map((row, rowIndex) => { - const cells = [row.cell1, row.cell2, row.cell3, row.cell4]; - const isHighlighted = rowIndex + 1 === highlightedHeaderIndex; - + {normalizedRows.map((cells, rowIndex) => { return ( {cells?.map((cell, cellIndex) => ( @@ -148,12 +180,8 @@ const ComparisonTableWithTextSlide = ({ data }: { data: Partial }) = className=" border-r border-t bg-white p-[33px] text-left text-[18px] leading-[1.2] last:border-r-0" style={{ borderColor: "var(--stroke,#bcc3c3)", - backgroundColor: isHighlighted - ? "var(--primary-color,#05443a)" - : "var(--card-color,#ffffff)", - color: isHighlighted - ? "var(--primary-text,#eef2f0)" - : "var(--primary-color,#123f38)", + backgroundColor: "var(--card-color,#ffffff)", + color: "var(--primary-color,#123f38)", }} > {cell} diff --git a/electron/servers/nextjs/app/presentation-templates/ProductOverview/CoverSlide.tsx b/electron/servers/nextjs/app/presentation-templates/ProductOverview/CoverSlide.tsx index 22a02183..acb54d8f 100644 --- a/electron/servers/nextjs/app/presentation-templates/ProductOverview/CoverSlide.tsx +++ b/electron/servers/nextjs/app/presentation-templates/ProductOverview/CoverSlide.tsx @@ -2,23 +2,23 @@ import * as z from "zod"; -export const slideLayoutId = "product-overview-cover-slide"; -export const slideLayoutName = "Product Overview Cover Slide"; +export const slideLayoutId = "cover-slide"; +export const slideLayoutName = "Cover Slide"; export const slideLayoutDescription = - "A cover slide with a compact logo in the top-left, a date in the top-right, a two-line centered title, and a city/building image anchored to the bottom with a soft fade into the background."; + "A cover slide with a compact logo in the top-left, a date/text/label in the top-right, a centered title, and a image anchored to the bottom with a soft fade into the background."; export const Schema = z.object({ - logoImage: z.object({ + image: z.object({ __image_url__: z.string().default("https://presenton-public.s3.ap-southeast-1.amazonaws.com/static/images/placeholder.jpg"), - __image_prompt__: z.string().min(10).max(100).default("Professional logo of the company"), - }).default({ + __image_prompt__: z.string().default("Image of the company"), + }).optional().default({ __image_url__: "https://presenton-public.s3.ap-southeast-1.amazonaws.com/static/images/placeholder.jpg", - __image_prompt__: "Professional logo of the company", + __image_prompt__: "Image of the company", }), - label: z.string().min(3).max(16).default("MARCH 2026").meta({ - description: "Date label shown at the top-right corner.", + label: z.string().min(3).max(16).optional().default("MARCH 2026").meta({ + description: "Date/text/label shown at the top-right corner.", }), titleLine1: z.string().min(3).max(18).default("Social Media").meta({ description: "First line of the cover title.", @@ -39,13 +39,12 @@ export type SchemaType = z.infer; const CoverSlide = ({ data }: { data: Partial }) => { - const { logoImage, label, titleLine1, titleLine2, backgroundImage } = data; return ( <>
}) => { >
- {logoImage?.__image_prompt__ + /> :

}

- {label} + {data.label || ''}

@@ -75,17 +74,17 @@ const CoverSlide = ({ data }: { data: Partial }) => {

- {titleLine1} + {data.titleLine1}
- {titleLine2} + {data.titleLine2}

- {backgroundImage?.__image_url__ && ( + {data.backgroundImage?.__image_url__ && ( {backgroundImage.__image_prompt__ )} diff --git a/electron/servers/nextjs/app/presentation-templates/ProductOverview/ImageGallerySlide.tsx b/electron/servers/nextjs/app/presentation-templates/ProductOverview/ImageGallerySlide.tsx index b8e49b0f..cf5c27a0 100644 --- a/electron/servers/nextjs/app/presentation-templates/ProductOverview/ImageGallerySlide.tsx +++ b/electron/servers/nextjs/app/presentation-templates/ProductOverview/ImageGallerySlide.tsx @@ -1,17 +1,17 @@ import * as z from "zod"; -export const slideLayoutId = "product-overview-image-gallery-slide"; -export const slideLayoutName = "Product Overview Image Gallery Slide"; +export const slideLayoutId = "title-description-with-image-gallery-slide"; +export const slideLayoutName = "Title Description with Image Gallery Slide"; export const slideLayoutDescription = - "A gallery slide with a title and paragraph on the left and a five-image collage on the right and bottom."; + "A text slide with a title on top and a description below, and a section containing a gallery of images."; export const Schema = z.object({ title: z.string().max(12).default("Image Gallery").meta({ - description: "Main gallery heading.", + description: "Main Title of the slide", }), - description: z.string().max(80).default( - "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do eiusmod tempor incididunt ut labore." + description: z.string().max(120).default( + "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do eiusmod tempor incididunt ut labore. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do eiusmod tempor incididunt ut labore." ).meta({ description: "Supporting paragraph shown under the title.", }), @@ -88,7 +88,7 @@ const ImageGallerySlide = ({ data }: { data: Partial }) => { <>
}) => {
-
+
{bottomWideImage?.__image_prompt__} }) => { <>
}) => { <>
}) => { className="flex h-[55px] w-[55px] items-center justify-center rounded-full bg-[#15342D]" style={{ backgroundColor: "var(--primary-color,#15342D)" }} > - {kpiIcon?.__icon_query__} */} + +

}) => { <>

}) => { <>
}) => { className="h-[244px] w-full object-cover" />
; const MissionVisionSlide = ({ data }: { data: Partial }) => { - const { title, missionLabel, missionBody, visionLabel, visionBody, image } = data; return ( <>
}) => { className="text-[80px] font-semibold leading-[108.4%] tracking-[-2.419px] text-[#15342D]" style={{ color: "var(--primary-color,#15342D)" }} > - {title} + {data.title}

@@ -71,13 +70,13 @@ const MissionVisionSlide = ({ data }: { data: Partial }) => { className="text-[20px] font-semibold tracking-[2.074px] text-white" style={{ color: "var(--primary-text,#edf2f1)" }} > - {missionLabel} + {data.topleftTextBlockLabel}

- {missionBody} + {data.topleftTextBlockBody}

@@ -89,24 +88,23 @@ const MissionVisionSlide = ({ data }: { data: Partial }) => { className="text-[20px] font-semibold tracking-[2.074px] text-white" style={{ color: "var(--primary-text,#edf2f1)" }} > - {visionLabel} + {data.bottomleftTextBlockLabel}

- {visionBody} + {data.bottomleftTextBlockBody}

- - {image?.__image_url__ && ( + {data.image?.__image_url__ && ( {image.__image_prompt__} )} diff --git a/electron/servers/nextjs/app/presentation-templates/ProductOverview/OurServicesSlide.tsx b/electron/servers/nextjs/app/presentation-templates/ProductOverview/OurServicesSlide.tsx index 25d76baf..d2adc108 100644 --- a/electron/servers/nextjs/app/presentation-templates/ProductOverview/OurServicesSlide.tsx +++ b/electron/servers/nextjs/app/presentation-templates/ProductOverview/OurServicesSlide.tsx @@ -1,28 +1,28 @@ import * as z from "zod"; -export const slideLayoutId = "product-overview-our-services-slide"; -export const slideLayoutName = "Product Overview Our Services Slide"; +export const slideLayoutId = "title-description-with-image-block-slide"; +export const slideLayoutName = "Title Description with Image Block Slide"; export const slideLayoutDescription = - "A services slide with title and intro copy on the left, a large image below, and a two-by-two service card matrix on the right."; + "A slide with a title on top and a description below, and a content section containing an image and a grid of cards of text."; -const ServiceSchema = z.object({ - heading: z.string().min(4).max(12).meta({ - description: "Service card heading.", +const CardSchema = z.object({ + heading: z.string().max(16).meta({ + description: "Card heading.", }), body: z.string().max(30).meta({ - description: "Service card short description.", + description: "Card short description.", }), - dark: z.boolean().default(false).meta({ - description: "Whether this service card uses the dark style.", + isHighlighted: z.boolean().default(false).meta({ + description: "Whether this card uses the dark style.", }), }); export const Schema = z.object({ - title: z.string().min(6).max(12).default("Our Services").meta({ + title: z.string().max(16).default("Our Services").meta({ description: "Main heading shown at the top-left.", }), - taglineLabel: z.string().min(3).max(10).default("TAGLINE").meta({ + taglineLabel: z.string().max(16).default("TAGLINE").meta({ description: "Small label above left paragraph.", }), taglineBody: z.string().max(30).default( @@ -41,17 +41,17 @@ export const Schema = z.object({ description: "Main image shown at the lower left side.", }), services: z - .array(ServiceSchema) + .array(CardSchema) .max(4) .default([ - { heading: "HEADING 1", body: "Lorem ipsum dolor sit amet, consectetur", dark: false }, - { heading: "HEADING 2", body: "Lorem ipsum dolor sit amet, consectetur", dark: true }, - { heading: "HEADING 3", body: "Lorem ipsum dolor sit amet, consectetur", dark: false }, - { heading: "HEADING 4", body: "Lorem ipsum dolor sit amet, consectetur", dark: false }, + { heading: "HEADING 1", body: "Lorem ipsum dolor sit amet, consectetur", isHighlighted: false }, + { heading: "HEADING 2", body: "Lorem ipsum dolor sit amet, consectetur", isHighlighted: true }, + { heading: "HEADING 3", body: "Lorem ipsum dolor sit amet, consectetur", isHighlighted: false }, + { heading: "HEADING 4", body: "Lorem ipsum dolor sit amet, consectetur", isHighlighted: false }, ]) .meta({ - description: "Four service cards rendered on the right side.", + description: "Cards rendered on the right side.", }), }); @@ -64,7 +64,7 @@ const OurServicesSlide = ({ data }: { data: Partial }) => { <>
}) => {
- {services?.map((service, index) => ( + {services?.map((card, index) => (
}) => {

- {service.heading} + {card.heading}

- {service.body} + {card.body}

))} diff --git a/electron/servers/nextjs/app/presentation-templates/ProductOverview/PricingPlanSlide.tsx b/electron/servers/nextjs/app/presentation-templates/ProductOverview/PricingPlanSlide.tsx index 95b10c34..370c360c 100644 --- a/electron/servers/nextjs/app/presentation-templates/ProductOverview/PricingPlanSlide.tsx +++ b/electron/servers/nextjs/app/presentation-templates/ProductOverview/PricingPlanSlide.tsx @@ -1,10 +1,11 @@ +import { RemoteSvgIcon } from "@/app/hooks/useRemoteSvgIcon"; import * as z from "zod"; -export const slideLayoutId = "product-overview-pricing-plan-slide"; -export const slideLayoutName = "Product Overview Pricing Plan Slide"; +export const slideLayoutId = "title-cards-list-with-text-slide"; +export const slideLayoutName = "Title with Cards List with Text"; export const slideLayoutDescription = - "A three-column pricing slide with one emphasized center plan and feature bullet lists for each plan."; + "A slide with a title on top and a content section containing a list of cards with text content."; const PlanSchema = z.object({ price: z.string().min(4).max(12).meta({ @@ -14,7 +15,7 @@ const PlanSchema = z.object({ description: "Short statement describing the plan.", }), features: z - .array(z.string().max(14)) + .array(z.string().max(16)) .max(4) .meta({ @@ -91,7 +92,7 @@ const PricingPlanSlide = ({ data }: { data: Partial }) => { <>
}) => {
{plan.features.map((feature, featureIndex) => (
- + {/* {featureIcon?.__icon_query__} + /> */}

}) => { <>

-
+

}) => { {title}

- - - -
+
{steps?.map((step, index) => { if (index % 2 === 0) { return ( @@ -109,11 +107,17 @@ const ProcessSlide = ({ data }: { data: Partial }) => { >
- {step.icon.__icon_query__} +
+ + +
+ @@ -168,7 +172,15 @@ const ProcessSlide = ({ data }: { data: Partial }) => { - {step.icon.__icon_query__} +
+ +
diff --git a/electron/servers/nextjs/app/presentation-templates/ProductOverview/ReportSnapshotSlide.tsx b/electron/servers/nextjs/app/presentation-templates/ProductOverview/ReportSnapshotSlide.tsx index d158a8e6..34d31063 100644 --- a/electron/servers/nextjs/app/presentation-templates/ProductOverview/ReportSnapshotSlide.tsx +++ b/electron/servers/nextjs/app/presentation-templates/ProductOverview/ReportSnapshotSlide.tsx @@ -13,11 +13,12 @@ import { Line, LabelList, } from "recharts"; +import { RemoteSvgIcon } from "@/app/hooks/useRemoteSvgIcon"; -export const slideLayoutId = "product-overview-report-snapshot-slide"; -export const slideLayoutName = "Product Overview Report Snapshot Slide"; +export const slideLayoutId = "title-description-with-chart-and-kpi-cards-slide"; +export const slideLayoutName = "Title Description with Chart and KPI Cards Slide"; export const slideLayoutDescription = - "A report summary slide with a left-edge photo strip, title and intro copy, a chart card that supports four visual styles, and KPI callout cards on the right."; + "A text slide with a title on top and a description below, and a content section containing a chart and a grid of KPI cards."; const LegacyBarSchema = z.object({ value: z.number().min(10).max(100).meta({ @@ -335,372 +336,380 @@ const ReportSnapshotSlide = ({ data }: { data: Partial }) => { <>
- {sideImage?.__image_url__ && ( - {sideImage.__image_prompt__} - )} +
-
-

- {title} -

-
-

+ )} +

+
- {taglineLabel} -

-

- {taglineBody} -

-
-
+

+ {title} +

-
-

- {chartTitle} -

- - {activeChartStyle === "mini-bars" && ( - <> -
- - - - - `$${value}`} - axisLine={false} - tickLine={false} - tick={{ fill: "var(--background-text,#6C7271)", fontSize: 10 }} - /> - - - - -
- -
+

- {footerLabel} + {taglineLabel}

+ {taglineBody} +

+
+
+
+
+

- {footerValue} + {chartTitle}

-
- - )} - {activeChartStyle === "donut" && ( -
-
- - - - {(donutData ?? []).map((entry, index) => ( - - ))} - - - -
-
- {(donutData ?? []).map((entry, index) => { - const percent = Math.round((entry.value / donutTotal) * 100); - return ( -
+ {activeChartStyle === "mini-bars" && ( + <> +
+ + + + + `$${value}`} + axisLine={false} + tickLine={false} + tick={{ fill: "var(--background-text,#6C7271)", fontSize: 10 }} + /> + + + + +
+ +
+

+ {footerLabel} +

+

+ {footerValue} +

+
+ + )} + + {activeChartStyle === "donut" && ( +
+
+ + + + {(donutData ?? []).map((entry, index) => ( + + ))} + + + +
+ +
+ {(donutData ?? []).map((entry, index) => { + const percent = Math.round((entry.value / donutTotal) * 100); + return ( +
+
+ +

+ {legendLabels?.[index] ?? entry.name} +

+
+

+ {percent}% +

+
+ ); + })} +
+
+ )} + + {activeChartStyle === "grouped-bars" && ( +
+
+ + + + + + + + + + + + + +
+ +

- {legendLabels?.[index] ?? entry.name} + {legendLabels?.[0] ?? "Option A"} +

+
+
+ +

+ {legendLabels?.[1] ?? "Option B"} +

+
+
+
+ )} + + {activeChartStyle === "dual-line" && ( +
+
+ + + + + + + + + +
+ +
+
+ +

+ {legendLabels?.[0] ?? "Option A"} +

+
+
+ +

+ {legendLabels?.[1] ?? "Option B"} +

+
+
+
+ )} +
+ +
+
+ {visibleMetricCards.map((metric, index) => ( +
+
+
+ {usePulseFallback ? ( + + ) : ( + + )} +
+

+ {metric.value}

- {percent}% + {metric.body}

- ); - })} -
-
- )} - - {activeChartStyle === "grouped-bars" && ( -
-
- - - - - - - - - - - - - -
- -
-
- -

- {legendLabels?.[0] ?? "Option A"} -

-
-
- -

- {legendLabels?.[1] ?? "Option B"} -

+ ))}
- )} - - {activeChartStyle === "dual-line" && ( -
-
- - - - - - - - - -
- -
-
- -

- {legendLabels?.[0] ?? "Option A"} -

-
-
- -

- {legendLabels?.[1] ?? "Option B"} -

-
-
-
- )} -
- -
-
- {visibleMetricCards.map((metric, index) => ( -
-
-
- {usePulseFallback ? ( - - ) : ( - {metricIcon?.__icon_query__} - )} -
-

- {metric.value} -

-
-

- {metric.body} -

-
- ))}
diff --git a/electron/servers/nextjs/app/presentation-templates/ProductOverview/TableOfContentSlide.tsx b/electron/servers/nextjs/app/presentation-templates/ProductOverview/TableOfContentSlide.tsx index e1bbeb54..02549efc 100644 --- a/electron/servers/nextjs/app/presentation-templates/ProductOverview/TableOfContentSlide.tsx +++ b/electron/servers/nextjs/app/presentation-templates/ProductOverview/TableOfContentSlide.tsx @@ -4,19 +4,19 @@ const PRODUCT_BG = "var(--background-color,#d7dddd)"; const PRODUCT_DARK = "var(--primary-color,#05463d)"; -export const slideLayoutId = "product-overview-table-of-content-slide"; -export const slideLayoutName = "Product Overview Table of Content Slide"; +export const slideLayoutId = "table-of-content-slide"; +export const slideLayoutName = "Table of Content Slide"; export const slideLayoutDescription = - "A two-column table-of-content slide with section titles and numbers on a dark left panel and a large title plus description paragraph on the right panel."; + "A two-column table of contents slide with section titles and numbers on a left panel and a title plus description paragraph on the right panel."; const SectionSchema = z.object({ - title: z.string().min(4).max(14).meta({ + title: z.string().min(4).max(25).meta({ description: "Section label shown in the left navigation column.", }), number: z.string().min(2).max(3).meta({ description: "Section number shown beside the section label.", }), - description: z.string().min(4).max(22).optional().meta({ + description: z.string().min(4).max(60).optional().meta({ description: "Section description shown in the right column.", }), }); @@ -25,22 +25,22 @@ export const Schema = z.object({ title: z.string().min(6).max(18).default("Table Of Content").meta({ description: "Heading in the right-side content area.", }), - description: z.string().min(50).max(120).default( + description: z.string().min(50).max(160).default( "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do eiusmod tempor incididunt ut labore." ).meta({ description: "Supporting descriptive paragraph under the heading.", }), sections: z .array(SectionSchema) - .max(6) .default([ - { title: "SECTION TITLE", number: "01", description: "Lorem ipsum dolor sit." }, - { title: "SECTION TITLE", number: "02", description: "Lorem ipsum dolor sit." }, - { title: "SECTION TITLE", number: "03", description: "Lorem ipsum dolor sit." }, - { title: "SECTION TITLE", number: "04", description: "Lorem ipsum dolor sit." }, - { title: "SECTION TITLE", number: "05", description: "Lorem ipsum dolor sit." }, - { title: "SECTION TITLE", number: "06", description: "Lorem ipsum dolor sit." }, + { title: "SECTION TITLE SECTION TITLE", number: "01", description: "Lorem ipsum dolor sit. Lorem ipsum dolor sit. Lorem ipsum dolor sit." }, + { title: "SECTION TITLE SECTION TITLE", number: "02", description: "Lorem ipsum dolor sit. Lorem ipsum dolor sit. Lorem ipsum dolor sit." }, + { title: "SECTION TITLE SECTION TITLE", number: "03", description: "Lorem ipsum dolor sit. Lorem ipsum dolor sit. Lorem ipsum dolor sit." }, + { title: "SECTION TITLE SECTION TITLE", number: "04", description: "Lorem ipsum dolor sit. Lorem ipsum dolor sit. Lorem ipsum dolor sit." }, + { title: "SECTION TITLE SECTION TITLE", number: "05", description: "Lorem ipsum dolor sit. Lorem ipsum dolor sit. Lorem ipsum dolor sit." }, + { title: "SECTION TITLE SECTION TITLE", number: "06", description: "Lorem ipsum dolor sit. Lorem ipsum dolor sit. Lorem ipsum dolor sit." }, + ]) .meta({ description: "Six rows listed in the table of contents panel.", @@ -56,17 +56,17 @@ const TableOfContentSlide = ({ data }: { data: Partial }) => { <>
-
-
+
+
3 ? 'space-y-[28px]' : 'space-y-[40px]'}`}> {sections?.map((section, index) => ( -
+