From 0c35f2107cd2c99e9d8f5342f348a7b517e39b81 Mon Sep 17 00:00:00 2001 From: shiva raj badu Date: Wed, 23 Jul 2025 21:18:08 +0545 Subject: [PATCH 1/7] style(nextjs): New layouts styles & description tuned --- .../components/TiptapText.tsx | 2 +- .../components/TiptapTextReplacer.tsx | 3 +- .../presentation/components/Header.tsx | 6 +- .../components/PresentationPage.tsx | 63 +++- .../presentation/components/SidePanel.tsx | 6 +- .../presentation/components/SortableSlide.tsx | 19 +- .../pitch-deck/AboutUsSlide.tsx | 99 +++--- .../pitch-deck/BusinessModelSlide.tsx | 227 ++++++------- .../pitch-deck/HelloFriendsSlide.tsx | 120 +++---- .../pitch-deck/MarketSizeSlide.tsx | 173 +++++----- .../pitch-deck/OurServiceSlide.tsx | 185 +++++------ .../pitch-deck/ProblemsSlide.tsx | 104 +++--- .../pitch-deck/SolutionsSlide.tsx | 209 ++++++------ .../pitch-deck/StatisticCircularSlide.tsx | 59 ++-- .../pitch-deck/StatisticDualChartSlide.tsx | 238 +++++++------- .../pitch-deck/StatisticSlide.tsx | 307 +++++++++--------- .../pitch-deck/TableOfContentsSlide.tsx | 188 ++++++----- .../pitch-deck/TestimonialSlide.tsx | 250 +++++++------- .../pitch-deck/ThankYouSlide.tsx | 161 ++++----- .../pitch-deck/TitleSlide.tsx | 107 +++--- .../pitch-deck/WhatWeBelieveSlide.tsx | 199 ++++++------ .../pitch-deck/setting.json | 2 +- 22 files changed, 1367 insertions(+), 1360 deletions(-) diff --git a/servers/nextjs/app/(presentation-generator)/components/TiptapText.tsx b/servers/nextjs/app/(presentation-generator)/components/TiptapText.tsx index d7958481..86645210 100644 --- a/servers/nextjs/app/(presentation-generator)/components/TiptapText.tsx +++ b/servers/nextjs/app/(presentation-generator)/components/TiptapText.tsx @@ -61,7 +61,7 @@ const TiptapText: React.FC = ({ return (
-
+
)} @@ -139,12 +121,12 @@ const HelloFriendsSlide = ({ data }: { data: Partial }) => {
{/* Overlapping Circular Office Image */} - {officeImage?.__image_url__ && ( + {speakerImage?.__image_url__ && (
{officeImage.__image_prompt__}
diff --git a/servers/nextjs/presentation-layouts/pitch-deck/MarketSizeSlide.tsx b/servers/nextjs/presentation-layouts/pitch-deck/MarketSizeSlide.tsx index be6daa20..4f3f8862 100644 --- a/servers/nextjs/presentation-layouts/pitch-deck/MarketSizeSlide.tsx +++ b/servers/nextjs/presentation-layouts/pitch-deck/MarketSizeSlide.tsx @@ -5,65 +5,63 @@ import { ImageSchema, IconSchema } from "../defaultSchemes"; // Schema definition export const Schema = z.object({ - mainTitle: z.string() - .min(5) - .max(15) - .default("MARKET SIZE") + sectionTitle: z.string() + .min(3) + .max(30) + .default("MARKET ANALYSIS") .meta({ - description: "Main title for the market size section", + description: "Main section heading - can be 'Market Size', 'Market Opportunity', 'Industry Overview', or similar", }), - subtitle: z.string() + sectionSubtitle: z.string() .min(10) - .max(25) - .default("OUR CLIENTS COME FROM EVERYWHERE") + .max(60) + .default("UNDERSTANDING THE OPPORTUNITY LANDSCAPE") .meta({ - description: "Subtitle describing global reach", + description: "Supporting subtitle that frames the market discussion and opportunity scope", }), - globalDescription: z.string() - .min(50) - .max(200) - .default("With a global perspective, our marketing agency has proudly served multinational clients, delivering tailored strategies that transcend borders and cultures, ensuring consistent brand success on a worldwide scale.") - .meta({ - description: "Description of global market presence", - }), - - worldMapImage: ImageSchema.default({ - __image_url__: "https://images.unsplash.com/photo-1516245834210-c4c142787335?ixlib=rb-4.0.3&auto=format&fit=crop&w=1200&q=80", - __image_prompt__: "World map with location pins showing global business presence" - }).meta({ - description: "World map image showing global reach", - }), - marketDefinitions: z.array(z.object({ - acronym: z.string().min(2).max(10), - fullName: z.string().min(10).max(50), - description: z.string().min(50).max(300) - })).min(3).max(3).default([ + marketType: z.string().min(3).max(30), + marketDescription: z.string().min(20).max(150), + marketValue: z.string().min(3).max(25).optional() + })).min(2).max(4).default([ { - acronym: "TAM", - fullName: "Total Available Market (TAM)", - description: "The Total Available Market (TAM) represents the entire potential demand for our product or service, reflecting the vast landscape of opportunities awaiting exploration and market capture." + marketType: "Total Addressable Market (TAM)", + marketDescription: "The overall revenue opportunity available if we achieved 100% market share across all segments and geographies.", + marketValue: "$50B" }, { - acronym: "SAM", - fullName: "Serviceable Available Market (SAM)", - description: "The Serviceable Available Market (SAM) represents the specific segment of the Total Available Market where our product or service can be realistically and effectively offered, defining the target audience for our strategic market approach." + marketType: "Serviceable Addressable Market (SAM)", + marketDescription: "The portion of TAM targeted by our products and services within our geographic reach.", + marketValue: "$15B" }, { - acronym: "SOM", - fullName: "Serviceable Obtainable Market (SOM)", - description: "The Serviceable Obtainable Market (SOM) signifies the realistic and achievable portion of the Serviceable Available Market where our business aims to capture market share, emphasizing our practical and strategic approach to market penetration." + marketType: "Serviceable Obtainable Market (SOM)", + marketDescription: "The portion of SAM that we can realistically capture based on our resources and market conditions.", + marketValue: "$3B" } ]).meta({ - description: "Market size definitions for TAM, SAM, and SOM", + description: "List of market definitions and opportunities with descriptions and potential values", + }), + + visualRepresentation: ImageSchema.default({ + __image_url__: "https://images.unsplash.com/photo-1597149962419-0d900ac2b46c?ixlib=rb-4.0.3&auto=format&fit=crop&w=800&q=80", + __image_prompt__: "World map showing global market reach and geographic distribution" + }).meta({ + description: "Visual that represents market scope - could be a world map, chart, or geographic visualization", }), showYellowUnderline: z.boolean() .default(true) .meta({ - description: "Show yellow decorative underline", + description: "Whether to display the decorative yellow underline accent", + }), + + showVisualAccents: z.boolean() + .default(true) + .meta({ + description: "Whether to display decorative visual accent elements", }), }) @@ -73,81 +71,84 @@ type SchemaType = z.infer; // Component definition const MarketSizeSlide = ({ data }: { data: Partial }) => { - const { mainTitle, subtitle, globalDescription, worldMapImage, marketDefinitions, showYellowUnderline } = data; + const { sectionTitle, sectionSubtitle, marketDefinitions, visualRepresentation, showYellowUnderline, showVisualAccents } = data; return (
{/* Main Content Area */}
- {/* Left Side - Teal Background with Map */} -
+ {/* Left Side - Content */} +
{/* Title Section */}
- {mainTitle && ( -

- {mainTitle} + {sectionTitle && ( +

+ {sectionTitle}

)} - {subtitle && ( + {sectionSubtitle && (

- {subtitle} + {sectionSubtitle}

)} {/* Yellow Decorative Underline */} {showYellowUnderline && ( -
+
)}
- {/* World Map Image */} - {worldMapImage?.__image_url__ && ( -
-
- {worldMapImage.__image_prompt__} -
-
- )} - - {/* Global Description */} - {globalDescription && ( -
-

- {globalDescription} -

-
- )} -
- - {/* Right Side - White Background with Market Definitions */} -
- {/* Market Definitions */} - {marketDefinitions && marketDefinitions.length >= 3 && ( -
- {marketDefinitions.slice(0, 3).map((definition, index) => ( -
- {/* Header with rounded background */} -
-

- {definition.fullName} + {/* Market Definitions List */} + {marketDefinitions && marketDefinitions.length > 0 && ( +
+ {marketDefinitions.map((market, index) => ( +
+
+

+ {market.marketType}

+ {market.marketValue && ( + + {market.marketValue} + + )}
- - {/* Description */} -

- {definition.description} +

+ {market.marketDescription}

))}
)}

+ + {/* Right Side - Visual Representation */} +
+ {/* Visual Accents */} + {showVisualAccents && ( + <> + {/* Decorative circles */} +
+
+ + )} + + {/* Visual Representation */} + {visualRepresentation?.__image_url__ && ( +
+ {visualRepresentation.__image_prompt__} +
+ )} +
+ + {/* Bottom accent strip */} +
); }; diff --git a/servers/nextjs/presentation-layouts/pitch-deck/OurServiceSlide.tsx b/servers/nextjs/presentation-layouts/pitch-deck/OurServiceSlide.tsx index 4a7f7e45..15c9dedf 100644 --- a/servers/nextjs/presentation-layouts/pitch-deck/OurServiceSlide.tsx +++ b/servers/nextjs/presentation-layouts/pitch-deck/OurServiceSlide.tsx @@ -5,62 +5,39 @@ import { ImageSchema, IconSchema } from "../defaultSchemes"; // Schema definition export const Schema = z.object({ - mainTitle: z.string() - .min(5) - .max(10) - .default("OUR SERVICE") + sectionTitle: z.string() + .min(3) + .max(30) + .default("OUR SERVICES") .meta({ - description: "Main title for the service section", + description: "Main section heading - can be 'Our Services', 'What We Offer', 'Service Portfolio', or similar", }), - - - services: z.array(z.object({ - title: z.string().min(5).max(40), - description: z.string().min(30).max(100), - image: ImageSchema - })).min(3).max(3).default([ - { - title: "Strategic Brand Development", - description: "Our agency specializes in strategic brand development, ensuring that your brand not only resonates with your target audience but also stands out in a crowded market.", - image: { - __image_url__: "https://images.unsplash.com/photo-1553877522-43269d4ea984?ixlib=rb-4.0.3&auto=format&fit=crop&w=800&q=80", - __image_prompt__: "Business team working on brand strategy with documents and tablet" - } - }, - { - title: "Data-Driven Marketing", - description: "Our data-driven approach ensures that every campaign is backed by insights, maximizing ROI and driving tangible results.", - image: { - __image_url__: "https://images.unsplash.com/photo-1551288049-bebda4e38f71?ixlib=rb-4.0.3&auto=format&fit=crop&w=800&q=80", - __image_prompt__: "Business analytics with charts, graphs and keyboard on desk" - } - }, - { - title: "Creative Content Production", - description: "Content is king, and our agency excels in producing creative, engaging, and impactful content that resonates with your audience.", - image: { - __image_url__: "https://images.unsplash.com/photo-1542744094-3a31f272c490?ixlib=rb-4.0.3&auto=format&fit=crop&w=800&q=80", - __image_prompt__: "Creative professional working on laptop with design and content" - } - } - ]).meta({ - description: "Three main services with titles, descriptions and images", - }), - - companyLogo: ImageSchema.default({ - __image_url__: "https://via.placeholder.com/40x40/FFFFFF/1D9A8A?text=C", - __image_prompt__: "Clean modern company logo icon in white" - }).meta({ - description: "Company logo icon", - }), - - companyName: z.string() - .min(2) - .max(25) - .default("Company Name") + sectionSubtitle: z.string() + .min(10) + .max(60) + .default("COMPREHENSIVE SOLUTIONS TAILORED FOR SUCCESS") .meta({ - description: "Company name for branding", + description: "Supporting subtitle that describes the service approach or value proposition", + }), + + serviceHighlight: ImageSchema.default({ + __image_url__: "https://images.unsplash.com/photo-1556761175-b413da4baf72?ixlib=rb-4.0.3&auto=format&fit=crop&w=800&q=80", + __image_prompt__: "Professional service delivery or team working on client solutions" + }).meta({ + description: "Visual that represents service delivery, expertise, or client collaboration", + }), + + showVisualAccents: z.boolean() + .default(true) + .meta({ + description: "Whether to display decorative visual accent elements", + }), + + showColorBlocks: z.boolean() + .default(true) + .meta({ + description: "Whether to show colored background sections for visual hierarchy", }), }) @@ -70,74 +47,60 @@ type SchemaType = z.infer; // Component definition const OurServiceSlide = ({ data }: { data: Partial }) => { - const { mainTitle, services, companyLogo, companyName } = data; + const { sectionTitle, sectionSubtitle, serviceHighlight, showVisualAccents, showColorBlocks } = data; return ( -
- {/* Header with Title and Company Branding */} -
- {/* Top Section */} -
- {/* Left - Title */} -
- {mainTitle && ( -

- {mainTitle} -

- )} -
+
+ {/* Main Content Area */} +
+ {/* Left - Title */} +
+ {sectionTitle && ( +

+ {sectionTitle} +

+ )} - {/* Right - Teal Background with Company Branding */} -
-
- {companyLogo?.__image_url__ && ( -
- {companyLogo.__image_prompt__} -
- )} - {companyName && ( - - {companyName} - - )} -
-
+ {sectionSubtitle && ( +

+ {sectionSubtitle} +

+ )} + + {/* Visual Accents */} + {showVisualAccents && ( + <> + {/* Decorative elements */} +
+
+ + )}
- {/* Bottom Section - Services Grid */} -
- {services && services.length >= 3 && ( -
- {services.slice(0, 3).map((service, index) => ( -
- {/* Service Image */} -
- {service.image.__image_prompt__} -
- - {/* Service Content */} -
-

- {service.title} -

-

- {service.description} -

-
-
- ))} + {/* Right - Service Highlight */} +
+ {/* Service Highlight Image */} + {serviceHighlight?.__image_url__ && ( +
+ {serviceHighlight.__image_prompt__}
)} + + {/* Color overlay if enabled */} + {showColorBlocks && ( +
+ )}
+ + {/* Bottom accent strip */} + {showColorBlocks && ( +
+ )}
); }; diff --git a/servers/nextjs/presentation-layouts/pitch-deck/ProblemsSlide.tsx b/servers/nextjs/presentation-layouts/pitch-deck/ProblemsSlide.tsx index 1060cae6..ad981a77 100644 --- a/servers/nextjs/presentation-layouts/pitch-deck/ProblemsSlide.tsx +++ b/servers/nextjs/presentation-layouts/pitch-deck/ProblemsSlide.tsx @@ -5,63 +5,63 @@ import { ImageSchema, IconSchema } from "../defaultSchemes"; // Schema definition export const Schema = z.object({ - mainTitle: z.string() - .min(5) - .max(20) - .default("PROBLEMS") - .meta({ - description: "Main title for the problems section", - }), - - subtitle: z.string() - .min(10) + sectionTitle: z.string() + .min(3) .max(25) - .default("WE WILL SOLVE THE PROBLEMS") + .default("CHALLENGES") .meta({ - description: "Subtitle describing the section", + description: "Main section heading - can be 'Problems', 'Challenges', 'Issues', or similar", }), - problems: z.array(z.object({ - number: z.string().min(1).max(3), - title: z.string().min(5).max(40), - description: z.string().min(20).max(200) - })).min(2).max(3).default([ + sectionSubtitle: z.string() + .min(10) + .max(50) + .default("KEY CHALLENGES TO ADDRESS") + .meta({ + description: "Supporting subtitle that frames the problem discussion", + }), + + challengeItems: z.array(z.object({ + itemNumber: z.string().min(1).max(3), + challengeTitle: z.string().min(5).max(40), + challengeDescription: z.string().min(20).max(200) + })).min(2).max(4).default([ { - number: "01", - title: "Lack of Brand Visibility", - description: "Many businesses struggle with gaining visibility in a saturated market. Our solution involves a comprehensive analysis of your brand, audience, and competitors, leading to the development of a strategic branding." + itemNumber: "01", + challengeTitle: "Inefficient Processes", + challengeDescription: "Current workflows and systems lack optimization, leading to wasted resources and reduced productivity across all operational areas." }, { - number: "02", - title: "Ineffective Digital Presence", - description: "Weak online presence can hinder business growth. Our agency offers an integrated approach to digital marketing, covering SEO optimization, social media management, content marketing, and more." + itemNumber: "02", + challengeTitle: "Limited Scalability", + challengeDescription: "Existing infrastructure and methodologies cannot accommodate growth, creating bottlenecks that hinder expansion and progress." }, { - number: "03", - title: "Lack of Targeted Lead Generation", - description: "Many businesses struggle with generating quality leads that convert into customers. Our solution involves a meticulous understanding of your target audience, allowing us to develop highly targeted lead generation campaigns." + itemNumber: "03", + challengeTitle: "Resource Constraints", + challengeDescription: "Limited availability of key resources including time, budget, and skilled personnel creates barriers to achieving desired outcomes." } ]).meta({ - description: "List of problems with numbers, titles and descriptions", + description: "List of key challenges or problems with numbered identification and detailed descriptions", }), - workspaceImage: ImageSchema.default({ + supportingVisual: ImageSchema.default({ __image_url__: "https://images.unsplash.com/photo-1542744173-8e7e53415bb0?ixlib=rb-4.0.3&auto=format&fit=crop&w=800&q=80", - __image_prompt__: "Clean modern workspace with laptop, plant, and documents on desk" + __image_prompt__: "Professional workspace showing analysis and problem-solving activities" }).meta({ - description: "Workspace image showing business environment", + description: "Visual that supports the problem discussion - could show analysis, challenges, or work environment", }), - showDecoCircle: z.boolean() + showVisualAccents: z.boolean() .default(true) .meta({ - description: "Show decorative circle element", + description: "Whether to display decorative visual accent elements", }), - showTealAccent: z.boolean() + showColorBlocks: z.boolean() .default(true) .meta({ - description: "Show teal accent block", + description: "Whether to show colored accent blocks for visual hierarchy", }), }) @@ -71,7 +71,7 @@ type SchemaType = z.infer; // Component definition const ProblemsSlide = ({ data }: { data: Partial }) => { - const { mainTitle, subtitle, problems, workspaceImage, showDecoCircle, showTealAccent } = data; + const { sectionTitle, sectionSubtitle, challengeItems, supportingVisual, showVisualAccents, showColorBlocks } = data; return (
@@ -81,38 +81,38 @@ const ProblemsSlide = ({ data }: { data: Partial }) => {
{/* Title Section */}
- {mainTitle && ( -

- {mainTitle} + {sectionTitle && ( +

+ {sectionTitle}

)} - {subtitle && ( + {sectionSubtitle && (

- {subtitle} + {sectionSubtitle}

)}
- {/* Problems List */} - {problems && problems.length > 0 && ( + {/* Challenge Items List */} + {challengeItems && challengeItems.length > 0 && (
- {problems.map((problem, index) => ( + {challengeItems.map((item, index) => (
{/* Number Circle */}
- {problem.number} + {item.itemNumber}
{/* Content */}

- {problem.title} + {item.challengeTitle}

- {problem.description} + {item.challengeDescription}

@@ -124,23 +124,23 @@ const ProblemsSlide = ({ data }: { data: Partial }) => { {/* Right Side - Image and Decorative Elements */}
{/* Decorative Circle */} - {showDecoCircle && ( + {showVisualAccents && (
)} - {/* Workspace Image */} - {workspaceImage?.__image_url__ && ( + {/* Supporting Visual */} + {supportingVisual?.__image_url__ && (
{workspaceImage.__image_prompt__}
)} {/* Teal Accent Block - Right Edge */} - {showTealAccent && ( + {showColorBlocks && (
)}
diff --git a/servers/nextjs/presentation-layouts/pitch-deck/SolutionsSlide.tsx b/servers/nextjs/presentation-layouts/pitch-deck/SolutionsSlide.tsx index 6e140485..4b83c8ea 100644 --- a/servers/nextjs/presentation-layouts/pitch-deck/SolutionsSlide.tsx +++ b/servers/nextjs/presentation-layouts/pitch-deck/SolutionsSlide.tsx @@ -5,72 +5,76 @@ import { ImageSchema, IconSchema } from "../defaultSchemes"; // Schema definition export const Schema = z.object({ - mainTitle: z.string() - .min(5) - .max(15) - .default("SOLUTIONS") - .meta({ - description: "Main title for the solutions section", - }), - - subtitle: z.string() - .min(10) + sectionTitle: z.string() + .min(3) .max(25) - .default("SOLUTIONS OF THE PROBLEMS") + .default("OUR SOLUTIONS") .meta({ - description: "Subtitle describing the section", + description: "Main section heading - can be 'Solutions', 'Our Approach', 'How We Help', or similar", }), - solutions: z.array(z.object({ - number: z.string().min(1).max(3), - title: z.string().min(5).max(40), - description: z.string().min(20).max(300) - })).min(2).max(3).default([ + sectionSubtitle: z.string() + .min(10) + .max(50) + .default("COMPREHENSIVE SOLUTIONS FOR YOUR NEEDS") + .meta({ + description: "Supporting subtitle that frames the solution discussion", + }), + + solutionItems: z.array(z.object({ + itemNumber: z.string().min(1).max(3), + solutionTitle: z.string().min(5).max(40), + solutionDescription: z.string().min(20).max(200) + })).min(2).max(4).default([ { - number: "01", - title: "Lack of Brand Visibility", - description: "By defining your unique value proposition and creating a consistent brand identity, we ensure your business stands out and remains memorable in the minds of your target audience." + itemNumber: "01", + solutionTitle: "Process Optimization", + solutionDescription: "Streamline workflows and implement efficient systems that reduce waste, improve productivity, and maximize resource utilization across all operational areas." }, { - number: "02", - title: "Ineffective Digital Presence", - description: "Through data-driven insights, we tailor strategies to maximize online visibility, engage your audience, and drive meaningful interactions, converting online engagements into tangible business outcomes." + itemNumber: "02", + solutionTitle: "Scalable Infrastructure", + solutionDescription: "Build robust, flexible systems and methodologies that can grow with your organization, eliminating bottlenecks and supporting expansion efforts." }, { - number: "03", - title: "Lack of Targeted Lead Generation", - description: "By leveraging strategic content, paid advertising, and personalized engagement tactics, we ensure that your marketing efforts are focused on reaching and converting the right audience." + itemNumber: "03", + solutionTitle: "Resource Management", + solutionDescription: "Strategic allocation and optimization of available resources including time, budget, and personnel to achieve maximum impact and desired outcomes." } ]).meta({ - description: "List of solutions with numbers, titles and descriptions", + description: "List of key solutions or approaches with numbered identification and detailed descriptions", }), - workspaceImages: ImageSchema.default({ - __image_url__: "https://images.unsplash.com/photo-1551288049-bebda4e38f71?ixlib=rb-4.0.3&auto=format&fit=crop&w=800&q=80", - __image_prompt__: "Business person working on laptop with charts and analytics" + primaryVisual: ImageSchema.default({ + __image_url__: "https://images.unsplash.com/photo-1560472354-b33ff0c44a43?ixlib=rb-4.0.3&auto=format&fit=crop&w=800&q=80", + __image_prompt__: "Modern workspace with team collaboration and strategic planning" }).meta({ - description: "Two workspace images for left side", + description: "Primary visual representing teamwork, strategy, or solution implementation", }), - companyLogo: ImageSchema.default({ - __image_url__: "https://via.placeholder.com/40x40/1D9A8A/FFFFFF?text=C", - __image_prompt__: "Clean modern company logo icon" + brandingVisual: ImageSchema.default({ + __image_url__: "https://via.placeholder.com/150x80/22C55E/FFFFFF?text=LOGO", + __image_prompt__: "Organization logo or brand mark" }).meta({ - description: "Company logo icon", + description: "Logo or branding element to maintain visual identity", }), - companyName: z.string() - .min(2) - .max(25) - .default("Company Name") - .meta({ - description: "Company name for branding", - }), - showYellowUnderline: z.boolean() .default(true) .meta({ - description: "Show yellow decorative underline", + description: "Whether to display the decorative yellow underline accent", + }), + + showVisualAccents: z.boolean() + .default(true) + .meta({ + description: "Whether to display decorative visual accent elements", + }), + + showColorBlocks: z.boolean() + .default(true) + .meta({ + description: "Whether to show colored background blocks for visual hierarchy", }), }) @@ -80,25 +84,50 @@ type SchemaType = z.infer; // Component definition const SolutionsSlide = ({ data }: { data: Partial }) => { - const { mainTitle, subtitle, solutions, workspaceImages, companyLogo, companyName, showYellowUnderline } = data; + const { sectionTitle, sectionSubtitle, solutionItems, primaryVisual, brandingVisual, showYellowUnderline, showVisualAccents, showColorBlocks } = data; return (
{/* Main Content Area */}
{/* Left Side - Images and Branding */} -
+
+ {/* Top Image Area */} + {primaryVisual?.__image_url__ && ( +
+ {primaryVisual.__image_prompt__} +
+ )} + + {/* Bottom Branding Area */} +
+ {brandingVisual?.__image_url__ && ( + {brandingVisual.__image_prompt__} + )} +
+
+ + {/* Right Side - Content */} +
{/* Title Section */}
- {mainTitle && ( -

- {mainTitle} + {sectionTitle && ( +

+ {sectionTitle}

)} - {subtitle && ( -

- {subtitle} + {sectionSubtitle && ( +

+ {sectionSubtitle}

)} @@ -108,70 +137,52 @@ const SolutionsSlide = ({ data }: { data: Partial }) => { )}
- {/* Images */} - {workspaceImages && ( -
- - - -
- {workspaceImages.__image_prompt__} -
-
- )} - - {/* Company Branding */} -
- {companyLogo?.__image_url__ && ( -
- {companyLogo.__image_prompt__} -
- )} - {companyName && ( - - {companyName} - - )} -
-
- - {/* Right Side - Teal Background with Solutions */} -
- {/* Solutions List */} - {solutions && solutions.length > 0 && ( + {/* Solution Items List */} + {solutionItems && solutionItems.length > 0 && (
- {solutions.map((solution, index) => ( -
+ {solutionItems.map((item, index) => ( +
{/* Number Circle */} -
- - {solution.number} +
+ + {item.itemNumber}
{/* Content */}

- {solution.title} + {item.solutionTitle}

-

- {solution.description} +

+ {item.solutionDescription}

))}
)} + + {/* Visual Accents */} + {showVisualAccents && ( + <> + {/* Decorative circles */} +
+
+ + )}
+ + {/* Color blocks for visual hierarchy */} + {showColorBlocks && ( + <> + {/* Bottom accent strip */} +
+ {/* Side accent */} +
+ + )}
); }; diff --git a/servers/nextjs/presentation-layouts/pitch-deck/StatisticCircularSlide.tsx b/servers/nextjs/presentation-layouts/pitch-deck/StatisticCircularSlide.tsx index 4ed6688b..3b939f8f 100644 --- a/servers/nextjs/presentation-layouts/pitch-deck/StatisticCircularSlide.tsx +++ b/servers/nextjs/presentation-layouts/pitch-deck/StatisticCircularSlide.tsx @@ -4,31 +4,38 @@ import { ImageSchema, IconSchema } from "../defaultSchemes"; // Schema definition export const Schema = z.object({ - mainTitle: z.string() - .min(5) - .max(15) - .default("STATISTIC") + sectionTitle: z.string() + .min(3) + .max(20) + .default("CLIENT SATISFACTION") .meta({ - description: "Main title for the statistic section", + description: "Main section heading - adapt to presentation topic (e.g., 'Climate Progress', 'Treatment Success', 'Learning Achievement', 'Project Completion')", }), - subtitle: z.string() + sectionSubtitle: z.string() .min(10) - .max(25) - .default("CLIENT'S SATISFACTION") + .max(35) + .default("MEASURING OUR IMPACT AND SUCCESS") .meta({ - description: "Subtitle describing the statistic focus", + description: "Supporting subtitle that provides context - adapt to topic (e.g., 'Tracking Climate Action Progress', 'Monitoring Patient Recovery Rates', 'Assessing Educational Outcomes')", }), description: z.string() - .min(100) - .max(400) + .min(2) + .max(230) .default("At the heart of our success lies the unwavering satisfaction of our clients. We take pride in fostering lasting partnerships, consistently exceeding expectations, and delivering results that not only meet but surpass the unique objectives of each client we serve.") .meta({ - description: "Description of client satisfaction approach", + description: "Name of the organization or entity being measured", }), - circularMetric: z.object({ + brandLogo: ImageSchema.default({ + __image_url__: "https://via.placeholder.com/40x40/22C55E/FFFFFF?text=L", + __image_prompt__: "Professional organization logo - clean and modern design" + }).meta({ + description: "Logo or brand mark representing the organization", + }), + + satisfactionRate: z.object({ value: z.number().min(0).max(100), label: z.string().min(5).max(30), percentage: z.string().min(2).max(5) @@ -37,7 +44,7 @@ export const Schema = z.object({ label: "CLIENT'S REPEAT ORDER", percentage: "90%" }).meta({ - description: "Main circular chart metric", + description: "CRITICAL: Provide topic-specific circular progress metric. For global warming: {value: 33, label: 'CO2 REDUCTION ACHIEVED', percentage: '33%'} or {value: 78, label: 'RENEWABLE ENERGY ADOPTION', percentage: '78%'}. For healthcare: {value: 95, label: 'PATIENT RECOVERY RATE', percentage: '95%'} or {value: 87, label: 'TREATMENT SUCCESS RATE', percentage: '87%'}. For education: {value: 92, label: 'GRADUATION SUCCESS RATE', percentage: '92%'}. Use realistic percentages and meaningful labels.", }), statisticBlocks: z.array(z.object({ @@ -56,7 +63,7 @@ export const Schema = z.object({ backgroundColor: "beige" } ]).meta({ - description: "Two statistic blocks with percentages and descriptions", + description: "ESSENTIAL: Provide two topic-relevant supporting statistics. For global warming: [{percentage: '1.1°C', description: 'Global temperature increase since pre-industrial times represents urgent need for climate action', backgroundColor: 'teal'}, {percentage: '410ppm', description: 'Current atmospheric CO2 levels are the highest in human history requiring immediate intervention', backgroundColor: 'beige'}]. For healthcare: [{percentage: '85%', description: 'Early detection rates have improved significantly with advanced screening technologies', backgroundColor: 'teal'}, {percentage: '72h', description: 'Average patient response time demonstrates our commitment to rapid care delivery', backgroundColor: 'beige'}]. Always provide factual, impactful statistics.", }), companyLogo: ImageSchema.default({ @@ -69,7 +76,7 @@ export const Schema = z.object({ companyName: z.string() .min(2) .max(25) - .default("Company Name") + .default("Deskpro") .meta({ description: "Company name for branding", }), @@ -81,7 +88,7 @@ type SchemaType = z.infer; // Component definition const StatisticCircularSlide = ({ data }: { data: Partial }) => { - const { mainTitle, subtitle, description, circularMetric, statisticBlocks, companyLogo, companyName } = data; + const { sectionTitle, sectionSubtitle, description, brandLogo, satisfactionRate, statisticBlocks, companyLogo, companyName } = data; const getBackgroundClass = (bg: string) => { switch (bg) { @@ -95,7 +102,7 @@ const StatisticCircularSlide = ({ data }: { data: Partial }) => { const radius = 150; const circumference = 2 * Math.PI * radius; const strokeDasharray = circumference; - const strokeDashoffset = circumference - (circumference * (circularMetric?.value || 90) / 100); + const strokeDashoffset = circumference - (circumference * (satisfactionRate?.value || 90) / 100); return (
@@ -105,15 +112,15 @@ const StatisticCircularSlide = ({ data }: { data: Partial }) => {
{/* Left - Title */}
- {mainTitle && ( + {sectionTitle && (

- {mainTitle} + {sectionTitle}

)} - {subtitle && ( + {sectionSubtitle && (

- {subtitle} + {sectionSubtitle}

)}
@@ -172,14 +179,14 @@ const StatisticCircularSlide = ({ data }: { data: Partial }) => { {/* Center Content */}
- {circularMetric?.label && ( + {satisfactionRate?.label && (

- {circularMetric.label} + {satisfactionRate.label}

)} - {circularMetric?.percentage && ( + {satisfactionRate?.percentage && ( - {circularMetric.percentage} + {satisfactionRate.percentage} )}
diff --git a/servers/nextjs/presentation-layouts/pitch-deck/StatisticDualChartSlide.tsx b/servers/nextjs/presentation-layouts/pitch-deck/StatisticDualChartSlide.tsx index 6578a6df..b0fe63f7 100644 --- a/servers/nextjs/presentation-layouts/pitch-deck/StatisticDualChartSlide.tsx +++ b/servers/nextjs/presentation-layouts/pitch-deck/StatisticDualChartSlide.tsx @@ -1,34 +1,34 @@ import * as z from "zod"; import { ImageSchema, IconSchema } from "../defaultSchemes"; import { ChartContainer, ChartTooltip, ChartTooltipContent } from '@/components/ui/chart'; -import { BarChart, Bar, AreaChart, Area, XAxis, YAxis, CartesianGrid, ResponsiveContainer } from "recharts"; +import { BarChart, Bar, AreaChart, Area, XAxis, YAxis, CartesianGrid } from "recharts"; // Schema definition export const Schema = z.object({ - mainTitle: z.string() - .min(5) - .max(15) - .default("STATISTIC") + sectionTitle: z.string() + .min(3) + .max(30) + .default("PERFORMANCE METRICS") .meta({ - description: "Main title for the statistic section", + description: "Main section heading - adapt to presentation topic (e.g., 'Climate Analysis', 'Health Outcomes', 'Research Data', 'Impact Assessment')", }), - companyLogo: ImageSchema.default({ - __image_url__: "https://via.placeholder.com/40x40/FFFFFF/1D9A8A?text=C", - __image_prompt__: "Clean modern company logo icon in white" - }).meta({ - description: "Company logo icon", - }), - - companyName: z.string() + organizationName: z.string() .min(2) - .max(25) - .default("Company Name") + .max(30) + .default("Your Organization") .meta({ - description: "Company name for branding", + description: "Name of the organization or entity presenting the data", }), + brandLogo: ImageSchema.default({ + __image_url__: "https://via.placeholder.com/40x40/22C55E/FFFFFF?text=L", + __image_prompt__: "Professional organization logo - clean and modern design" + }).meta({ + description: "Logo or brand mark representing the organization", + }), + barChartData: z.array(z.object({ name: z.string(), series1: z.number(), @@ -41,7 +41,7 @@ export const Schema = z.object({ { name: "Item 4", series1: 18, series2: 14, series3: 22 }, { name: "Item 5", series1: 22, series2: 20, series3: 8 } ]).meta({ - description: "Bar chart data for customer satisfaction", + description: "CRITICAL: Provide topic-specific data for the left bar chart. For global warming: 5 years of data (2020-2024) with CO2 emissions by sector (Transport, Industry, Energy) with actual values. For healthcare: Patient outcomes across 5 categories (Prevention, Treatment, Recovery) with real percentages. For education: Student performance across 5 metrics (Reading, Math, Science) with grade levels. Use realistic data patterns and values.", }), areaChartData: z.array(z.object({ @@ -56,7 +56,7 @@ export const Schema = z.object({ { name: "Item 4", series1: 50, series2: 45, series3: 85 }, { name: "Item 5", series1: 80, series2: 75, series3: 120 } ]).meta({ - description: "Area chart data for repeat order rate", + description: "CRITICAL: Provide topic-specific data for the right area chart. For global warming: Cumulative data over 5 time periods showing renewable energy adoption, carbon reduction efforts, and policy implementations with realistic growth trends. For healthcare: Cumulative patient care metrics showing improvement over time. For education: Progressive learning outcomes showing student advancement. Ensure data shows meaningful trends relevant to the topic.", }), leftChartTitle: z.string() @@ -64,7 +64,7 @@ export const Schema = z.object({ .max(40) .default("Our Customer's Satisfaction") .meta({ - description: "Title for the left chart", + description: "IMPORTANT: Provide topic-specific title for left chart. For global warming: 'Global CO2 Emissions by Sector', 'Temperature Rise by Region', 'Renewable Energy Adoption'. For healthcare: 'Patient Treatment Outcomes', 'Healthcare Quality Metrics', 'Recovery Success Rates'. For education: 'Student Performance by Subject', 'Learning Progress Assessment', 'Academic Achievement Trends'.", }), leftChartDescription: z.string() @@ -72,7 +72,7 @@ export const Schema = z.object({ .max(200) .default("An impressive client satisfaction rate underscores our unwavering commitment to delivering exceptional service and exceeding expectations.") .meta({ - description: "Description for the left chart", + description: "ESSENTIAL: Provide topic-relevant description explaining the left chart data. For global warming: Explain emission sources, trends, and implications. For healthcare: Describe treatment effectiveness and patient outcomes. For education: Explain performance metrics and learning indicators. Make it informative and specific to the data shown.", }), rightChartTitle: z.string() @@ -80,7 +80,7 @@ export const Schema = z.object({ .max(40) .default("Repeat Order Rate") .meta({ - description: "Title for the right chart", + description: "IMPORTANT: Provide topic-specific title for right chart. For global warming: 'Climate Action Progress', 'Carbon Reduction Timeline', 'Sustainability Milestones'. For healthcare: 'Patient Recovery Timeline', 'Treatment Progress Tracking', 'Health Improvement Trajectory'. For education: 'Learning Progress Over Time', 'Student Development Path', 'Academic Growth Timeline'.", }), rightChartDescription: z.string() @@ -88,7 +88,7 @@ export const Schema = z.object({ .max(200) .default("Our remarkable client repeat order rate of 123 times are testament to the quality of our products/services and the trust our clients place in our ability.") .meta({ - description: "Description for the right chart", + description: "ESSENTIAL: Provide topic-relevant description explaining the right chart's cumulative/timeline data. For global warming: Describe progress in climate action, policy impact, or environmental improvements. For healthcare: Explain patient journey and recovery progression. For education: Describe learning advancement and skill development over time. Make it specific and data-driven.", }), }) @@ -114,43 +114,33 @@ type SchemaType = z.infer; // Component definition const StatisticDualChartSlide = ({ data }: { data: Partial }) => { - const { - mainTitle, - companyLogo, - companyName, - barChartData, - areaChartData, - leftChartTitle, - leftChartDescription, - rightChartTitle, - rightChartDescription - } = data; + const { sectionTitle, organizationName, brandLogo, barChartData, areaChartData, leftChartTitle, leftChartDescription, rightChartTitle, rightChartDescription } = data; return (
{/* Header Section */}
{/* Title */} - {mainTitle && ( + {sectionTitle && (

- {mainTitle} + {sectionTitle}

)} {/* Company Branding */}
- {companyLogo?.__image_url__ && ( + {brandLogo?.__image_url__ && (
{companyLogo.__image_prompt__}
)} - {companyName && ( + {organizationName && ( - {companyName} + {organizationName} )}
@@ -180,45 +170,45 @@ const StatisticDualChartSlide = ({ data }: { data: Partial }) => { {barChartData && barChartData.length > 0 && (
- - - - - - } /> - - - - - + + + + + + } /> + + + + +
)} @@ -260,50 +250,50 @@ const StatisticDualChartSlide = ({ data }: { data: Partial }) => { {areaChartData && areaChartData.length > 0 && (
- - - - - - } /> - - - - - + + + + + + } /> + + + + +
)} diff --git a/servers/nextjs/presentation-layouts/pitch-deck/StatisticSlide.tsx b/servers/nextjs/presentation-layouts/pitch-deck/StatisticSlide.tsx index 535ee86c..17748b55 100644 --- a/servers/nextjs/presentation-layouts/pitch-deck/StatisticSlide.tsx +++ b/servers/nextjs/presentation-layouts/pitch-deck/StatisticSlide.tsx @@ -1,40 +1,57 @@ import * as z from "zod"; import { ImageSchema, IconSchema } from "../defaultSchemes"; import { ChartContainer, ChartTooltip, ChartTooltipContent } from '@/components/ui/chart'; -import { LineChart, Line, XAxis, YAxis, CartesianGrid, ResponsiveContainer } from "recharts"; +import { LineChart, Line, XAxis, YAxis, CartesianGrid } from "recharts"; // Schema definition export const Schema = z.object({ - mainTitle: z.string() - .min(5) - .max(12) - .default("STATISTIC") + sectionTitle: z.string() + .min(3) + .max(30) + .default("KEY STATISTICS") .meta({ - description: "Main title for the statistic section", + description: "Main section heading - adapt to presentation topic (e.g., 'Climate Data', 'Health Metrics', 'Performance Stats', 'Research Findings')", }), - subtitle: z.string() + sectionSubtitle: z.string() .min(10) - .max(18) - .default("CLIENT'S SATISFACTION") + .max(60) + .default("DATA-DRIVEN INSIGHTS AND PERFORMANCE") .meta({ - description: "Subtitle describing the statistic focus", + description: "Supporting subtitle that frames the data - adapt to topic (e.g., 'Global Temperature Trends and Impact', 'Patient Outcomes and Recovery Rates', 'Student Achievement and Progress')", }), - description: z.string() - .min(80) - .max(200) - .default("At the heart of our success lies the unwavering satisfaction of our clients. We take pride in fostering lasting partnerships, consistently exceeding expectations, and delivering results that not only meet but surpass the unique objectives of each client we serve.") + statisticValue: z.string() + .min(1) + .max(15) + .default("85%") .meta({ - description: "Description of client satisfaction approach", + description: "CRITICAL: Provide the most important statistic for the topic. For global warming: '1.1°C', '+2.1°C', '410ppm', '33%'. For healthcare: '95%', '72 hours', '89%'. For education: '78%', '3.2 GPA', '92%'. Use real, impactful numbers relevant to the presentation topic.", }), - businessImage: ImageSchema.default({ - __image_url__: "https://images.unsplash.com/photo-1552664730-d307ca884978?ixlib=rb-4.0.3&auto=format&fit=crop&w=800&q=80", - __image_prompt__: "Business team meeting discussing charts and documents at table" + statisticLabel: z.string() + .min(5) + .max(40) + .default("Client Satisfaction Rate") + .meta({ + description: "IMPORTANT: Provide topic-specific label for the main statistic. For global warming: 'Global Temperature Rise Since 1880', 'CO2 Concentration Increase', 'Arctic Ice Loss Rate'. For healthcare: 'Patient Recovery Rate', 'Treatment Success Rate', 'Early Detection Rate'. For education: 'Graduation Success Rate', 'Student Engagement Level', 'Learning Improvement Rate'.", + }), + + supportingVisual: ImageSchema.default({ + __image_url__: "https://images.unsplash.com/photo-1460925895917-afdab827c52f?ixlib=rb-4.0.3&auto=format&fit=crop&w=800&q=80", + __image_prompt__: "Business analytics dashboard with charts and data visualization" }).meta({ - description: "Business meeting image showing team collaboration", + description: "ADAPT the image prompt to match the presentation topic: For global warming: 'Climate monitoring station with temperature sensors and weather equipment', 'Scientists analyzing ice core data in Arctic research facility'. For healthcare: 'Medical monitoring equipment displaying patient vital signs', 'Healthcare analytics dashboard showing treatment outcomes'. For education: 'Educational assessment data on computer screens', 'Students using digital learning platforms'.", + }), + + bulletPoints: z.array(z.string().min(10).max(100)).min(2).max(5).default([ + "Consistent performance improvement over 12 months", + "High customer retention and satisfaction scores", + "Measurable ROI across all key performance indicators", + "Data-driven decision making and strategic optimization" + ]).meta({ + description: "ESSENTIAL: Provide topic-relevant supporting facts and insights. For global warming: 'Global average temperature has risen 1.1°C since pre-industrial times', 'Arctic sea ice is declining at 13% per decade', 'CO2 levels are highest in 3 million years', 'Renewable energy adoption increased 85% in last decade'. For healthcare: 'Early detection improves survival rates by 85%', 'Telemedicine reduced patient wait times by 60%', 'Preventive care decreased hospital readmissions by 40%'. Always provide factual, verifiable statements related to the presentation topic.", }), chartData: z.array(z.object({ @@ -43,42 +60,26 @@ export const Schema = z.object({ series2: z.number(), series3: z.number() })).min(5).max(5).default([ - { name: "Item 1", series1: 18, series2: 0, series3: 0 }, - { name: "Item 2", series1: 30, series2: 12, series3: 8 }, - { name: "Item 3", series1: 26, series2: 38, series3: 20 }, - { name: "Item 4", series1: 40, series2: 30, series3: 35 }, - { name: "Item 5", series1: 42, series2: 45, series3: 32 } + { name: "Jan", series1: 18, series2: 0, series3: 0 }, + { name: "Feb", series1: 30, series2: 12, series3: 8 }, + { name: "Mar", series1: 26, series2: 38, series3: 20 }, + { name: "Apr", series1: 40, series2: 30, series3: 35 }, + { name: "May", series1: 42, series2: 45, series3: 32 } ]).meta({ - description: "Line chart data for satisfaction metrics", - }), - - bulletPoints: z.array(z.object({ - text: z.string().min(20).max(100), - color: z.enum(["teal", "beige", "light"]) - })).min(3).max(3).default([ - { - text: "From brand positioning and messaging to visual identity, we guide you through every step.", - color: "teal" - }, - { - text: "Navigate the path to increased sales with our insightful report and offering a strategic roadmap.", - color: "beige" - }, - { - text: "Amplify your revenue streams, engage customers, and unlock the full potential of your business.", - color: "light" - } - ]).meta({ - description: "Three bullet points with different colored indicators", + description: "CRITICAL: Provide topic-specific time-series data for line chart. For global warming: Monthly temperature anomalies, CO2 levels, ice coverage data with realistic values. For healthcare: Patient recovery rates, treatment success metrics, diagnostic accuracy over time. For education: Student performance trends, learning progress, engagement metrics. Use realistic data patterns showing meaningful trends.", }), showYellowUnderline: z.boolean() .default(true) .meta({ - description: "Show yellow decorative underline", + description: "Whether to display the decorative yellow underline accent", }), - + showVisualAccents: z.boolean() + .default(true) + .meta({ + description: "Whether to display decorative visual accent elements", + }), }) // Chart configuration @@ -103,73 +104,72 @@ type SchemaType = z.infer; // Component definition const StatisticSlide = ({ data }: { data: Partial }) => { - const { mainTitle, subtitle, description, businessImage, chartData, bulletPoints, showYellowUnderline } = data; - - const getColorClass = (color: string) => { - switch (color) { - case "teal": return "bg-teal-600"; - case "beige": return "bg-yellow-300"; - case "light": return "bg-gray-300"; - default: return "bg-gray-300"; - } - }; + const { sectionTitle, sectionSubtitle, statisticValue, statisticLabel, supportingVisual, bulletPoints, chartData, showYellowUnderline, showVisualAccents } = data; return (
{/* Main Content Area */}
- {/* Left Side - Teal Background with Content and Image */} -
- {/* Top Content Section */} -
- {/* Title Section */} -
- {mainTitle && ( -

- {mainTitle} -

- )} + {/* Left Side - Teal Background */} +
+ {/* Title Section */} +
+ {sectionTitle && ( +

+ {sectionTitle} +

+ )} - {subtitle && ( -

- {subtitle} -

- )} + {sectionSubtitle && ( +

+ {sectionSubtitle} +

+ )} - {/* Yellow Decorative Underline */} - {showYellowUnderline && ( -
- )} -
+ {/* Yellow Decorative Underline */} + {showYellowUnderline && ( +
+ )} +
- {/* Description */} - {description && ( -
-

- {description} -

+ {/* Large Statistic Display */} +
+ {statisticValue && ( +
+ {statisticValue}
)} -
- - {/* Bottom Business Image */} -
- {businessImage?.__image_url__ && ( - - {businessImage.__image_prompt__} - + {statisticLabel && ( +

+ {statisticLabel} +

)} - -
+ + {/* Business Image */} + {supportingVisual?.__image_url__ && ( +
+
+ {supportingVisual.__image_prompt__} +
+
+ )} + + {/* Visual Accents */} + {showVisualAccents && ( + <> +
+
+ + )}
- {/* Right Side - Chart and Bullet Points */} -
+ {/* Right Side - White Background with Chart and Bullet Points */} +
{/* Chart Section */}
{/* Chart Legend */} @@ -192,47 +192,47 @@ const StatisticSlide = ({ data }: { data: Partial }) => { {chartData && chartData.length > 0 && (
- - - - - - } /> - - - - - + + + + + + } /> + + + + +
)} @@ -242,19 +242,28 @@ const StatisticSlide = ({ data }: { data: Partial }) => {
{bulletPoints && bulletPoints.length > 0 && ( <> - {bulletPoints.map((point, index) => ( -
-
-

- {point.text} -

-
- ))} + {bulletPoints.map((point, index) => { + // Rotate colors for visual variety + const colors = ['bg-teal-600', 'bg-yellow-300', 'bg-gray-400']; + const dotColor = colors[index % colors.length]; + + return ( +
+
+

+ {point} +

+
+ ); + })} )}
+ + {/* Bottom accent strip */} +
); }; diff --git a/servers/nextjs/presentation-layouts/pitch-deck/TableOfContentsSlide.tsx b/servers/nextjs/presentation-layouts/pitch-deck/TableOfContentsSlide.tsx index 0abf8ebd..261fe221 100644 --- a/servers/nextjs/presentation-layouts/pitch-deck/TableOfContentsSlide.tsx +++ b/servers/nextjs/presentation-layouts/pitch-deck/TableOfContentsSlide.tsx @@ -5,63 +5,78 @@ import { ImageSchema, IconSchema } from "../defaultSchemes"; // Schema definition export const Schema = z.object({ - - mainTitle: z.string() - .min(5) - .max(20) - .default("TABLE OF CONTENT") + sectionTitle: z.string() + .min(3) + .max(30) + .default("TABLE OF CONTENTS") .meta({ - description: "Main title for the table of contents", + description: "Main heading for the content overview - can be 'Agenda', 'Overview', 'Contents', or similar", }), - subtitle: z.string() + sectionSubtitle: z.string() .min(10) - .max(25) - .default("PITCH DECK PRESENTATION") + .max(60) + .default("PRESENTATION OVERVIEW AND AGENDA") .meta({ - description: "Subtitle describing the presentation type", + description: "Supporting subtitle that explains what the audience will learn or see", }), contentItems: z.array(z.object({ - number: z.string().min(1).max(3), - title: z.string().min(3).max(30) - })).min(4).max(8).default([ - { number: "01", title: "Hello Friends!" }, - { number: "02", title: "About Us" }, - { number: "03", title: "What We Believe" }, - { number: "04", title: "Problems & Solutions" }, - { number: "05", title: "Market Size" }, - { number: "06", title: "Statistic" } + itemNumber: z.string().min(1).max(3), + contentTitle: z.string().min(3).max(40), + contentDescription: z.string().min(10).max(100).optional() + })).min(3).max(8).default([ + { + itemNumber: "01", + contentTitle: "Introduction & Welcome", + contentDescription: "Brief overview and objectives" + }, + { + itemNumber: "02", + contentTitle: "About Our Organization", + contentDescription: "Background and mission" + }, + { + itemNumber: "03", + contentTitle: "Key Challenges", + contentDescription: "Current issues and opportunities" + }, + { + itemNumber: "04", + contentTitle: "Our Solutions", + contentDescription: "Proposed approaches and methods" + }, + { + itemNumber: "05", + contentTitle: "Implementation Plan", + contentDescription: "Timeline and next steps" + }, + { + itemNumber: "06", + contentTitle: "Questions & Discussion", + contentDescription: "Interactive engagement" + } ]).meta({ - description: "List of content items with numbers and titles", + description: "List of presentation sections with numbered sequence and brief descriptions", }), - heroImage: ImageSchema.default({ - __image_url__: "https://images.unsplash.com/photo-1498050108023-c5249f4df085?ixlib=rb-4.0.3&auto=format&fit=crop&w=800&q=80", - __image_prompt__: "Modern laptop and office workspace on wooden desk" + brandingVisual: ImageSchema.default({ + __image_url__: "https://via.placeholder.com/200x100/22C55E/FFFFFF?text=BRAND", + __image_prompt__: "Organization logo or brand visual element" }).meta({ - description: "Hero image showing professional workspace", + description: "Logo or branding element displayed prominently for visual identity", }), - companyLogo: ImageSchema.default({ - __image_url__: "https://via.placeholder.com/40x40/1D9A8A/FFFFFF?text=C", - __image_prompt__: "Clean modern company logo icon" - }).meta({ - description: "Company logo icon", - }), - - companyName: z.string() - .min(2) - .max(25) - .default("Company Name") - .meta({ - description: "Company name for branding", - }), - - decorativeCircle: z.boolean() + showDecorations: z.boolean() .default(true) .meta({ - description: "Show decorative circle element", + description: "Whether to display decorative visual elements like underlines and accents", + }), + + useColumnLayout: z.boolean() + .default(true) + .meta({ + description: "Whether to arrange content items in two columns for better space utilization", }), }) @@ -71,45 +86,56 @@ type SchemaType = z.infer; // Component definition const TableOfContentsSlide = ({ data }: { data: Partial }) => { - - const { mainTitle, subtitle, contentItems, heroImage, companyLogo, companyName, decorativeCircle } = data; + const { sectionTitle, sectionSubtitle, contentItems, brandingVisual, showDecorations, useColumnLayout } = data; return (
{/* Main Content Area */}
{/* Left Side - Content */} -
+
{/* Title Section */}
- {mainTitle && ( -

- {mainTitle} + {sectionTitle && ( +

+ {sectionTitle}

)} {/* Decorative underline */} -
+ {showDecorations && ( +
+ )} - {subtitle && ( + {sectionSubtitle && (

- {subtitle} + {sectionSubtitle}

)}
{/* Content Items */} {contentItems && contentItems.length > 0 && ( -
+
{contentItems.map((item, index) => ( -
-
- - {item.number} +
+ {/* Number Circle */} +
+ + {item.itemNumber}
-
- {item.title} + + {/* Content */} +
+

+ {item.contentTitle} +

+ {item.contentDescription && ( +

+ {item.contentDescription} +

+ )}
))} @@ -117,43 +143,33 @@ const TableOfContentsSlide = ({ data }: { data: Partial }) => { )}
- {/* Right Side - Image and Branding */} -
- {/* Hero Image */} - {heroImage?.__image_url__ && ( -
+ {/* Right Side - Branding and Visual Elements */} +
+ {/* Branding Visual */} + {brandingVisual?.__image_url__ && ( +
{heroImage.__image_prompt__}
)} - {/* Decorative Circle */} - {decorativeCircle && ( -
+ {/* Decorative Elements */} + {showDecorations && ( + <> + {/* Decorative circles */} +
+
+
+ )} - - {/* Company Branding */} -
- {companyLogo?.__image_url__ && ( -
- {companyLogo.__image_prompt__} -
- )} - {companyName && ( - - {companyName} - - )} -
+ + {/* Bottom accent strip */} +
); }; diff --git a/servers/nextjs/presentation-layouts/pitch-deck/TestimonialSlide.tsx b/servers/nextjs/presentation-layouts/pitch-deck/TestimonialSlide.tsx index 71b672ff..2be34797 100644 --- a/servers/nextjs/presentation-layouts/pitch-deck/TestimonialSlide.tsx +++ b/servers/nextjs/presentation-layouts/pitch-deck/TestimonialSlide.tsx @@ -1,72 +1,89 @@ import * as z from "zod"; + import { ImageSchema, IconSchema } from "../defaultSchemes"; // Schema definition export const Schema = z.object({ - mainTitle: z.string() - .min(5) - .max(15) - .default("TESTIMONIAL") + sectionTitle: z.string() + .min(3) + .max(30) + .default("CLIENT TESTIMONIALS") .meta({ - description: "Main title for the testimonial section", + description: "Main section heading - can be 'Testimonials', 'Client Feedback', 'Reviews', or similar", }), - companyLogo: ImageSchema.default({ - __image_url__: "https://via.placeholder.com/40x40/FFFFFF/1D9A8A?text=C", - __image_prompt__: "Clean modern company logo icon in white" + organizationName: z.string() + .min(2) + .max(30) + .default("Your Organization") + .meta({ + description: "Name of the organization or entity being featured", + }), + + brandLogo: ImageSchema.default({ + __image_url__: "https://via.placeholder.com/40x40/22C55E/FFFFFF?text=L", + __image_prompt__: "Professional organization logo - clean and modern design" }).meta({ - description: "Company logo icon", + description: "Logo or brand mark representing the organization", }), - companyName: z.string() - .min(2) - .max(25) - .default("Company Name") - .meta({ - description: "Company name for branding", - }), - - testimonials: z.array(z.object({ - text: z.string().min(30).max(200), - clientName: z.string().min(2).max(30), - clientPhoto: ImageSchema, + testimonialItems: z.array(z.object({ + clientName: z.string().min(2).max(40), + clientTitle: z.string().min(5).max(60), + clientCompany: z.string().min(2).max(40), + testimonialText: z.string().min(50).max(300), rating: z.number().min(1).max(5), - backgroundColor: z.enum(["beige", "teal", "light"]) - })).min(3).max(3).default([ + clientPhoto: ImageSchema + })).min(2).max(4).default([ { - text: "In a world flooded with marketing noise, this company stands out as a beacon of creativity and effectiveness.", - clientName: "Benjamin Shah", + clientName: "Sarah Johnson", + clientTitle: "Chief Executive Officer", + clientCompany: "TechCorp Solutions", + testimonialText: "Working with this team has been transformative for our business. Their expertise, dedication, and innovative approach exceeded our expectations and delivered remarkable results.", + rating: 5, + clientPhoto: { + __image_url__: "https://images.unsplash.com/photo-1494790108755-2616b612b830?ixlib=rb-4.0.3&auto=format&fit=crop&w=400&q=80", + __image_prompt__: "Professional businesswoman headshot" + } + }, + { + clientName: "Michael Chen", + clientTitle: "Director of Operations", + clientCompany: "Global Innovations Inc", + testimonialText: "The level of professionalism and quality of service provided was outstanding. They understood our needs perfectly and delivered solutions that truly made a difference.", + rating: 5, clientPhoto: { __image_url__: "https://images.unsplash.com/photo-1472099645785-5658abf4ff4e?ixlib=rb-4.0.3&auto=format&fit=crop&w=400&q=80", - __image_prompt__: "Professional headshot of smiling businessman" - }, - rating: 5, - backgroundColor: "beige" + __image_prompt__: "Professional businessman headshot" + } }, { - text: "The level of expertise and personalized attention to our unique needs has made them an invaluable partner.", - clientName: "Murad Naser", - clientPhoto: { - __image_url__: "https://images.unsplash.com/photo-1507003211169-0a1dd7228f2d?ixlib=rb-4.0.3&auto=format&fit=crop&w=400&q=80", - __image_prompt__: "Professional headshot of confident businessman with beard" - }, + clientName: "Emily Rodriguez", + clientTitle: "Marketing Manager", + clientCompany: "Creative Dynamics", + testimonialText: "Exceptional service and results that spoke for themselves. The team's attention to detail and commitment to excellence made our collaboration highly successful.", rating: 5, - backgroundColor: "teal" - }, - { - text: "I've been thoroughly impressed with the exceptional level of service and creativity they bring to the table.", - clientName: "Drew Feig", clientPhoto: { - __image_url__: "https://images.unsplash.com/photo-1500648767791-00dcc994a43e?ixlib=rb-4.0.3&auto=format&fit=crop&w=400&q=80", - __image_prompt__: "Professional headshot of smiling young businessman" - }, - rating: 5, - backgroundColor: "light" + __image_url__: "https://images.unsplash.com/photo-1580489944761-15a19d654956?ixlib=rb-4.0.3&auto=format&fit=crop&w=400&q=80", + __image_prompt__: "Professional woman headshot" + } } ]).meta({ - description: "Three client testimonials with photos and ratings", + description: "List of client testimonials with ratings, photos, and detailed feedback", }), + + showRatings: z.boolean() + .default(true) + .meta({ + description: "Whether to display star ratings for each testimonial", + }), + + showClientPhotos: z.boolean() + .default(true) + .meta({ + description: "Whether to show client photos alongside testimonials", + }), }) // Type inference @@ -75,101 +92,104 @@ type SchemaType = z.infer; // Component definition const TestimonialSlide = ({ data }: { data: Partial }) => { - const { mainTitle, companyLogo, companyName, testimonials } = data; + const { sectionTitle, organizationName, brandLogo, testimonialItems, showRatings, showClientPhotos } = data; - const getBackgroundClass = (bg: string) => { - switch (bg) { - case "teal": return "bg-teal-600 text-white"; - case "beige": return "bg-yellow-100 text-gray-900"; - case "light": return "bg-gray-100 text-gray-900"; - default: return "bg-gray-100 text-gray-900"; - } - }; - - const getStarColor = (bg: string) => { - return bg === "teal" ? "text-yellow-400" : "text-yellow-500"; - }; - - const renderStars = (rating: number, backgroundColor: string) => { - return ( -
- {[...Array(5)].map((_, index) => ( - - - - ))} -
- ); + // Helper function to render stars + const renderStars = (rating: number) => { + return Array.from({ length: 5 }, (_, i) => ( + + + + )); }; return ( -
+
{/* Header Section */}
{/* Title */} - {mainTitle && ( -

- {mainTitle} + {sectionTitle && ( +

+ {sectionTitle}

)} {/* Company Branding */}
- {companyLogo?.__image_url__ && ( + {brandLogo?.__image_url__ && (
{companyLogo.__image_prompt__}
)} - {companyName && ( - - {companyName} + {organizationName && ( + + {organizationName} )}
- {/* Testimonials Section */} -
- {testimonials && testimonials.length > 0 && ( -
- {testimonials.map((testimonial, index) => ( -
- {/* Stars */} - {renderStars(testimonial.rating, testimonial.backgroundColor)} + {/* Testimonials Content */} +
+ {testimonialItems && testimonialItems.length > 0 && ( +
+ {testimonialItems.slice(0, 3).map((item, index) => { + // Rotate background colors for visual variety + const bgColors = ['bg-yellow-100', 'bg-teal-100', 'bg-gray-100']; + const bgColor = bgColors[index % bgColors.length]; - {/* Testimonial Text */} -

- {testimonial.text} -

+ return ( +
+ {/* Stars Rating */} + {showRatings && ( +
+ {renderStars(item.rating)} +
+ )} - {/* Client Photo */} - {testimonial.clientPhoto?.__image_url__ && ( -
- {testimonial.clientPhoto.__image_prompt__} + {/* Testimonial Text */} +

+ "{item.testimonialText}" +

+ + {/* Client Info */} +
+ {/* Client Photo */} + {showClientPhotos && item.clientPhoto?.__image_url__ && ( +
+ {item.clientPhoto.__image_prompt__} +
+ )} + + {/* Client Details */} +
+

+ {item.clientName} +

+

+ {item.clientTitle} +

+

+ {item.clientCompany} +

+
- )} - - {/* Client Name */} -

- {testimonial.clientName} -

-
- ))} +
+ ); + })}
)}
diff --git a/servers/nextjs/presentation-layouts/pitch-deck/ThankYouSlide.tsx b/servers/nextjs/presentation-layouts/pitch-deck/ThankYouSlide.tsx index 695c51ad..237e3e0d 100644 --- a/servers/nextjs/presentation-layouts/pitch-deck/ThankYouSlide.tsx +++ b/servers/nextjs/presentation-layouts/pitch-deck/ThankYouSlide.tsx @@ -5,68 +5,73 @@ import { ImageSchema, IconSchema } from "../defaultSchemes"; // Schema definition export const Schema = z.object({ - - companyName: z.string() + organizationName: z.string() .min(2) - .max(15) - .default("Company Name") + .max(30) + .default("Your Organization") .meta({ - description: "Company name displayed prominently", + description: "Name of the organization, company, or entity presenting", }), - mainTitle: z.string() - .min(5) - .max(20) + primaryMessage: z.string() + .min(3) + .max(25) .default("THANK YOU") .meta({ - description: "Main thank you title in large bold letters", + description: "Main closing message - can be 'Thank You', 'Questions?', 'Let's Connect', or similar", }), - subtitle: z.string() - .min(10) - .max(40) - .default("FOR YOUR NICE ATTENTION") + secondaryMessage: z.string() + .min(5) + .max(60) + .default("FOR YOUR TIME AND ATTENTION") .meta({ - description: "Subtitle thanking the audience", + description: "Supporting message that completes the primary message or adds context", }), - companyLogo: ImageSchema.default({ - __image_url__: "https://via.placeholder.com/40x40/22C55E/FFFFFF?text=C", - __image_prompt__: "Company logo - geometric green icon" + brandLogo: ImageSchema.default({ + __image_url__: "https://via.placeholder.com/40x40/22C55E/FFFFFF?text=L", + __image_prompt__: "Professional organization logo - clean and modern design" }).meta({ - description: "Company logo icon", + description: "Logo or brand mark representing the presenting organization", }), - contactInfo: z.object({ - telephone: z.string().min(10).max(20).default("+123-456-7890"), - address: z.string().min(10).max(50).default("123 Anywhere St., Any City, ST 12345"), - website: z.string().min(10).max(30).default("www.reallygreatsite.com") + contactDetails: z.object({ + phoneNumber: z.string().min(10).max(20).default("+1-234-567-8900"), + physicalAddress: z.string().min(10).max(60).default("123 Business Ave, City, State 12345"), + websiteUrl: z.string().min(10).max(40).default("www.yourorganization.com") }).default({ - telephone: "+123-456-7890", - address: "123 Anywhere St., Any City, ST 12345", - website: "www.reallygreatsite.com" + phoneNumber: "+1-234-567-8900", + physicalAddress: "123 Business Ave, City, State 12345", + websiteUrl: "www.yourorganization.com" }).meta({ - description: "Company contact information", + description: "Contact information for follow-up communication and connection", }), presentationDate: z.string() - .min(5) + .min(3) .max(20) - .default("December 2023") + .default("Current Month Year") .meta({ - description: "Date of the presentation", + description: "Date when the presentation was given or document was created", }), - decorativeCircle: z.boolean() + showDecorations: z.boolean() .default(true) .meta({ - description: "Show decorative circle element", + description: "Whether to display decorative visual elements like background shapes", }), - arrowButton: z.boolean() + showNavigationArrow: z.boolean() .default(true) .meta({ - description: "Show navigation arrow button", + description: "Whether to show a navigation arrow for interactive presentations", + }), + + showContactInfo: z.boolean() + .default(true) + .meta({ + description: "Whether to display contact information in the footer", }), }) @@ -76,7 +81,7 @@ type SchemaType = z.infer; // Component definition const ThankYouSlide = ({ data }: { data: Partial }) => { - const { companyName, mainTitle, subtitle, companyLogo, contactInfo, presentationDate, decorativeCircle, arrowButton } = data; + const { organizationName, primaryMessage, secondaryMessage, brandLogo, contactDetails, presentationDate, showDecorations, showNavigationArrow, showContactInfo } = data; return (
@@ -84,24 +89,24 @@ const ThankYouSlide = ({ data }: { data: Partial }) => {
{/* Company Logo and Name */}
- {companyLogo?.__image_url__ && ( + {brandLogo?.__image_url__ && (
{companyLogo.__image_prompt__}
)} - {companyName && ( + {organizationName && ( - {companyName} + {organizationName} )}
{/* Arrow Button */} - {arrowButton && ( + {showNavigationArrow && (
@@ -111,7 +116,7 @@ const ThankYouSlide = ({ data }: { data: Partial }) => {
{/* Decorative Circle */} - {decorativeCircle && ( + {showDecorations && (
)} @@ -119,18 +124,18 @@ const ThankYouSlide = ({ data }: { data: Partial }) => {
{/* Main Title */} - {mainTitle && ( + {primaryMessage && (

- {mainTitle} + {primaryMessage}

)} {/* Subtitle with Circle Bullet */} - {subtitle && ( + {secondaryMessage && (

- {subtitle} + {secondaryMessage}

)} @@ -138,44 +143,46 @@ const ThankYouSlide = ({ data }: { data: Partial }) => {
{/* Footer with Contact Info */} -
-
-
- {/* Telephone */} - {contactInfo?.telephone && ( -
-
Telephone
-
{contactInfo.telephone}
-
- )} + {showContactInfo && ( +
+
+
+ {/* Telephone */} + {contactDetails?.phoneNumber && ( +
+
Telephone
+
{contactDetails.phoneNumber}
+
+ )} - {/* Address */} - {contactInfo?.address && ( -
-
Address
-
{contactInfo.address}
-
- )} + {/* Address */} + {contactDetails?.physicalAddress && ( +
+
Address
+
{contactDetails.physicalAddress}
+
+ )} - {/* Website */} - {contactInfo?.website && ( -
-
Website
-
{contactInfo.website}
+ {/* Website */} + {contactDetails?.websiteUrl && ( +
+
Website
+
{contactDetails.websiteUrl}
+
+ )} +
+ + {/* Presentation Date */} + {presentationDate && ( +
+
+ {presentationDate} +
)}
- - {/* Presentation Date */} - {presentationDate && ( -
-
- {presentationDate} -
-
- )}
-
+ )}
); }; diff --git a/servers/nextjs/presentation-layouts/pitch-deck/TitleSlide.tsx b/servers/nextjs/presentation-layouts/pitch-deck/TitleSlide.tsx index 6b1d41e9..9e6bbdee 100644 --- a/servers/nextjs/presentation-layouts/pitch-deck/TitleSlide.tsx +++ b/servers/nextjs/presentation-layouts/pitch-deck/TitleSlide.tsx @@ -5,68 +5,67 @@ import { ImageSchema, IconSchema } from "../defaultSchemes"; // Schema definition export const Schema = z.object({ - - companyName: z.string() + organizationName: z.string() .min(2) - .max(15) - .default("Thynk Unlimited") + .max(25) + .default("Your Organization") .meta({ - description: "Company name displayed prominently", + description: "Name of the organization, company, or entity presenting", }), - mainTitle: z.string() + primaryTitle: z.string() + .min(3) + .max(30) + .default("PRESENTATION TITLE") + .meta({ + description: "Main headline or title for the presentation - should be impactful and attention-grabbing", + }), + + secondaryTitle: z.string() .min(5) - .max(15) - .default("PITCH DECK") + .max(50) + .default("PROFESSIONAL PRESENTATION") .meta({ - description: "Main title in large bold letters", + description: "Subtitle that provides context about the presentation type or purpose", }), - subtitle: z.string() - .min(10) - .max(40) - .default("BUSINESS PRESENTATION") - .meta({ - description: "Subtitle describing the presentation type", - }), - - companyLogo: ImageSchema.default({ - __image_url__: "https://via.placeholder.com/40x40/22C55E/FFFFFF?text=T", - __image_prompt__: "Thynk Unlimited logo - geometric green icon" + brandLogo: ImageSchema.default({ + __image_url__: "https://via.placeholder.com/40x40/22C55E/FFFFFF?text=L", + __image_prompt__: "Professional organization logo - clean and modern design" }).meta({ - description: "Company logo icon", + description: "Logo or brand mark representing the presenting organization", }), - contactInfo: z.object({ - telephone: z.string().min(10).max(20).default("+123-456-7890"), - address: z.string().min(10).max(50).default("123 Anywhere St., Any City, ST 12345"), - website: z.string().min(10).max(30).default("www.reallygreatsite.com") + contactDetails: z.object({ + phoneNumber: z.string().min(10).max(20).default("+1-234-567-8900"), + physicalAddress: z.string().min(10).max(60).default("123 Business Ave, City, State 12345"), + websiteUrl: z.string().min(10).max(40).default("www.yourorganization.com") }).default({ - telephone: "+123-456-7890", - address: "123 Anywhere St., Any City, ST 12345", - website: "www.reallygreatsite.com" + phoneNumber: "+1-234-567-8900", + physicalAddress: "123 Business Ave, City, State 12345", + websiteUrl: "www.yourorganization.com" }).meta({ - description: "Company contact information", + description: "Contact information including phone, address, and website for follow-up communication", }), presentationDate: z.string() - .min(5) + .min(3) .max(20) - .default("December 2023") + .default("Current Month Year") .meta({ - description: "Date of the presentation", + description: "Date when the presentation is being given or was created", }), - decorativeCircle: z.boolean() + showDecorations: z.boolean() .default(true) .meta({ - description: "Show decorative circle element", + description: "Whether to display decorative visual elements like background shapes", }), - arrowButton: z.boolean() + showNavigationArrow: z.boolean() .default(true) .meta({ - description: "Show navigation arrow button", + description: "Whether to show a navigation arrow button for presentation flow", }), }) @@ -77,7 +76,7 @@ type SchemaType = z.infer; const ThynkTitleSlide = ({ data }: { data: Partial }) => { - const { companyName, mainTitle, subtitle, companyLogo, contactInfo, presentationDate, decorativeCircle, arrowButton } = data; + const { organizationName, primaryTitle, secondaryTitle, brandLogo, contactDetails, presentationDate, showDecorations, showNavigationArrow } = data; return (
@@ -85,24 +84,24 @@ const ThynkTitleSlide = ({ data }: { data: Partial }) => {
{/* Company Logo and Name */}
- {companyLogo?.__image_url__ && ( + {brandLogo?.__image_url__ && (
{companyLogo.__image_prompt__}
)} - {companyName && ( + {organizationName && ( - {companyName} + {organizationName} )}
{/* Arrow Button */} - {arrowButton && ( + {showNavigationArrow && (
@@ -112,7 +111,7 @@ const ThynkTitleSlide = ({ data }: { data: Partial }) => {
{/* Decorative Circle */} - {decorativeCircle && ( + {showDecorations && (
)} @@ -120,18 +119,18 @@ const ThynkTitleSlide = ({ data }: { data: Partial }) => {
{/* Main Title */} - {mainTitle && ( + {primaryTitle && (

- {mainTitle} + {primaryTitle}

)} {/* Subtitle with Circle Bullet */} - {subtitle && ( + {secondaryTitle && (

- {subtitle} + {secondaryTitle}

)} @@ -143,26 +142,26 @@ const ThynkTitleSlide = ({ data }: { data: Partial }) => {
{/* Telephone */} - {contactInfo?.telephone && ( + {contactDetails?.phoneNumber && (
Telephone
-
{contactInfo.telephone}
+
{contactDetails.phoneNumber}
)} {/* Address */} - {contactInfo?.address && ( + {contactDetails?.physicalAddress && (
Address
-
{contactInfo.address}
+
{contactDetails.physicalAddress}
)} {/* Website */} - {contactInfo?.website && ( + {contactDetails?.websiteUrl && (
Website
-
{contactInfo.website}
+
{contactDetails.websiteUrl}
)}
diff --git a/servers/nextjs/presentation-layouts/pitch-deck/WhatWeBelieveSlide.tsx b/servers/nextjs/presentation-layouts/pitch-deck/WhatWeBelieveSlide.tsx index 0ab76e6f..bd507218 100644 --- a/servers/nextjs/presentation-layouts/pitch-deck/WhatWeBelieveSlide.tsx +++ b/servers/nextjs/presentation-layouts/pitch-deck/WhatWeBelieveSlide.tsx @@ -5,66 +5,57 @@ import { ImageSchema, IconSchema } from "../defaultSchemes"; // Schema definition export const Schema = z.object({ - - mainTitle: z.string() - .min(5) - .max(15) - .default("WHAT WE BELIEVE") - .meta({ - description: "Main title for the beliefs section", - }), - - subtitle: z.string() - .min(10) + sectionTitle: z.string() + .min(3) .max(30) - .default("ABOUT OUR VISION AND MISSION") + .default("OUR VISION & MISSION") .meta({ - description: "Subtitle describing the section", + description: "Main section heading - can be 'Our Values', 'What We Believe', 'Our Philosophy', or similar", }), - visionTitle: z.string() - .min(3) - .max(15) - .default("VISION") + sectionSubtitle: z.string() + .min(10) + .max(60) + .default("GUIDING PRINCIPLES AND CORE BELIEFS") .meta({ - description: "Vision section title", + description: "Supporting subtitle that introduces the organization's foundational concepts", }), - visionText: z.string() - .min(50) - .max(300) - .default("Our vision is to be the catalyst for transformative marketing solutions that redefine industry standards. We envision a future where brands not only captivate their audience but also inspire meaningful connections.") + visionStatement: z.string() + .min(30) + .max(200) + .default("We envision a future where innovative solutions transform challenges into opportunities, creating sustainable value for all stakeholders.") .meta({ - description: "Vision statement text", + description: "Vision statement describing the organization's aspirational future goals and impact", }), - missionTitle: z.string() - .min(3) - .max(15) - .default("MISSION") - .meta({ - description: "Mission section title", - }), - - missionText: z.string() - .min(50) - .max(400) - .default("Our mission is to deliver strategic and impactful marketing solutions that propel businesses to new heights of success. We are committed to leveraging our expertise in data-driven insights, creative storytelling, and cutting-edge technology to craft bespoke campaigns.") - .meta({ - description: "Mission statement text", - }), - - teamImage: ImageSchema.default({ - __image_url__: "https://images.unsplash.com/photo-1522202176988-66273c2fd55f?ixlib=rb-4.0.3&auto=format&fit=crop&w=800&q=80", - __image_prompt__: "Business team collaboration meeting with documents and discussion" + missionContent: z.object({ + missionTitle: z.string().min(3).max(30).default("Our Mission"), + missionDescription: z.string().min(50).max(300).default("To deliver exceptional value through strategic innovation, collaborative partnerships, and unwavering commitment to excellence. We believe in empowering organizations with the tools, insights, and support needed to achieve sustainable growth and meaningful impact in their communities.") + }).default({ + missionTitle: "Our Mission", + missionDescription: "To deliver exceptional value through strategic innovation, collaborative partnerships, and unwavering commitment to excellence. We believe in empowering organizations with the tools, insights, and support needed to achieve sustainable growth and meaningful impact in their communities." }).meta({ - description: "Team collaboration image", + description: "Mission section with title and detailed description of organizational purpose and approach", }), - showYellowAccent: z.boolean() + supportingVisual: ImageSchema.default({ + __image_url__: "https://images.unsplash.com/photo-1522202176988-66273c2fd55f?ixlib=rb-4.0.3&auto=format&fit=crop&w=800&q=80", + __image_prompt__: "Diverse team collaborating and planning together in modern workspace" + }).meta({ + description: "Visual that represents collaboration, vision, or organizational culture", + }), + + showVisualAccents: z.boolean() .default(true) .meta({ - description: "Show yellow accent block", + description: "Whether to display decorative visual accent elements", + }), + + showColorBlocks: z.boolean() + .default(true) + .meta({ + description: "Whether to show colored background sections for visual hierarchy", }), }) @@ -74,84 +65,88 @@ type SchemaType = z.infer; // Component definition const WhatWeBelieveSlide = ({ data }: { data: Partial }) => { - - const { mainTitle, subtitle, visionTitle, visionText, missionTitle, missionText, teamImage, showYellowAccent } = data; + const { sectionTitle, sectionSubtitle, visionStatement, missionContent, supportingVisual, showVisualAccents, showColorBlocks } = data; return (
{/* Main Content Area */}
{/* Left Side - Image */} -
- {/* Team Image */} - {teamImage?.__image_url__ && ( -
+
+ {supportingVisual?.__image_url__ && ( +
{teamImage.__image_prompt__}
)} - {/* Yellow Accent Block - Bottom Left */} - {showYellowAccent && ( -
+ {/* Visual Accents */} + {showVisualAccents && ( + <> + {/* Decorative circles */} +
+
+ )} - - {/* Teal Accent Block - Bottom */} -
{/* Right Side - Content */} -
-
- - {/* Title Section */} -
- {mainTitle && ( -

- {mainTitle} -

- )} - - {subtitle && ( -

- {subtitle} -

- )} -
- - {/* Vision Section */} -
- {visionTitle && ( -

- {visionTitle} -

- )} - {visionText && ( -

- {visionText} -

- )} -
- -
- {/* Mission Section with Teal Background */} -
- {missionTitle && ( -

- {missionTitle} -

+
+ {/* Title Section */} +
+ {sectionTitle && ( +

+ {sectionTitle} +

)} - {missionText && ( -

- {missionText} + + {sectionSubtitle && ( +

+ {sectionSubtitle}

)}
+ + {/* Vision Section */} + {visionStatement && ( +
+

Vision

+

+ {visionStatement} +

+
+ )} + + {/* Mission Section with Teal Background */} + {missionContent && ( +
+ {missionContent.missionTitle && ( +

+ {missionContent.missionTitle} +

+ )} + {missionContent.missionDescription && ( +

+ {missionContent.missionDescription} +

+ )} +
+ )}
+ + {/* Color blocks for visual hierarchy */} + {showColorBlocks && ( + <> + {/* Bottom accent strip */} +
+ {/* Left accent */} +
+ + )}
); }; diff --git a/servers/nextjs/presentation-layouts/pitch-deck/setting.json b/servers/nextjs/presentation-layouts/pitch-deck/setting.json index 4b565369..00660bc1 100644 --- a/servers/nextjs/presentation-layouts/pitch-deck/setting.json +++ b/servers/nextjs/presentation-layouts/pitch-deck/setting.json @@ -1,5 +1,5 @@ { - "description": "This is a new pitch deck layout with a focus on simplicity and clarity.", + "description": "Professional presentation layouts with clean design and flexible content fields. Suitable for business pitches, organizational overviews, product presentations, and various corporate communications.", "ordered": false, "isDefault": false } \ No newline at end of file From f6e425abdc4a0d64a4d0abf278f725e9dab45278 Mon Sep 17 00:00:00 2001 From: shiva raj badu Date: Wed, 23 Jul 2025 21:21:02 +0545 Subject: [PATCH 2/7] refactor(nextjs): Sonner title bold removed --- servers/nextjs/components/ui/sonner.tsx | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/servers/nextjs/components/ui/sonner.tsx b/servers/nextjs/components/ui/sonner.tsx index ab735da6..357596f2 100644 --- a/servers/nextjs/components/ui/sonner.tsx +++ b/servers/nextjs/components/ui/sonner.tsx @@ -25,7 +25,7 @@ const Toaster = ({ ...props }: ToasterProps) => { } [data-sonner-toast][data-type="success"] [data-title] { color: rgb(15 23 42) !important; /* slate-900 */ - font-weight: 600 !important; + font-weight: 500 !important; } [data-sonner-toast][data-type="success"] [data-description] { color: rgb(71 85 105) !important; /* slate-600 */ @@ -39,7 +39,7 @@ const Toaster = ({ ...props }: ToasterProps) => { } [data-sonner-toast][data-type="error"] [data-title] { color: rgb(15 23 42) !important; /* slate-900 */ - font-weight: 600 !important; + font-weight: 500 !important; } [data-sonner-toast][data-type="error"] [data-description] { color: rgb(71 85 105) !important; /* slate-600 */ @@ -53,7 +53,7 @@ const Toaster = ({ ...props }: ToasterProps) => { } [data-sonner-toast][data-type="info"] [data-title] { color: rgb(15 23 42) !important; /* slate-900 */ - font-weight: 600 !important; + font-weight: 500 !important; } [data-sonner-toast][data-type="info"] [data-description] { color: rgb(71 85 105) !important; /* slate-600 */ @@ -67,7 +67,7 @@ const Toaster = ({ ...props }: ToasterProps) => { } [data-sonner-toast][data-type="warning"] [data-title] { color: rgb(15 23 42) !important; /* slate-900 */ - font-weight: 600 !important; + font-weight: 500 !important; } [data-sonner-toast][data-type="warning"] [data-description] { color: rgb(71 85 105) !important; /* slate-600 */ @@ -81,7 +81,7 @@ const Toaster = ({ ...props }: ToasterProps) => { } [data-sonner-toast][data-type="loading"] [data-title] { color: rgb(15 23 42) !important; /* slate-900 */ - font-weight: 600 !important; + font-weight: 500 !important; } [data-sonner-toast][data-type="loading"] [data-description] { color: rgb(71 85 105) !important; /* slate-600 */ From 27781ef72b9e2a646ecd5d4556786f8ad6721753 Mon Sep 17 00:00:00 2001 From: shiva raj badu Date: Wed, 23 Jul 2025 21:46:22 +0545 Subject: [PATCH 3/7] fix(nextjs): Fix DND & click event issue on sidepanel --- .../components/PresentationPage.tsx | 51 ++++--------------- .../presentation/components/SidePanel.tsx | 6 ++- .../components/SortableListItem.tsx | 24 ++++----- .../presentation/components/SortableSlide.tsx | 29 +++++------ 4 files changed, 39 insertions(+), 71 deletions(-) diff --git a/servers/nextjs/app/(presentation-generator)/presentation/components/PresentationPage.tsx b/servers/nextjs/app/(presentation-generator)/presentation/components/PresentationPage.tsx index 37fc7873..92a38c1d 100644 --- a/servers/nextjs/app/(presentation-generator)/presentation/components/PresentationPage.tsx +++ b/servers/nextjs/app/(presentation-generator)/presentation/components/PresentationPage.tsx @@ -18,13 +18,9 @@ import { } from "../hooks"; import { PresentationPageProps } from "../types"; import LoadingState from "./LoadingState"; -import { useRouter, useSearchParams } from "next/navigation"; const PresentationPage: React.FC = ({ presentation_id }) => { - const router = useRouter(); - const searchParams = useSearchParams(); - const isPresentMode = searchParams.get("mode") === "present"; - const stream = searchParams.get("stream"); + // State management const [loading, setLoading] = useState(true); const [selectedSlide, setSelectedSlide] = useState(0); @@ -51,6 +47,14 @@ const PresentationPage: React.FC = ({ presentation_id }) setError ); + const { + isPresentMode, + stream, + handleSlideClick, + toggleFullscreen, + handlePresentExit, + handleSlideChange, + } = usePresentationNavigation(presentation_id, selectedSlide, setSelectedSlide, setIsFullscreen); // Initialize streaming usePresentationStreaming( @@ -63,46 +67,12 @@ const PresentationPage: React.FC = ({ presentation_id }) + const onSlideChange = (newSlide: number) => { handleSlideChange(newSlide, presentationData); }; - const handleSlideClick = useCallback((index: number) => { - console.log("handleSlideClick", index); - const slideElement = document.getElementById(`slide-${index}`); - if (slideElement) { - slideElement.scrollIntoView({ - behavior: "smooth", - block: "center", - }); - setSelectedSlide(index); - } - }, [setSelectedSlide]); - const toggleFullscreen = useCallback(() => { - if (!document.fullscreenElement) { - document.documentElement.requestFullscreen(); - setIsFullscreen(true); - } else { - document.exitFullscreen(); - setIsFullscreen(false); - } - }, [setIsFullscreen]); - - const handlePresentExit = useCallback(() => { - setIsFullscreen(false); - router.push(`/presentation?id=${presentation_id}`); - }, [router, presentation_id, setIsFullscreen]); - - const handleSlideChange = useCallback((newSlide: number, presentationData: any) => { - if (newSlide >= 0 && newSlide < presentationData?.slides.length!) { - setSelectedSlide(newSlide); - router.push( - `/presentation?id=${presentation_id}&mode=present&slide=${newSlide}`, - { scroll: false } - ); - } - }, [router, presentation_id, setSelectedSlide]); // Presentation Mode View if (isPresentMode) { @@ -110,7 +80,6 @@ const PresentationPage: React.FC = ({ presentation_id }) { - setMouseDownTime(Date.now()); - }; + const handleClick = (e: React.MouseEvent) => { + const now = Date.now(); - const handleMouseUp = () => { - const mouseUpTime = Date.now(); - const timeDiff = mouseUpTime - mouseDownTime; + // Debounce clicks - only allow one click every 300ms + if (now - lastClickTime.current < 300) { + return; + } - // If the mouse was down for less than 200ms, consider it a click - if (timeDiff < 200 && !isDragging) { + // Only trigger click if not dragging + if (!isDragging) { + lastClickTime.current = now; onSlideClick(slide.index); } }; @@ -48,8 +49,7 @@ export function SortableListItem({ slide, index, selectedSlide, onSlideClick }: style={style} {...attributes} {...listeners} - onMouseDown={handleMouseDown} - onMouseUp={handleMouseUp} + onClick={handleClick} className={`p-3 cursor-pointer ring-0 border-[3px] rounded-lg slide-box ${selectedSlide === index ? ' border-[#5141e5] ' diff --git a/servers/nextjs/app/(presentation-generator)/presentation/components/SortableSlide.tsx b/servers/nextjs/app/(presentation-generator)/presentation/components/SortableSlide.tsx index 14bc87b4..5e6ac054 100644 --- a/servers/nextjs/app/(presentation-generator)/presentation/components/SortableSlide.tsx +++ b/servers/nextjs/app/(presentation-generator)/presentation/components/SortableSlide.tsx @@ -1,7 +1,7 @@ import { useSortable } from '@dnd-kit/sortable'; import { CSS } from '@dnd-kit/utilities'; import { Slide } from '../../types/slide'; -import { useState } from 'react'; +import { useRef } from 'react'; interface SortableSlideProps { slide: Slide; @@ -12,7 +12,7 @@ interface SortableSlideProps { } export function SortableSlide({ slide, index, selectedSlide, onSlideClick, renderSlideContent }: SortableSlideProps) { - const [mouseDownTime, setMouseDownTime] = useState(0); + const lastClickTime = useRef(0); const { attributes, @@ -29,20 +29,17 @@ export function SortableSlide({ slide, index, selectedSlide, onSlideClick, rende opacity: isDragging ? 0.5 : 1 }; - const handleMouseDown = () => { - console.log("mouse down"); - setMouseDownTime(Date.now()); - }; + const handleClick = (e: React.MouseEvent) => { + const now = Date.now(); - const handleMouseUp = () => { - console.log("mouse up"); - const mouseUpTime = Date.now(); - const timeDiff = mouseUpTime - mouseDownTime; - console.log("timeDiff", timeDiff); + // Debounce clicks - only allow one click every 300ms + if (now - lastClickTime.current < 300) { + return; + } - // If the mouse was down for less than 300ms, consider it a click - if (timeDiff < 300 && !isDragging) { - console.log("clicked"); + // Only trigger click if not dragging + if (!isDragging) { + lastClickTime.current = now; onSlideClick(slide.index); } }; @@ -53,9 +50,7 @@ export function SortableSlide({ slide, index, selectedSlide, onSlideClick, rende style={style} {...attributes} {...listeners} - onMouseDown={handleMouseDown} - onMouseUp={handleMouseUp} - + onClick={handleClick} className={` cursor-pointer border-[3px] relative p-1 shadow-lg rounded-md transition-all duration-200 ${selectedSlide === index ? ' border-[#5141e5]' : 'border-gray-300' }`} > From 817abf9b2e224a8cf8f55017a0e0f06a24edd1e1 Mon Sep 17 00:00:00 2001 From: shiva raj badu Date: Wed, 23 Jul 2025 22:46:22 +0545 Subject: [PATCH 4/7] refactor(nextjs): Default layout field validation before rendering --- .../hooks/useGroupLayouts.tsx | 3 ++ .../presentation/components/Header.tsx | 8 ++-- .../components/PresentationPage.tsx | 2 - .../default/Type10SlideLayout.tsx | 33 ++++++------- .../default/Type1SlideLayout.tsx | 23 +++++----- .../default/Type2NumberedSlideLayout.tsx | 32 ++++++------- .../default/Type2SlideLayout.tsx | 32 ++++++------- .../default/Type2TimelineSlideLayout.tsx | 25 +++++----- .../default/Type3SlideLayout.tsx | 22 ++++----- .../default/Type4SlideLayout.tsx | 37 +++++++-------- .../default/Type5SlideLayout.tsx | 23 +++++----- .../default/Type6SlideLayout.tsx | 28 +++++------ .../default/Type7SlideLayout.tsx | 40 ++++++++-------- .../default/Type8SlideLayout.tsx | 46 +++++++++---------- .../default/Type9SlideLayout.tsx | 28 +++++------ .../pitch-deck/AboutUsSlide.tsx | 2 +- 16 files changed, 186 insertions(+), 198 deletions(-) diff --git a/servers/nextjs/app/(presentation-generator)/hooks/useGroupLayouts.tsx b/servers/nextjs/app/(presentation-generator)/hooks/useGroupLayouts.tsx index e7450a14..3624ea76 100644 --- a/servers/nextjs/app/(presentation-generator)/hooks/useGroupLayouts.tsx +++ b/servers/nextjs/app/(presentation-generator)/hooks/useGroupLayouts.tsx @@ -36,6 +36,7 @@ export const useGroupLayouts = () => { // Render slide content with group validation, automatic Tiptap text editing, and editable images/icons const renderSlideContent = useMemo(() => { return (slide: any, isEditMode: boolean) => { + console.time("renderSlideContent"); const Layout = getGroupLayout(slide.layout, slide.layout_group); if (!Layout) { return ( @@ -75,8 +76,10 @@ export const useGroupLayouts = () => { ); } + console.timeEnd("renderSlideContent"); return ; }; + }, [getGroupLayout, dispatch]); return { diff --git a/servers/nextjs/app/(presentation-generator)/presentation/components/Header.tsx b/servers/nextjs/app/(presentation-generator)/presentation/components/Header.tsx index 3d907c52..bb0afebf 100644 --- a/servers/nextjs/app/(presentation-generator)/presentation/components/Header.tsx +++ b/servers/nextjs/app/(presentation-generator)/presentation/components/Header.tsx @@ -162,15 +162,15 @@ const Header = ({ {/* Desktop Export Button with Popover */} -
- +
+ - + @@ -186,7 +186,7 @@ const Header = ({ return (
+ }} className="bg-[#5146E5] w-full shadow-lg sticky top-0"> = ({ presentation_id }) ); - - const onSlideChange = (newSlide: number) => { handleSlideChange(newSlide, presentationData); }; diff --git a/servers/nextjs/presentation-layouts/default/Type10SlideLayout.tsx b/servers/nextjs/presentation-layouts/default/Type10SlideLayout.tsx index d124c960..409d7213 100644 --- a/servers/nextjs/presentation-layouts/default/Type10SlideLayout.tsx +++ b/servers/nextjs/presentation-layouts/default/Type10SlideLayout.tsx @@ -108,17 +108,12 @@ export const Schema = type10SlideSchema export type Type10SlideData = z.infer interface Type10SlideLayoutProps { - data?: Partial + data: Partial } const Type10SlideLayout: React.FC = ({ data: slideData }) => { - const chartData = slideData?.data || []; - const chartType = slideData?.chartType || 'line'; - const color = slideData?.color || '#3b82f6'; - const dataKey = slideData?.dataKey || 'value'; - const categoryKey = slideData?.categoryKey || 'name'; - const showLegend = slideData?.showLegend || false; - const showTooltip = slideData?.showTooltip || true; + const { title, items, chartData, chartType = 'line', color = '#3b82f6', dataKey = 'value', categoryKey = 'name', showLegend = false, showTooltip = true } = slideData; + const renderChart = () => { const commonProps = { data: chartData, @@ -188,7 +183,7 @@ const Type10SlideLayout: React.FC = ({ data: slideData } dataKey={dataKey} label={({ name, percent }) => `${name} ${(percent * 100).toFixed(0)}%`} > - {chartData.map((entry, index) => ( + {chartData.map((entry: any, index: number) => ( ))} @@ -219,9 +214,9 @@ const Type10SlideLayout: React.FC = ({ data: slideData } >
-

- {slideData?.title || 'Chart Analysis'} -

+ {title &&

+ {title || 'Chart Analysis'} +

}
@@ -234,7 +229,7 @@ const Type10SlideLayout: React.FC = ({ data: slideData }
- {slideData?.items?.map((item, index) => ( + {items && items.map((item, index) => (
= ({ data: slideData }
- {item.icon?.__icon_query__ + />}
-

+ {item.heading &&

{item.heading} -

-

+ } + {item.description &&

{item.description} -

+

}
diff --git a/servers/nextjs/presentation-layouts/default/Type1SlideLayout.tsx b/servers/nextjs/presentation-layouts/default/Type1SlideLayout.tsx index 05247cf6..75b945ed 100644 --- a/servers/nextjs/presentation-layouts/default/Type1SlideLayout.tsx +++ b/servers/nextjs/presentation-layouts/default/Type1SlideLayout.tsx @@ -26,10 +26,11 @@ export const Schema = type1SlideSchema export type Type1SlideData = z.infer interface Type1SlideLayoutProps { - data?: Partial + data: Partial } const Type1SlideLayout: React.FC = ({ data: slideData }) => { + const { title, description, image } = slideData; return (
= ({ data: slideData })
{/* Title */} -

- {slideData?.title || ' This is the title of slide'} -

+ {title &&

+ {title} +

} {/* Description */} -

- {slideData?.description || 'This is a test of the hot reload system! If you can see this text, hot reload is working perfectly. Changes should appear instantly without page refresh.'} -

+ {description &&

+ {description} +

}
{/* Image */}
- {slideData?.image?.__image_prompt__ + />}
diff --git a/servers/nextjs/presentation-layouts/default/Type2NumberedSlideLayout.tsx b/servers/nextjs/presentation-layouts/default/Type2NumberedSlideLayout.tsx index 3a2dacdc..e03a3cf3 100644 --- a/servers/nextjs/presentation-layouts/default/Type2NumberedSlideLayout.tsx +++ b/servers/nextjs/presentation-layouts/default/Type2NumberedSlideLayout.tsx @@ -39,18 +39,18 @@ export const Schema = type2NumberedSlideSchema export type Type2NumberedSlideData = z.infer interface Type2NumberedSlideLayoutProps { - data?: Partial + data: Partial } const Type2NumberedSlideLayout: React.FC = ({ data: slideData }) => { - const items = slideData?.items || [] - const isGridLayout = items.length >= 4 + const { title, items } = slideData; + const isGridLayout = items?.length && items?.length >= 4 const numberTranslations: string[] = ['01', '02', '03', '04', '05', '06'] const renderGridContent = () => { return (
- {items.map((item, index) => ( + {items?.map((item, index) => (
= ({ dat {numberTranslations[index] || `0${index + 1}`}
-

+ {item.heading &&

{item.heading} -

-

+ } + {item.description &&

{item.description} -

+

}
@@ -80,7 +80,7 @@ const Type2NumberedSlideLayout: React.FC = ({ dat const renderHorizontalContent = () => { return (
- {items.map((item, index) => ( + {items?.map((item, index) => (
= ({ dat {numberTranslations[index] || `0${index + 1}`}
-

+ {item.heading &&

{item.heading} -

-

+ } + {item.description &&

{item.description} -

+

}
))} @@ -111,9 +111,9 @@ const Type2NumberedSlideLayout: React.FC = ({ dat >
-

- {slideData?.title || 'Main Title'} -

+ {title &&

+ {title} +

}
{isGridLayout ? renderGridContent() : renderHorizontalContent()} diff --git a/servers/nextjs/presentation-layouts/default/Type2SlideLayout.tsx b/servers/nextjs/presentation-layouts/default/Type2SlideLayout.tsx index 30c875e5..0d72d880 100644 --- a/servers/nextjs/presentation-layouts/default/Type2SlideLayout.tsx +++ b/servers/nextjs/presentation-layouts/default/Type2SlideLayout.tsx @@ -39,29 +39,29 @@ export const Schema = type2SlideSchema export type Type2SlideData = z.infer interface Type2SlideLayoutProps { - data?: Partial + data: Partial } const Type2SlideLayout: React.FC = ({ data: slideData }) => { - const items = slideData?.items || [] - const isGridLayout = items.length >= 4 + const { title, items } = slideData; + const isGridLayout = items?.length && items?.length >= 4 const renderGridContent = () => { return (
- {items.map((item, index) => ( + {items?.map((item, index) => (
-

+ {item.heading &&

{item.heading} -

-

+ } + {item.description &&

{item.description} -

+

}
))} @@ -72,19 +72,19 @@ const Type2SlideLayout: React.FC = ({ data: slideData }) const renderHorizontalContent = () => { return (
- {items.map((item, index) => ( + {items?.map((item, index) => (
-

+ {item.heading &&

{item.heading} -

-

+ } + {item.description &&

{item.description} -

+

}
))} @@ -98,9 +98,9 @@ const Type2SlideLayout: React.FC = ({ data: slideData }) >
-

- {slideData?.title || 'Main Title'} -

+ {title &&

+ {title} +

}
{isGridLayout ? renderGridContent() : renderHorizontalContent()} diff --git a/servers/nextjs/presentation-layouts/default/Type2TimelineSlideLayout.tsx b/servers/nextjs/presentation-layouts/default/Type2TimelineSlideLayout.tsx index f29d3b39..3e5942e9 100644 --- a/servers/nextjs/presentation-layouts/default/Type2TimelineSlideLayout.tsx +++ b/servers/nextjs/presentation-layouts/default/Type2TimelineSlideLayout.tsx @@ -39,12 +39,11 @@ export const Schema = type2TimelineSlideSchema export type Type2TimelineSlideData = z.infer interface Type2TimelineSlideLayoutProps { - data?: Partial + data: Partial } const Type2TimelineSlideLayout: React.FC = ({ data: slideData }) => { - const items = slideData?.items || [] - const numberTranslations: string[] = ['01', '02', '03', '04', '05', '06'] + const { title, items } = slideData; const renderTimelineContent = () => { return ( @@ -55,27 +54,27 @@ const Type2TimelineSlideLayout: React.FC = ({ dat
{/* Timeline Numbers */} - {items.map((_, index) => ( + {items && items.map((_, index) => (
- {numberTranslations[index] || `0${index + 1}`} + `0${index + 1}`
))}
{/* Timeline Content */}
- {items.map((item, index) => ( + {items && items.map((item, index) => (
-

+ {item.heading &&

{item.heading} -

-

+ } + {item.description &&

{item.description} -

+

}
))} @@ -89,9 +88,9 @@ const Type2TimelineSlideLayout: React.FC = ({ dat className=" rounded-sm max-w-[1280px] w-full shadow-lg px-3 sm:px-12 lg:px-20 py-[10px] sm:py-[40px] flex flex-col items-center justify-center max-h-[720px] aspect-video bg-white relative z-20 mx-auto" >
-

- {slideData?.title || 'Main Title'} -

+ {title &&

+ {title} +

}
{renderTimelineContent()} diff --git a/servers/nextjs/presentation-layouts/default/Type3SlideLayout.tsx b/servers/nextjs/presentation-layouts/default/Type3SlideLayout.tsx index c860b9b5..c07b8090 100644 --- a/servers/nextjs/presentation-layouts/default/Type3SlideLayout.tsx +++ b/servers/nextjs/presentation-layouts/default/Type3SlideLayout.tsx @@ -55,11 +55,11 @@ export const Schema = type3SlideSchema export type Type3SlideData = z.infer interface Type3SlideLayoutProps { - data?: Partial + data: Partial } const Type3SlideLayout: React.FC = ({ data: slideData }) => { - const items = slideData?.items || [] + const { title, items } = slideData; const getGridCols = (length: number) => { switch (length) { @@ -77,13 +77,13 @@ const Type3SlideLayout: React.FC = ({ data: slideData }) >
-

- {slideData?.title || 'Featured Content'} -

+ {title &&

+ {title} +

}
-
- {items.map((item, index) => ( +
+ {items && items.map((item, index) => (
= ({ data: slideData }) {/* Content */}
-

+ {item.heading &&

{item.heading} -

-

+ } + {item.description &&

{item.description} -

+

}
))} diff --git a/servers/nextjs/presentation-layouts/default/Type4SlideLayout.tsx b/servers/nextjs/presentation-layouts/default/Type4SlideLayout.tsx index d103b18a..7b863ff1 100644 --- a/servers/nextjs/presentation-layouts/default/Type4SlideLayout.tsx +++ b/servers/nextjs/presentation-layouts/default/Type4SlideLayout.tsx @@ -1,6 +1,6 @@ import { ChartContainer, ChartLegend, ChartLegendContent, ChartTooltip, ChartTooltipContent } from '@/components/ui/chart'; import React from 'react' -import { BarChart, Bar, LineChart, Line, PieChart, Pie, AreaChart, Area, ScatterChart, Scatter, XAxis, YAxis, CartesianGrid, Cell, ResponsiveContainer } from "recharts"; +import { BarChart, Bar, LineChart, Line, PieChart, Pie, AreaChart, Area, ScatterChart, Scatter, XAxis, YAxis, CartesianGrid, Cell } from "recharts"; import * as z from "zod"; export const layoutId = 'type4-slide' @@ -77,17 +77,14 @@ export const Schema = type4SlideSchema export type Type4SlideData = z.infer interface Type4SlideLayoutProps { - data?: Partial + data: Partial } const Type4SlideLayout: React.FC = ({ data: slideData }) => { - const chartData = slideData?.data || []; - const chartType = slideData?.chartType || 'line'; - const color = slideData?.color || '#3b82f6'; - const dataKey = slideData?.dataKey || 'value'; - const categoryKey = slideData?.categoryKey || 'name'; - const showLegend = slideData?.showLegend || false; - const showTooltip = slideData?.showTooltip || true; + + const { title, description, data, dataKey, categoryKey, color, showLegend = false, showTooltip = true, chartType = 'bar' } = slideData; + + const chartData = data || []; const renderChart = () => { const commonProps = { data: chartData, @@ -103,7 +100,7 @@ const Type4SlideLayout: React.FC = ({ data: slideData }) {showTooltip && } />} {showLegend && } />} - + ); @@ -117,7 +114,7 @@ const Type4SlideLayout: React.FC = ({ data: slideData }) {showLegend && } />} = ({ data: slideData }) {showLegend && } />} = ({ data: slideData }) cy="40%" outerRadius={70} fill={color} - dataKey={dataKey} + dataKey={dataKey || 'value'} label={({ name, percent }) => `${name} ${(percent * 100).toFixed(0)}%`} > {chartData.map((entry, index) => ( @@ -172,7 +169,7 @@ const Type4SlideLayout: React.FC = ({ data: slideData }) {showTooltip && } />} {showLegend && } />} - + ); @@ -186,9 +183,9 @@ const Type4SlideLayout: React.FC = ({ data: slideData }) className=" rounded-sm w-full max-w-[1280px] px-3 py-[10px] sm:px-12 lg:px-20 sm:py-[40px] lg:py-[86px] shadow-lg max-h-[720px] flex flex-col items-center justify-center aspect-video bg-white relative z-20 mx-auto" > -

- {slideData?.title || 'Chart Analysis'} -

+ {title &&

+ {title} +

}
@@ -199,9 +196,9 @@ const Type4SlideLayout: React.FC = ({ data: slideData })
-

- {slideData?.description || 'This chart shows important data trends and insights that help understand the current situation and make informed decisions.'} -

+ {description &&

+ {description} +

}
diff --git a/servers/nextjs/presentation-layouts/default/Type5SlideLayout.tsx b/servers/nextjs/presentation-layouts/default/Type5SlideLayout.tsx index 3ba077f1..75fc2daa 100644 --- a/servers/nextjs/presentation-layouts/default/Type5SlideLayout.tsx +++ b/servers/nextjs/presentation-layouts/default/Type5SlideLayout.tsx @@ -42,11 +42,12 @@ export const Schema = type5SlideSchema export type Type5SlideData = z.infer interface Type5SlideLayoutProps { - data?: Partial + data: Partial } const Type5SlideLayout: React.FC = ({ data: slideData }) => { + const { title, description, items } = slideData; return (
= ({ data: slideData })
{/* Left section - Title and Description */}
-

- {slideData?.title || 'Key Points'} -

+ {title &&

+ {title} +

} -

- {slideData?.description || 'Here is the main description that provides context and introduction to the numbered points on the right side.'} -

+ {description &&

+ {description} +

}
{/* Right section - Numbered items */} @@ -80,12 +81,12 @@ const Type5SlideLayout: React.FC = ({ data: slideData }) {`0${index + 1}`}
-

+ {item.heading &&

{item.heading} -

-

+ } + {item.description &&

{item.description} -

+

}
diff --git a/servers/nextjs/presentation-layouts/default/Type6SlideLayout.tsx b/servers/nextjs/presentation-layouts/default/Type6SlideLayout.tsx index f7e4a517..f7d6fff6 100644 --- a/servers/nextjs/presentation-layouts/default/Type6SlideLayout.tsx +++ b/servers/nextjs/presentation-layouts/default/Type6SlideLayout.tsx @@ -61,12 +61,12 @@ export const Schema = type6SlideSchema export type Type6SlideData = z.infer interface Type6SlideLayoutProps { - data?: Partial + data: Partial } const Type6SlideLayout: React.FC = ({ data: slideData }) => { - const items = slideData?.items || [] - const isGridLayout = items.length >= 4 + const { title, items } = slideData; + const isGridLayout = items && items.length >= 4 const getGridCols = (length: number) => { switch (length) { @@ -82,8 +82,8 @@ const Type6SlideLayout: React.FC = ({ data: slideData }) const renderGridContent = () => { return ( -
4 ? 'md:grid-cols-3' : 'md:grid-cols-2'} gap-4 sm:gap-6 lg:gap-8 mt-4 lg:mt-12 w-full`}> - {items.map((item, index) => ( +
4 ? 'md:grid-cols-3' : 'md:grid-cols-2'} gap-4 sm:gap-6 lg:gap-8 mt-4 lg:mt-12 w-full`}> + {items && items.map((item, index) => (
= ({ data: slideData }) const renderHorizontalContent = () => { return ( -
- {items.map((item, index) => ( +
+ {items && items.map((item, index) => (
= ({ data: slideData })
-

+ {item.heading &&

{item.heading} -

-

+ } + {item.description &&

{item.description} -

+

}
))} @@ -148,9 +148,9 @@ const Type6SlideLayout: React.FC = ({ data: slideData }) >
-

- {slideData?.title || 'Our Services'} -

+ {title &&

+ {title} +

}
{isGridLayout ? renderGridContent() : renderHorizontalContent()} diff --git a/servers/nextjs/presentation-layouts/default/Type7SlideLayout.tsx b/servers/nextjs/presentation-layouts/default/Type7SlideLayout.tsx index c802e405..7c40b72e 100644 --- a/servers/nextjs/presentation-layouts/default/Type7SlideLayout.tsx +++ b/servers/nextjs/presentation-layouts/default/Type7SlideLayout.tsx @@ -66,12 +66,12 @@ export const Schema = type7SlideSchema export type Type7SlideData = z.infer interface Type7SlideLayoutProps { - data?: Partial + data: Partial } const Type7SlideLayout: React.FC = ({ data: slideData }) => { - const items = slideData?.items || [] - const isGridLayout = items.length >= 4 + const { title, items } = slideData; + const isGridLayout = items && items.length >= 4 const getGridCols = (length: number) => { switch (length) { @@ -87,8 +87,8 @@ const Type7SlideLayout: React.FC = ({ data: slideData }) const renderGridContent = () => { return ( -
4 ? 'md:grid-cols-3' : 'md:grid-cols-2'} gap-4 sm:gap-6 lg:gap-8 mt-4 lg:mt-12 w-full`}> - {items.map((item, index) => ( +
4 ? 'md:grid-cols-3' : 'md:grid-cols-2'} gap-4 sm:gap-6 lg:gap-8 mt-4 lg:mt-12 w-full`}> + {items && items.map((item, index) => (
= ({ data: slideData })
-

+ {item.heading &&

{item.heading} -

-

+ } + {item.description &&

{item.description} -

+

}
@@ -123,8 +123,8 @@ const Type7SlideLayout: React.FC = ({ data: slideData }) const renderHorizontalContent = () => { return ( -
- {items.map((item, index) => ( +
+ {items && items.map((item, index) => (
= ({ data: slideData }) >
- {item.icon?.__icon_query__ + />}
-

+ {item.heading &&

{item.heading} -

-

+ } + {item.description &&

{item.description} -

+

}
))} @@ -160,9 +160,9 @@ const Type7SlideLayout: React.FC = ({ data: slideData }) className=" rounded-sm w-full max-w-[1280px] font-inter shadow-lg px-3 sm:px-12 lg:px-20 py-[10px] sm:py-[40px] lg:py-[86px] flex flex-col items-center justify-center max-h-[720px] aspect-video bg-white relative z-20 mx-auto" >
-

- {slideData?.title || 'Our Services'} -

+ {title &&

+ {title} +

}
{isGridLayout ? renderGridContent() : renderHorizontalContent()} diff --git a/servers/nextjs/presentation-layouts/default/Type8SlideLayout.tsx b/servers/nextjs/presentation-layouts/default/Type8SlideLayout.tsx index d234a0c7..94e2a502 100644 --- a/servers/nextjs/presentation-layouts/default/Type8SlideLayout.tsx +++ b/servers/nextjs/presentation-layouts/default/Type8SlideLayout.tsx @@ -61,18 +61,18 @@ export const Schema = type8SlideSchema export type Type8SlideData = z.infer interface Type8SlideLayoutProps { - data?: Partial + data: Partial } const Type8SlideLayout: React.FC = ({ data: slideData }) => { - const items = slideData?.items || [] + const { title, description, items } = slideData; const renderItems = () => { - if (items.length === 2) { + if (items && items.length === 2) { // Vertical stacked layout for 2 items return (
- {items.map((item, index) => ( + {items && items.map((item, index) => (
= ({ data: slideData }) >
- {item.icon?.__icon_query__ + />}
-

+ {item.heading &&

{item.heading} -

-

+ } + {item.description &&

{item.description} -

+

}
))} @@ -105,7 +105,7 @@ const Type8SlideLayout: React.FC = ({ data: slideData }) // Horizontal layout with side icons for 3+ items return (
- {items.map((item, index) => ( + {items && items.map((item, index) => (
= ({ data: slideData })
- {item.icon?.__icon_query__ + />}
-

+ {item.heading &&

{item.heading} -

-

+ } + {item.description &&

{item.description} -

+

}
@@ -146,13 +146,13 @@ const Type8SlideLayout: React.FC = ({ data: slideData })
{/* Left section - Title and Description */}
-

- {slideData?.title || 'Key Features'} -

+ {title &&

+ {title} +

} -

- {slideData?.description || 'Here is the main description that provides context and introduces the key features outlined on the right side.'} -

+ {description &&

+ {description} +

}
{/* Right section - Items */} diff --git a/servers/nextjs/presentation-layouts/default/Type9SlideLayout.tsx b/servers/nextjs/presentation-layouts/default/Type9SlideLayout.tsx index 61d1d71d..f49e4296 100644 --- a/servers/nextjs/presentation-layouts/default/Type9SlideLayout.tsx +++ b/servers/nextjs/presentation-layouts/default/Type9SlideLayout.tsx @@ -97,17 +97,11 @@ export const Schema = type9SlideSchema export type Type9SlideData = z.infer interface Type9SlideLayoutProps { - data?: Partial + data: Partial } const Type9SlideLayout: React.FC = ({ data: slideData }) => { - const chartData = slideData?.data || []; - const chartType = slideData?.chartType || 'line'; - const color = slideData?.color || '#3b82f6'; - const dataKey = slideData?.dataKey || 'value'; - const categoryKey = slideData?.categoryKey || 'name'; - const showLegend = slideData?.showLegend || false; - const showTooltip = slideData?.showTooltip || true; + const { title, items, chartData, chartType = 'line', color = '#3b82f6', dataKey = 'value', categoryKey = 'name', showLegend = false, showTooltip = true } = slideData; const renderChart = () => { const commonProps = { data: chartData, @@ -177,7 +171,7 @@ const Type9SlideLayout: React.FC = ({ data: slideData }) dataKey={dataKey} label={({ name, percent }) => `${name} ${(percent * 100).toFixed(0)}%`} > - {chartData.map((entry, index) => ( + {chartData.map((entry: any, index: number) => ( ))} @@ -206,9 +200,9 @@ const Type9SlideLayout: React.FC = ({ data: slideData }) className=" rounded-sm w-full max-w-[1280px] px-3 py-[10px] sm:px-12 lg:px-20 sm:py-[40px] lg:py-[86px] shadow-lg max-h-[720px] flex flex-col items-center justify-center aspect-video bg-white relative z-20 mx-auto" > -

- {slideData?.title || 'Chart Analysis'} -

+ {title &&

+ {title} +

}
@@ -220,7 +214,7 @@ const Type9SlideLayout: React.FC = ({ data: slideData })
- {slideData?.items?.map((item, index) => ( + {items && items.map((item, index) => (
= ({ data: slideData }) {`0${index + 1}`}
-

+ {item.heading &&

{item.heading} -

-

+ } + {item.description &&

{item.description} -

+

}
diff --git a/servers/nextjs/presentation-layouts/pitch-deck/AboutUsSlide.tsx b/servers/nextjs/presentation-layouts/pitch-deck/AboutUsSlide.tsx index ef9e3a40..bb8abc9d 100644 --- a/servers/nextjs/presentation-layouts/pitch-deck/AboutUsSlide.tsx +++ b/servers/nextjs/presentation-layouts/pitch-deck/AboutUsSlide.tsx @@ -74,7 +74,7 @@ export const Schema = z.object({ // Type inference type SchemaType = z.infer; -// Component definition +// Component definitionz const AboutUsSlide = ({ data }: { data: Partial }) => { const { sectionTitle, sectionSubtitle, organizationDescription, additionalContext, featuredImage, showVisualAccents, showColorBlocks, showAccentSquare } = data; From 56cb9f0fe2201f4e871baab918acab2673ee9a5e Mon Sep 17 00:00:00 2001 From: sudipnext Date: Wed, 23 Jul 2025 23:06:05 +0545 Subject: [PATCH 5/7] Add modern pitch deck slide layouts for market size, validation, traction, business model, team, and thank you slides - Implemented Market Size Slide Layout with schema and default data - Created Market Validation Slide Layout with customizable comparison data - Developed Company Traction Slide Layout featuring dynamic growth statistics - Introduced Business Model Slide Layout showcasing CAC metrics - Added Modern Team Slide Layout to display team member profiles - Designed Thank You Slide Layout for closing presentations - Included a settings JSON file for modern layout configurations --- .../modern/1IntroSlideLayout.tsx | 112 +++++++ .../modern/2AboutCompanySlideLayout.tsx | 140 ++++++++ .../modern/3ProblemSlideLayout.tsx | 161 ++++++++++ .../modern/4SolutionSlideLayout.tsx | 169 ++++++++++ .../modern/5ProductOverviewSlideLayout.tsx | 301 ++++++++++++++++++ .../modern/6MarketSizeSlideLayout.tsx | 153 +++++++++ .../modern/7MarketValidationSlideLayout.tsx | 193 +++++++++++ .../modern/8CompanyTractionSlideLayout.tsx | 267 ++++++++++++++++ .../modern/9BusinessModelSlideLayout.tsx | 140 ++++++++ .../presentation-layouts/modern/setting.json | 5 + .../modern/z10TeamSlideLayout.tsx | 199 ++++++++++++ .../modern/z11ThankYouSlideLayout.tsx | 147 +++++++++ 12 files changed, 1987 insertions(+) create mode 100644 servers/nextjs/presentation-layouts/modern/1IntroSlideLayout.tsx create mode 100644 servers/nextjs/presentation-layouts/modern/2AboutCompanySlideLayout.tsx create mode 100644 servers/nextjs/presentation-layouts/modern/3ProblemSlideLayout.tsx create mode 100644 servers/nextjs/presentation-layouts/modern/4SolutionSlideLayout.tsx create mode 100644 servers/nextjs/presentation-layouts/modern/5ProductOverviewSlideLayout.tsx create mode 100644 servers/nextjs/presentation-layouts/modern/6MarketSizeSlideLayout.tsx create mode 100644 servers/nextjs/presentation-layouts/modern/7MarketValidationSlideLayout.tsx create mode 100644 servers/nextjs/presentation-layouts/modern/8CompanyTractionSlideLayout.tsx create mode 100644 servers/nextjs/presentation-layouts/modern/9BusinessModelSlideLayout.tsx create mode 100644 servers/nextjs/presentation-layouts/modern/setting.json create mode 100644 servers/nextjs/presentation-layouts/modern/z10TeamSlideLayout.tsx create mode 100644 servers/nextjs/presentation-layouts/modern/z11ThankYouSlideLayout.tsx diff --git a/servers/nextjs/presentation-layouts/modern/1IntroSlideLayout.tsx b/servers/nextjs/presentation-layouts/modern/1IntroSlideLayout.tsx new file mode 100644 index 00000000..ff02a905 --- /dev/null +++ b/servers/nextjs/presentation-layouts/modern/1IntroSlideLayout.tsx @@ -0,0 +1,112 @@ +import React from "react"; +import * as z from "zod"; + +export const layoutId = "intro-pitchdeck-slide"; +export const layoutName = "Intro Pitch Deck Slide"; +export const layoutDescription = + "A visually appealing introduction slide for a pitch deck, featuring a large title, company name, date, and contact information with a modern design."; +const introPitchDeckSchema = z.object({ + title: z.string().min(2).max(15).default("Pitch Deck").meta({ + description: "Main title of the slide", + }), + description: z.string().default("").meta({ + description: "Empty description as per the design", + }), + contactNumber: z.string().default("+123-456-7890").meta({ + description: "Contact phone number displayed in footer", + }), + contactAddress: z + .string() + .default("123 Anywhere St., Any City, ST 123") + .meta({ + description: "Contact address displayed in footer", + }), + contactWebsite: z.string().default("www.reallygreatsite.com").meta({ + description: "Contact website URL displayed in footer", + }), + companyName: z.string().default("presenton").meta({ + description: "Company name displayed in header", + }), + date: z.string().default("June 13, 2038").meta({ + description: "Date of the presentation", + }), +}); + +export const Schema = introPitchDeckSchema; +export type IntroPitchDeckData = z.infer; + +interface IntroSlideLayoutProps { + data?: Partial; +} + +const IntroPitchDeckSlide: React.FC = ({ + data: slideData, +}) => { + return ( + <> + {/* Montserrat Font */} + +
+ {/* Top Header */} +
+ {slideData?.companyName} + {slideData?.date} +
+ + {/* Main Title */} +
+

+ {slideData?.title} + {/* Blue underline */} + +

+
+ + {/* Bottom Contact Row */} +
+
+ 📞 + {slideData?.contactNumber} +
+
+ 📍 + {slideData?.contactAddress} +
+
+ 🌐 + {slideData?.contactWebsite} +
+
+
+ + ); +}; + +export default IntroPitchDeckSlide; diff --git a/servers/nextjs/presentation-layouts/modern/2AboutCompanySlideLayout.tsx b/servers/nextjs/presentation-layouts/modern/2AboutCompanySlideLayout.tsx new file mode 100644 index 00000000..d08f439d --- /dev/null +++ b/servers/nextjs/presentation-layouts/modern/2AboutCompanySlideLayout.tsx @@ -0,0 +1,140 @@ +import React from "react"; +import * as z from "zod"; +import { ImageSchema, IconSchema } from "@/presentation-layouts/defaultSchemes"; + +export const layoutId = "about-company-slide"; +export const layoutName = "About Our Company Slide"; +export const layoutDescription = + "A slide layout providing an overview of the company, its background, and key information."; + +const aboutCompanySlideSchema = z.object({ + title: z.string().min(3).max(60).default("About Our Company").meta({ + description: "Main title of the slide", + }), + content: z + .string() + .min(50) + .max(500) + .default( + "In the presentation session, the background/introduction can be filled with information that is arranged systematically and effectively with respect to an interesting topic to be used as material for discussion at the opening of the presentation session. The introduction can provide a general overview for those who are listening to your presentation so that the key words on the topic of discussion are emphasized during this background/introductory presentation session.", + ) + .meta({ + description: "Main content text describing the company or topic", + }), + companyName: z.string().min(2).max(50).default("presenton").meta({ + description: "Company name displayed in header", + }), + date: z.string().min(5).max(30).default("June 13, 2038").meta({ + description: "Date displayed in header", + }), + image: ImageSchema.optional().meta({ + description: + "Optional supporting image for the slide (building, office, etc.)", + }), +}); + +export const Schema = aboutCompanySlideSchema; + +export type AboutCompanySlideData = z.infer; + +interface AboutCompanySlideLayoutProps { + data?: Partial; +} + +const AboutCompanySlideLayout: React.FC = ({ + data: slideData, +}) => { + return ( + <> + {/* Import fonts */} + + +
+ {/* Header */} +
+ {slideData?.companyName} + {slideData?.date} +
+ + {/* Main content area */} +
+ {/* Left side - Image */} +
+
+ {slideData?.image ? ( + {slideData.image.__image_prompt__} + ) : ( + /* Default building facade */ +
+ {/* Building structure simulation */} +
+ + {/* Horizontal lines (building floors) */} +
+ {[...Array(12)].map((_, i) => ( +
+ ))} +
+ + {/* Vertical lines (building columns) */} +
+ {[...Array(6)].map((_, i) => ( +
+ ))} +
+ + {/* Windows */} +
+ {[...Array(32)].map((_, i) => ( +
+ ))} +
+ + {/* Building edge highlight */} +
+
+ )} +
+
+ + {/* Right side - Content */} +
+

+ {slideData?.title || "About Our Company"} +

+ +
+ {slideData?.content || + "In the presentation session, the background/introduction can be filled with information that is arranged systematically and effectively with respect to an interesting topic to be used as material for discussion at the opening of the presentation session. The introduction can provide a general overview for those who are listening to your presentation so that the key words on the topic of discussion are emphasized during this background/introductory presentation session."} +
+
+
+
+ + ); +}; + +export default AboutCompanySlideLayout; diff --git a/servers/nextjs/presentation-layouts/modern/3ProblemSlideLayout.tsx b/servers/nextjs/presentation-layouts/modern/3ProblemSlideLayout.tsx new file mode 100644 index 00000000..6b244f53 --- /dev/null +++ b/servers/nextjs/presentation-layouts/modern/3ProblemSlideLayout.tsx @@ -0,0 +1,161 @@ +import React from "react"; +import * as z from "zod"; +import { ImageSchema, IconSchema } from "@/presentation-layouts/defaultSchemes"; + +export const layoutId = "problem-statement-slide"; +export const layoutName = "Problem Statement Slide"; +export const layoutDescription = + "A slide layout designed to present a clear problem statement, including categories of problems, company information, and an optional image."; + +const problemStatementSlideSchema = z.object({ + title: z.string().min(3).max(40).default("Problem").meta({ + description: "Main title of the problem statement slide", + }), + description: z + .string() + .min(50) + .max(500) + .default( + "A problem needs to be discussed further and in detail because this problem is the main foundation in the initial development of a product, service, and decision making. Without a well-defined problem, it will have an impact on a job that is unfocused, unmanaged, and less relevant.", + ) + .meta({ + description: "Main content text describing the problem statement", + }), + problemCategories: z + .array( + z.object({ + title: z.string().min(3).max(30).meta({ + description: "Title of the problem category", + }), + description: z.string().min(20).max(200).meta({ + description: "Description of the problem category", + }), + icon: IconSchema.optional().meta({ + description: "Optional icon for the problem category", + }), + }), + ) + .min(2) + .max(4) + .default([ + { + title: "Inefficiency", + description: + "Businesses struggle to find digital tools that meet their needs, causing operational slowdowns.", + icon: { + __icon_url__: + "https://cdn.jsdelivr.net/npm/lucide@latest/dist/esm/icons/alert-triangle.js", + __icon_query__: "warning alert inefficiency", + }, + }, + { + title: "High Costs", + description: + "Outdated systems increase expenses, while small businesses struggle to expand their market reach.", + icon: { + __icon_url__: + "https://cdn.jsdelivr.net/npm/lucide@latest/dist/esm/icons/trending-up.js", + __icon_query__: "trending up costs chart", + }, + }, + ]) + .meta({ + description: + "List of problem categories with titles, descriptions, and optional icons", + }), + companyName: z.string().min(2).max(50).default("Rimberio").meta({ + description: "Company name displayed in header", + }), + date: z.string().min(5).max(30).default("June 13, 2038").meta({ + description: "Date displayed in header", + }), +}); + +export const Schema = problemStatementSlideSchema; + +export type ProblemStatementSlideData = z.infer< + typeof problemStatementSlideSchema +>; + +interface ProblemStatementSlideLayoutProps { + data?: Partial; +} + +const ProblemStatementSlideLayout: React.FC< + ProblemStatementSlideLayoutProps +> = ({ data: slideData }) => { + const problemCategories = slideData?.problemCategories || []; + + return ( + <> + {/* Import fonts */} + + +
+ {/* Header */} +
+ {slideData?.companyName} + {slideData?.date} +
+ + {/* Main content area */} +
+ {/* Left side - Main Problem */} +
+
+

+ {slideData?.title} +

+ +
+ {slideData?.description} +
+
+
+ + {/* Right side - Problem Categories with Icons */} +
+
+ {problemCategories.map((category, index) => ( +
+
+ {category.icon?.__icon_query__} +
+
+

+ {category.title} +

+

+ {category.description} +

+
+
+ ))} +
+
+
+ + {/* Bottom border line */} +
+
+ + ); +}; + +export default ProblemStatementSlideLayout; diff --git a/servers/nextjs/presentation-layouts/modern/4SolutionSlideLayout.tsx b/servers/nextjs/presentation-layouts/modern/4SolutionSlideLayout.tsx new file mode 100644 index 00000000..c8f02e06 --- /dev/null +++ b/servers/nextjs/presentation-layouts/modern/4SolutionSlideLayout.tsx @@ -0,0 +1,169 @@ +import React from "react"; +import * as z from "zod"; +import { IconSchema } from "@/presentation-layouts/defaultSchemes"; + +export const layoutId = "solution-slide"; +export const layoutName = "Solution Slide"; +export const layoutDescription = + "A slide layout designed to present a solution to previously identified problems, showcasing key aspects of the solution with sections and icons."; + +const solutionSlideSchema = z.object({ + companyName: z.string().min(2).max(50).default("presenton").meta({ + description: "Company name displayed in header", + }), + date: z.string().min(5).max(50).default("June 13, 2038").meta({ + description: "Date displayed in header", + }), + title: z.string().min(3).max(40).default("Solution").meta({ + description: "Main title of the slide", + }), + mainDescription: z + .string() + .min(20) + .max(300) + .default( + "Show that we offer a solution that solves the problems previously described and identified. Make sure that the solutions we offer uphold the values of effectiveness, efficiency, and are highly relevant to the market situation and society.", + ) + .meta({ + description: "Main content text describing the solution", + }), + sections: z + .array( + z.object({ + title: z.string().min(3).max(30).meta({ + description: "Section title", + }), + description: z.string().min(5).max(80).meta({ + description: "Section description", + }), + icon: IconSchema.optional().meta({ + description: "Icon for the section", + }), + }), + ) + .min(2) + .max(4) + .default([ + { + title: "Market", + description: "Innovative and widely accepted.", + icon: { + __icon_query__: "market innovation", + __icon_url__: + "https://cdn.jsdelivr.net/npm/lucide@latest/dist/esm/icons/globe.js", + }, + }, + { + title: "Industry", + description: "Based on sound market decisions.", + icon: { + __icon_query__: "industry building", + __icon_url__: + "https://cdn.jsdelivr.net/npm/lucide@latest/dist/esm/icons/building.js", + }, + }, + { + title: "SEM", + description: "Driven by precise data and analysis.", + icon: { + __icon_query__: "SEM data analysis", + __icon_url__: + "https://cdn.jsdelivr.net/npm/lucide@latest/dist/esm/icons/chart-bar.js", + }, + }, + { + title: "End User", + description: "Focused on real user impact.", + icon: { + __icon_query__: "end user impact", + __icon_url__: + "https://cdn.jsdelivr.net/npm/lucide@latest/dist/esm/icons/user.js", + }, + }, + ]) + .meta({ + description: + "List of solution sections with titles, descriptions, and optional icons", + }), +}); + +export const Schema = solutionSlideSchema; + +export type SolutionSlideData = z.infer; + +interface SolutionSlideLayoutProps { + data?: Partial; +} + +const SolutionSlideLayout: React.FC = ({ + data: slideData, +}) => { + const sections = slideData?.sections || []; + + return ( + <> + {/* Import Google Fonts */} + + +
+ {/* Header */} +
+ {slideData?.companyName} + {slideData?.date} +
+ + {/* Main Content */} +
+ {/* Title and Description */} +
+

+ {slideData?.title} +

+

+ {slideData?.mainDescription} +

+
+ {/* Four Small Boxes in a Row */} +
+ {sections.map((section, idx) => ( +
+
+ {section?.icon?.__icon_url__ && ( + {section.icon.__icon_query__} + )} +
+

+ {section.title} +

+
+

+ {section.description} +

+
+ ))} +
+
+ + {/* Bottom Border */} +
+
+ + ); +}; + +export default SolutionSlideLayout; diff --git a/servers/nextjs/presentation-layouts/modern/5ProductOverviewSlideLayout.tsx b/servers/nextjs/presentation-layouts/modern/5ProductOverviewSlideLayout.tsx new file mode 100644 index 00000000..037a8907 --- /dev/null +++ b/servers/nextjs/presentation-layouts/modern/5ProductOverviewSlideLayout.tsx @@ -0,0 +1,301 @@ +import React from "react"; +import * as z from "zod"; +import { ImageSchema } from "@/presentation-layouts/defaultSchemes"; + +export const layoutId = "product-overview-slide"; +export const layoutName = "Product Overview Slide"; +export const layoutDescription = + "A slide layout designed to showcase a company's products or services, highlighting their features and benefits in a structured format."; + +const productOverviewSlideSchema = z.object({ + companyName: z.string().min(2).max(50).default("presenton").meta({ + description: "Company name displayed in header", + }), + date: z.string().min(5).max(50).default("June 13, 2038").meta({ + description: "Date displayed in header", + }), + title: z.string().min(3).max(40).default("Product Overview").meta({ + description: "Main title of the slide", + }), + mainDescription: z + .string() + .min(50) + .max(400) + .default( + "Provide an explanation of the general profile of the services we have. Arrange information about our products services in a systematic and fact-based manner. Also express our pride in the service that we have done well.", + ) + .meta({ + description: "Main content text describing the product overview", + }), + products: z + .array( + z.object({ + title: z.string().min(3).max(50).meta({ + description: "Product title", + }), + description: z.string().min(30).max(200).meta({ + description: "Product description", + }), + image: ImageSchema.meta({ + description: "Product image", + }), + isBlueBackground: z.boolean().default(false).meta({ + description: "Whether the product box has a blue background", + }), + }), + ) + .min(2) + .max(4) + .default([ + { + title: "Internet of Things", + description: + "Detail and explain each product. Our examination of community and market issues increases with additional products/services.", + image: { + __image_url__: + "https://images.unsplash.com/photo-1558618666-fcd25c85cd64?w=300&h=200&fit=crop", + __image_prompt__: "Person working on electronics with headphones", + }, + isBlueBackground: true, + }, + { + title: "Smart Home Platform", + description: + "Our alternate product category is available. Our products must work together to solve social and economic issues.", + image: { + __image_url__: + "https://images.unsplash.com/photo-1573164713988-8665fc963095?w=300&h=200&fit=crop", + __image_prompt__: + "Woman working at computer with technical equipment", + }, + isBlueBackground: true, + }, + ]) + .meta({ + description: "List of products or services to showcase", + }), +}); + +export const Schema = productOverviewSlideSchema; + +export type ProductOverviewSlideData = z.infer< + typeof productOverviewSlideSchema +>; + +interface ProductOverviewSlideLayoutProps { + data?: Partial; +} + +const ProductOverviewSlideLayout: React.FC = ({ + data: slideData, +}) => { + const products = slideData?.products || []; + + // Make the product boxes smaller + const PRODUCT_BOX_HEIGHT = 400; // px (smaller than before) + const PRODUCT_BOX_WIDTH = 200; // px (smaller than before) + const TEXT_SECTION_HEIGHT = Math.round(PRODUCT_BOX_HEIGHT * 0.56); // ~190px + const IMAGE_SECTION_HEIGHT = PRODUCT_BOX_HEIGHT - TEXT_SECTION_HEIGHT; // ~150px + + return ( + <> + {/* Import Google Fonts */} + + +
+ {/* Header */} +
+ {slideData?.companyName} + {slideData?.date} +
+ 6+ + {/* Main Content */} +
+ {/* Title and Description on the left */} +
+

+ {slideData?.title} +

+

+ {slideData?.mainDescription} +

+
+ + {/* Product Grid on the right */} +
+ {/* First Column: Normal order (Text above, Image below) */} +
+ {products[0] && ( +
+ {/* Top Section - Blue background with text */} +
+

+ {products[0].title} +

+

+ {products[0].description} +

+
+ {/* Bottom Section - Image */} +
+ { +
+
+ )} + {products[2] && ( +
+
+

+ {products[2].title} +

+

+ {products[2].description} +

+
+
+ { +
+
+ )} +
+ {/* Second Column: Reverse order (Image above, Text below) */} +
+ {products[1] && ( +
+ {/* Top Section - Image */} +
+ { +
+ {/* Bottom Section - Blue background with text */} +
+

+ {products[1].title} +

+

+ {products[1].description} +

+
+
+ )} + {products[3] && ( +
+
+ { +
+
+

+ {products[3].title} +

+

+ {products[3].description} +

+
+
+ )} +
+
+
+ {/* Bottom Border */} +
+
+ + ); +}; + +export default ProductOverviewSlideLayout; diff --git a/servers/nextjs/presentation-layouts/modern/6MarketSizeSlideLayout.tsx b/servers/nextjs/presentation-layouts/modern/6MarketSizeSlideLayout.tsx new file mode 100644 index 00000000..fcc375e1 --- /dev/null +++ b/servers/nextjs/presentation-layouts/modern/6MarketSizeSlideLayout.tsx @@ -0,0 +1,153 @@ +import React from "react"; +import * as z from "zod"; +import { ImageSchema } from "@/presentation-layouts/defaultSchemes"; + +export const layoutId = "market-size-pitchdeck-slide"; +export const layoutName = "Market Size Pitch Deck Slide"; +export const layoutDescription = + "A professional slide layout designed to present market size statistics, including TAM, SAM, and SOM, with a world map and key metrics."; + +const marketSizeSlideSchema = z.object({ + title: z.string().default("Market Size").meta({ + description: "Main slide title", + }), + companyName: z.string().default("Rimberio").meta({ + description: "Presenter's name", + }), + date: z.string().default("June 13, 2038").meta({ + description: "Presentation date", + }), + mapImage: ImageSchema.default({ + __image_url__: + "https://upload.wikimedia.org/wikipedia/commons/8/80/World_map_-_low_resolution.svg", // You can quickly find a world map image via a Google search or use a free resource like Wikimedia Commons + __image_prompt__: "World map with location pins or points", + }), + marketStats: z + .array( + z.object({ + label: z.string(), + value: z.string(), + description: z.string(), + }), + ) + .min(1) + .max(3) + .default([ + { + label: "Total Available Market (TAM)", + value: "1.4 Billion", + description: + "In the TAM Section, we can fill in the potential of any person who can buy an offer or the maximum amount of revenue a business can earn by selling their offer.", + }, + { + label: "Serviceable Available Market (SAM)", + value: "194 Million", + description: + "It is a part of TAM that has the potential to become a target market for the company by considering the type of product, technology available and geographical conditions.", + }, + { + label: "Serviceable Obtainable Market (SOM)", + value: "167 Million", + description: + "The SOM is a smaller fraction of the SAM that is the target of a serviceable and realistically achievable market in the short to medium term.", + }, + ]), + description: z + .string() + .default( + "Market size is the total amount of all sales and customers that can be seen directly by stakeholders. This technique is usually calculated at the end of the year, the market size can be used by companies to determine the potential of their market and business in the future. This is very useful, especially for new companies that will offer services to those who are interested in our services.", + ) + .meta({ + description: "Main description text for the slide", + }), +}); + +export const Schema = marketSizeSlideSchema; +export type MarketSizeSlideData = z.infer; + +interface MarketSizeSlideProps { + data?: Partial; +} + +const MarketSizeSlideLayout: React.FC = ({ + data: slideData, +}) => { + const stats = slideData?.marketStats || []; + + return ( + <> + {/* Montserrat Font */} + + +
+ {/* Header */} +
+ {slideData?.companyName || "Rimberio"} + {slideData?.date || "June 13, 2038"} +
+ + {/* Main Content */} +
+ {/* Title and Map on the left */} +
+
+ {/* Move the title down to align with the top of the market stats */} +

+ {slideData?.title || "Market Size"} +

+
+ Market World Map with Points +
+

+ {slideData?.description || + "Market size is the total amount of all sales and customers that can be seen directly by stakeholders. This technique is usually calculated at the end of the year, the market size can be used by companies to determine the potential of their market and business in the future."} +

+
+
+ + {/* Market Stats on the right */} +
+
+ {stats.map((stat, index) => ( +
+
+
+ {stat.label} +
+
+ {stat.value} +
+
+

+ {stat.description} +

+
+ ))} +
+
+
+
+ + ); +}; + +export default MarketSizeSlideLayout; diff --git a/servers/nextjs/presentation-layouts/modern/7MarketValidationSlideLayout.tsx b/servers/nextjs/presentation-layouts/modern/7MarketValidationSlideLayout.tsx new file mode 100644 index 00000000..540c5386 --- /dev/null +++ b/servers/nextjs/presentation-layouts/modern/7MarketValidationSlideLayout.tsx @@ -0,0 +1,193 @@ +import React from "react"; +import * as z from "zod"; +import { Card } from "@/components/ui/card"; +import { Table, TableHeader, TableBody } from "@/components/ui/table"; +import { ChartContainer } from "@/components/ui/chart"; +import { ImageSchema } from "@/presentation-layouts/defaultSchemes"; +import { BarChart, Bar, XAxis, YAxis, Tooltip, Cell } from "recharts"; + +export const layoutId = "market-validation-slide"; +export const layoutName = "Market Validation Slide"; +export const layoutDescription = + "A slide layout designed to present market validation data, including flexible market validation metrics, comparisons, and an optional decorative image."; + +// Make the schema generic: allow any label/value pairs for comparison +const marketValidationSchema = z.object({ + companyName: z.string().min(2).max(50).default("presenton").meta({ + description: "Company name in header", + }), + date: z.string().min(5).max(50).default("June 13, 2038").meta({ + description: "Date in header", + }), + title: z.string().min(3).max(40).default("Market Validation").meta({ + description: "Title of the slide", + }), + description: z + .string() + .min(50) + .max(400) + .default( + "It’s a market testing stage to ensure that the products produced by the company can be accepted and effectively used by the broad market. For start-up companies, we can use data already achieved by similar products from other companies.", + ) + .meta({ + description: + "Main description text for the slide explaining market validation", + }), + // Generic comparisonData: label for row, label for metric, and value + comparisonData: z + .array( + z.object({ + label: z.string().min(2).max(50).meta({ + description: + "Name of comparison entity (e.g., company, product, etc.)", + }), + metricLabel: z.string().min(2).max(50).meta({ + description: + "Label for the metric being compared (e.g., Users, Revenue, etc.)", + }), + value: z.number().min(0).meta({ + description: "Numeric value for the metric", + }), + }), + ) + .min(2) + .max(5) + .default([ + { label: "Thynk Unlimited", metricLabel: "Revenue ($K)", value: 2650 }, + { label: "Salford & Co.", metricLabel: "Revenue ($K)", value: 1850 }, + { label: "Liceria & Co.", metricLabel: "Revenue ($K)", value: 1010 }, + ]) + .meta({ + description: "Market benchmark data (generic metric)", + }), + image: ImageSchema.optional().meta({ + description: "Optional decorative image", + }), +}); + +export const Schema = marketValidationSchema; + +export type MarketValidationSlideData = z.infer; + +interface MarketValidationSlideLayoutProps { + data?: Partial; +} + +const MarketValidationSlideLayout: React.FC< + MarketValidationSlideLayoutProps +> = ({ data: slideData }) => { + const comparisonData = slideData?.comparisonData || []; + + // Chart color palette (shadcn blue and gray) + const chartColors = ["#2563eb", "#1e40af", "#60a5fa", "#93c5fd", "#dbeafe"]; + + // Determine the metric label to use (assume all rows use the same metricLabel) + const metricLabel = + comparisonData.length > 0 ? comparisonData[0].metricLabel : "Metric"; + + return ( + <> + + +
+ {/* Header */} +
+ {slideData?.companyName} + {slideData?.date} +
+ + {/* Main Content */} +
+ {/* Left Column */} +
+

+ {slideData?.title} +

+

+ {slideData?.description} +

+
+ + {/* Right Column - Chart on top, Table on bottom */} +
+ {/* Bar Chart */} + +
+ + + + + + {/* Legend removed */} + + {comparisonData.map((entry, idx) => ( + + ))} + + + +
+
+ {/* Table of comparison data */} + + + + + + + + + + {comparisonData.map((entry) => ( + + + + + ))} + +
+ {comparisonData.length > 0 ? "Name" : "Name"} + + {metricLabel} +
{entry.label} + {entry.value.toLocaleString()} +
+
+
+
+ +
+
+ + ); +}; + +export default MarketValidationSlideLayout; diff --git a/servers/nextjs/presentation-layouts/modern/8CompanyTractionSlideLayout.tsx b/servers/nextjs/presentation-layouts/modern/8CompanyTractionSlideLayout.tsx new file mode 100644 index 00000000..56905cde --- /dev/null +++ b/servers/nextjs/presentation-layouts/modern/8CompanyTractionSlideLayout.tsx @@ -0,0 +1,267 @@ +import React from "react"; +import { + LineChart, + Line, + XAxis, + YAxis, + CartesianGrid, + Tooltip, + Legend, + ResponsiveContainer, +} from "recharts"; +import * as z from "zod"; + +export const layoutId = "company-traction-slide"; +export const layoutName = "Company Traction Slide"; +export const layoutDescription = + "A slide layout designed to present company traction data, including growth statistics over the years, a chart visualization, and key metrics in a visually appealing format."; + +// growthStats: list of dicts, each dict is { year: string, : number, : number, ... } +const tractionSchema = z.object({ + companyName: z.string().default("presention"), + date: z.string().default("June 13, 2038"), + title: z.string().default("Company Traction"), + description: z + .string() + .default( + "Traction is a period where the company is feeling momentum during its development period. If traction momentum is not harnessed, sales figures can decline and the customer base can shrink. In general, companies will judge success by the amount of revenue and new customers they receive.", + ), + // growthStats is a list of objects, each with a 'year' and any number of metric keys (all numbers) + growthStats: z + .array( + z + .object({ + year: z.string(), + }) + .catchall(z.number()), + ) + .min(1) + .max(20) + .default([ + { + year: "2020", + artificialIntelligence: 5, + internetOfThings: 10, + others: 8, + }, + { + year: "2021", + artificialIntelligence: 10, + internetOfThings: 20, + others: 15, + }, + { + year: "2022", + artificialIntelligence: 20, + internetOfThings: 30, + others: 22, + }, + { + year: "2023", + artificialIntelligence: 28, + internetOfThings: 38, + others: 29, + }, + { + year: "2024", + artificialIntelligence: 35, + internetOfThings: 45, + others: 34, + }, + { + year: "2025", + artificialIntelligence: 45, + internetOfThings: 53, + others: 42, + }, + { + year: "2026", + artificialIntelligence: 55, + internetOfThings: 65, + others: 52, + }, + { + year: "2029", + artificialIntelligence: 55, + internetOfThings: 65, + others: 52, + }, + ]), +}); + +export const Schema = tractionSchema; +export type CompanyTractionData = z.infer; + +interface Props { + data?: Partial; +} + +// Helper: assign colors to series +const defaultColors = [ + "#1E4CD9", + "#3b82f6", + "#f59e0b", + "#10b981", + "#ef4444", + "#a21caf", + "#6366f1", + "#f43f5e", + "#fbbf24", + "#14b8a6", +]; + +function getSeriesKeys( + growthStats: Array>, +): string[] { + if (!growthStats.length) return []; + // Exclude 'year' or any non-numeric keys + const first = growthStats[0]; + return Object.keys(first).filter( + (key) => key !== "year" && typeof first[key] === "number", + ); +} + +// Compute stats for right column, generic for all series +function computeStats( + growthStats: Array>, + seriesKeys: string[], +) { + if (!growthStats.length) return []; + const first = growthStats[0]; + const last = growthStats[growthStats.length - 1]; + return seriesKeys.map((key) => { + const start = typeof first[key] === "number" ? (first[key] as number) : 0; + const end = typeof last[key] === "number" ? (last[key] as number) : 0; + const growth = start === 0 ? 0 : ((end - start) / Math.abs(start)) * 100; + return { + label: key + .replace(/([A-Z])/g, " $1") + .replace(/^./, (str) => str.toUpperCase()), + value: `${growth >= 0 ? "+" : ""}${Math.round(growth)}% growth`, + description: `${key + .replace(/([A-Z])/g, " $1") + .replace(/^./, (str) => str.toUpperCase())} growth over the period.`, + }; + }); +} + +const CompanyTractionSlideLayout: React.FC = ({ data }) => { + const growthStats = data?.growthStats || []; + + // Dynamically determine series keys + const seriesKeys = getSeriesKeys(growthStats); + + // Prepare stats for the right column, generic for all series + const stats = computeStats(growthStats, seriesKeys); + + return ( + <> + +
+ {/* Header */} +
+ {data?.companyName} + {data?.date} +
+ + {/* Main Content */} +
+ {/* Left Column - Chart with Title Below */} +
+

+ {data?.title} +

+
+
+ + + + + + + + {seriesKeys.map((key, idx) => ( + str.toUpperCase())} + dot={{ + r: 4, + fill: defaultColors[idx % defaultColors.length], + }} + activeDot={{ + r: 6, + fill: defaultColors[idx % defaultColors.length], + }} + /> + ))} + + +
+
+
+ + {/* Right Column - Description and Stats */} +
+

+ {data?.description || + "Traction is a period where the company is feeling momentum during its development period. If traction momentum is not harnessed, sales figures can decline and the customer base can shrink. In general, companies will judge success by the amount of revenue and new customers they receive."} +

+
+ {stats.map((stat, index) => ( +
+
+ {stat.label} +
+
+ {stat.value} +
+

+ {stat.description} +

+
+ ))} +
+
+
+
+
+ + ); +}; + +export default CompanyTractionSlideLayout; diff --git a/servers/nextjs/presentation-layouts/modern/9BusinessModelSlideLayout.tsx b/servers/nextjs/presentation-layouts/modern/9BusinessModelSlideLayout.tsx new file mode 100644 index 00000000..199948b9 --- /dev/null +++ b/servers/nextjs/presentation-layouts/modern/9BusinessModelSlideLayout.tsx @@ -0,0 +1,140 @@ +import React from "react"; +import * as z from "zod"; +import { + BarChart, + Bar, + CartesianGrid, + XAxis, + YAxis, + Tooltip, + ResponsiveContainer, + Legend, +} from "recharts"; + +export const layoutId = "business-model-slide"; +export const layoutName = "Business Model Slide"; +export const layoutDescription = + "A business model presentation slide displaying CAC metrics and monetization strategy."; + +const businessModelSchema = z.object({ + companyName: z.string().default("presenton"), + date: z.string().default("June 13, 2038"), + title: z.string().default("Business Model"), + description: z + .string() + .default( + "Describe how you monetize, who your customers are, your distribution channels or fee structure. The goal is to give an idea of how this business will sustain your product or service and explain how your company will make money and achieve its goals. This can be shown with graphs, statistics, or charts. Use the Lifetime Value (LTV) and Customer Acquisition Cost (CAC) metrics to provide a clearer picture.", + ), + cacChart: z + .array( + z.object({ + label: z.string(), + percentage: z.number(), + }), + ) + .default([ + { label: "Internet of Things", percentage: 70 }, + { label: "Artificial Intelligence", percentage: 60 }, + ]), +}); + +export const Schema = businessModelSchema; +export type BusinessModelData = z.infer; + +interface Props { + data?: Partial; +} + +const BusinessModelSlide: React.FC = ({ data }) => { + const cacChartData = + data?.cacChart && Array.isArray(data.cacChart) && data.cacChart.length > 0 + ? data.cacChart + : [ + { label: "Internet of Things", percentage: 70 }, + { label: "Artificial Intelligence", percentage: 60 }, + ]; + + return ( + <> + +
+ {/* Header */} +
+ {data?.companyName} + {data?.date} +
+ + {/* Main Content */} +
+ {/* Left Column - Chart with Title Below */} +
+

+ {data?.title} +

+
+
+ + + + + + + + + + +
+
+
+ + {/* Right Column - Description and Optional Image */} +
+

+ {data?.description} +

+
+
+
+
+ + ); +}; + +export default BusinessModelSlide; diff --git a/servers/nextjs/presentation-layouts/modern/setting.json b/servers/nextjs/presentation-layouts/modern/setting.json new file mode 100644 index 00000000..b88e362b --- /dev/null +++ b/servers/nextjs/presentation-layouts/modern/setting.json @@ -0,0 +1,5 @@ +{ + "description": "Modern white and blue business pitch deck layouts with clean, professional design", + "ordered": false, + "isDefault": false +} diff --git a/servers/nextjs/presentation-layouts/modern/z10TeamSlideLayout.tsx b/servers/nextjs/presentation-layouts/modern/z10TeamSlideLayout.tsx new file mode 100644 index 00000000..394e8c14 --- /dev/null +++ b/servers/nextjs/presentation-layouts/modern/z10TeamSlideLayout.tsx @@ -0,0 +1,199 @@ +import React from "react"; +import * as z from "zod"; +import { ImageSchema } from "@/presentation-layouts/defaultSchemes"; + +export const layoutId = "modern-team-slide"; +export const layoutName = "Modern Team Slide"; +export const layoutDescription = + "A clean modern team slide showcasing team members with professional profiles and blue-white design."; + +const teamMemberSchema = z.object({ + name: z.string().min(2).max(50).meta({ + description: "Team member's full name", + }), + position: z.string().min(2).max(50).meta({ + description: "Job title or position", + }), + description: z.string().min(20).max(120).meta({ + description: "Brief professional description of the team member", + }), + image: ImageSchema, + linkedIn: z.string().optional().meta({ + description: "LinkedIn profile URL (optional)", + }), +}); + +const modernTeamSlideSchema = z.object({ + title: z.string().min(3).max(40).default("Our Team").meta({ + description: "Main title of the slide", + }), + subtitle: z.string().min(10).max(120).optional().meta({ + description: "Optional subtitle describing the team", + }), + teamMembers: z + .array(teamMemberSchema) + .min(2) + .max(4) + .default([ + { + name: "Sarah Johnson", + position: "CEO & Founder", + description: + "Strategic leader with 15+ years experience in technology and business development. Former VP at Fortune 500 company.", + image: { + __image_url__: + "https://plus.unsplash.com/premium_photo-1661589856899-6dd0871f9db6?fm=jpg&q=60&w=3000&ixlib=rb-4.1.0&ixid=M3wxMjA3fDB8MHxzZWFyY2h8NXx8YnVzaW5lc3N3b21lbnxlbnwwfHwwfHx8MA%3D%3D", + __image_prompt__: "Professional businesswoman CEO headshot", + }, + }, + { + name: "Michael Chen", + position: "CTO", + description: + "Technology expert specializing in scalable architecture and AI solutions. PhD in Computer Science from MIT.", + image: { + __image_url__: + "https://images.unsplash.com/photo-1472099645785-5658abf4ff4e?ixlib=rb-4.0.3&auto=format&fit=crop&w=400&q=80", + __image_prompt__: "Professional businessman CTO headshot", + }, + }, + { + name: "Emily Rodriguez", + position: "VP of Sales", + description: + "Sales leader with proven track record of building high-performing teams and driving revenue growth in B2B markets.", + image: { + __image_url__: + "https://images.unsplash.com/photo-1438761681033-6461ffad8d80?ixlib=rb-4.0.3&auto=format&fit=crop&w=400&q=80", + __image_prompt__: "Professional businesswoman VP headshot", + }, + }, + { + name: "David Kim", + position: "Head of Product", + description: + "Product strategist focused on user experience and market-driven solutions. Former product manager at leading tech companies.", + image: { + __image_url__: + "https://images.unsplash.com/photo-1507003211169-0a1dd7228f2d?ixlib=rb-4.0.3&auto=format&fit=crop&w=400&q=80", + __image_prompt__: "Professional businessman product manager headshot", + }, + }, + ]) + .meta({ + description: "List of team members with their information", + }), + companyName: z.string().default("presenton").meta({ + description: "Company name to display in the header", + }), + date: z.string().default("June 13, 2038").meta({ + description: "Date to display in the header", + }), +}); + +export const Schema = modernTeamSlideSchema; + +export type ModernTeamSlideData = z.infer; + +interface ModernTeamSlideLayoutProps { + data?: Partial; +} + +const ModernTeamSlideLayout: React.FC = ({ + data: slideData, +}) => { + return ( + <> + {/* Import Montserrat Font */} + + +
+ {/* Header */} +
+ {slideData?.companyName} + {slideData?.date} +
+ + {/* Main Content */} +
+ {/* Title */} +

+ {slideData?.title} +

+ {/* Subtitle */} +

+ {slideData?.subtitle} +

+ {/* Team Members Row */} +
+ {slideData?.teamMembers?.map((member, idx) => ( +
+ {/* Photo */} +
+ {member.image.__image_prompt__ +
+ {/* Name */} +
+ {member.name} +
+ {/* Position Badge */} +
+ {member.position} +
+ {/* Description */} +
+ {member.description} +
+ {/* LinkedIn Link (if provided) */} + {member.linkedIn && ( + + + + + LinkedIn + + )} +
+ ))} +
+
+ {/* Bottom Divider */} +
+
+ + ); +}; + +export default ModernTeamSlideLayout; diff --git a/servers/nextjs/presentation-layouts/modern/z11ThankYouSlideLayout.tsx b/servers/nextjs/presentation-layouts/modern/z11ThankYouSlideLayout.tsx new file mode 100644 index 00000000..805aeae8 --- /dev/null +++ b/servers/nextjs/presentation-layouts/modern/z11ThankYouSlideLayout.tsx @@ -0,0 +1,147 @@ +import React from "react"; +import * as z from "zod"; + +export const layoutId = "thank-you-slide"; +export const layoutName = "Thank You Slide"; +export const layoutDescription = + "A simple, plain thank you slide for closing presentations."; + +const thankYouSlideSchema = z.object({ + title: z.string().min(3).max(40).default("Thank You!").meta({ + description: "Main thank you message", + }), + subtitle: z.string().min(0).max(100).default("").meta({ + description: "Optional subtitle or closing remark", + }), + companyName: z.string().min(2).max(50).default("Rimberio").meta({ + description: "Company name displayed in header", + }), + date: z.string().min(5).max(30).default("June 13, 2038").meta({ + description: "Date displayed in header", + }), + address: z + .string() + .min(5) + .max(100) + .default("123 Anywhere St., Any City, ST 12345") + .meta({ + description: "Company address for contact section", + }), + phone: z.string().min(5).max(30).default("+123-456-7890").meta({ + description: "Company phone number for contact section", + }), + website: z.string().min(5).max(100).default("www.reallygreatsite.com").meta({ + description: "Company website for contact section", + }), + email: z.string().default("info@reallygreatsite.com").meta({ + description: "Company email address for contact section", + }), +}); + +export const Schema = thankYouSlideSchema; + +export type ThankYouSlideData = z.infer; + +interface ThankYouSlideLayoutProps { + data?: Partial; +} + +const ThankYouSlideLayout: React.FC = ({ data }) => { + return ( + <> + {/* Import fonts */} + + +
+ {/* Header */} +
+ {data?.companyName || "Rimberio"} + {data?.date || "June 13, 2038"} +
+ + {/* Main content area */} +
+ {/* Thank You and description */} +
+

+ {data?.title || "Thank You!"} +

+ {data?.subtitle && ( +
+ {data.subtitle} +
+ )} +
+ Write down your hopes for the future of your company. Don't forget + to thank the company for the opportunity and convince related + parties to support your company. +
+
+ + {/* Footer area */} +
+ {/* Left: We are ready to assist you */} +
+
+ We are ready to assist you +
+
+ {/* Right: Contacts */} +
+
+ + 📍 + + {data?.address} +
+
+ + 📞 + + {data?.phone} +
+
+ + 🌐 + + {data?.website} +
+
+ + ✉️ + + {data?.email} +
+
+
+
+ + {/* Bottom border line */} +
+
+ + ); +}; + +export default ThankYouSlideLayout; From 343fd970e77cd37d88f1cb4d29ea8fe0d3d87ea0 Mon Sep 17 00:00:00 2001 From: shiva raj badu Date: Wed, 23 Jul 2025 23:23:22 +0545 Subject: [PATCH 6/7] fix(nextjs): Z-Index issue with loader & editor solved --- .../components/TiptapText.tsx | 11 ++-- .../presentation/components/Header.tsx | 63 ++++++++++--------- .../pitch-deck/AboutUsSlide.tsx | 4 +- .../pitch-deck/HelloFriendsSlide.tsx | 2 +- .../pitch-deck/MarketSizeSlide.tsx | 2 +- .../pitch-deck/ProblemsSlide.tsx | 2 +- .../pitch-deck/TitleSlide.tsx | 2 +- .../pitch-deck/WhatWeBelieveSlide.tsx | 2 +- 8 files changed, 48 insertions(+), 40 deletions(-) diff --git a/servers/nextjs/app/(presentation-generator)/components/TiptapText.tsx b/servers/nextjs/app/(presentation-generator)/components/TiptapText.tsx index 86645210..f8fbe707 100644 --- a/servers/nextjs/app/(presentation-generator)/components/TiptapText.tsx +++ b/servers/nextjs/app/(presentation-generator)/components/TiptapText.tsx @@ -59,9 +59,11 @@ const TiptapText: React.FC = ({ } return ( -
- -
+ <> + +
+ ); }; diff --git a/servers/nextjs/app/(presentation-generator)/presentation/components/Header.tsx b/servers/nextjs/app/(presentation-generator)/presentation/components/Header.tsx index bb0afebf..8c8d41fd 100644 --- a/servers/nextjs/app/(presentation-generator)/presentation/components/Header.tsx +++ b/servers/nextjs/app/(presentation-generator)/presentation/components/Header.tsx @@ -162,7 +162,9 @@ const Header = ({ {/* Desktop Export Button with Popover */} -
+
- + @@ -184,44 +186,47 @@ const Header = ({ ); return ( -
+ <> - - - - Presentation logo - +
- {isStreaming && ( - - )} + className="bg-[#5146E5] w-full shadow-lg sticky top-0 "> + + + + + Presentation logo + + + {/* Desktop Menu */} +
+ {isStreaming && ( + + )} - - -
+ + +
- {/* Mobile Menu */} -
- + {/* Mobile Menu */} +
+ -
- +
+
-
+
+ ); }; diff --git a/servers/nextjs/presentation-layouts/pitch-deck/AboutUsSlide.tsx b/servers/nextjs/presentation-layouts/pitch-deck/AboutUsSlide.tsx index bb8abc9d..b19ac0e9 100644 --- a/servers/nextjs/presentation-layouts/pitch-deck/AboutUsSlide.tsx +++ b/servers/nextjs/presentation-layouts/pitch-deck/AboutUsSlide.tsx @@ -125,12 +125,12 @@ const AboutUsSlide = ({ data }: { data: Partial }) => {
{/* Yellow Square - Top Right */} {showAccentSquare && ( -
+
)} {/* Decorative Circle - On Yellow Square */} {showVisualAccents && ( -
+
)} {/* Business Image - Left positioned */} diff --git a/servers/nextjs/presentation-layouts/pitch-deck/HelloFriendsSlide.tsx b/servers/nextjs/presentation-layouts/pitch-deck/HelloFriendsSlide.tsx index 01143f50..dea6a62b 100644 --- a/servers/nextjs/presentation-layouts/pitch-deck/HelloFriendsSlide.tsx +++ b/servers/nextjs/presentation-layouts/pitch-deck/HelloFriendsSlide.tsx @@ -122,7 +122,7 @@ const HelloFriendsSlide = ({ data }: { data: Partial }) => { {/* Overlapping Circular Office Image */} {speakerImage?.__image_url__ && ( -
+
}) => { {/* Visual Representation */} {visualRepresentation?.__image_url__ && ( -
+
{visualRepresentation.__image_prompt__} }) => { {/* Supporting Visual */} {supportingVisual?.__image_url__ && ( -
+
{supportingVisual.__image_prompt__} }) => { )} {/* Main Content */} -
+
{/* Main Title */} {primaryTitle && ( diff --git a/servers/nextjs/presentation-layouts/pitch-deck/WhatWeBelieveSlide.tsx b/servers/nextjs/presentation-layouts/pitch-deck/WhatWeBelieveSlide.tsx index bd507218..95c9bdb7 100644 --- a/servers/nextjs/presentation-layouts/pitch-deck/WhatWeBelieveSlide.tsx +++ b/servers/nextjs/presentation-layouts/pitch-deck/WhatWeBelieveSlide.tsx @@ -74,7 +74,7 @@ const WhatWeBelieveSlide = ({ data }: { data: Partial }) => { {/* Left Side - Image */}
{supportingVisual?.__image_url__ && ( -
+
{supportingVisual.__image_prompt__} Date: Thu, 24 Jul 2025 00:38:16 +0545 Subject: [PATCH 7/7] refactor(nextjs): Modern layout refactored --- .../components/TiptapTextReplacer.tsx | 19 ++++++++++ .../modern/1IntroSlideLayout.tsx | 37 +++++++++++-------- .../modern/2AboutCompanySlideLayout.tsx | 2 +- .../modern/3ProblemSlideLayout.tsx | 28 ++++++++++++-- .../modern/4SolutionSlideLayout.tsx | 6 +-- .../modern/5ProductOverviewSlideLayout.tsx | 6 +-- .../modern/6MarketSizeSlideLayout.tsx | 12 +++--- .../modern/7MarketValidationSlideLayout.tsx | 4 +- .../modern/8CompanyTractionSlideLayout.tsx | 4 +- .../modern/9BusinessModelSlideLayout.tsx | 14 +++---- .../modern/z10TeamSlideLayout.tsx | 2 +- .../modern/z11ThankYouSlideLayout.tsx | 15 ++------ 12 files changed, 94 insertions(+), 55 deletions(-) diff --git a/servers/nextjs/app/(presentation-generator)/components/TiptapTextReplacer.tsx b/servers/nextjs/app/(presentation-generator)/components/TiptapTextReplacer.tsx index 1e573de8..266671f7 100644 --- a/servers/nextjs/app/(presentation-generator)/components/TiptapTextReplacer.tsx +++ b/servers/nextjs/app/(presentation-generator)/components/TiptapTextReplacer.tsx @@ -73,6 +73,25 @@ const TiptapTextReplacer: React.FC = ({ paddingBottom: computedStyles.paddingBottom, paddingLeft: computedStyles.paddingLeft, paddingRight: computedStyles.paddingRight, + borderRadius: computedStyles.borderRadius, + border: computedStyles.border, + backgroundColor: computedStyles.backgroundColor, + opacity: computedStyles.opacity, + zIndex: computedStyles.zIndex, + cursor: computedStyles.cursor, + boxShadow: computedStyles.boxShadow, + textShadow: computedStyles.textShadow, + textDecoration: computedStyles.textDecoration, + textTransform: computedStyles.textTransform, + letterSpacing: computedStyles.letterSpacing, + wordSpacing: computedStyles.wordSpacing, + textOverflow: computedStyles.textOverflow, + whiteSpace: computedStyles.whiteSpace, + wordBreak: computedStyles.wordBreak, + overflow: computedStyles.overflow, + textAlignLast: computedStyles.textAlignLast, + + }; // Try to find matching data path diff --git a/servers/nextjs/presentation-layouts/modern/1IntroSlideLayout.tsx b/servers/nextjs/presentation-layouts/modern/1IntroSlideLayout.tsx index ff02a905..72df461d 100644 --- a/servers/nextjs/presentation-layouts/modern/1IntroSlideLayout.tsx +++ b/servers/nextjs/presentation-layouts/modern/1IntroSlideLayout.tsx @@ -6,7 +6,7 @@ export const layoutName = "Intro Pitch Deck Slide"; export const layoutDescription = "A visually appealing introduction slide for a pitch deck, featuring a large title, company name, date, and contact information with a modern design."; const introPitchDeckSchema = z.object({ - title: z.string().min(2).max(15).default("Pitch Deck").meta({ + title: z.string().min(2).max(15).default("Pitch Deck and badu").meta({ description: "Main title of the slide", }), description: z.string().default("").meta({ @@ -36,12 +36,13 @@ export const Schema = introPitchDeckSchema; export type IntroPitchDeckData = z.infer; interface IntroSlideLayoutProps { - data?: Partial; + data: Partial; } const IntroPitchDeckSlide: React.FC = ({ data: slideData, }) => { + const { title, description, contactNumber, contactAddress, contactWebsite, companyName, date } = slideData; return ( <> {/* Montserrat Font */} @@ -50,7 +51,7 @@ const IntroPitchDeckSlide: React.FC = ({ rel="stylesheet" />
= ({ transform: "translateY(-50%)", }} > -

- {slideData?.title} + {title} {/* Blue underline */} = ({ transition: "width 0.3s", }} /> -

+ }
{/* Bottom Contact Row */}
-
+ {contactNumber &&
📞 - {slideData?.contactNumber} -
-
+ {contactNumber} +
} + {contactAddress &&
📍 - {slideData?.contactAddress} -
-
+ {contactAddress} +
} + {contactWebsite &&
🌐 - {slideData?.contactWebsite} -
+ {contactWebsite} +
} + {description &&
+ 💬 + {description} +
}
diff --git a/servers/nextjs/presentation-layouts/modern/2AboutCompanySlideLayout.tsx b/servers/nextjs/presentation-layouts/modern/2AboutCompanySlideLayout.tsx index d08f439d..43029265 100644 --- a/servers/nextjs/presentation-layouts/modern/2AboutCompanySlideLayout.tsx +++ b/servers/nextjs/presentation-layouts/modern/2AboutCompanySlideLayout.tsx @@ -8,7 +8,7 @@ export const layoutDescription = "A slide layout providing an overview of the company, its background, and key information."; const aboutCompanySlideSchema = z.object({ - title: z.string().min(3).max(60).default("About Our Company").meta({ + title: z.string().min(3).max(30).default("About Our Company").meta({ description: "Main title of the slide", }), content: z diff --git a/servers/nextjs/presentation-layouts/modern/3ProblemSlideLayout.tsx b/servers/nextjs/presentation-layouts/modern/3ProblemSlideLayout.tsx index 6b244f53..280d2fb3 100644 --- a/servers/nextjs/presentation-layouts/modern/3ProblemSlideLayout.tsx +++ b/servers/nextjs/presentation-layouts/modern/3ProblemSlideLayout.tsx @@ -8,13 +8,13 @@ export const layoutDescription = "A slide layout designed to present a clear problem statement, including categories of problems, company information, and an optional image."; const problemStatementSlideSchema = z.object({ - title: z.string().min(3).max(40).default("Problem").meta({ + title: z.string().min(3).max(20).default("Problem").meta({ description: "Main title of the problem statement slide", }), description: z .string() .min(50) - .max(500) + .max(200) .default( "A problem needs to be discussed further and in detail because this problem is the main foundation in the initial development of a product, service, and decision making. Without a well-defined problem, it will have an impact on a job that is unfocused, unmanaged, and less relevant.", ) @@ -27,7 +27,7 @@ const problemStatementSlideSchema = z.object({ title: z.string().min(3).max(30).meta({ description: "Title of the problem category", }), - description: z.string().min(20).max(200).meta({ + description: z.string().min(20).max(100).meta({ description: "Description of the problem category", }), icon: IconSchema.optional().meta({ @@ -58,6 +58,26 @@ const problemStatementSlideSchema = z.object({ __icon_query__: "trending up costs chart", }, }, + { + title: "Inefficiency", + description: + "Businesses struggle to find digital tools that meet their needs, causing operational slowdowns.", + icon: { + __icon_url__: + "https://cdn.jsdelivr.net/npm/lucide@latest/dist/esm/icons/alert-triangle.js", + __icon_query__: "warning alert inefficiency", + }, + }, + { + title: "Inefficiency", + description: + "Businesses struggle to find digital tools that meet their needs, causing operational slowdowns.", + icon: { + __icon_url__: + "https://cdn.jsdelivr.net/npm/lucide@latest/dist/esm/icons/alert-triangle.js", + __icon_query__: "warning alert inefficiency", + }, + }, ]) .meta({ description: @@ -111,7 +131,7 @@ const ProblemStatementSlideLayout: React.FC< {/* Left side - Main Problem */}
-

+

{slideData?.title}

diff --git a/servers/nextjs/presentation-layouts/modern/4SolutionSlideLayout.tsx b/servers/nextjs/presentation-layouts/modern/4SolutionSlideLayout.tsx index c8f02e06..6879f1c6 100644 --- a/servers/nextjs/presentation-layouts/modern/4SolutionSlideLayout.tsx +++ b/servers/nextjs/presentation-layouts/modern/4SolutionSlideLayout.tsx @@ -14,7 +14,7 @@ const solutionSlideSchema = z.object({ date: z.string().min(5).max(50).default("June 13, 2038").meta({ description: "Date displayed in header", }), - title: z.string().min(3).max(40).default("Solution").meta({ + title: z.string().min(3).max(25).default("Businesses struggle").meta({ description: "Main title of the slide", }), mainDescription: z @@ -22,7 +22,7 @@ const solutionSlideSchema = z.object({ .min(20) .max(300) .default( - "Show that we offer a solution that solves the problems previously described and identified. Make sure that the solutions we offer uphold the values of effectiveness, efficiency, and are highly relevant to the market situation and society.", + "Show that we offer a solution that solves the problems previously described and identified. Make sure that the solutions we offer uphold the values of effectiveness, efficiency, and are highly relevant to the market situation and societyshiva raj badu is here and what is hsd sdksdf klfdslkf lkflkfsldkf.", ) .meta({ description: "Main content text describing the solution", @@ -124,7 +124,7 @@ const SolutionSlideLayout: React.FC = ({
{/* Title and Description */}
-

+

{slideData?.title}

diff --git a/servers/nextjs/presentation-layouts/modern/5ProductOverviewSlideLayout.tsx b/servers/nextjs/presentation-layouts/modern/5ProductOverviewSlideLayout.tsx index 037a8907..fdca64fe 100644 --- a/servers/nextjs/presentation-layouts/modern/5ProductOverviewSlideLayout.tsx +++ b/servers/nextjs/presentation-layouts/modern/5ProductOverviewSlideLayout.tsx @@ -33,7 +33,7 @@ const productOverviewSlideSchema = z.object({ title: z.string().min(3).max(50).meta({ description: "Product title", }), - description: z.string().min(30).max(200).meta({ + description: z.string().min(30).max(140).meta({ description: "Product description", }), image: ImageSchema.meta({ @@ -45,7 +45,7 @@ const productOverviewSlideSchema = z.object({ }), ) .min(2) - .max(4) + .max(2) .default([ { title: "Internet of Things", @@ -121,7 +121,7 @@ const ProductOverviewSlideLayout: React.FC = ({

{/* Title and Description on the left */}
-

+

{slideData?.title}

diff --git a/servers/nextjs/presentation-layouts/modern/6MarketSizeSlideLayout.tsx b/servers/nextjs/presentation-layouts/modern/6MarketSizeSlideLayout.tsx index fcc375e1..41c78820 100644 --- a/servers/nextjs/presentation-layouts/modern/6MarketSizeSlideLayout.tsx +++ b/servers/nextjs/presentation-layouts/modern/6MarketSizeSlideLayout.tsx @@ -8,10 +8,10 @@ export const layoutDescription = "A professional slide layout designed to present market size statistics, including TAM, SAM, and SOM, with a world map and key metrics."; const marketSizeSlideSchema = z.object({ - title: z.string().default("Market Size").meta({ + title: z.string().min(3).max(15).default("Market Size").meta({ description: "Main slide title", }), - companyName: z.string().default("Rimberio").meta({ + companyName: z.string().min(3).max(30).default("Rimberio").meta({ description: "Presenter's name", }), date: z.string().default("June 13, 2038").meta({ @@ -25,9 +25,9 @@ const marketSizeSlideSchema = z.object({ marketStats: z .array( z.object({ - label: z.string(), - value: z.string(), - description: z.string(), + label: z.string().min(3).max(30), + value: z.string().min(3).max(30), + description: z.string().min(3).max(130), }), ) .min(1) @@ -101,7 +101,7 @@ const MarketSizeSlideLayout: React.FC = ({

{/* Move the title down to align with the top of the market stats */}

{slideData?.title || "Market Size"} diff --git a/servers/nextjs/presentation-layouts/modern/7MarketValidationSlideLayout.tsx b/servers/nextjs/presentation-layouts/modern/7MarketValidationSlideLayout.tsx index 540c5386..6c2eb84f 100644 --- a/servers/nextjs/presentation-layouts/modern/7MarketValidationSlideLayout.tsx +++ b/servers/nextjs/presentation-layouts/modern/7MarketValidationSlideLayout.tsx @@ -19,7 +19,7 @@ const marketValidationSchema = z.object({ date: z.string().min(5).max(50).default("June 13, 2038").meta({ description: "Date in header", }), - title: z.string().min(3).max(40).default("Market Validation").meta({ + title: z.string().min(3).max(20).default("Market Validation").meta({ description: "Title of the slide", }), description: z @@ -108,7 +108,7 @@ const MarketValidationSlideLayout: React.FC<
{/* Left Column */}
-

+

{slideData?.title}

diff --git a/servers/nextjs/presentation-layouts/modern/8CompanyTractionSlideLayout.tsx b/servers/nextjs/presentation-layouts/modern/8CompanyTractionSlideLayout.tsx index 56905cde..e2f93dd8 100644 --- a/servers/nextjs/presentation-layouts/modern/8CompanyTractionSlideLayout.tsx +++ b/servers/nextjs/presentation-layouts/modern/8CompanyTractionSlideLayout.tsx @@ -23,6 +23,8 @@ const tractionSchema = z.object({ title: z.string().default("Company Traction"), description: z .string() + .min(3) + .max(200) .default( "Traction is a period where the company is feeling momentum during its development period. If traction momentum is not harnessed, sales figures can decline and the customer base can shrink. In general, companies will judge success by the amount of revenue and new customers they receive.", ), @@ -176,7 +178,7 @@ const CompanyTractionSlideLayout: React.FC = ({ data }) => {

{/* Left Column - Chart with Title Below */}
-

+

{data?.title}

diff --git a/servers/nextjs/presentation-layouts/modern/9BusinessModelSlideLayout.tsx b/servers/nextjs/presentation-layouts/modern/9BusinessModelSlideLayout.tsx index 199948b9..f92d80cc 100644 --- a/servers/nextjs/presentation-layouts/modern/9BusinessModelSlideLayout.tsx +++ b/servers/nextjs/presentation-layouts/modern/9BusinessModelSlideLayout.tsx @@ -19,7 +19,7 @@ export const layoutDescription = const businessModelSchema = z.object({ companyName: z.string().default("presenton"), date: z.string().default("June 13, 2038"), - title: z.string().default("Business Model"), + title: z.string().min(3).max(20).default("Business Model"), description: z .string() .default( @@ -28,8 +28,8 @@ const businessModelSchema = z.object({ cacChart: z .array( z.object({ - label: z.string(), - percentage: z.number(), + label: z.string().min(3).max(20), + percentage: z.number().min(0).max(100), }), ) .default([ @@ -50,9 +50,9 @@ const BusinessModelSlide: React.FC = ({ data }) => { data?.cacChart && Array.isArray(data.cacChart) && data.cacChart.length > 0 ? data.cacChart : [ - { label: "Internet of Things", percentage: 70 }, - { label: "Artificial Intelligence", percentage: 60 }, - ]; + { label: "Internet of Things", percentage: 70 }, + { label: "Artificial Intelligence", percentage: 60 }, + ]; return ( <> @@ -76,7 +76,7 @@ const BusinessModelSlide: React.FC = ({ data }) => {
{/* Left Column - Chart with Title Below */}
-

+

{data?.title}

diff --git a/servers/nextjs/presentation-layouts/modern/z10TeamSlideLayout.tsx b/servers/nextjs/presentation-layouts/modern/z10TeamSlideLayout.tsx index 394e8c14..b3e37c34 100644 --- a/servers/nextjs/presentation-layouts/modern/z10TeamSlideLayout.tsx +++ b/servers/nextjs/presentation-layouts/modern/z10TeamSlideLayout.tsx @@ -24,7 +24,7 @@ const teamMemberSchema = z.object({ }); const modernTeamSlideSchema = z.object({ - title: z.string().min(3).max(40).default("Our Team").meta({ + title: z.string().min(3).max(20).default("Our Team").meta({ description: "Main title of the slide", }), subtitle: z.string().min(10).max(120).optional().meta({ diff --git a/servers/nextjs/presentation-layouts/modern/z11ThankYouSlideLayout.tsx b/servers/nextjs/presentation-layouts/modern/z11ThankYouSlideLayout.tsx index 805aeae8..aa85af2d 100644 --- a/servers/nextjs/presentation-layouts/modern/z11ThankYouSlideLayout.tsx +++ b/servers/nextjs/presentation-layouts/modern/z11ThankYouSlideLayout.tsx @@ -13,7 +13,7 @@ const thankYouSlideSchema = z.object({ subtitle: z.string().min(0).max(100).default("").meta({ description: "Optional subtitle or closing remark", }), - companyName: z.string().min(2).max(50).default("Rimberio").meta({ + companyName: z.string().min(2).max(30).default("Rimberio").meta({ description: "Company name displayed in header", }), date: z.string().min(5).max(30).default("June 13, 2038").meta({ @@ -73,11 +73,8 @@ const ThankYouSlideLayout: React.FC = ({ data }) => { {/* Thank You and description */}

{data?.title || "Thank You!"}

@@ -86,11 +83,7 @@ const ThankYouSlideLayout: React.FC = ({ data }) => { {data.subtitle}
)} -
- Write down your hopes for the future of your company. Don't forget - to thank the company for the opportunity and convince related - parties to support your company. -
+
{/* Footer area */}