From 16aec6b5e88792f70f94690960448e5c8a6ba20c Mon Sep 17 00:00:00 2001 From: sauravniraula Date: Fri, 1 Aug 2025 21:41:28 +0545 Subject: [PATCH] feat(nextjs): adds new classic dark layout --- servers/fastapi/chroma/chroma.sqlite3 | Bin 4329472 -> 4329472 bytes .../classic-dark/1-TitleSlide.tsx | 87 ++++++++++ .../classic-dark/2-ChartAndMetrics.tsx | 160 ++++++++++++++++++ .../classic-dark/3-BarGraph.tsx | 152 +++++++++++++++++ .../classic-dark/4-Comparison.tsx | 120 +++++++++++++ .../classic-dark/5-Metrics.tsx | 141 +++++++++++++++ .../6-BulletPointWithDescription.tsx | 103 +++++++++++ .../classic-dark/settings.json | 5 + 8 files changed, 768 insertions(+) create mode 100644 servers/nextjs/presentation-layouts/classic-dark/1-TitleSlide.tsx create mode 100644 servers/nextjs/presentation-layouts/classic-dark/2-ChartAndMetrics.tsx create mode 100644 servers/nextjs/presentation-layouts/classic-dark/3-BarGraph.tsx create mode 100644 servers/nextjs/presentation-layouts/classic-dark/4-Comparison.tsx create mode 100644 servers/nextjs/presentation-layouts/classic-dark/5-Metrics.tsx create mode 100644 servers/nextjs/presentation-layouts/classic-dark/6-BulletPointWithDescription.tsx create mode 100644 servers/nextjs/presentation-layouts/classic-dark/settings.json diff --git a/servers/fastapi/chroma/chroma.sqlite3 b/servers/fastapi/chroma/chroma.sqlite3 index 8f76332c15cb4e2f3d53c1ee9ff9f3b84661ae1b..838ef47853a5ba4d0517990baf7b0af183480a45 100644 GIT binary patch delta 306 zcmWm9HxdD10Dw_z<*;(jIp>^yj2Yt?4x%ulprp_%T)-&YL9^oqj^b0i1HAq1q}}5j zkv5m;O4>ZO_l8a=Z_U+~**#s~wW61WtT7){aa4r_EoA7RhXF>IV1@-&*kFeO2b^%h z4G+BV!H)of2qBCJqKF}m1d>Q0jSRBLA&&xzD4~oBs;Hrk2AXK0jSjl#p^pKE7-5VF QrkLUXo@4P+#j^GJ0exJ3!2kdN delta 300 zcmWm9HxdB>061H8liY&_s1 z3!7_VEo`2 + +interface TitleSlideLayoutProps { + data: Partial +} + +const TitleSlideLayout: React.FC = ({ data: slideData }) => { + const { title, subtitle, presenter, date, image } = slideData; + + return ( +
+ +
+ {/* Left side - Text content */} +
+ {/* Title */} + {title && ( +

+ {title} +

+ )} + + {/* Subtitle */} + {subtitle && ( +

+ {subtitle} +

+ )} + + {/* Presenter and date */} +
+ Presenter: {presenter} | {date} +
+
+ + {/* Right side - Visual elements */} +
+ {image && ( +
+ {image.__image_prompt__} +
+ )} +
+
+
+ ) +} + +export default TitleSlideLayout diff --git a/servers/nextjs/presentation-layouts/classic-dark/2-ChartAndMetrics.tsx b/servers/nextjs/presentation-layouts/classic-dark/2-ChartAndMetrics.tsx new file mode 100644 index 00000000..806dac67 --- /dev/null +++ b/servers/nextjs/presentation-layouts/classic-dark/2-ChartAndMetrics.tsx @@ -0,0 +1,160 @@ +import React from 'react' +import * as z from "zod"; +import { ChartContainer, ChartLegend, ChartLegendContent, ChartTooltip, ChartTooltipContent } from '@/components/ui/chart'; +import { PieChart, Pie, Cell } from "recharts"; + +export const layoutId = 'classic-dark-piechart-and-metrics' +export const layoutName = 'Classic Dark Pie Chart and Metrics' +export const layoutDescription = 'A modern slide with dark background, metrics on the left, and pie chart visualization on the right.' + +const chartDataSchema = z.object({ + name: z.string().meta({ description: "Data point name" }), + value: z.number().meta({ description: "Data point value" }), +}); + +const pieChartAndMetricsSchema = z.object({ + title: z.string().min(3).max(100).default('Introduction to Nepal\'s Trade').meta({ + description: "Main title of the slide", + }), + description: z.string().min(10).max(200).default('Nepal\'s landlocked geography heavily influences its trade, fostering reliance on India and China.').meta({ + description: "Description text", + }), + metrics: z.array(z.object({ + label: z.string().meta({ description: "Metric label" }), + value: z.string().meta({ description: "Metric value" }), + percentage: z.string().optional().meta({ description: "Optional percentage" }), + })).min(2).max(4).default([ + { label: 'Exports (2023)', value: '$2.85 billion', percentage: '6.76% of GDP' }, + { label: 'Imports (2023)', value: '$17.39 billion', percentage: '42.64% of GDP' }, + { label: 'GDP (2022)', value: '$40.83 billion' }, + { label: 'Trade Deficit (2022)', value: '-$12.44 billion' }, + ]).meta({ + description: "List of key metrics", + }), + chartData: z.array(chartDataSchema).min(2).max(4).default([ + { name: 'Imports', value: 42.64 }, + { name: 'Exports', value: 6.76 }, + { name: 'Other GDP', value: 50.6 }, + ]).meta({ + description: "Pie chart data", + }), + showLegend: z.boolean().default(true).meta({ + description: "Whether to show chart legend", + }), + showTooltip: z.boolean().default(true).meta({ + description: "Whether to show chart tooltip", + }), +}) + +const chartConfig = { + value: { + label: "Value", + }, + name: { + label: "Name", + }, +}; + +const CHART_COLORS = [ + '#8b5cf6', + '#3b82f6', + '#a855f7', +]; + +export const Schema = pieChartAndMetricsSchema + +export type PieChartAndMetricsData = z.infer + +interface PieChartAndMetricsLayoutProps { + data: Partial +} + +const PieChartAndMetricsLayout: React.FC = ({ data: slideData }) => { + const { title, description, metrics, chartData, showLegend = true, showTooltip = true } = slideData; + + const CustomLegend = () => ( +
+ {chartData?.map((entry, index) => ( +
+
+ {entry.name} +
+ ))} +
+ ); + + const renderPieChart = () => { + return ( + + {showTooltip && } />} + `${name} ${(percent * 100).toFixed(0)}%`} + labelLine={false} + fontSize={18} + > + {chartData?.map((entry, index) => ( + + ))} + + + ); + }; + + return ( +
+ +
+ {/* Left side - Text content and metrics */} +
+ {/* Title */} + {title && ( +

+ {title} +

+ )} + + {/* Description */} + {description && ( +

+ {description} +

+ )} + + {/* Metrics */} + {metrics && metrics.length > 0 && ( +
+ {metrics.map((metric, index) => ( +
+ • {metric.label}: + {metric.value} + {metric.percentage && ( + ({metric.percentage}) + )} +
+ ))} +
+ )} +
+ + {/* Right side - Chart */} +
+
+ + {renderPieChart()} + + {showLegend && } +
+
+
+
+ ) +} + +export default PieChartAndMetricsLayout \ No newline at end of file diff --git a/servers/nextjs/presentation-layouts/classic-dark/3-BarGraph.tsx b/servers/nextjs/presentation-layouts/classic-dark/3-BarGraph.tsx new file mode 100644 index 00000000..7f73ef69 --- /dev/null +++ b/servers/nextjs/presentation-layouts/classic-dark/3-BarGraph.tsx @@ -0,0 +1,152 @@ +import React from 'react' +import * as z from "zod"; +import { ChartContainer, ChartLegend, ChartLegendContent, ChartTooltip, ChartTooltipContent } from '@/components/ui/chart'; +import { BarChart, Bar, XAxis, YAxis, CartesianGrid, Cell } from "recharts"; + +export const layoutId = 'classic-dark-bar-graph' +export const layoutName = 'Classic Dark Bar Graph' +export const layoutDescription = 'A modern slide with dark background, gradient title, bar chart visualization, and footer text.' + +const barDataSchema = z.object({ + name: z.string().meta({ description: "Product name" }), + value: z.number().meta({ description: "Export value in millions" }), +}); + +const barGraphSchema = z.object({ + title: z.string().min(3).max(100).default('Export Overview: Key Products').meta({ + description: "Main title of the slide", + }), + description: z.string().min(10).max(150).default('Nepal\'s total exports were $1.3 billion in 2022, a 21% decrease from 2021, but showed a 47.5% YoY increase by Nov 2024.').meta({ + description: "Description text", + }), + chartData: z.array(barDataSchema).min(2).max(6).default([ + { name: 'Soybean Oil (non-crude)', value: 180 }, + { name: 'Palm Oil (non-crude)', value: 180 }, + { name: 'Carpets/Textile Floor...', value: 80 }, + { name: 'Cardamom', value: 50 }, + { name: 'Felt Products', value: 40 }, + ]).meta({ + description: "Bar chart data", + }), + showLegend: z.boolean().default(true).meta({ + description: "Whether to show chart legend", + }), + showTooltip: z.boolean().default(true).meta({ + description: "Whether to show chart tooltip", + }), +}) + +const chartConfig = { + value: { + label: "Value ($M)", + }, + name: { + label: "Product", + }, +}; + +const BAR_COLORS = [ + '#8b5cf6', // Dark purple for top products + '#8b5cf6', // Dark purple for top products + '#a855f7', // Light purple for other products + '#a855f7', // Light purple for other products + '#a855f7', // Light purple for other products +]; + +export const Schema = barGraphSchema + +export type BarGraphData = z.infer + +interface BarGraphLayoutProps { + data: Partial +} + +const BarGraphLayout: React.FC = ({ data: slideData }) => { + const { title, description, chartData, showLegend = false, showTooltip = true } = slideData; + + const CustomLegend = () => ( +
+ {chartData?.map((entry, index) => ( +
+
+ {entry.name} +
+ ))} +
+ ); + + const renderBarChart = () => { + return ( + + + { + if (value.length > 15) { + return value.substring(0, 15) + '...'; + } + return value; + }} + /> + `$${value.toFixed(0)}.00`} + /> + {showTooltip && } />} + + {chartData?.map((entry, index) => ( + + ))} + + + ); + }; + + return ( +
+ +
+ {/* Header section */} +
+ {/* Title */} + {title && ( +

+ {title} +

+ )} + + {/* Description */} + {description && ( +

+ {description} +

+ )} +
+ + {/* Chart section */} +
+
+ + {renderBarChart()} + + {showLegend && } +
+
+
+
+ ) +} + +export default BarGraphLayout \ No newline at end of file diff --git a/servers/nextjs/presentation-layouts/classic-dark/4-Comparison.tsx b/servers/nextjs/presentation-layouts/classic-dark/4-Comparison.tsx new file mode 100644 index 00000000..3fa9bec6 --- /dev/null +++ b/servers/nextjs/presentation-layouts/classic-dark/4-Comparison.tsx @@ -0,0 +1,120 @@ +import React from 'react' +import * as z from "zod"; +import { ImageSchema } from '@/presentation-layouts/defaultSchemes'; + +export const layoutId = 'classic-dark-comparison' +export const layoutName = 'Classic Dark Comparison' +export const layoutDescription = 'A modern slide with dark background, image on the left (2/5), and comparison content on the right (3/5).' + +const comparisonItemSchema = z.object({ + name: z.string().min(3).max(30).meta({ description: "Commodity name" }), + value: z.string().min(3).max(30).meta({ description: "Value" }), + when: z.string().min(3).max(30).meta({ description: "When the value was recorded" }), + details: z.string().min(3).max(50).optional().meta({ description: "Additional details" }), +}); + +const comparisonSectionSchema = z.object({ + title: z.string().min(3).max(50).meta({ description: "Section title" }), + items: z.array(comparisonItemSchema).min(1).max(3).meta({ description: "List of items in the section" }), +}); + +const comparisonSchema = z.object({ + title: z.string().min(3).max(100).default('Key Commodities in Focus').meta({ + description: "Main title of the slide", + }), + comparisonSections: z.array(comparisonSectionSchema).min(2).max(2).default([ + { + title: 'Exports', + items: [ + { name: 'Soybean Oil', value: '$186.91 million', when: '2022' }, + { name: 'Cardamom', value: '$46.64 million', when: '2022', details: 'primarily to India' }, + ] + }, + { + title: 'Imports', + items: [ + { name: 'Crude Soybean Oil', value: '$347.77 million', when: '2022' }, + { name: 'Petroleum Products', value: '$3.15 billion', when: '2022', details: '22% of total imports' }, + { name: 'Vehicles/Parts', value: '$526 million', when: '2022', details: 'down 45% from 2021' }, + ] + } + ]).meta({ + description: "Comparison sections with title and data items", + }), + image: ImageSchema.default({ + __image_url__: 'https://images.pexels.com/photos/9669089/pexels-photo-9669089.jpeg', + __image_prompt__: 'Map of South Asia showing Nepal and neighboring countries with trade routes highlighted' + }).meta({ + description: "Comparison visualization image", + }), +}) + +export const Schema = comparisonSchema + +export type ComparisonData = z.infer + +interface ComparisonLayoutProps { + data: Partial +} + +const ComparisonLayout: React.FC = ({ data: slideData }) => { + const { title, comparisonSections, image } = slideData; + + return ( +
+ +
+ {/* Left side - Image (2/5) */} +
+ {image && ( +
+ {image.__image_prompt__} +
+ )} +
+ + {/* Right side - Content (3/5) */} +
+ {/* Title */} + {title && ( +

+ {title} +

+ )} + + {/* Comparison Sections */} +
+ {comparisonSections && comparisonSections.map((section, sectionIndex) => ( +
+

+ {section.title} +

+ {section.items && section.items.length > 0 && ( +
+ {section.items.map((item, index) => ( +
+ {item.name}: {item.value} ({item.when}) + {item.details && ( + , {item.details} + )} +
+ ))} +
+ )} +
+ ))} +
+
+
+
+ ) +} + +export default ComparisonLayout \ No newline at end of file diff --git a/servers/nextjs/presentation-layouts/classic-dark/5-Metrics.tsx b/servers/nextjs/presentation-layouts/classic-dark/5-Metrics.tsx new file mode 100644 index 00000000..7e7db991 --- /dev/null +++ b/servers/nextjs/presentation-layouts/classic-dark/5-Metrics.tsx @@ -0,0 +1,141 @@ +import React from 'react' +import * as z from "zod"; +import { IconSchema } from '@/presentation-layouts/defaultSchemes'; + +export const layoutId = 'classic-dark-metrics' +export const layoutName = 'Classic Dark Metrics' +export const layoutDescription = 'A modern slide with dark background, metric cards arranged in a grid with icons and data.' + +const metricItemSchema = z.object({ + title: z.string().min(3).max(50).meta({ description: "Metric title" }), + value: z.string().min(3).max(30).meta({ description: "Metric value" }), + percentage: z.string().min(3).max(30).meta({ description: "Percentage value" }), + icon: IconSchema.meta({ description: "Icon for the metric" }), +}); + +const metricsSchema = z.object({ + title: z.string().min(3).max(100).default('Top Export Destinations').meta({ + description: "Main title of the slide", + }), + description: z.string().min(10).max(200).default('Nepal exports 760 products to 132 countries, with a strong focus on regional trade.').meta({ + description: "Description text", + }), + metrics: z.array(metricItemSchema).min(2).max(6).default([ + { + title: 'India', + value: '$935 million', + percentage: '71.93%', + icon: { + __icon_url__: '/static/icons/placeholder.png', + __icon_query__: 'star rating' + } + }, + { + title: 'United States', + value: '$147 million', + percentage: '11.32%', + icon: { + __icon_url__: '/static/icons/placeholder.png', + __icon_query__: 'flag country' + } + }, + { + title: 'Germany', + value: '$33 million', + percentage: '2.51%', + icon: { + __icon_url__: '/static/icons/placeholder.png', + __icon_query__: 'user person' + } + }, + { + title: 'Turkey', + value: '$26 million', + percentage: '2.01%', + icon: { + __icon_url__: '/static/icons/placeholder.png', + __icon_query__: 'pen tool' + } + }, + { + title: 'United Kingdom', + value: '$24 million', + percentage: '1.83%', + icon: { + __icon_url__: '/static/icons/placeholder.png', + __icon_query__: 'message chat' + } + }, + ]).meta({ + description: "Metric cards data", + }), +}) + +export const Schema = metricsSchema + +export type MetricsData = z.infer + +interface MetricsLayoutProps { + data: Partial +} + +const MetricsLayout: React.FC = ({ data: slideData }) => { + const { title, description, metrics } = slideData; + + return ( +
+ +
+ {/* Header section */} +
+ {/* Title */} + {title && ( +

+ {title} +

+ )} + + {/* Description */} + {description && ( +

+ {description} +

+ )} +
+ + {/* Metrics Cards Grid */} +
+
+ {metrics && metrics.map((metric, index) => ( +
+ {/* Metric Card with overlapping icon */} +
+ {/* Icon overlapping the top */} +
+ {metric.icon.__icon_query__} +
+ + {/* Content with top padding for icon space */} +
+

+ {metric.title} +

+

+ {metric.value} ({metric.percentage}) +

+
+
+
+ ))} +
+
+
+
+ ) +} + +export default MetricsLayout \ No newline at end of file diff --git a/servers/nextjs/presentation-layouts/classic-dark/6-BulletPointWithDescription.tsx b/servers/nextjs/presentation-layouts/classic-dark/6-BulletPointWithDescription.tsx new file mode 100644 index 00000000..cfcb6b32 --- /dev/null +++ b/servers/nextjs/presentation-layouts/classic-dark/6-BulletPointWithDescription.tsx @@ -0,0 +1,103 @@ +import React from 'react' +import * as z from "zod"; +import { ImageSchema } from '@/presentation-layouts/defaultSchemes'; + +export const layoutId = 'classic-dark-bullet-point-with-description' +export const layoutName = 'Classic Dark Bullet Point with Description' +export const layoutDescription = 'A modern slide with dark background, image on the left (2/5), and bullet points with descriptions in boxes on the right (3/5).' + +const bulletPointSchema = z.object({ + title: z.string().min(3).max(80).meta({ description: "Bullet point title" }), + content: z.string().min(10).max(150).meta({ description: "Bullet point content (max 150 characters)" }), +}); + +const bulletPointWithDescriptionSchema = z.object({ + title: z.string().min(3).max(100).default('Trade Policies and Challenges').meta({ + description: "Main title of the slide", + }), + bulletPoints: z.array(bulletPointSchema).min(2).max(3).default([ + { + title: 'Tariffs', + content: 'Effectively Applied Tariff (2022): 11.59%. Most Favored Nation Tariff (2022): 12.87%. Duty-free imports: $412.11 million.' + }, + { + title: 'Forex Reserves', + content: '$8.18 billion in 2019, covering 8 months of imports.' + }, + { + title: 'Import Ban Impact', + content: 'Luxury goods ban (Apr-Dec 2022) cut deficit by 15.45% but reduced export earnings by 21.44%.' + } + ]).meta({ + description: "Bullet points with descriptions (max 3 items)", + }), + image: ImageSchema.default({ + __image_url__: 'https://images.pexels.com/photos/9669089/pexels-photo-9669089.jpeg', + __image_prompt__: 'Stylized mountainous landscape with trade arrows and network connections, dark gradient background with orange sun and purple mountains' + }).meta({ + description: "Visual representation image", + }), +}) + +export const Schema = bulletPointWithDescriptionSchema + +export type BulletPointWithDescriptionData = z.infer + +interface BulletPointWithDescriptionLayoutProps { + data: Partial +} + +const BulletPointWithDescriptionLayout: React.FC = ({ data: slideData }) => { + const { title, bulletPoints, image } = slideData; + + return ( +
+ +
+ {/* Left side - Image (2/5) */} +
+ {image && ( +
+ {image.__image_prompt__} +
+ )} +
+ + {/* Right side - Content (3/5) */} +
+ {/* Title */} + {title && ( +

+ {title} +

+ )} + + {/* Bullet Points */} + {bulletPoints && bulletPoints.length > 0 && ( +
+ {bulletPoints.map((point, index) => ( +
+

+ {point.title} +

+

+ {point.content} +

+
+ ))} +
+ )} +
+
+
+ ) +} + +export default BulletPointWithDescriptionLayout \ No newline at end of file diff --git a/servers/nextjs/presentation-layouts/classic-dark/settings.json b/servers/nextjs/presentation-layouts/classic-dark/settings.json new file mode 100644 index 00000000..2e888eab --- /dev/null +++ b/servers/nextjs/presentation-layouts/classic-dark/settings.json @@ -0,0 +1,5 @@ +{ + "description": "Classic dark layout for presentations", + "ordered": false, + "default": false +} \ No newline at end of file