diff --git a/servers/fastapi/utils/llm_calls/generate_presentation_outlines.py b/servers/fastapi/utils/llm_calls/generate_presentation_outlines.py index 1bd860eb..cd10de25 100644 --- a/servers/fastapi/utils/llm_calls/generate_presentation_outlines.py +++ b/servers/fastapi/utils/llm_calls/generate_presentation_outlines.py @@ -50,8 +50,6 @@ You are an expert presentation creator. Generate structured presentations based - Generate **exactly** the number of slides requested - Distribute content **evenly** across slides - Create **balanced information flow** - - """ diff --git a/servers/fastapi/utils/llm_calls/generate_slide_content.py b/servers/fastapi/utils/llm_calls/generate_slide_content.py index 5346314b..5a865ac9 100644 --- a/servers/fastapi/utils/llm_calls/generate_slide_content.py +++ b/servers/fastapi/utils/llm_calls/generate_slide_content.py @@ -7,7 +7,6 @@ from utils.llm_provider import ( get_google_llm_client, get_llm_client, get_nano_model, - get_small_model, is_google_selected, ) from utils.schema_utils import remove_fields_from_schema @@ -20,10 +19,12 @@ system_prompt = """ 2. Generate structured slide based on the outline and title. # Notes - - **Strictly follow the max and min character limit for each property in the slide.** - Slide body should not use words like "This slide", "This presentation". - Rephrase the slide body to make it flow naturally. + - Provide prompt to generate image on "__image_prompt__" property. + - Provide query to search icon on "__icon_query__" property. - Do not use markdown formatting in slide body. + - **Strictly follow the max and min character limit for every property in the slide.** """ diff --git a/servers/nextjs/presentation-layouts/8-slides-ordered/1IntroSlideLayout.tsx b/servers/nextjs/presentation-layouts/8-slides-ordered/1IntroSlideLayout.tsx new file mode 100644 index 00000000..17058b0a --- /dev/null +++ b/servers/nextjs/presentation-layouts/8-slides-ordered/1IntroSlideLayout.tsx @@ -0,0 +1,117 @@ +import React from 'react' +import * as z from "zod"; +import { ImageSchema } from '@/presentation-layouts/defaultSchemes'; + +export const layoutId = 'general-intro-slide' +export const layoutName = 'Intro Slide' +export const layoutDescription = 'A clean slide layout with title, description text, presenter info, and a supporting image.' + +const introSlideSchema = z.object({ + title: z.string().min(3).max(50).default('Product Overview').meta({ + description: "Main title of the slide", + }), + description: z.string().min(10).max(200).default('Our product offers customizable dashboards for real-time reporting and data-driven decisions. It integrates with third-party tools to enhance operations and scales with business growth for improved efficiency.').meta({ + description: "Main description text content", + }), + presenterName: z.string().min(2).max(50).default('John Doe').meta({ + description: "Name of the presenter", + }), + presentationDate: z.string().min(2).max(50).default('December 2024').meta({ + description: "Date of the presentation", + }), + image: ImageSchema.default({ + __image_url__: 'https://images.unsplash.com/photo-1552664730-d307ca884978?ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D&auto=format&fit=crop&w=1000&q=80', + __image_prompt__: 'Business team in meeting room discussing product features and solutions' + }).meta({ + description: "Supporting image for the slide", + }) +}) + +export const Schema = introSlideSchema + +export type IntroSlideData = z.infer + +interface IntroSlideLayoutProps { + data?: Partial +} + +const IntroSlideLayout: React.FC = ({ data: slideData }) => { + // Generate initials from presenter name + const getInitials = (name: string) => { + return name.split(' ').map(word => word.charAt(0).toUpperCase()).join(''); + }; + + const presenterInitials = getInitials(slideData?.presenterName || 'John Doe'); + return ( + <> + {/* Import Google Fonts */} + + +
+ + + {/* Main Content */} +
+ {/* Left Section - Image */} +
+
+ {slideData?.image?.__image_prompt__ +
+
+ + {/* Right Section - Content */} +
+ {/* Title */} +

+ {slideData?.title || 'Product Overview'} +

+ + {/* Purple accent line */} +
+ + {/* Description */} +

+ {slideData?.description || 'Our product offers customizable dashboards for real-time reporting and data-driven decisions. It integrates with third-party tools to enhance operations and scales with business growth for improved efficiency.'} +

+ + {/* Presenter Section */} +
+
+ {/* Custom Initials Icon */} +
+ + {presenterInitials} + +
+ + {/* Presenter Info */} +
+ + {slideData?.presenterName || 'John Doe'} + + + {slideData?.presentationDate || 'December 2024'} + +
+
+
+
+
+
+ + ) +} + +export default IntroSlideLayout \ No newline at end of file diff --git a/servers/nextjs/presentation-layouts/8-slides-ordered/2BasicInfoSlideLayout.tsx b/servers/nextjs/presentation-layouts/8-slides-ordered/2BasicInfoSlideLayout.tsx new file mode 100644 index 00000000..460ec5d9 --- /dev/null +++ b/servers/nextjs/presentation-layouts/8-slides-ordered/2BasicInfoSlideLayout.tsx @@ -0,0 +1,87 @@ +import React from 'react' +import * as z from "zod"; +import { ImageSchema } from '@/presentation-layouts/defaultSchemes'; + +export const layoutId = 'basic-info-slide' +export const layoutName = 'Basic Info' +export const layoutDescription = 'A clean slide layout with title, description text, and a supporting image.' + +const basicInfoSlideSchema = z.object({ + title: z.string().min(3).max(50).default('Product Overview').meta({ + description: "Main title of the slide", + }), + description: z.string().min(10).max(200).default('Our product offers customizable dashboards for real-time reporting and data-driven decisions. It integrates with third-party tools to enhance operations and scales with business growth for improved efficiency.').meta({ + description: "Main description text content", + }), + image: ImageSchema.default({ + __image_url__: 'https://images.unsplash.com/photo-1552664730-d307ca884978?ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D&auto=format&fit=crop&w=1000&q=80', + __image_prompt__: 'Business team in meeting room discussing product features and solutions' + }).meta({ + description: "Supporting image for the slide", + }) +}) + +export const Schema = basicInfoSlideSchema + +export type BasicInfoSlideData = z.infer + +interface BasicInfoSlideLayoutProps { + data?: Partial +} + +const BasicInfoSlideLayout: React.FC = ({ data: slideData }) => { + + + return ( + <> + {/* Import Google Fonts */} + + +
+ + + {/* Main Content */} +
+ {/* Left Section - Image */} +
+
+ {slideData?.image?.__image_prompt__ +
+
+ + {/* Right Section - Content */} +
+ {/* Title */} +

+ {slideData?.title || 'Product Overview'} +

+ + {/* Purple accent line */} +
+ + {/* Description */} +

+ {slideData?.description || 'Our product offers customizable dashboards for real-time reporting and data-driven decisions. It integrates with third-party tools to enhance operations and scales with business growth for improved efficiency.'} +

+ + +
+
+
+ + ) +} + +export default BasicInfoSlideLayout \ No newline at end of file diff --git a/servers/nextjs/presentation-layouts/8-slides-ordered/3BulletIconsOnlySlideLayout.tsx b/servers/nextjs/presentation-layouts/8-slides-ordered/3BulletIconsOnlySlideLayout.tsx new file mode 100644 index 00000000..4fccedda --- /dev/null +++ b/servers/nextjs/presentation-layouts/8-slides-ordered/3BulletIconsOnlySlideLayout.tsx @@ -0,0 +1,191 @@ +import React from 'react' +import * as z from "zod"; +import { ImageSchema, IconSchema } from '@/presentation-layouts/defaultSchemes'; + +export const layoutId = 'bullet-icons-only-slide' +export const layoutName = 'Bullet Icons Only' +export const layoutDescription = 'A slide layout with title, grid of bullet points with icons (no descriptions), and a supporting image.' + +const bulletIconsOnlySlideSchema = z.object({ + title: z.string().min(3).max(50).default('Solutions').meta({ + description: "Main title of the slide", + }), + image: ImageSchema.default({ + __image_url__: 'https://images.unsplash.com/photo-1552664730-d307ca884978?ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D&auto=format&fit=crop&w=1000&q=80', + __image_prompt__: 'Business professionals collaborating and discussing solutions' + }).meta({ + description: "Supporting image for the slide", + }), + bulletPoints: z.array(z.object({ + title: z.string().min(2).max(80).meta({ + description: "Bullet point title", + }), + subtitle: z.string().min(5).max(150).optional().meta({ + description: "Optional short subtitle or brief explanation", + }), + icon: IconSchema, + })).min(2).max(4).default([ + { + title: 'Custom Software', + subtitle: 'We create tailored software to optimize processes and boost efficiency.', + icon: { + __icon_url__: 'https://cdn.jsdelivr.net/npm/lucide@latest/dist/esm/icons/code.js', + __icon_query__: 'code software development' + } + }, + { + title: 'Digital Consulting', + subtitle: 'Our consultants guide organizations in leveraging the latest technologies.', + icon: { + __icon_url__: 'https://cdn.jsdelivr.net/npm/lucide@latest/dist/esm/icons/users.js', + __icon_query__: 'users consulting team' + } + }, + { + title: 'Support Services', + subtitle: 'We provide ongoing support to help businesses adapt and maintain performance.', + icon: { + __icon_url__: 'https://cdn.jsdelivr.net/npm/lucide@latest/dist/esm/icons/headphones.js', + __icon_query__: 'headphones support service' + } + }, + { + title: 'Scalable Marketing', + subtitle: 'Our data-driven strategies help businesses expand their reach and engagement.', + icon: { + __icon_url__: 'https://cdn.jsdelivr.net/npm/lucide@latest/dist/esm/icons/trending-up.js', + __icon_query__: 'trending up marketing growth' + } + } + ]).meta({ + description: "List of bullet points with icons and optional subtitles", + }) +}) + +export const Schema = bulletIconsOnlySlideSchema + +export type BulletIconsOnlySlideData = z.infer + +interface BulletIconsOnlySlideLayoutProps { + data?: Partial +} + +const BulletIconsOnlySlideLayout: React.FC = ({ data: slideData }) => { + const bulletPoints = slideData?.bulletPoints || [] + + // Function to determine grid classes based on number of bullets + const getGridClasses = (count: number) => { + if (count <= 2) { + return 'grid-cols-1 gap-6' + } else if (count <= 4) { + return 'grid-cols-2 gap-6' + } else { + return 'grid-cols-2 lg:grid-cols-3 gap-6' + } + } + + return ( + <> + {/* Import Google Fonts */} + + +
+ {/* Decorative Wave Patterns */} +
+ + + + +
+ +
+ + + +
+ + {/* Main Content */} +
+ {/* Left Section - Title and Bullet Points */} +
+ {/* Title */} +

+ {slideData?.title || 'Solutions'} +

+ + {/* Bullet Points Grid */} +
+ {bulletPoints.map((bullet, index) => ( +
+ {/* Icon */} +
+ {bullet.icon.__icon_query__} +
+ + {/* Content */} +
+

+ {bullet.title} +

+ {bullet.subtitle && ( +

+ {bullet.subtitle} +

+ )} +
+
+ ))} +
+
+ + {/* Right Section - Image */} +
+ {/* Decorative Elements */} +
+ + + +
+ +
+ + + +
+ + {/* Main Image */} +
+ {slideData?.image?.__image_prompt__ +
+
+
+
+ + ) +} + +export default BulletIconsOnlySlideLayout \ No newline at end of file diff --git a/servers/nextjs/presentation-layouts/8-slides-ordered/4BulletWithIconsSlideLayout.tsx b/servers/nextjs/presentation-layouts/8-slides-ordered/4BulletWithIconsSlideLayout.tsx new file mode 100644 index 00000000..8a1bb69f --- /dev/null +++ b/servers/nextjs/presentation-layouts/8-slides-ordered/4BulletWithIconsSlideLayout.tsx @@ -0,0 +1,164 @@ +import React from 'react' +import * as z from "zod"; +import { ImageSchema, IconSchema } from '@/presentation-layouts/defaultSchemes'; + +export const layoutId = 'bullet-with-icons-slide' +export const layoutName = 'Bullet with Icons' +export const layoutDescription = 'A bullets style slide with main content, supporting image, and bullet points with icons and descriptions.' + +const bulletWithIconsSlideSchema = z.object({ + title: z.string().min(3).max(50).default('Problem').meta({ + description: "Main title of the slide", + }), + description: z.string().max(150).default('Businesses face challenges with outdated technology and rising costs, limiting efficiency and growth in competitive markets.').meta({ + description: "Main description text explaining the problem or topic", + }), + image: ImageSchema.default({ + __image_url__: 'https://images.unsplash.com/photo-1552664730-d307ca884978?ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D&auto=format&fit=crop&w=1000&q=80', + __image_prompt__: 'Business people analyzing documents and charts in office' + }).meta({ + description: "Supporting image for the slide", + }), + bulletPoints: z.array(z.object({ + title: z.string().min(2).max(80).meta({ + description: "Bullet point title", + }), + description: z.string().min(10).max(150).meta({ + description: "Bullet point description", + }), + icon: IconSchema, + })).min(1).max(3).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 bullet points with icons and descriptions", + }) +}) + +export const Schema = bulletWithIconsSlideSchema + +export type BulletWithIconsSlideData = z.infer + +interface BulletWithIconsSlideLayoutProps { + data?: Partial +} + +const BulletWithIconsSlideLayout: React.FC = ({ data: slideData }) => { + const bulletPoints = slideData?.bulletPoints || [] + + return ( + <> + {/* Import Google Fonts */} + + +
+ + + {/* Main Content */} +
+ {/* Title Section - Full Width */} +
+

+ {slideData?.title || 'Problem'} +

+
+ + {/* Content Container */} +
+ {/* Left Section - Image with Grid Pattern */} +
+ {/* Grid Pattern Background */} +
+ + + + + + + + +
+ + {/* Image Container */} +
+
+ {slideData?.image?.__image_prompt__ +
+
+ + {/* Decorative Sparkle */} +
+ + + +
+
+ + {/* Right Section - Content */} +
+ {/* Description */} +

+ {slideData?.description || 'Businesses face challenges with outdated technology and rising costs, limiting efficiency and growth in competitive markets.'} +

+ + {/* Bullet Points */} +
+ {bulletPoints.map((bullet, index) => ( +
+ {/* Icon */} +
+ {bullet.icon.__icon_query__} +
+ + {/* Content */} +
+

+ {bullet.title} +

+
+

+ {bullet.description} +

+
+
+ ))} +
+
+
+
+
+ + ) +} + +export default BulletWithIconsSlideLayout \ No newline at end of file diff --git a/servers/nextjs/presentation-layouts/8-slides-ordered/5BasicInfo.tsx b/servers/nextjs/presentation-layouts/8-slides-ordered/5BasicInfo.tsx new file mode 100644 index 00000000..460ec5d9 --- /dev/null +++ b/servers/nextjs/presentation-layouts/8-slides-ordered/5BasicInfo.tsx @@ -0,0 +1,87 @@ +import React from 'react' +import * as z from "zod"; +import { ImageSchema } from '@/presentation-layouts/defaultSchemes'; + +export const layoutId = 'basic-info-slide' +export const layoutName = 'Basic Info' +export const layoutDescription = 'A clean slide layout with title, description text, and a supporting image.' + +const basicInfoSlideSchema = z.object({ + title: z.string().min(3).max(50).default('Product Overview').meta({ + description: "Main title of the slide", + }), + description: z.string().min(10).max(200).default('Our product offers customizable dashboards for real-time reporting and data-driven decisions. It integrates with third-party tools to enhance operations and scales with business growth for improved efficiency.').meta({ + description: "Main description text content", + }), + image: ImageSchema.default({ + __image_url__: 'https://images.unsplash.com/photo-1552664730-d307ca884978?ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D&auto=format&fit=crop&w=1000&q=80', + __image_prompt__: 'Business team in meeting room discussing product features and solutions' + }).meta({ + description: "Supporting image for the slide", + }) +}) + +export const Schema = basicInfoSlideSchema + +export type BasicInfoSlideData = z.infer + +interface BasicInfoSlideLayoutProps { + data?: Partial +} + +const BasicInfoSlideLayout: React.FC = ({ data: slideData }) => { + + + return ( + <> + {/* Import Google Fonts */} + + +
+ + + {/* Main Content */} +
+ {/* Left Section - Image */} +
+
+ {slideData?.image?.__image_prompt__ +
+
+ + {/* Right Section - Content */} +
+ {/* Title */} +

+ {slideData?.title || 'Product Overview'} +

+ + {/* Purple accent line */} +
+ + {/* Description */} +

+ {slideData?.description || 'Our product offers customizable dashboards for real-time reporting and data-driven decisions. It integrates with third-party tools to enhance operations and scales with business growth for improved efficiency.'} +

+ + +
+
+
+ + ) +} + +export default BasicInfoSlideLayout \ No newline at end of file diff --git a/servers/nextjs/presentation-layouts/8-slides-ordered/6NumberedBulletsSlideLayout.tsx b/servers/nextjs/presentation-layouts/8-slides-ordered/6NumberedBulletsSlideLayout.tsx new file mode 100644 index 00000000..103398ef --- /dev/null +++ b/servers/nextjs/presentation-layouts/8-slides-ordered/6NumberedBulletsSlideLayout.tsx @@ -0,0 +1,148 @@ +import React from 'react' +import * as z from "zod"; +import { ImageSchema } from '@/presentation-layouts/defaultSchemes'; + +export const layoutId = 'numbered-bullets-slide' +export const layoutName = 'Numbered Bullets' +export const layoutDescription = 'A slide layout with large title, supporting image, and numbered bullet points with descriptions.' + +const numberedBulletsSlideSchema = z.object({ + title: z.string().min(3).max(50).default('Market Validation').meta({ + description: "Main title of the slide", + }), + image: ImageSchema.default({ + __image_url__: 'https://images.unsplash.com/photo-1552664730-d307ca884978?ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D&auto=format&fit=crop&w=1000&q=80', + __image_prompt__: 'Business people analyzing charts and data on wall' + }).meta({ + description: "Supporting image for the slide", + }), + bulletPoints: z.array(z.object({ + title: z.string().min(2).max(80).meta({ + description: "Bullet point title", + }), + description: z.string().min(10).max(150).meta({ + description: "Bullet point description", + }), + })).min(1).max(4).default([ + { + title: 'Customer Insights', + description: 'Surveys reveal that 78% of businesses are planning to invest in digital solutions, with 85% preferring customized approaches.' + }, + { + title: 'Pilot Program Success', + description: 'The survey revealed that 78% of businesses plan to invest in digital solutions, and 85% prefer a tailored approach.' + }, + { + title: 'Pilot Program Success', + description: 'The survey revealed that 78% of businesses plan to invest in digital solutions, and 85% prefer a tailored approach.' + }, + { + title: 'Pilot Program Success', + description: 'The survey revealed that 78% of businesses plan to invest in digital solutions, and 85% prefer a tailored approach.' + } + ]).meta({ + description: "List of numbered bullet points with descriptions", + }) +}) + +export const Schema = numberedBulletsSlideSchema + +export type NumberedBulletsSlideData = z.infer + +interface NumberedBulletsSlideLayoutProps { + data?: Partial +} + +const NumberedBulletsSlideLayout: React.FC = ({ data: slideData }) => { + const bulletPoints = slideData?.bulletPoints || [] + + return ( + <> + {/* Import Google Fonts */} + + +
+ + {/* Main Content Container */} +
+ {/* Top Section - Title and Image */} +
+ {/* Title Section */} +
+

+ {slideData?.title || 'Market Validation'} +

+ {/* Purple accent line */} +
+
+ + {/* Image Section */} +
+ {slideData?.image?.__image_prompt__ +
+
+ + {/* Numbered Bullet Points */} +
+ {bulletPoints.map((bullet, index) => ( +
+ {/* Number */} +
+
+ {String(index + 1).padStart(2, '0')} +
+
+ + {/* Content */} +
+

+ {bullet.title} +

+

+ {bullet.description} +

+
+
+ ))} +
+ + {/* Decorative Wave Pattern at Bottom */} +
+ + + + + + + + + + +
+
+
+ + ) +} + +export default NumberedBulletsSlideLayout \ No newline at end of file diff --git a/servers/nextjs/presentation-layouts/8-slides-ordered/7MetricsWithImageSlideLayout.tsx b/servers/nextjs/presentation-layouts/8-slides-ordered/7MetricsWithImageSlideLayout.tsx new file mode 100644 index 00000000..11fcbf86 --- /dev/null +++ b/servers/nextjs/presentation-layouts/8-slides-ordered/7MetricsWithImageSlideLayout.tsx @@ -0,0 +1,128 @@ +import React from 'react' +import * as z from "zod"; +import { ImageSchema } from '@/presentation-layouts/defaultSchemes'; + +export const layoutId = 'metrics-with-image-slide' +export const layoutName = 'Metrics with Image' +export const layoutDescription = 'A slide layout with supporting image on the left and title, description, and metrics grid on the right. Can be used alternatively with MetricSlide.' + +const metricsWithImageSlideSchema = z.object({ + title: z.string().min(3).max(50).default('Competitive Advantage').meta({ + description: "Main title of the slide", + }), + description: z.string().min(10).max(150).default('Ginyard International Co. stands out by offering custom digital solutions tailored to client needs, alongside long-term support to ensure lasting relationships and continuous adaptation.').meta({ + description: "Description text below the title", + }), + image: ImageSchema.default({ + __image_url__: 'https://images.unsplash.com/photo-1551288049-bebda4e38f71?ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D&auto=format&fit=crop&w=1000&q=80', + __image_prompt__: 'Person holding tablet with analytics dashboard and charts' + }).meta({ + description: "Supporting image for the slide", + }), + metrics: z.array(z.object({ + label: z.string().min(2).max(100).meta({ + description: "Metric label/title" + }), + value: z.string().min(1).max(20).meta({ + description: "Metric value (e.g., 200+, 95%, 50%)" + }), + })).min(1).max(4).default([ + { + label: 'Satisfied Clients', + value: '200+' + }, + { + label: 'Client Retention Rate', + value: '95%' + }, + + ]).meta({ + description: "List of key business metrics to display", + }) +}) + +export const Schema = metricsWithImageSlideSchema + +export type MetricsWithImageSlideData = z.infer + +interface MetricsWithImageSlideLayoutProps { + data?: Partial +} + +const MetricsWithImageSlideLayout: React.FC = ({ data: slideData }) => { + const metrics = slideData?.metrics || [] + + return ( + <> + {/* Import Google Fonts */} + + +
+ {/* Decorative Wave Patterns */} +
+ + + + +
+ +
+ + + +
+ + {/* Main Content */} +
+ {/* Left Section - Image */} +
+
+ {slideData?.image?.__image_prompt__ +
+
+ + {/* Right Section - Content and Metrics */} +
+ {/* Title */} +

+ {slideData?.title || 'Competitive Advantage'} +

+ + {/* Description */} +

+ {slideData?.description || 'Ginyard International Co. stands out by offering custom digital solutions tailored to client needs, alongside long-term support to ensure lasting relationships and continuous adaptation.'} +

+ + {/* Metrics Grid */} +
+ {metrics.map((metric, index) => ( +
+
+ {metric.label} +
+
+ {metric.value} +
+
+ ))} +
+
+
+
+ + ) +} + +export default MetricsWithImageSlideLayout \ No newline at end of file diff --git a/servers/nextjs/presentation-layouts/8-slides-ordered/8Conslusion.tsx b/servers/nextjs/presentation-layouts/8-slides-ordered/8Conslusion.tsx new file mode 100644 index 00000000..a2e6d352 --- /dev/null +++ b/servers/nextjs/presentation-layouts/8-slides-ordered/8Conslusion.tsx @@ -0,0 +1,87 @@ +import React from 'react' +import * as z from "zod"; +import { ImageSchema } from '@/presentation-layouts/defaultSchemes'; + +export const layoutId = 'basic-info-slide' +export const layoutName = 'Basic Info' +export const layoutDescription = 'A clean slide layout with title, description text, and a supporting image.' + +const basicInfoSlideSchema = z.object({ + title: z.string().min(3).max(50).default('Product Overview').meta({ + description: "Main title of the slide", + }), + description: z.string().min(10).max(150).default('Our product offers customizable dashboards for real-time reporting and data-driven decisions. It integrates with third-party tools to enhance operations and scales with business growth for improved efficiency.').meta({ + description: "Main description text content", + }), + image: ImageSchema.default({ + __image_url__: 'https://images.unsplash.com/photo-1552664730-d307ca884978?ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D&auto=format&fit=crop&w=1000&q=80', + __image_prompt__: 'Business team in meeting room discussing product features and solutions' + }).meta({ + description: "Supporting image for the slide", + }) +}) + +export const Schema = basicInfoSlideSchema + +export type BasicInfoSlideData = z.infer + +interface BasicInfoSlideLayoutProps { + data?: Partial +} + +const BasicInfoSlideLayout: React.FC = ({ data: slideData }) => { + + + return ( + <> + {/* Import Google Fonts */} + + +
+ + + {/* Main Content */} +
+ {/* Left Section - Image */} +
+
+ {slideData?.image?.__image_prompt__ +
+
+ + {/* Right Section - Content */} +
+ {/* Title */} +

+ {slideData?.title || 'Product Overview'} +

+ + {/* Purple accent line */} +
+ + {/* Description */} +

+ {slideData?.description || 'Our product offers customizable dashboards for real-time reporting and data-driven decisions. It integrates with third-party tools to enhance operations and scales with business growth for improved efficiency.'} +

+ + +
+
+
+ + ) +} + +export default BasicInfoSlideLayout \ No newline at end of file diff --git a/servers/nextjs/presentation-layouts/8-slides-ordered/setting.json b/servers/nextjs/presentation-layouts/8-slides-ordered/setting.json new file mode 100644 index 00000000..d79eac72 --- /dev/null +++ b/servers/nextjs/presentation-layouts/8-slides-ordered/setting.json @@ -0,0 +1,5 @@ +{ + "description": "Ordered layouts for presentations", + "ordered": true, + "isDefault": false +} \ No newline at end of file