update: professional template
This commit is contained in:
parent
d6adc55602
commit
2e015451e1
15 changed files with 0 additions and 3059 deletions
|
|
@ -1,168 +0,0 @@
|
|||
import * as z from "zod";
|
||||
|
||||
import { ImageSchema, IconSchema } from "../defaultSchemes";
|
||||
|
||||
export const layoutName = "About Us Slide";
|
||||
export const layoutId = "about-us-slide";
|
||||
export const layoutDescription =
|
||||
"A slide with an introduction to the organization";
|
||||
|
||||
// Schema definition
|
||||
export const Schema = z.object({
|
||||
sectionTitle: z.string().min(3).max(25).default("ABOUT US").meta({
|
||||
description:
|
||||
"Main section heading - can be used for any organizational introduction",
|
||||
}),
|
||||
|
||||
sectionSubtitle: z
|
||||
.string()
|
||||
.min(5)
|
||||
.max(40)
|
||||
.default("GET TO KNOW US BETTER")
|
||||
.meta({
|
||||
description:
|
||||
"Supporting subtitle that invites audience engagement and builds connection",
|
||||
}),
|
||||
|
||||
organizationDescription: z
|
||||
.string()
|
||||
.min(50)
|
||||
.max(300)
|
||||
.default(
|
||||
"We believe in the transformative power of innovation, strategic thinking, and cutting-edge solutions. Our mission is simple: to empower organizations with comprehensive strategies that not only elevate performance but also drive tangible growth and success."
|
||||
)
|
||||
.meta({
|
||||
description:
|
||||
"Primary description of the organization's mission, values, and approach",
|
||||
}),
|
||||
|
||||
additionalContext: z
|
||||
.string()
|
||||
.min(30)
|
||||
.max(150)
|
||||
.default(
|
||||
"What sets us apart is not just our expertise but our commitment to understanding the unique needs of each client."
|
||||
)
|
||||
.meta({
|
||||
description:
|
||||
"Additional context or differentiating statement about the organization",
|
||||
}),
|
||||
|
||||
featuredImage: ImageSchema.default({
|
||||
__image_url__:
|
||||
"https://images.unsplash.com/photo-1454165804606-c3d57bc86b40?ixlib=rb-4.0.3&auto=format&fit=crop&w=800&q=80",
|
||||
__image_prompt__:
|
||||
"Professional business team analyzing data and working collaboratively",
|
||||
}).meta({
|
||||
description:
|
||||
"Primary visual that represents the organization's work or environment",
|
||||
}),
|
||||
|
||||
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",
|
||||
}),
|
||||
|
||||
showAccentSquare: z.boolean().default(true).meta({
|
||||
description: "Whether to display the accent square decoration element",
|
||||
}),
|
||||
});
|
||||
|
||||
// Type inference
|
||||
type SchemaType = z.infer<typeof Schema>;
|
||||
|
||||
// Component definitionz
|
||||
const AboutUsSlide = ({ data }: { data: Partial<SchemaType> }) => {
|
||||
const {
|
||||
sectionTitle,
|
||||
sectionSubtitle,
|
||||
organizationDescription,
|
||||
additionalContext,
|
||||
featuredImage,
|
||||
showVisualAccents,
|
||||
showColorBlocks,
|
||||
showAccentSquare,
|
||||
} = data;
|
||||
|
||||
return (
|
||||
<div className="aspect-video max-w-[1280px] w-full bg-white relative overflow-hidden">
|
||||
{/* Main Content Area */}
|
||||
<div className="h-full flex">
|
||||
{/* Left Side - Content */}
|
||||
<div className="w-3/5 relative bg-white px-16 py-12 flex flex-col justify-center">
|
||||
{/* Title Section */}
|
||||
<div className="mb-0">
|
||||
{sectionTitle && (
|
||||
<h1 className="text-3xl lg:text-4xl font-black text-teal-700 leading-tight mb-4">
|
||||
{sectionTitle}
|
||||
</h1>
|
||||
)}
|
||||
|
||||
{sectionSubtitle && (
|
||||
<p className="text-base font-semibold text-gray-800 tracking-wide mb-6">
|
||||
{sectionSubtitle}
|
||||
</p>
|
||||
)}
|
||||
|
||||
{/* Decorative gray line */}
|
||||
<div className="w-1 h-20 bg-gray-400 mb-8"></div>
|
||||
</div>
|
||||
|
||||
{/* Description Text */}
|
||||
{organizationDescription && (
|
||||
<p className="text-base leading-relaxed text-gray-700 max-w-xl">
|
||||
{organizationDescription}
|
||||
</p>
|
||||
)}
|
||||
|
||||
{/* Additional Text */}
|
||||
{additionalContext && (
|
||||
<div>
|
||||
<p className="text-base leading-relaxed text-gray-700 max-w-xl">
|
||||
{additionalContext}
|
||||
</p>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
|
||||
{/* Right Side - Image and Decorative Elements */}
|
||||
<div className="w-2/5 relative">
|
||||
{/* Yellow Square - Top Right */}
|
||||
{showAccentSquare && (
|
||||
<div className="absolute bottom-0 right-0 w-24 h-24 bg-yellow-300 z-10"></div>
|
||||
)}
|
||||
|
||||
{/* Decorative Circle - On Yellow Square */}
|
||||
{showVisualAccents && (
|
||||
<div className="absolute top-6 right-6 w-6 h-6 border-2 border-teal-600 rounded-full z-20"></div>
|
||||
)}
|
||||
|
||||
{/* Business Image - Left positioned */}
|
||||
{featuredImage?.__image_url__ && (
|
||||
<div className="absolute right-36 top-1/2 -translate-y-1/2 h-[500px] w-[350px] z-20 shadow-lg">
|
||||
<img
|
||||
src={featuredImage.__image_url__}
|
||||
alt={featuredImage.__image_prompt__}
|
||||
className="w-full h-full object-cover"
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{/* Teal Accent Areas */}
|
||||
{showColorBlocks && (
|
||||
<>
|
||||
{/* Vertical Teal Strip - Center */}
|
||||
<div className="absolute top-0 right-0 bottom-16 h-full w-[300px] bg-teal-600 z-10"></div>
|
||||
</>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default AboutUsSlide;
|
||||
|
|
@ -1,212 +0,0 @@
|
|||
import React from "react";
|
||||
import * as z from "zod";
|
||||
|
||||
import { ImageSchema, IconSchema } from "../defaultSchemes";
|
||||
import {
|
||||
ChartContainer,
|
||||
ChartLegend,
|
||||
ChartLegendContent,
|
||||
ChartTooltip,
|
||||
ChartTooltipContent,
|
||||
} from "@/components/ui/chart";
|
||||
import { BarChart, Bar, XAxis, YAxis, CartesianGrid } from "recharts";
|
||||
|
||||
export const layoutName = "Business Model Slide";
|
||||
export const layoutId = "business-model-slide";
|
||||
export const layoutDescription = "A slide with a business model";
|
||||
|
||||
// Schema definition
|
||||
export const Schema = z.object({
|
||||
sectionTitle: z.string().min(3).max(30).default("BUSINESS MODEL").meta({
|
||||
description:
|
||||
"Main section heading - adapt to presentation topic (e.g., 'Revenue Strategy', 'Funding Model', 'Implementation Plan', 'Solution Framework')",
|
||||
}),
|
||||
|
||||
sectionSubtitle: z
|
||||
.string()
|
||||
.min(10)
|
||||
.max(60)
|
||||
.default("SUSTAINABLE REVENUE AND VALUE CREATION")
|
||||
.meta({
|
||||
description:
|
||||
"Supporting subtitle that describes the approach - adapt to topic (e.g., 'Carbon Reduction Strategy', 'Healthcare Delivery Model', 'Educational Framework')",
|
||||
}),
|
||||
|
||||
modelDescription: z
|
||||
.string()
|
||||
.min(50)
|
||||
.max(300)
|
||||
.default(
|
||||
"Our business model focuses on creating sustainable value through multiple revenue streams, strategic partnerships, and customer-centric solutions. We prioritize long-term relationships and scalable growth opportunities."
|
||||
)
|
||||
.meta({
|
||||
description:
|
||||
"IMPORTANT: Provide topic-specific description of the model/approach. For global warming: describe carbon reduction strategies, renewable energy adoption, sustainability metrics. For healthcare: treatment protocols, patient care models. For education: learning methodologies, curriculum design. Always provide concrete, relevant details for the presentation topic.",
|
||||
}),
|
||||
|
||||
headerVisual: ImageSchema.default({
|
||||
__image_url__:
|
||||
"https://images.unsplash.com/photo-1559136555-9303baea8ebd?ixlib=rb-4.0.3&auto=format&fit=crop&w=800&q=80",
|
||||
__image_prompt__:
|
||||
"Business strategy meeting with charts, graphs and team collaboration",
|
||||
}).meta({
|
||||
description:
|
||||
"Header visual representing the topic area - ADAPT the image prompt to match presentation topic (e.g., 'Climate scientists analyzing global warming data', 'Medical team reviewing patient care protocols', 'Teachers planning educational curriculum')",
|
||||
}),
|
||||
|
||||
chartData: z
|
||||
.array(
|
||||
z.object({
|
||||
category: z.string().min(3).max(25),
|
||||
value: z.number().min(0).max(100),
|
||||
color: z.string().min(3).max(20).optional(),
|
||||
})
|
||||
)
|
||||
.min(2)
|
||||
.max(6)
|
||||
.default([
|
||||
{ category: "Product Sales", value: 45, color: "#22C55E" },
|
||||
{ category: "Services", value: 30, color: "#0891B2" },
|
||||
{ category: "Partnerships", value: 15, color: "#FDE047" },
|
||||
{ category: "Licensing", value: 10, color: "#F97316" },
|
||||
])
|
||||
.meta({
|
||||
description:
|
||||
"CRITICAL: Provide actual data relevant to the presentation topic. For global warming: CO2 emission sources (Transport 29%, Energy 25%, Industry 21%, Agriculture 24%), temperature rise by decade, renewable energy adoption rates. For healthcare: treatment success rates, patient demographics, cost breakdowns. For education: student performance metrics, learning outcomes, resource allocation. Always use REAL topic-specific data with appropriate categories and realistic values.",
|
||||
}),
|
||||
|
||||
showChart: z.boolean().default(true).meta({
|
||||
description:
|
||||
"Whether to display the data visualization - typically keep true for data-driven presentations",
|
||||
}),
|
||||
|
||||
showVisualAccents: z.boolean().default(true).meta({
|
||||
description: "Whether to display decorative visual accent elements",
|
||||
}),
|
||||
});
|
||||
|
||||
// Chart configuration
|
||||
const chartConfig = {
|
||||
series1: {
|
||||
label: "Series 1",
|
||||
color: "#1D9A8A",
|
||||
},
|
||||
series2: {
|
||||
label: "Series 2",
|
||||
color: "#E8F4B8",
|
||||
},
|
||||
series3: {
|
||||
label: "Series 3",
|
||||
color: "#A8C97F",
|
||||
},
|
||||
};
|
||||
|
||||
// Type inference
|
||||
type SchemaType = z.infer<typeof Schema>;
|
||||
|
||||
// Component definition
|
||||
const BusinessModelSlide = ({ data }: { data: Partial<SchemaType> }) => {
|
||||
const {
|
||||
sectionTitle,
|
||||
sectionSubtitle,
|
||||
modelDescription,
|
||||
headerVisual,
|
||||
chartData,
|
||||
showChart,
|
||||
showVisualAccents,
|
||||
} = data;
|
||||
|
||||
return (
|
||||
<div className="aspect-video max-w-[1280px] w-full bg-white relative overflow-hidden">
|
||||
{/* Header Image Section */}
|
||||
{headerVisual?.__image_url__ && (
|
||||
<div className="h-32 w-full relative">
|
||||
<img
|
||||
src={headerVisual.__image_url__}
|
||||
alt={headerVisual.__image_prompt__}
|
||||
className="w-full h-full object-cover"
|
||||
/>
|
||||
<div className="absolute inset-0 bg-black bg-opacity-40"></div>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{/* Main Content Area */}
|
||||
<div className="flex h-[calc(100%-8rem)]">
|
||||
{/* Left Side - Content */}
|
||||
<div className="w-1/2 px-16 py-8 flex flex-col justify-start">
|
||||
{/* Title Section */}
|
||||
<div className="mb-6">
|
||||
{sectionTitle && (
|
||||
<h1 className="text-3xl lg:text-4xl font-black text-teal-700 leading-tight mb-4">
|
||||
{sectionTitle}
|
||||
</h1>
|
||||
)}
|
||||
|
||||
{sectionSubtitle && (
|
||||
<p className="text-base font-semibold text-gray-800 tracking-wide mb-6">
|
||||
{sectionSubtitle}
|
||||
</p>
|
||||
)}
|
||||
</div>
|
||||
|
||||
{/* Model Description */}
|
||||
{modelDescription && (
|
||||
<div>
|
||||
<p className="text-base leading-relaxed text-gray-700">
|
||||
{modelDescription}
|
||||
</p>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{/* Visual Accents */}
|
||||
{showVisualAccents && (
|
||||
<>
|
||||
<div className="absolute bottom-8 left-8 w-6 h-6 bg-yellow-300 rounded-full"></div>
|
||||
<div className="absolute top-40 right-1/2 w-4 h-4 bg-teal-600 rounded-full"></div>
|
||||
</>
|
||||
)}
|
||||
</div>
|
||||
|
||||
{/* Right Side - Chart */}
|
||||
<div className="w-1/2 px-8 py-8 flex flex-col justify-center">
|
||||
{showChart && chartData && chartData.length > 0 && (
|
||||
<div className="h-80 w-full">
|
||||
<ChartContainer
|
||||
config={{
|
||||
value: {
|
||||
label: "Value",
|
||||
color: "hsl(var(--chart-1))",
|
||||
},
|
||||
}}
|
||||
className="h-full w-full"
|
||||
>
|
||||
<BarChart
|
||||
data={chartData}
|
||||
margin={{ top: 20, right: 20, bottom: 20, left: 20 }}
|
||||
>
|
||||
<CartesianGrid strokeDasharray="3 3" stroke="#e5e7eb" />
|
||||
<XAxis
|
||||
dataKey="category"
|
||||
stroke="#6b7280"
|
||||
fontSize={12}
|
||||
angle={-45}
|
||||
textAnchor="end"
|
||||
height={60}
|
||||
/>
|
||||
<YAxis stroke="#6b7280" fontSize={12} />
|
||||
<ChartTooltip content={<ChartTooltipContent />} />
|
||||
<Bar dataKey="value" fill="#0891b2" radius={[4, 4, 0, 0]} />
|
||||
</BarChart>
|
||||
</ChartContainer>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Bottom accent strip */}
|
||||
<div className="absolute bottom-0 left-0 right-0 h-2 bg-teal-600"></div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default BusinessModelSlide;
|
||||
|
|
@ -1,174 +0,0 @@
|
|||
import * as z from "zod";
|
||||
|
||||
import { ImageSchema, IconSchema } from "../defaultSchemes";
|
||||
|
||||
export const layoutName = "Market Size Slide";
|
||||
export const layoutId = "market-size-slide";
|
||||
export const layoutDescription = "A slide with a market size analysis";
|
||||
|
||||
// Schema definition
|
||||
export const Schema = z.object({
|
||||
sectionTitle: z.string().min(3).max(30).default("MARKET ANALYSIS").meta({
|
||||
description:
|
||||
"Main section heading - can be 'Market Size', 'Market Opportunity', 'Industry Overview', or similar",
|
||||
}),
|
||||
|
||||
sectionSubtitle: z
|
||||
.string()
|
||||
.min(10)
|
||||
.max(60)
|
||||
.default("UNDERSTANDING THE OPPORTUNITY LANDSCAPE")
|
||||
.meta({
|
||||
description:
|
||||
"Supporting subtitle that frames the market discussion and opportunity scope",
|
||||
}),
|
||||
|
||||
marketDefinitions: z
|
||||
.array(
|
||||
z.object({
|
||||
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(3)
|
||||
.default([
|
||||
{
|
||||
marketType: "Total Addressable Market (TAM)",
|
||||
marketDescription:
|
||||
"The overall revenue opportunity available if we achieved 100% market share across all segments and geographies.",
|
||||
marketValue: "$50B",
|
||||
},
|
||||
{
|
||||
marketType: "Serviceable Addressable Market (SAM)",
|
||||
marketDescription:
|
||||
"The portion of TAM targeted by our products and services within our geographic reach.",
|
||||
marketValue: "$15B",
|
||||
},
|
||||
{
|
||||
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:
|
||||
"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: "Whether to display the decorative yellow underline accent",
|
||||
}),
|
||||
|
||||
showVisualAccents: z.boolean().default(true).meta({
|
||||
description: "Whether to display decorative visual accent elements",
|
||||
}),
|
||||
});
|
||||
|
||||
// Type inference
|
||||
type SchemaType = z.infer<typeof Schema>;
|
||||
|
||||
// Component definition
|
||||
const MarketSizeSlide = ({ data }: { data: Partial<SchemaType> }) => {
|
||||
const {
|
||||
sectionTitle,
|
||||
sectionSubtitle,
|
||||
marketDefinitions,
|
||||
visualRepresentation,
|
||||
showYellowUnderline,
|
||||
showVisualAccents,
|
||||
} = data;
|
||||
|
||||
return (
|
||||
<div className="aspect-video max-w-[1280px] w-full bg-white relative overflow-hidden">
|
||||
{/* Main Content Area */}
|
||||
<div className="h-full flex">
|
||||
{/* Left Side - Content */}
|
||||
<div className="w-3/5 relative bg-white px-16 py-12 flex flex-col justify-start">
|
||||
{/* Title Section */}
|
||||
<div className="mb-8">
|
||||
{sectionTitle && (
|
||||
<h1 className="text-3xl lg:text-4xl font-black leading-tight mb-4">
|
||||
{sectionTitle}
|
||||
</h1>
|
||||
)}
|
||||
|
||||
{sectionSubtitle && (
|
||||
<p className="text-base font-semibold tracking-wide mb-4">
|
||||
{sectionSubtitle}
|
||||
</p>
|
||||
)}
|
||||
|
||||
{/* Yellow Decorative Underline */}
|
||||
{showYellowUnderline && (
|
||||
<div className="w-24 h-1 bg-yellow-300 mb-8"></div>
|
||||
)}
|
||||
</div>
|
||||
|
||||
{/* Market Definitions List */}
|
||||
{marketDefinitions && marketDefinitions.length > 0 && (
|
||||
<div className="space-y-6">
|
||||
{marketDefinitions.map((market, index) => (
|
||||
<div key={index} className="border-l-4 border-teal-600 pl-6">
|
||||
<div className="flex items-center justify-between mb-2">
|
||||
<h3 className="text-lg font-bold text-gray-900">
|
||||
{market.marketType}
|
||||
</h3>
|
||||
{market.marketValue && (
|
||||
<span className="text-xl font-bold text-teal-600">
|
||||
{market.marketValue}
|
||||
</span>
|
||||
)}
|
||||
</div>
|
||||
<p className="text-base leading-relaxed text-gray-700">
|
||||
{market.marketDescription}
|
||||
</p>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
|
||||
{/* Right Side - Visual Representation */}
|
||||
<div className="w-2/5 relative bg-gray-50">
|
||||
{/* Visual Accents */}
|
||||
{showVisualAccents && (
|
||||
<>
|
||||
{/* Decorative circles */}
|
||||
<div className="absolute top-8 right-8 w-6 h-6 bg-teal-600 rounded-full opacity-60 z-20"></div>
|
||||
<div className="absolute bottom-12 left-8 w-4 h-4 bg-yellow-300 rounded-full z-20"></div>
|
||||
</>
|
||||
)}
|
||||
|
||||
{/* Visual Representation */}
|
||||
{visualRepresentation?.__image_url__ && (
|
||||
<div className="absolute inset-8 shadow-lg">
|
||||
<img
|
||||
src={visualRepresentation.__image_url__}
|
||||
alt={visualRepresentation.__image_prompt__}
|
||||
className="w-full h-full object-cover rounded-lg"
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Bottom accent strip */}
|
||||
<div className="absolute bottom-0 left-0 right-0 h-3 bg-teal-600"></div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default MarketSizeSlide;
|
||||
|
|
@ -1,147 +0,0 @@
|
|||
import * as z from "zod";
|
||||
|
||||
import { ImageSchema, IconSchema } from "../defaultSchemes";
|
||||
|
||||
export const layoutName = "Our Service Slide";
|
||||
export const layoutId = "our-service-slide";
|
||||
export const layoutDescription = "A slide with a list of services";
|
||||
|
||||
// Schema definition
|
||||
export const Schema = z.object({
|
||||
sectionTitle: z.string().min(3).max(30).default("OUR SERVICES").meta({
|
||||
description:
|
||||
"Main section heading - can be 'Our Services', 'What We Offer', 'Service Portfolio', or similar",
|
||||
}),
|
||||
|
||||
sectionSubtitle: z
|
||||
.string()
|
||||
.min(10)
|
||||
.max(60)
|
||||
.default("COMPREHENSIVE SOLUTIONS TAILORED FOR SUCCESS")
|
||||
.meta({
|
||||
description:
|
||||
"Supporting subtitle that describes the service approach or value proposition",
|
||||
}),
|
||||
|
||||
bulletPoints: z
|
||||
.array(z.string().min(10).max(40))
|
||||
.min(4)
|
||||
.max(6)
|
||||
.default([
|
||||
"Customized solutions for your business",
|
||||
"Expert guidance and support",
|
||||
"Innovative technology solutions",
|
||||
"Comprehensive service portfolio",
|
||||
])
|
||||
.meta({
|
||||
description: "Bullet points to describe the services offered",
|
||||
}),
|
||||
|
||||
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",
|
||||
}),
|
||||
});
|
||||
|
||||
// Type inference
|
||||
type SchemaType = z.infer<typeof Schema>;
|
||||
|
||||
// Component definition
|
||||
const OurServiceSlide = ({ data }: { data: Partial<SchemaType> }) => {
|
||||
const {
|
||||
sectionTitle,
|
||||
sectionSubtitle,
|
||||
serviceHighlight,
|
||||
showVisualAccents,
|
||||
showColorBlocks,
|
||||
bulletPoints,
|
||||
} = data;
|
||||
|
||||
return (
|
||||
<div className="aspect-video max-w-[1280px] w-full bg-white relative overflow-hidden">
|
||||
{/* Main Content Area */}
|
||||
<div className="h-full flex">
|
||||
{/* Left - Title */}
|
||||
<div className="w-1/2 px-16 py-12 bg-gray-100">
|
||||
{sectionTitle && (
|
||||
<h1 className="text-3xl lg:text-4xl font-black text-teal-700 leading-tight mb-4">
|
||||
{sectionTitle}
|
||||
</h1>
|
||||
)}
|
||||
|
||||
{sectionSubtitle && (
|
||||
<p className="text-base font-semibold text-gray-800 tracking-wide">
|
||||
{sectionSubtitle}
|
||||
</p>
|
||||
)}
|
||||
|
||||
<div className="mt-16 space-y-4">
|
||||
{bulletPoints &&
|
||||
bulletPoints.map((point, index) => (
|
||||
<div
|
||||
key={index}
|
||||
className="text-base font-semibold text-gray-800 tracking-wide"
|
||||
>
|
||||
<div className="flex gap-3 items-center">
|
||||
<div className="min-w-8 min-h-8 bg-teal-700 rounded-full "></div>
|
||||
<p className="text-lg font-medium text-gray-800 tracking-wide">
|
||||
{point}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
|
||||
{/* Visual Accents */}
|
||||
{showVisualAccents && (
|
||||
<>
|
||||
{/* Decorative elements */}
|
||||
<div className="absolute bottom-16 left-16 w-8 h-8 bg-yellow-300 rounded-full"></div>
|
||||
<div className="absolute top-20 right-20 w-4 h-4 bg-teal-600 rounded-full"></div>
|
||||
</>
|
||||
)}
|
||||
</div>
|
||||
|
||||
{/* Right - Service Highlight */}
|
||||
<div className="w-1/2 relative">
|
||||
{/* Service Highlight Image */}
|
||||
{serviceHighlight?.__image_url__ && (
|
||||
<div className="h-full w-full">
|
||||
<img
|
||||
src={serviceHighlight.__image_url__}
|
||||
alt={serviceHighlight.__image_prompt__}
|
||||
className="w-full h-full object-cover"
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{/* Color overlay if enabled */}
|
||||
{showColorBlocks && (
|
||||
<div className="absolute inset-0 bg-teal-600 bg-opacity-20"></div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Bottom accent strip */}
|
||||
{showColorBlocks && (
|
||||
<div className="absolute bottom-0 left-0 right-0 h-3 bg-teal-600"></div>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default OurServiceSlide;
|
||||
|
|
@ -1,172 +0,0 @@
|
|||
import * as z from "zod";
|
||||
|
||||
import { ImageSchema, IconSchema } from "../defaultSchemes";
|
||||
|
||||
export const layoutName = "Problems Slide";
|
||||
export const layoutId = "problems-slide";
|
||||
export const layoutDescription = "A slide with a list of problems";
|
||||
|
||||
// Schema definition
|
||||
export const Schema = z.object({
|
||||
sectionTitle: z.string().min(3).max(25).default("CHALLENGES").meta({
|
||||
description:
|
||||
"Main section heading - can be 'Problems', 'Challenges', 'Issues', or similar",
|
||||
}),
|
||||
|
||||
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(3)
|
||||
.default([
|
||||
{
|
||||
itemNumber: "01",
|
||||
challengeTitle: "Inefficient Processes",
|
||||
challengeDescription:
|
||||
"Current workflows and systems lack optimization, leading to wasted resources and reduced productivity across all operational areas.",
|
||||
},
|
||||
{
|
||||
itemNumber: "02",
|
||||
challengeTitle: "Limited Scalability",
|
||||
challengeDescription:
|
||||
"Existing infrastructure and methodologies cannot accommodate growth, creating bottlenecks that hinder expansion and progress.",
|
||||
},
|
||||
{
|
||||
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 key challenges or problems with numbered identification and detailed descriptions",
|
||||
}),
|
||||
|
||||
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__:
|
||||
"Professional workspace showing analysis and problem-solving activities",
|
||||
}).meta({
|
||||
description:
|
||||
"Visual that supports the problem discussion - could show analysis, challenges, or work environment",
|
||||
}),
|
||||
|
||||
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 accent blocks for visual hierarchy",
|
||||
}),
|
||||
});
|
||||
|
||||
// Type inference
|
||||
type SchemaType = z.infer<typeof Schema>;
|
||||
|
||||
// Component definition
|
||||
const ProblemsSlide = ({ data }: { data: Partial<SchemaType> }) => {
|
||||
const {
|
||||
sectionTitle,
|
||||
sectionSubtitle,
|
||||
challengeItems,
|
||||
supportingVisual,
|
||||
showVisualAccents,
|
||||
showColorBlocks,
|
||||
} = data;
|
||||
|
||||
return (
|
||||
<div className="aspect-video max-w-[1280px] w-full bg-white relative overflow-hidden">
|
||||
{/* Main Content Area */}
|
||||
<div className="h-full flex">
|
||||
{/* Left Side - Content */}
|
||||
<div className="w-3/5 relative bg-white px-16 py-12 flex flex-col justify-start">
|
||||
{/* Title Section */}
|
||||
<div className="mb-12">
|
||||
{sectionTitle && (
|
||||
<h1 className="text-3xl lg:text-4xl font-black text-teal-700 leading-tight mb-4">
|
||||
{sectionTitle}
|
||||
</h1>
|
||||
)}
|
||||
|
||||
{sectionSubtitle && (
|
||||
<p className="text-base font-semibold text-gray-800 tracking-wide">
|
||||
{sectionSubtitle}
|
||||
</p>
|
||||
)}
|
||||
</div>
|
||||
|
||||
{/* Challenge Items List */}
|
||||
{challengeItems && challengeItems.length > 0 && (
|
||||
<div className="space-y-8">
|
||||
{challengeItems.map((item, index) => (
|
||||
<div key={index} className="flex items-start space-x-6">
|
||||
{/* Number Circle */}
|
||||
<div className="w-16 h-16 bg-yellow-200 rounded-full flex items-center justify-center flex-shrink-0">
|
||||
<span className="text-teal-700 font-bold text-xl">
|
||||
{item.itemNumber}
|
||||
</span>
|
||||
</div>
|
||||
|
||||
{/* Content */}
|
||||
<div className="flex-1">
|
||||
<h3 className="text-xl font-bold text-gray-900 mb-3">
|
||||
{item.challengeTitle}
|
||||
</h3>
|
||||
<p className="text-base leading-relaxed text-gray-700">
|
||||
{item.challengeDescription}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
|
||||
{/* Right Side - Image and Decorative Elements */}
|
||||
<div className="w-2/5 relative">
|
||||
{/* Decorative Circle */}
|
||||
{showVisualAccents && (
|
||||
<div className="absolute top-12 left-8 w-8 h-8 border-4 border-teal-600 rounded-full z-20"></div>
|
||||
)}
|
||||
|
||||
{/* Supporting Visual */}
|
||||
{supportingVisual?.__image_url__ && (
|
||||
<div className="absolute top-8 right-8 bottom-20 left-4 shadow-lg">
|
||||
<img
|
||||
src={supportingVisual.__image_url__}
|
||||
alt={supportingVisual.__image_prompt__}
|
||||
className="w-full h-full object-cover rounded-lg"
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{/* Teal Accent Block - Right Edge */}
|
||||
{showColorBlocks && (
|
||||
<div className="absolute top-0 right-0 bottom-0 w-16 bg-teal-600 z-10"></div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Bottom Teal Stripe */}
|
||||
<div className="absolute bottom-0 left-0 right-0 h-4 bg-teal-600 z-5"></div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default ProblemsSlide;
|
||||
|
|
@ -1,208 +0,0 @@
|
|||
import * as z from "zod";
|
||||
|
||||
import { ImageSchema, IconSchema } from "../defaultSchemes";
|
||||
|
||||
export const layoutName = "Solutions Slide";
|
||||
export const layoutId = "solutions-slide";
|
||||
export const layoutDescription = "A slide with a list of solutions";
|
||||
|
||||
// Schema definition
|
||||
export const Schema = z.object({
|
||||
sectionTitle: z.string().min(3).max(25).default("OUR SOLUTIONS").meta({
|
||||
description:
|
||||
"Main section heading - can be 'Solutions', 'Our Approach', 'How We Help', or similar",
|
||||
}),
|
||||
|
||||
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(3)
|
||||
.default([
|
||||
{
|
||||
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.",
|
||||
},
|
||||
{
|
||||
itemNumber: "02",
|
||||
solutionTitle: "Scalable Infrastructure",
|
||||
solutionDescription:
|
||||
"Build robust, flexible systems and methodologies that can grow with your organization, eliminating bottlenecks and supporting expansion efforts.",
|
||||
},
|
||||
{
|
||||
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 key solutions or approaches with numbered identification and detailed descriptions",
|
||||
}),
|
||||
|
||||
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:
|
||||
"Primary visual representing teamwork, strategy, or solution implementation",
|
||||
}),
|
||||
|
||||
brandingVisual: ImageSchema.default({
|
||||
__image_url__: "https://via.placeholder.com/150x80/22C55E/FFFFFF?text=LOGO",
|
||||
__image_prompt__: "Organization logo or brand mark",
|
||||
}).meta({
|
||||
description: "Logo or branding element to maintain visual identity",
|
||||
}),
|
||||
|
||||
showYellowUnderline: z.boolean().default(true).meta({
|
||||
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",
|
||||
}),
|
||||
});
|
||||
|
||||
// Type inference
|
||||
type SchemaType = z.infer<typeof Schema>;
|
||||
|
||||
// Component definition
|
||||
const SolutionsSlide = ({ data }: { data: Partial<SchemaType> }) => {
|
||||
const {
|
||||
sectionTitle,
|
||||
sectionSubtitle,
|
||||
solutionItems,
|
||||
primaryVisual,
|
||||
brandingVisual,
|
||||
showYellowUnderline,
|
||||
showVisualAccents,
|
||||
showColorBlocks,
|
||||
} = data;
|
||||
|
||||
return (
|
||||
<div className="aspect-video max-w-[1280px] w-full bg-white relative overflow-hidden">
|
||||
{/* Main Content Area */}
|
||||
<div className="h-full flex">
|
||||
{/* Left Side - Images and Branding */}
|
||||
<div className="w-2/5 relative bg-gray-100 flex flex-col">
|
||||
{/* Top Image Area */}
|
||||
{primaryVisual?.__image_url__ && (
|
||||
<div className="flex-1 relative">
|
||||
<img
|
||||
src={primaryVisual.__image_url__}
|
||||
alt={primaryVisual.__image_prompt__}
|
||||
className="w-full h-full object-cover"
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{/* Bottom Branding Area */}
|
||||
<div className="h-24 bg-white flex items-center justify-center px-8">
|
||||
{brandingVisual?.__image_url__ && (
|
||||
<img
|
||||
src={brandingVisual.__image_url__}
|
||||
alt={brandingVisual.__image_prompt__}
|
||||
className="h-12 object-contain"
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Right Side - Content */}
|
||||
<div className="w-3/5 relative bg-teal-600 px-16 py-12 flex flex-col justify-start">
|
||||
{/* Title Section */}
|
||||
<div className="mb-8">
|
||||
{sectionTitle && (
|
||||
<h1 className="text-3xl lg:text-4xl font-black text-white leading-tight mb-4">
|
||||
{sectionTitle}
|
||||
</h1>
|
||||
)}
|
||||
|
||||
{sectionSubtitle && (
|
||||
<p className="text-base font-semibold text-gray-100 tracking-wide mb-4">
|
||||
{sectionSubtitle}
|
||||
</p>
|
||||
)}
|
||||
|
||||
{/* Yellow Decorative Underline */}
|
||||
{showYellowUnderline && (
|
||||
<div className="w-24 h-1 bg-yellow-300"></div>
|
||||
)}
|
||||
</div>
|
||||
|
||||
{/* Solution Items List */}
|
||||
{solutionItems && solutionItems.length > 0 && (
|
||||
<div className="space-y-8">
|
||||
{solutionItems.map((item, index) => (
|
||||
<div key={index} className="flex items-start space-x-6">
|
||||
{/* Number Circle */}
|
||||
<div className="w-16 h-16 bg-yellow-300 rounded-full flex items-center justify-center flex-shrink-0">
|
||||
<span className="text-teal-700 font-bold text-xl">
|
||||
{item.itemNumber}
|
||||
</span>
|
||||
</div>
|
||||
|
||||
{/* Content */}
|
||||
<div className="flex-1">
|
||||
<h3 className="text-xl font-bold text-white mb-3">
|
||||
{item.solutionTitle}
|
||||
</h3>
|
||||
<p className="text-base leading-relaxed text-gray-100">
|
||||
{item.solutionDescription}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
)}
|
||||
|
||||
{/* Visual Accents */}
|
||||
{showVisualAccents && (
|
||||
<>
|
||||
{/* Decorative circles */}
|
||||
<div className="absolute top-8 right-8 w-4 h-4 bg-yellow-300 rounded-full"></div>
|
||||
<div className="absolute bottom-16 right-12 w-3 h-3 bg-yellow-200 rounded-full"></div>
|
||||
</>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Color blocks for visual hierarchy */}
|
||||
{showColorBlocks && (
|
||||
<>
|
||||
{/* Bottom accent strip */}
|
||||
<div className="absolute bottom-0 left-0 right-0 h-3 bg-yellow-300"></div>
|
||||
{/* Side accent */}
|
||||
<div className="absolute top-0 left-0 bottom-0 w-1 bg-yellow-400"></div>
|
||||
</>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default SolutionsSlide;
|
||||
|
|
@ -1,268 +0,0 @@
|
|||
import * as z from "zod";
|
||||
import { ImageSchema, IconSchema } from "../defaultSchemes";
|
||||
|
||||
export const layoutName = "Statistic Circular Slide";
|
||||
export const layoutId = "statistic-circular-slide";
|
||||
export const layoutDescription = "A slide with a circular statistic";
|
||||
|
||||
// Schema definition
|
||||
export const Schema = z.object({
|
||||
sectionTitle: z.string().min(3).max(20).default("CLIENT SATISFACTION").meta({
|
||||
description:
|
||||
"Main section heading - adapt to presentation topic (e.g., 'Climate Progress', 'Treatment Success', 'Learning Achievement', 'Project Completion')",
|
||||
}),
|
||||
|
||||
sectionSubtitle: z
|
||||
.string()
|
||||
.min(10)
|
||||
.max(35)
|
||||
.default("MEASURING OUR IMPACT AND SUCCESS")
|
||||
.meta({
|
||||
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(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: "Name of the organization or entity being measured",
|
||||
}),
|
||||
|
||||
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),
|
||||
})
|
||||
.default({
|
||||
value: 90,
|
||||
label: "CLIENT'S REPEAT ORDER",
|
||||
percentage: "90%",
|
||||
})
|
||||
.meta({
|
||||
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({
|
||||
percentage: z.string().min(2).max(5),
|
||||
description: z.string().min(20).max(150),
|
||||
backgroundColor: z.enum(["teal", "beige"]),
|
||||
})
|
||||
)
|
||||
.min(2)
|
||||
.max(2)
|
||||
.default([
|
||||
{
|
||||
percentage: "90%",
|
||||
description:
|
||||
"Our client loyalty speaks volumes as evidenced by a robust repeat order rate",
|
||||
backgroundColor: "teal",
|
||||
},
|
||||
{
|
||||
percentage: "99%",
|
||||
description:
|
||||
"Our paramount focus on client satisfaction is the bedrock of our agency's success.",
|
||||
backgroundColor: "beige",
|
||||
},
|
||||
])
|
||||
.meta({
|
||||
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({
|
||||
__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("Deskpro").meta({
|
||||
description: "Company name for branding",
|
||||
}),
|
||||
});
|
||||
|
||||
// Type inference
|
||||
type SchemaType = z.infer<typeof Schema>;
|
||||
|
||||
// Component definition
|
||||
const StatisticCircularSlide = ({ data }: { data: Partial<SchemaType> }) => {
|
||||
const {
|
||||
sectionTitle,
|
||||
sectionSubtitle,
|
||||
description,
|
||||
brandLogo,
|
||||
satisfactionRate,
|
||||
statisticBlocks,
|
||||
companyLogo,
|
||||
companyName,
|
||||
} = data;
|
||||
|
||||
const getBackgroundClass = (bg: string) => {
|
||||
switch (bg) {
|
||||
case "teal":
|
||||
return "bg-teal-600 text-white";
|
||||
case "beige":
|
||||
return "bg-yellow-200 text-gray-900";
|
||||
default:
|
||||
return "bg-gray-200 text-gray-900";
|
||||
}
|
||||
};
|
||||
|
||||
// Calculate stroke dash array for circular progress
|
||||
const radius = 150;
|
||||
const circumference = 2 * Math.PI * radius;
|
||||
const strokeDasharray = circumference;
|
||||
const strokeDashoffset =
|
||||
circumference - (circumference * (satisfactionRate?.value || 90)) / 100;
|
||||
|
||||
return (
|
||||
<div className="aspect-video max-w-[1280px] w-full bg-white relative overflow-hidden">
|
||||
{/* Main Content Area */}
|
||||
<div className="h-full flex flex-col">
|
||||
{/* Header Section */}
|
||||
<div className="flex h-32">
|
||||
{/* Left - Title */}
|
||||
<div className="w-1/2 px-16 py-8 bg-gray-100 flex flex-col justify-center">
|
||||
{sectionTitle && (
|
||||
<h1 className="text-4xl lg:text-5xl font-black text-teal-700 leading-tight mb-2">
|
||||
{sectionTitle}
|
||||
</h1>
|
||||
)}
|
||||
|
||||
{sectionSubtitle && (
|
||||
<p className="text-base font-semibold text-gray-800 tracking-wide">
|
||||
{sectionSubtitle}
|
||||
</p>
|
||||
)}
|
||||
</div>
|
||||
|
||||
{/* Right - Company Branding */}
|
||||
<div className="w-1/2 bg-teal-600 px-16 py-8 flex items-center justify-end">
|
||||
<div className="flex items-center space-x-3">
|
||||
{companyLogo?.__image_url__ && (
|
||||
<div className="w-10 h-10">
|
||||
<img
|
||||
src={companyLogo.__image_url__}
|
||||
alt={companyLogo.__image_prompt__}
|
||||
className="w-full h-full object-contain"
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
{companyName && (
|
||||
<span className="text-xl font-bold text-white">
|
||||
{companyName}
|
||||
</span>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Content Section */}
|
||||
<div className="flex-1 flex">
|
||||
{/* Left Side - Circular Chart */}
|
||||
<div className="w-1/2 px-8 py-8 bg-gray-100 flex items-center justify-center">
|
||||
<div className="relative">
|
||||
{/* Circular Progress SVG */}
|
||||
<svg width="340" height="340" className="transform -rotate-90">
|
||||
{/* Background circle */}
|
||||
<circle
|
||||
cx="170"
|
||||
cy="170"
|
||||
r={radius}
|
||||
stroke="#E5E7EB"
|
||||
strokeWidth="25"
|
||||
fill="transparent"
|
||||
/>
|
||||
{/* Progress circle */}
|
||||
<circle
|
||||
cx="170"
|
||||
cy="170"
|
||||
r={radius}
|
||||
stroke="#1D9A8A"
|
||||
strokeWidth="25"
|
||||
fill="transparent"
|
||||
strokeDasharray={strokeDasharray}
|
||||
strokeDashoffset={strokeDashoffset}
|
||||
strokeLinecap="round"
|
||||
className="transition-all duration-1000 ease-out"
|
||||
/>
|
||||
</svg>
|
||||
|
||||
{/* Center Content */}
|
||||
<div className="absolute inset-0 flex flex-col items-center justify-center">
|
||||
{satisfactionRate?.label && (
|
||||
<p className="text-sm font-semibold text-gray-800 mb-4 text-center max-w-32 leading-tight">
|
||||
{satisfactionRate.label}
|
||||
</p>
|
||||
)}
|
||||
{satisfactionRate?.percentage && (
|
||||
<span className="text-7xl font-black text-teal-700">
|
||||
{satisfactionRate.percentage}
|
||||
</span>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Right Side - Content and Statistics */}
|
||||
<div className="w-1/2 bg-white flex flex-col">
|
||||
{/* Description */}
|
||||
<div className="px-16 py-8 flex-1 flex items-start justify-center flex-col">
|
||||
{description && (
|
||||
<p className="text-base leading-relaxed text-gray-700">
|
||||
{description}
|
||||
</p>
|
||||
)}
|
||||
</div>
|
||||
|
||||
{/* Statistics Blocks */}
|
||||
{statisticBlocks && statisticBlocks.length > 0 && (
|
||||
<div className="px-16 pb-8 space-y-4">
|
||||
{statisticBlocks.map((block, index) => (
|
||||
<div key={index} className="flex items-stretch">
|
||||
{/* Percentage Block */}
|
||||
<div
|
||||
className={`w-24 h-20 ${getBackgroundClass(
|
||||
block.backgroundColor
|
||||
)} flex items-center justify-center flex-shrink-0`}
|
||||
>
|
||||
<span className="text-2xl font-black">
|
||||
{block.percentage}
|
||||
</span>
|
||||
</div>
|
||||
|
||||
{/* Description Block */}
|
||||
<div className="flex-1 border-2 border-gray-900 p-4 h-20 flex items-center">
|
||||
<p className="text-sm leading-relaxed text-gray-900">
|
||||
{block.description}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default StatisticCircularSlide;
|
||||
|
|
@ -1,361 +0,0 @@
|
|||
import React from "react";
|
||||
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,
|
||||
} from "recharts";
|
||||
|
||||
export const layoutName = "Statistic Dual Chart Slide";
|
||||
export const layoutId = "statistic-dual-chart-slide";
|
||||
export const layoutDescription = "A slide with a statistic and a chart";
|
||||
|
||||
// Schema definition
|
||||
export const Schema = z.object({
|
||||
sectionTitle: z.string().min(3).max(30).default("PERFORMANCE METRICS").meta({
|
||||
description:
|
||||
"Main section heading - adapt to presentation topic (e.g., 'Climate Analysis', 'Health Outcomes', 'Research Data', 'Impact Assessment')",
|
||||
}),
|
||||
|
||||
organizationName: z
|
||||
.string()
|
||||
.min(2)
|
||||
.max(30)
|
||||
.default("Your Organization")
|
||||
.meta({
|
||||
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(),
|
||||
series2: z.number(),
|
||||
series3: z.number(),
|
||||
})
|
||||
)
|
||||
.min(5)
|
||||
.max(5)
|
||||
.default([
|
||||
{ name: "Item 1", series1: 5, series2: 5, series3: 8 },
|
||||
{ name: "Item 2", series1: 8, series2: 8, series3: 15 },
|
||||
{ name: "Item 3", series1: 15, series2: 10, series3: 18 },
|
||||
{ name: "Item 4", series1: 18, series2: 14, series3: 22 },
|
||||
{ name: "Item 5", series1: 22, series2: 20, series3: 8 },
|
||||
])
|
||||
.meta({
|
||||
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({
|
||||
name: z.string(),
|
||||
series1: z.number(),
|
||||
series2: z.number(),
|
||||
series3: z.number(),
|
||||
})
|
||||
)
|
||||
.min(5)
|
||||
.max(5)
|
||||
.default([
|
||||
{ name: "Item 1", series1: 20, series2: 30, series3: 15 },
|
||||
{ name: "Item 2", series1: 40, series2: 45, series3: 35 },
|
||||
{ name: "Item 3", series1: 45, series2: 50, series3: 80 },
|
||||
{ name: "Item 4", series1: 50, series2: 45, series3: 85 },
|
||||
{ name: "Item 5", series1: 80, series2: 75, series3: 120 },
|
||||
])
|
||||
.meta({
|
||||
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()
|
||||
.min(5)
|
||||
.max(40)
|
||||
.default("Our Customer's Satisfaction")
|
||||
.meta({
|
||||
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()
|
||||
.min(20)
|
||||
.max(200)
|
||||
.default(
|
||||
"An impressive client satisfaction rate underscores our unwavering commitment to delivering exceptional service and exceeding expectations."
|
||||
)
|
||||
.meta({
|
||||
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().min(5).max(40).default("Repeat Order Rate").meta({
|
||||
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()
|
||||
.min(20)
|
||||
.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:
|
||||
"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.",
|
||||
}),
|
||||
});
|
||||
|
||||
// Chart configuration
|
||||
const chartConfig = {
|
||||
series1: {
|
||||
label: "Series 1",
|
||||
color: "#1D9A8A",
|
||||
},
|
||||
series2: {
|
||||
label: "Series 2",
|
||||
color: "#A8C97F",
|
||||
},
|
||||
series3: {
|
||||
label: "Series 3",
|
||||
color: "#E8F4B8",
|
||||
},
|
||||
};
|
||||
|
||||
// Type inference
|
||||
type SchemaType = z.infer<typeof Schema>;
|
||||
|
||||
// Component definition
|
||||
const StatisticDualChartSlide = ({ data }: { data: Partial<SchemaType> }) => {
|
||||
const {
|
||||
sectionTitle,
|
||||
organizationName,
|
||||
brandLogo,
|
||||
barChartData,
|
||||
areaChartData,
|
||||
leftChartTitle,
|
||||
leftChartDescription,
|
||||
rightChartTitle,
|
||||
rightChartDescription,
|
||||
} = data;
|
||||
|
||||
return (
|
||||
<div className="aspect-video max-w-[1280px] w-full bg-white relative overflow-hidden">
|
||||
{/* Header Section */}
|
||||
<div className="h-20 bg-teal-600 px-16 py-4 flex justify-between items-center">
|
||||
{/* Title */}
|
||||
{sectionTitle && (
|
||||
<h1 className="text-4xl font-black text-white">{sectionTitle}</h1>
|
||||
)}
|
||||
|
||||
{/* Company Branding */}
|
||||
<div className="flex items-center space-x-3">
|
||||
{brandLogo?.__image_url__ && (
|
||||
<div className="w-8 h-8">
|
||||
<img
|
||||
src={brandLogo.__image_url__}
|
||||
alt={brandLogo.__image_prompt__}
|
||||
className="w-full h-full object-contain"
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
{organizationName && (
|
||||
<span className="text-lg font-bold text-white">
|
||||
{organizationName}
|
||||
</span>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Content Section */}
|
||||
<div className="flex-1 h-[calc(100%-80px)] flex">
|
||||
{/* Left Chart Section */}
|
||||
<div className="w-1/2 p-8 bg-gray-50 flex flex-col">
|
||||
{/* Chart Legend */}
|
||||
<div className="flex items-center justify-start mb-4 space-x-4">
|
||||
<div className="flex items-center space-x-2">
|
||||
<div className="w-3 h-3 bg-teal-600 rounded-full"></div>
|
||||
<span className="text-sm text-gray-600">Series 1</span>
|
||||
</div>
|
||||
<div className="flex items-center space-x-2">
|
||||
<div className="w-3 h-3 bg-green-400 rounded-full"></div>
|
||||
<span className="text-sm text-gray-600">Series 2</span>
|
||||
</div>
|
||||
<div className="flex items-center space-x-2">
|
||||
<div className="w-3 h-3 bg-yellow-200 rounded-full"></div>
|
||||
<span className="text-sm text-gray-600">Series 3</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Bar Chart */}
|
||||
{barChartData && barChartData.length > 0 && (
|
||||
<div className="flex-1 mb-6">
|
||||
<ChartContainer config={chartConfig} className="h-full w-full">
|
||||
<BarChart
|
||||
data={barChartData}
|
||||
margin={{ top: 10, right: 20, left: 0, bottom: 30 }}
|
||||
barCategoryGap="20%"
|
||||
>
|
||||
<CartesianGrid strokeDasharray="3 3" stroke="#f0f0f0" />
|
||||
<XAxis
|
||||
dataKey="name"
|
||||
axisLine={false}
|
||||
tickLine={false}
|
||||
tick={{ fontSize: 12, fill: "#666" }}
|
||||
/>
|
||||
<YAxis
|
||||
axisLine={false}
|
||||
tickLine={false}
|
||||
tick={{ fontSize: 12, fill: "#666" }}
|
||||
/>
|
||||
<ChartTooltip content={<ChartTooltipContent />} />
|
||||
<Bar
|
||||
dataKey="series1"
|
||||
fill="#1D9A8A"
|
||||
radius={[2, 2, 0, 0]}
|
||||
barSize={15}
|
||||
/>
|
||||
<Bar
|
||||
dataKey="series2"
|
||||
fill="#A8C97F"
|
||||
radius={[2, 2, 0, 0]}
|
||||
barSize={15}
|
||||
/>
|
||||
<Bar
|
||||
dataKey="series3"
|
||||
fill="#E8F4B8"
|
||||
radius={[2, 2, 0, 0]}
|
||||
barSize={15}
|
||||
/>
|
||||
</BarChart>
|
||||
</ChartContainer>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{/* Chart Description */}
|
||||
<div className="space-y-3">
|
||||
{leftChartTitle && (
|
||||
<h3 className="text-xl font-bold text-gray-900">
|
||||
{leftChartTitle}
|
||||
</h3>
|
||||
)}
|
||||
{leftChartDescription && (
|
||||
<p className="text-base leading-relaxed text-gray-700">
|
||||
{leftChartDescription}
|
||||
</p>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Right Chart Section */}
|
||||
<div className="w-1/2 p-8 bg-white flex flex-col">
|
||||
{/* Chart Legend */}
|
||||
<div className="flex items-center justify-end mb-4 space-x-4">
|
||||
<div className="flex items-center space-x-2">
|
||||
<div className="w-3 h-3 bg-yellow-200 rounded-full"></div>
|
||||
<span className="text-sm text-gray-600">Series 1</span>
|
||||
</div>
|
||||
<div className="flex items-center space-x-2">
|
||||
<div className="w-3 h-3 bg-green-400 rounded-full"></div>
|
||||
<span className="text-sm text-gray-600">Series 2</span>
|
||||
</div>
|
||||
<div className="flex items-center space-x-2">
|
||||
<div className="w-3 h-3 bg-teal-600 rounded-full"></div>
|
||||
<span className="text-sm text-gray-600">Series 3</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Area Chart */}
|
||||
{areaChartData && areaChartData.length > 0 && (
|
||||
<div className="flex-1 mb-6">
|
||||
<ChartContainer config={chartConfig} className="h-full w-full">
|
||||
<AreaChart
|
||||
data={areaChartData}
|
||||
margin={{ top: 10, right: 20, left: 0, bottom: 30 }}
|
||||
>
|
||||
<CartesianGrid strokeDasharray="3 3" stroke="#f0f0f0" />
|
||||
<XAxis
|
||||
dataKey="name"
|
||||
axisLine={false}
|
||||
tickLine={false}
|
||||
tick={{ fontSize: 12, fill: "#666" }}
|
||||
/>
|
||||
<YAxis
|
||||
axisLine={false}
|
||||
tickLine={false}
|
||||
tick={{ fontSize: 12, fill: "#666" }}
|
||||
/>
|
||||
<ChartTooltip content={<ChartTooltipContent />} />
|
||||
<Area
|
||||
type="monotone"
|
||||
dataKey="series3"
|
||||
stackId="1"
|
||||
stroke="#1D9A8A"
|
||||
fill="#1D9A8A"
|
||||
fillOpacity={0.8}
|
||||
/>
|
||||
<Area
|
||||
type="monotone"
|
||||
dataKey="series2"
|
||||
stackId="1"
|
||||
stroke="#A8C97F"
|
||||
fill="#A8C97F"
|
||||
fillOpacity={0.8}
|
||||
/>
|
||||
<Area
|
||||
type="monotone"
|
||||
dataKey="series1"
|
||||
stackId="1"
|
||||
stroke="#E8F4B8"
|
||||
fill="#E8F4B8"
|
||||
fillOpacity={0.8}
|
||||
/>
|
||||
</AreaChart>
|
||||
</ChartContainer>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{/* Chart Description */}
|
||||
<div className="space-y-3">
|
||||
{rightChartTitle && (
|
||||
<h3 className="text-xl font-bold text-gray-900">
|
||||
{rightChartTitle}
|
||||
</h3>
|
||||
)}
|
||||
{rightChartDescription && (
|
||||
<p className="text-base leading-relaxed text-gray-700">
|
||||
{rightChartDescription}
|
||||
</p>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default StatisticDualChartSlide;
|
||||
|
|
@ -1,301 +0,0 @@
|
|||
import React from "react";
|
||||
import * as z from "zod";
|
||||
import { ImageSchema, IconSchema } from "../defaultSchemes";
|
||||
import {
|
||||
ChartContainer,
|
||||
ChartTooltip,
|
||||
ChartTooltipContent,
|
||||
} from "@/components/ui/chart";
|
||||
import { LineChart, Line, XAxis, YAxis, CartesianGrid } from "recharts";
|
||||
|
||||
export const layoutName = "Statistic Slide";
|
||||
export const layoutId = "statistic-slide";
|
||||
export const layoutDescription = "A slide with a statistic";
|
||||
|
||||
// Schema definition
|
||||
export const Schema = z.object({
|
||||
sectionTitle: z.string().min(3).max(30).default("KEY STATISTICS").meta({
|
||||
description:
|
||||
"Main section heading - adapt to presentation topic (e.g., 'Climate Data', 'Health Metrics', 'Performance Stats', 'Research Findings')",
|
||||
}),
|
||||
|
||||
sectionSubtitle: z
|
||||
.string()
|
||||
.min(10)
|
||||
.max(60)
|
||||
.default("DATA-DRIVEN INSIGHTS AND PERFORMANCE")
|
||||
.meta({
|
||||
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')",
|
||||
}),
|
||||
|
||||
statisticValue: z.string().min(1).max(15).default("85%").meta({
|
||||
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.",
|
||||
}),
|
||||
|
||||
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:
|
||||
"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({
|
||||
name: z.string(),
|
||||
series1: z.number(),
|
||||
series2: z.number(),
|
||||
series3: z.number(),
|
||||
})
|
||||
)
|
||||
.min(5)
|
||||
.max(5)
|
||||
.default([
|
||||
{ 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:
|
||||
"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: "Whether to display the decorative yellow underline accent",
|
||||
}),
|
||||
|
||||
showVisualAccents: z.boolean().default(true).meta({
|
||||
description: "Whether to display decorative visual accent elements",
|
||||
}),
|
||||
});
|
||||
|
||||
// Chart configuration
|
||||
const chartConfig = {
|
||||
series1: {
|
||||
label: "Series 1",
|
||||
color: "#1D9A8A",
|
||||
},
|
||||
series2: {
|
||||
label: "Series 2",
|
||||
color: "#A8C97F",
|
||||
},
|
||||
series3: {
|
||||
label: "Series 3",
|
||||
color: "#E8F4B8",
|
||||
},
|
||||
};
|
||||
|
||||
// Type inference
|
||||
type SchemaType = z.infer<typeof Schema>;
|
||||
|
||||
// Component definition
|
||||
const StatisticSlide = ({ data }: { data: Partial<SchemaType> }) => {
|
||||
const {
|
||||
sectionTitle,
|
||||
sectionSubtitle,
|
||||
statisticValue,
|
||||
statisticLabel,
|
||||
supportingVisual,
|
||||
bulletPoints,
|
||||
chartData,
|
||||
showYellowUnderline,
|
||||
showVisualAccents,
|
||||
} = data;
|
||||
|
||||
return (
|
||||
<div className="aspect-video max-w-[1280px] w-full bg-white relative overflow-hidden">
|
||||
{/* Main Content Area */}
|
||||
<div className="h-full flex">
|
||||
{/* Left Side - Teal Background */}
|
||||
<div className="w-1/2 relative bg-teal-600 px-16 py-12 flex flex-col text-white">
|
||||
{/* Title Section */}
|
||||
<div className="mb-8">
|
||||
{sectionTitle && (
|
||||
<h1 className="text-3xl lg:text-4xl font-black leading-tight mb-4">
|
||||
{sectionTitle}
|
||||
</h1>
|
||||
)}
|
||||
|
||||
{sectionSubtitle && (
|
||||
<p className="text-base font-semibold tracking-wide mb-4">
|
||||
{sectionSubtitle}
|
||||
</p>
|
||||
)}
|
||||
|
||||
{/* Yellow Decorative Underline */}
|
||||
{showYellowUnderline && (
|
||||
<div className="w-24 h-1 bg-yellow-300 mb-8"></div>
|
||||
)}
|
||||
</div>
|
||||
|
||||
{/* Large Statistic Display */}
|
||||
<div className="mb-8">
|
||||
{statisticValue && (
|
||||
<div className="text-8xl font-black text-yellow-300 mb-4">
|
||||
{statisticValue}
|
||||
</div>
|
||||
)}
|
||||
{statisticLabel && (
|
||||
<h2 className="text-2xl font-bold">{statisticLabel}</h2>
|
||||
)}
|
||||
</div>
|
||||
|
||||
{/* Business Image */}
|
||||
{supportingVisual?.__image_url__ && (
|
||||
<div className="flex-1 flex items-end">
|
||||
<div className="w-full h-48">
|
||||
<img
|
||||
src={supportingVisual.__image_url__}
|
||||
alt={supportingVisual.__image_prompt__}
|
||||
className="w-full h-full object-cover rounded-lg"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{/* Visual Accents */}
|
||||
{showVisualAccents && (
|
||||
<>
|
||||
<div className="absolute top-8 right-8 w-6 h-6 bg-yellow-300 rounded-full"></div>
|
||||
<div className="absolute bottom-12 left-8 w-4 h-4 bg-yellow-200 rounded-full"></div>
|
||||
</>
|
||||
)}
|
||||
</div>
|
||||
|
||||
{/* Right Side - White Background with Chart and Bullet Points */}
|
||||
<div className="w-1/2 relative bg-white px-16 py-12">
|
||||
{/* Chart Section */}
|
||||
<div className="flex-1 px-8 pt-8">
|
||||
{/* Chart Legend */}
|
||||
<div className="flex items-center justify-end mb-4 space-x-4">
|
||||
<div className="flex items-center space-x-2">
|
||||
<div className="w-3 h-3 bg-yellow-300 rounded-full"></div>
|
||||
<span className="text-sm text-gray-600">Series 1</span>
|
||||
</div>
|
||||
<div className="flex items-center space-x-2">
|
||||
<div className="w-3 h-3 bg-gray-300 rounded-full"></div>
|
||||
<span className="text-sm text-gray-600">Series 2</span>
|
||||
</div>
|
||||
<div className="flex items-center space-x-2">
|
||||
<div className="w-3 h-3 bg-teal-600 rounded-full"></div>
|
||||
<span className="text-sm text-gray-600">Series 3</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Chart Container */}
|
||||
{chartData && chartData.length > 0 && (
|
||||
<div className="h-64">
|
||||
<ChartContainer config={chartConfig} className="h-full w-full">
|
||||
<LineChart
|
||||
data={chartData}
|
||||
margin={{ top: 10, right: 20, left: 0, bottom: 30 }}
|
||||
>
|
||||
<CartesianGrid strokeDasharray="3 3" stroke="#f0f0f0" />
|
||||
<XAxis
|
||||
dataKey="name"
|
||||
axisLine={false}
|
||||
tickLine={false}
|
||||
tick={{ fontSize: 12, fill: "#666" }}
|
||||
/>
|
||||
<YAxis
|
||||
axisLine={false}
|
||||
tickLine={false}
|
||||
tick={{ fontSize: 12, fill: "#666" }}
|
||||
/>
|
||||
<ChartTooltip content={<ChartTooltipContent />} />
|
||||
<Line
|
||||
type="monotone"
|
||||
dataKey="series1"
|
||||
stroke="#E8F4B8"
|
||||
strokeWidth={3}
|
||||
dot={{ fill: "#E8F4B8", strokeWidth: 2, r: 4 }}
|
||||
/>
|
||||
<Line
|
||||
type="monotone"
|
||||
dataKey="series2"
|
||||
stroke="#A8C97F"
|
||||
strokeWidth={3}
|
||||
dot={{ fill: "#A8C97F", strokeWidth: 2, r: 4 }}
|
||||
/>
|
||||
<Line
|
||||
type="monotone"
|
||||
dataKey="series3"
|
||||
stroke="#1D9A8A"
|
||||
strokeWidth={3}
|
||||
dot={{ fill: "#1D9A8A", strokeWidth: 2, r: 4 }}
|
||||
/>
|
||||
</LineChart>
|
||||
</ChartContainer>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
|
||||
{/* Bullet Points Section */}
|
||||
<div className="px-8 pb-6 space-y-4 mt-10">
|
||||
{bulletPoints && bulletPoints.length > 0 && (
|
||||
<>
|
||||
{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 (
|
||||
<div key={index} className="flex items-start space-x-4">
|
||||
<div
|
||||
className={`w-6 h-6 ${dotColor} rounded-full flex-shrink-0 mt-1`}
|
||||
></div>
|
||||
<p className="text-base leading-relaxed text-gray-700">
|
||||
{point}
|
||||
</p>
|
||||
</div>
|
||||
);
|
||||
})}
|
||||
</>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Bottom accent strip */}
|
||||
<div className="absolute bottom-0 left-0 right-0 h-3 bg-yellow-300"></div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default StatisticSlide;
|
||||
|
|
@ -1,197 +0,0 @@
|
|||
import * as z from "zod";
|
||||
|
||||
import { ImageSchema, IconSchema } from "../defaultSchemes";
|
||||
|
||||
export const layoutName = "Table of Contents Slide";
|
||||
export const layoutId = "table-of-contents-slide";
|
||||
export const layoutDescription = "A slide with a table of contents";
|
||||
|
||||
// Schema definition
|
||||
export const Schema = z.object({
|
||||
sectionTitle: z.string().min(3).max(30).default("TABLE OF CONTENTS").meta({
|
||||
description:
|
||||
"Main heading for the content overview - can be 'Agenda', 'Overview', 'Contents', or similar",
|
||||
}),
|
||||
|
||||
sectionSubtitle: z
|
||||
.string()
|
||||
.min(10)
|
||||
.max(60)
|
||||
.default("PRESENTATION OVERVIEW AND AGENDA")
|
||||
.meta({
|
||||
description:
|
||||
"Supporting subtitle that explains what the audience will learn or see",
|
||||
}),
|
||||
|
||||
contentItems: z
|
||||
.array(
|
||||
z.object({
|
||||
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 presentation sections with numbered sequence and brief descriptions",
|
||||
}),
|
||||
|
||||
brandingVisual: ImageSchema.default({
|
||||
__image_url__:
|
||||
"https://via.placeholder.com/200x100/22C55E/FFFFFF?text=BRAND",
|
||||
__image_prompt__: "Organization logo or brand visual element",
|
||||
}).meta({
|
||||
description:
|
||||
"Logo or branding element displayed prominently for visual identity",
|
||||
}),
|
||||
|
||||
showDecorations: z.boolean().default(true).meta({
|
||||
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",
|
||||
}),
|
||||
});
|
||||
|
||||
// Type inference
|
||||
type SchemaType = z.infer<typeof Schema>;
|
||||
|
||||
// Component definition
|
||||
const TableOfContentsSlide = ({ data }: { data: Partial<SchemaType> }) => {
|
||||
const {
|
||||
sectionTitle,
|
||||
sectionSubtitle,
|
||||
contentItems,
|
||||
brandingVisual,
|
||||
showDecorations,
|
||||
useColumnLayout,
|
||||
} = data;
|
||||
|
||||
return (
|
||||
<div className="aspect-video max-w-[1280px] w-full bg-white relative overflow-hidden">
|
||||
{/* Main Content Area */}
|
||||
<div className="h-full flex">
|
||||
{/* Left Side - Content */}
|
||||
<div className="w-3/5 px-16 py-12 flex flex-col justify-start">
|
||||
{/* Title Section */}
|
||||
<div className="mb-12">
|
||||
{sectionTitle && (
|
||||
<h1 className="text-3xl lg:text-4xl font-black text-teal-700 leading-tight mb-4">
|
||||
{sectionTitle}
|
||||
</h1>
|
||||
)}
|
||||
|
||||
{/* Decorative underline */}
|
||||
{showDecorations && (
|
||||
<div className="w-32 h-1 bg-yellow-300 mb-6"></div>
|
||||
)}
|
||||
|
||||
{sectionSubtitle && (
|
||||
<p className="text-base font-medium text-gray-700 tracking-wide">
|
||||
{sectionSubtitle}
|
||||
</p>
|
||||
)}
|
||||
</div>
|
||||
|
||||
{/* Content Items */}
|
||||
{contentItems && contentItems.length > 0 && (
|
||||
<div
|
||||
className={`grid ${
|
||||
useColumnLayout ? "grid-cols-2" : "grid-cols-1"
|
||||
} gap-x-16 gap-y-8`}
|
||||
>
|
||||
{contentItems.map((item, index) => (
|
||||
<div key={index} className="flex items-start space-x-4">
|
||||
{/* Number Circle */}
|
||||
<div className="w-10 h-10 bg-yellow-200 rounded-full flex items-center justify-center flex-shrink-0">
|
||||
<span className="text-teal-700 font-bold text-sm">
|
||||
{item.itemNumber}
|
||||
</span>
|
||||
</div>
|
||||
|
||||
{/* Content */}
|
||||
<div className="flex-1">
|
||||
<h3 className="text-lg font-bold text-gray-900 mb-1">
|
||||
{item.contentTitle}
|
||||
</h3>
|
||||
{item.contentDescription && (
|
||||
<p className="text-sm text-gray-600 leading-relaxed">
|
||||
{item.contentDescription}
|
||||
</p>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
|
||||
{/* Right Side - Branding and Visual Elements */}
|
||||
<div className="w-2/5 relative bg-gray-50 flex items-center justify-center">
|
||||
{/* Branding Visual */}
|
||||
{brandingVisual?.__image_url__ && (
|
||||
<div className="text-center">
|
||||
<img
|
||||
src={brandingVisual.__image_url__}
|
||||
alt={brandingVisual.__image_prompt__}
|
||||
className="max-w-64 max-h-32 object-contain mx-auto"
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{/* Decorative Elements */}
|
||||
{showDecorations && (
|
||||
<>
|
||||
{/* Decorative circles */}
|
||||
<div className="absolute top-8 right-8 w-6 h-6 bg-teal-600 rounded-full opacity-60"></div>
|
||||
<div className="absolute bottom-12 left-8 w-4 h-4 bg-yellow-300 rounded-full"></div>
|
||||
<div className="absolute top-32 left-12 w-3 h-3 bg-teal-400 rounded-full"></div>
|
||||
</>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Bottom accent strip */}
|
||||
<div className="absolute bottom-0 left-0 right-0 h-2 bg-teal-600"></div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default TableOfContentsSlide;
|
||||
|
|
@ -1,221 +0,0 @@
|
|||
import * as z from "zod";
|
||||
|
||||
import { ImageSchema, IconSchema } from "../defaultSchemes";
|
||||
|
||||
export const layoutName = "Testimonial Slide";
|
||||
export const layoutId = "testimonial-slide";
|
||||
export const layoutDescription = "A slide with a testimonial";
|
||||
|
||||
// Schema definition
|
||||
export const Schema = z.object({
|
||||
sectionTitle: z.string().min(3).max(30).default("CLIENT TESTIMONIALS").meta({
|
||||
description:
|
||||
"Main section heading - can be 'Testimonials', 'Client Feedback', 'Reviews', or similar",
|
||||
}),
|
||||
|
||||
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: "Logo or brand mark representing the organization",
|
||||
}),
|
||||
|
||||
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),
|
||||
clientPhoto: ImageSchema,
|
||||
})
|
||||
)
|
||||
.min(2)
|
||||
.max(3)
|
||||
.default([
|
||||
{
|
||||
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 businessman headshot",
|
||||
},
|
||||
},
|
||||
{
|
||||
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,
|
||||
clientPhoto: {
|
||||
__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:
|
||||
"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
|
||||
type SchemaType = z.infer<typeof Schema>;
|
||||
|
||||
// Component definition
|
||||
const TestimonialSlide = ({ data }: { data: Partial<SchemaType> }) => {
|
||||
const {
|
||||
sectionTitle,
|
||||
organizationName,
|
||||
brandLogo,
|
||||
testimonialItems,
|
||||
showRatings,
|
||||
showClientPhotos,
|
||||
} = data;
|
||||
|
||||
// Helper function to render stars
|
||||
const renderStars = (rating: number) => {
|
||||
return Array.from({ length: 5 }, (_, i) => (
|
||||
<svg
|
||||
key={i}
|
||||
className={`w-4 h-4 ${
|
||||
i < rating ? "text-yellow-400" : "text-gray-300"
|
||||
}`}
|
||||
fill="currentColor"
|
||||
viewBox="0 0 20 20"
|
||||
>
|
||||
<path d="M9.049 2.927c.3-.921 1.603-.921 1.902 0l1.07 3.292a1 1 0 00.95.69h3.462c.969 0 1.371 1.24.588 1.81l-2.8 2.034a1 1 0 00-.364 1.118l1.07 3.292c.3.921-.755 1.688-1.54 1.118l-2.8-2.034a1 1 0 00-1.175 0l-2.8 2.034c-.784.57-1.838-.197-1.539-1.118l1.07-3.292a1 1 0 00-.364-1.118L2.98 8.72c-.783-.57-.38-1.81.588-1.81h3.461a1 1 0 00.951-.69l1.07-3.292z" />
|
||||
</svg>
|
||||
));
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="aspect-video max-w-[1280px] w-full bg-white relative overflow-hidden">
|
||||
{/* Header Section */}
|
||||
<div className="h-20 bg-teal-600 px-16 py-4 flex justify-between items-center">
|
||||
{/* Title */}
|
||||
{sectionTitle && (
|
||||
<h1 className="text-2xl font-black text-white">{sectionTitle}</h1>
|
||||
)}
|
||||
|
||||
{/* Company Branding */}
|
||||
<div className="flex items-center space-x-3">
|
||||
{brandLogo?.__image_url__ && (
|
||||
<div className="w-8 h-8">
|
||||
<img
|
||||
src={brandLogo.__image_url__}
|
||||
alt={brandLogo.__image_prompt__}
|
||||
className="w-full h-full object-contain"
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
{organizationName && (
|
||||
<span className="text-base font-bold text-white">
|
||||
{organizationName}
|
||||
</span>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Testimonials Content */}
|
||||
<div className="flex-1 px-16 py-12 bg-gray-50">
|
||||
{testimonialItems && testimonialItems.length > 0 && (
|
||||
<div className="grid grid-cols-3 gap-8 h-full">
|
||||
{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];
|
||||
|
||||
return (
|
||||
<div
|
||||
key={index}
|
||||
className={`${bgColor} rounded-lg p-6 flex flex-col`}
|
||||
>
|
||||
{/* Stars Rating */}
|
||||
{showRatings && (
|
||||
<div className="flex space-x-1 mb-4">
|
||||
{renderStars(item.rating)}
|
||||
</div>
|
||||
)}
|
||||
|
||||
{/* Testimonial Text */}
|
||||
<p className="text-base leading-relaxed text-gray-800 mb-6 flex-1">
|
||||
"{item.testimonialText}"
|
||||
</p>
|
||||
|
||||
{/* Client Info */}
|
||||
<div className="flex items-center space-x-4">
|
||||
{/* Client Photo */}
|
||||
{showClientPhotos && item.clientPhoto?.__image_url__ && (
|
||||
<div className="w-12 h-12 rounded-full overflow-hidden flex-shrink-0">
|
||||
<img
|
||||
src={item.clientPhoto.__image_url__}
|
||||
alt={item.clientPhoto.__image_prompt__}
|
||||
className="w-full h-full object-cover"
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{/* Client Details */}
|
||||
<div className="flex-1">
|
||||
<h4 className="text-lg font-bold text-gray-900">
|
||||
{item.clientName}
|
||||
</h4>
|
||||
<p className="text-sm text-gray-600">
|
||||
{item.clientTitle}
|
||||
</p>
|
||||
<p className="text-sm font-semibold text-teal-600">
|
||||
{item.clientCompany}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default TestimonialSlide;
|
||||
|
|
@ -1,229 +0,0 @@
|
|||
import * as z from "zod";
|
||||
|
||||
import { ImageSchema, IconSchema } from "../defaultSchemes";
|
||||
|
||||
export const layoutName = "Thank You Slide";
|
||||
export const layoutId = "thank-you-slide";
|
||||
export const layoutDescription = "A slide with a thank you message";
|
||||
|
||||
// Schema definition
|
||||
export const Schema = z.object({
|
||||
organizationName: z
|
||||
.string()
|
||||
.min(2)
|
||||
.max(30)
|
||||
.default("Your Organization")
|
||||
.meta({
|
||||
description: "Name of the organization, company, or entity presenting",
|
||||
}),
|
||||
|
||||
primaryMessage: z.string().min(3).max(25).default("THANK YOU").meta({
|
||||
description:
|
||||
"Main closing message - can be 'Thank You', 'Questions?', 'Let's Connect', or similar",
|
||||
}),
|
||||
|
||||
secondaryMessage: z
|
||||
.string()
|
||||
.min(5)
|
||||
.max(60)
|
||||
.default("FOR YOUR TIME AND ATTENTION")
|
||||
.meta({
|
||||
description:
|
||||
"Supporting message that completes the primary message or adds context",
|
||||
}),
|
||||
|
||||
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 presenting organization",
|
||||
}),
|
||||
|
||||
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({
|
||||
phoneNumber: "+1-234-567-8900",
|
||||
physicalAddress: "123 Business Ave, City, State 12345",
|
||||
websiteUrl: "www.yourorganization.com",
|
||||
})
|
||||
.meta({
|
||||
description:
|
||||
"Contact information for follow-up communication and connection",
|
||||
}),
|
||||
|
||||
presentationDate: z
|
||||
.string()
|
||||
.min(3)
|
||||
.max(20)
|
||||
.default("Current Month Year")
|
||||
.meta({
|
||||
description:
|
||||
"Date when the presentation was given or document was created",
|
||||
}),
|
||||
|
||||
showDecorations: z.boolean().default(true).meta({
|
||||
description:
|
||||
"Whether to display decorative visual elements like background shapes",
|
||||
}),
|
||||
|
||||
showNavigationArrow: z.boolean().default(true).meta({
|
||||
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",
|
||||
}),
|
||||
});
|
||||
|
||||
// Type inference
|
||||
type SchemaType = z.infer<typeof Schema>;
|
||||
|
||||
// Component definition
|
||||
const ThankYouSlide = ({ data }: { data: Partial<SchemaType> }) => {
|
||||
const {
|
||||
organizationName,
|
||||
primaryMessage,
|
||||
secondaryMessage,
|
||||
brandLogo,
|
||||
contactDetails,
|
||||
presentationDate,
|
||||
showDecorations,
|
||||
showNavigationArrow,
|
||||
showContactInfo,
|
||||
} = data;
|
||||
|
||||
return (
|
||||
<div className="aspect-video max-w-[1280px] w-full bg-white relative overflow-hidden">
|
||||
{/* Header with Logo and Arrow */}
|
||||
<div className="absolute top-0 left-0 right-0 px-16 py-8 flex justify-between items-center z-20">
|
||||
{/* Company Logo and Name */}
|
||||
<div className="flex items-center space-x-3">
|
||||
{brandLogo?.__image_url__ && (
|
||||
<div className="w-10 h-10">
|
||||
<img
|
||||
src={brandLogo.__image_url__}
|
||||
alt={brandLogo.__image_prompt__}
|
||||
className="w-full h-full object-contain"
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
{organizationName && (
|
||||
<span className="text-2xl font-bold text-gray-900">
|
||||
{organizationName}
|
||||
</span>
|
||||
)}
|
||||
</div>
|
||||
|
||||
{/* Arrow Button */}
|
||||
{showNavigationArrow && (
|
||||
<div className="w-12 h-12 bg-teal-600 rounded-full flex items-center justify-center">
|
||||
<svg
|
||||
className="w-6 h-6 text-white"
|
||||
fill="none"
|
||||
stroke="currentColor"
|
||||
viewBox="0 0 24 24"
|
||||
>
|
||||
<path
|
||||
strokeLinecap="round"
|
||||
strokeLinejoin="round"
|
||||
strokeWidth={2}
|
||||
d="M9 5l7 7-7 7"
|
||||
/>
|
||||
</svg>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
|
||||
{/* Decorative Circle */}
|
||||
{showDecorations && (
|
||||
<div className="absolute top-20 right-16 w-96 h-96 bg-yellow-100 rounded-full opacity-60 z-10"></div>
|
||||
)}
|
||||
|
||||
{/* Main Content */}
|
||||
<div className="relative z-15 h-full flex flex-col justify-center px-16">
|
||||
<div className="max-w-4xl">
|
||||
{/* Main Title */}
|
||||
{primaryMessage && (
|
||||
<h1 className="text-8xl lg:text-9xl font-black text-teal-700 leading-none tracking-tight mb-4">
|
||||
{primaryMessage}
|
||||
</h1>
|
||||
)}
|
||||
|
||||
{/* Subtitle with Circle Bullet */}
|
||||
{secondaryMessage && (
|
||||
<div className="flex items-center space-x-4 mb-12">
|
||||
<div className="w-4 h-4 bg-teal-600 rounded-full"></div>
|
||||
<h2 className="text-2xl font-bold text-gray-800 tracking-wide">
|
||||
{secondaryMessage}
|
||||
</h2>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Footer with Contact Info */}
|
||||
{showContactInfo && (
|
||||
<div className="absolute bottom-0 left-0 right-0 px-16 py-8 border-t-2 border-gray-300">
|
||||
<div className="flex justify-between items-center text-gray-700">
|
||||
<div className="flex space-x-16 text-sm">
|
||||
{/* Telephone */}
|
||||
{contactDetails?.phoneNumber && (
|
||||
<div>
|
||||
<div className="font-semibold text-gray-900 mb-1">
|
||||
Telephone
|
||||
</div>
|
||||
<div>{contactDetails.phoneNumber}</div>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{/* Address */}
|
||||
{contactDetails?.physicalAddress && (
|
||||
<div>
|
||||
<div className="font-semibold text-gray-900 mb-1">
|
||||
Address
|
||||
</div>
|
||||
<div>{contactDetails.physicalAddress}</div>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{/* Website */}
|
||||
{contactDetails?.websiteUrl && (
|
||||
<div>
|
||||
<div className="font-semibold text-gray-900 mb-1">
|
||||
Website
|
||||
</div>
|
||||
<div>{contactDetails.websiteUrl}</div>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
|
||||
{/* Presentation Date */}
|
||||
{presentationDate && (
|
||||
<div className="text-right">
|
||||
<div className="text-lg font-bold text-gray-900">
|
||||
{presentationDate}
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default ThankYouSlide;
|
||||
|
|
@ -1,217 +0,0 @@
|
|||
import * as z from "zod";
|
||||
|
||||
import { ImageSchema, IconSchema } from "../defaultSchemes";
|
||||
|
||||
export const layoutName = "Title Slide";
|
||||
export const layoutId = "title-slide";
|
||||
export const layoutDescription = "A slide with a title and subtitle";
|
||||
|
||||
// Schema definition
|
||||
export const Schema = z.object({
|
||||
organizationName: z
|
||||
.string()
|
||||
.min(2)
|
||||
.max(25)
|
||||
.default("Your Organization")
|
||||
.meta({
|
||||
description: "Name of the organization, company, or entity presenting",
|
||||
}),
|
||||
|
||||
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(50)
|
||||
.default("PROFESSIONAL PRESENTATION")
|
||||
.meta({
|
||||
description:
|
||||
"Subtitle that provides context about the presentation type or purpose",
|
||||
}),
|
||||
|
||||
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 presenting organization",
|
||||
}),
|
||||
|
||||
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({
|
||||
phoneNumber: "+1-234-567-8900",
|
||||
physicalAddress: "123 Business Ave, City, State 12345",
|
||||
websiteUrl: "www.yourorganization.com",
|
||||
})
|
||||
.meta({
|
||||
description:
|
||||
"Contact information including phone, address, and website for follow-up communication",
|
||||
}),
|
||||
|
||||
presentationDate: z
|
||||
.string()
|
||||
.min(3)
|
||||
.max(20)
|
||||
.default("Current Month Year")
|
||||
.meta({
|
||||
description: "Date when the presentation is being given or was created",
|
||||
}),
|
||||
|
||||
showDecorations: z.boolean().default(true).meta({
|
||||
description:
|
||||
"Whether to display decorative visual elements like background shapes",
|
||||
}),
|
||||
|
||||
showNavigationArrow: z.boolean().default(true).meta({
|
||||
description:
|
||||
"Whether to show a navigation arrow button for presentation flow",
|
||||
}),
|
||||
});
|
||||
|
||||
// Type inference
|
||||
type SchemaType = z.infer<typeof Schema>;
|
||||
|
||||
// Component definition
|
||||
const ThynkTitleSlide = ({ data }: { data: Partial<SchemaType> }) => {
|
||||
const {
|
||||
organizationName,
|
||||
primaryTitle,
|
||||
secondaryTitle,
|
||||
brandLogo,
|
||||
contactDetails,
|
||||
presentationDate,
|
||||
showDecorations,
|
||||
showNavigationArrow,
|
||||
} = data;
|
||||
|
||||
return (
|
||||
<div className="aspect-video max-w-[1280px] w-full bg-white relative overflow-hidden">
|
||||
{/* Header with Logo and Arrow */}
|
||||
<div className="absolute top-0 left-0 right-0 px-16 py-8 flex justify-between items-center z-20">
|
||||
{/* Company Logo and Name */}
|
||||
<div className="flex items-center space-x-3">
|
||||
{brandLogo?.__image_url__ && (
|
||||
<div className="w-10 h-10">
|
||||
<img
|
||||
src={brandLogo.__image_url__}
|
||||
alt={brandLogo.__image_prompt__}
|
||||
className="w-full h-full object-contain"
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
{organizationName && (
|
||||
<span className="text-2xl font-bold text-gray-900">
|
||||
{organizationName}
|
||||
</span>
|
||||
)}
|
||||
</div>
|
||||
|
||||
{/* Arrow Button */}
|
||||
{showNavigationArrow && (
|
||||
<div className="w-12 h-12 bg-teal-600 rounded-full flex items-center justify-center">
|
||||
<svg
|
||||
className="w-6 h-6 text-white"
|
||||
fill="none"
|
||||
stroke="currentColor"
|
||||
viewBox="0 0 24 24"
|
||||
>
|
||||
<path
|
||||
strokeLinecap="round"
|
||||
strokeLinejoin="round"
|
||||
strokeWidth={2}
|
||||
d="M9 5l7 7-7 7"
|
||||
/>
|
||||
</svg>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
|
||||
{/* Decorative Circle */}
|
||||
{showDecorations && (
|
||||
<div className="absolute top-20 right-16 w-96 h-96 bg-yellow-100 rounded-full opacity-60 z-10"></div>
|
||||
)}
|
||||
|
||||
{/* Main Content */}
|
||||
<div className="relative h-full flex flex-col justify-center px-16">
|
||||
<div className="">
|
||||
{/* Main Title */}
|
||||
{primaryTitle && (
|
||||
<h1 className="text-4xl lg:text-5xl font-black text-teal-700 leading-none tracking-tight mb-4">
|
||||
{primaryTitle}
|
||||
</h1>
|
||||
)}
|
||||
|
||||
{/* Subtitle with Circle Bullet */}
|
||||
{secondaryTitle && (
|
||||
<div className="flex items-center space-x-4 mb-12">
|
||||
<div className="w-4 h-4 bg-teal-600 rounded-full"></div>
|
||||
<h2 className="text-xl font-bold text-gray-800 tracking-wide">
|
||||
{secondaryTitle}
|
||||
</h2>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Footer with Contact Info */}
|
||||
<div className="absolute bottom-0 left-0 right-0 px-16 py-8 border-t-2 border-gray-300">
|
||||
<div className="flex justify-between items-center text-gray-700">
|
||||
<div className="flex space-x-16 text-sm">
|
||||
{/* Telephone */}
|
||||
{contactDetails?.phoneNumber && (
|
||||
<div>
|
||||
<div className="font-semibold text-gray-900 mb-1">
|
||||
Telephone
|
||||
</div>
|
||||
<div>{contactDetails.phoneNumber}</div>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{/* Address */}
|
||||
{contactDetails?.physicalAddress && (
|
||||
<div>
|
||||
<div className="font-semibold text-gray-900 mb-1">Address</div>
|
||||
<div>{contactDetails.physicalAddress}</div>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{/* Website */}
|
||||
{contactDetails?.websiteUrl && (
|
||||
<div>
|
||||
<div className="font-semibold text-gray-900 mb-1">Website</div>
|
||||
<div>{contactDetails.websiteUrl}</div>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
|
||||
{/* Presentation Date */}
|
||||
{presentationDate && (
|
||||
<div className="text-right">
|
||||
<div className="text-lg font-bold text-gray-900">
|
||||
{presentationDate}
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default ThynkTitleSlide;
|
||||
|
|
@ -1,179 +0,0 @@
|
|||
import * as z from "zod";
|
||||
|
||||
import { ImageSchema, IconSchema } from "../defaultSchemes";
|
||||
|
||||
export const layoutName = "What We Believe Slide";
|
||||
export const layoutId = "what-we-believe-slide";
|
||||
export const layoutDescription =
|
||||
"A slide that describes the organization's vision and mission";
|
||||
|
||||
// Schema definition
|
||||
export const Schema = z.object({
|
||||
sectionTitle: z.string().min(3).max(30).default("OUR VISION & MISSION").meta({
|
||||
description:
|
||||
"Main section heading - can be 'Our Values', 'What We Believe', 'Our Philosophy', or similar",
|
||||
}),
|
||||
|
||||
sectionSubtitle: z
|
||||
.string()
|
||||
.min(10)
|
||||
.max(60)
|
||||
.default("GUIDING PRINCIPLES AND CORE BELIEFS")
|
||||
.meta({
|
||||
description:
|
||||
"Supporting subtitle that introduces the organization's foundational concepts",
|
||||
}),
|
||||
|
||||
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 describing the organization's aspirational future goals and impact",
|
||||
}),
|
||||
|
||||
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:
|
||||
"Mission section with title and detailed description of organizational purpose and approach",
|
||||
}),
|
||||
|
||||
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: "Whether to display decorative visual accent elements",
|
||||
}),
|
||||
|
||||
showColorBlocks: z.boolean().default(true).meta({
|
||||
description:
|
||||
"Whether to show colored background sections for visual hierarchy",
|
||||
}),
|
||||
});
|
||||
|
||||
// Type inference
|
||||
type SchemaType = z.infer<typeof Schema>;
|
||||
|
||||
// Component definition
|
||||
const WhatWeBelieveSlide = ({ data }: { data: Partial<SchemaType> }) => {
|
||||
const {
|
||||
sectionTitle,
|
||||
sectionSubtitle,
|
||||
visionStatement,
|
||||
missionContent,
|
||||
supportingVisual,
|
||||
showVisualAccents,
|
||||
showColorBlocks,
|
||||
} = data;
|
||||
|
||||
return (
|
||||
<div className="aspect-video max-w-[1280px] w-full bg-white relative overflow-hidden">
|
||||
{/* Main Content Area */}
|
||||
<div className="h-full flex">
|
||||
{/* Left Side - Image */}
|
||||
<div className="w-2/5 relative">
|
||||
{supportingVisual?.__image_url__ && (
|
||||
<div className="absolute inset-8 shadow-lg">
|
||||
<img
|
||||
src={supportingVisual.__image_url__}
|
||||
alt={supportingVisual.__image_prompt__}
|
||||
className="w-full h-full object-cover rounded-lg"
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{/* Visual Accents */}
|
||||
{showVisualAccents && (
|
||||
<>
|
||||
{/* Decorative circles */}
|
||||
<div className="absolute top-4 right-4 w-6 h-6 bg-teal-600 rounded-full opacity-70 z-20"></div>
|
||||
<div className="absolute bottom-8 left-8 w-4 h-4 bg-yellow-300 rounded-full z-20"></div>
|
||||
</>
|
||||
)}
|
||||
</div>
|
||||
|
||||
{/* Right Side - Content */}
|
||||
<div className="w-3/5 relative bg-white px-16 py-12 flex flex-col justify-start">
|
||||
{/* Title Section */}
|
||||
<div className="mb-8">
|
||||
{sectionTitle && (
|
||||
<h1 className="text-3xl lg:text-4xl font-black text-teal-700 leading-tight mb-4">
|
||||
{sectionTitle}
|
||||
</h1>
|
||||
)}
|
||||
|
||||
{sectionSubtitle && (
|
||||
<p className="text-base font-semibold text-gray-800 tracking-wide mb-8">
|
||||
{sectionSubtitle}
|
||||
</p>
|
||||
)}
|
||||
</div>
|
||||
|
||||
{/* Vision Section */}
|
||||
{visionStatement && (
|
||||
<div className="mb-8">
|
||||
<h2 className="text-xl font-bold text-gray-900 mb-4">Vision</h2>
|
||||
<p className="text-base leading-relaxed text-gray-700">
|
||||
{visionStatement}
|
||||
</p>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{/* Mission Section with Teal Background */}
|
||||
{missionContent && (
|
||||
<div className="bg-teal-600 px-8 py-6 rounded-lg">
|
||||
{missionContent.missionTitle && (
|
||||
<h2 className="text-xl font-bold text-white mb-4">
|
||||
{missionContent.missionTitle}
|
||||
</h2>
|
||||
)}
|
||||
{missionContent.missionDescription && (
|
||||
<p className="text-base leading-relaxed text-gray-100">
|
||||
{missionContent.missionDescription}
|
||||
</p>
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Color blocks for visual hierarchy */}
|
||||
{showColorBlocks && (
|
||||
<>
|
||||
{/* Bottom accent strip */}
|
||||
<div className="absolute bottom-0 left-0 right-0 h-2 bg-teal-600"></div>
|
||||
{/* Left accent */}
|
||||
<div className="absolute top-0 left-0 bottom-0 w-2 bg-yellow-300"></div>
|
||||
</>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default WhatWeBelieveSlide;
|
||||
|
|
@ -1,5 +0,0 @@
|
|||
{
|
||||
"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,
|
||||
"default": false
|
||||
}
|
||||
Loading…
Add table
Reference in a new issue