presenton/servers/nextjs/app/presentation-templates/Code/TableSlide.tsx
sudipnext c7860127f2 feat: add support for optional embedded Ollama and enhance database migration handling
- Updated docker-compose.yml to allow disabling embedded Ollama via environment variable.
- Refactored Dockerfile and Dockerfile.dev for improved dependency management and installation process.
- Enhanced FastAPI migration scripts to handle orphaned Alembic revisions and added new database migration logic.
- Improved error handling in background tasks and Codex authentication endpoints.
- Added support for font file uploads with better validation and extraction of font names.
- Introduced new image search functionality with support for Pexels and Pixabay APIs.
2026-04-15 15:39:35 +05:45

160 lines
5.2 KiB
TypeScript

import * as z from "zod";
const DEFAULT_TABLE_COLUMNS = ["Feature", "Column 1", "Column 2", "Column 3"];
const DEFAULT_ROWS = [
{ cells: ["Component-based", "check", "check", "check"] },
{ cells: ["TypeScript Support", "check", "check", "check"] },
{ cells: ["Learning Curve", "Medium", "Easy", "Steep"] },
{ cells: ["Bundle Size", "40KB", "34KB", "167KB"] },
{ cells: ["Performance", "Excellent", "Excellent", "Good"] },
{ cells: ["Community Size", "Huge", "Large", "Large"] },
];
const ComparisonRowSchema = z.object({
cells: z.array(z.string().max(24)).min(1).max(6).meta({
description: "Cell values for this row in left-to-right order. Match the number of table columns.",
}),
});
export const slideLayoutId = "table-slide";
export const slideLayoutName = "Table Slide";
export const slideLayoutDescription =
"A slide with title and a table.";
export const Schema = z.object({
title: z.string().min(6).max(18).default("Comparison").meta({
description: "Slide title shown above the table.",
}),
tableColumns: z.array(z.string().max(18)).min(1).max(6).meta({
description: "Table columns shown in the first row.",
}).default(DEFAULT_TABLE_COLUMNS),
rows: z
.array(ComparisonRowSchema)
.min(1)
.max(6)
.default(DEFAULT_ROWS)
.meta({
description: "Table rows where each row contains a cells array matching the table columns.",
}),
}).superRefine((value, ctx) => {
value.rows.forEach((row, rowIndex) => {
if (row.cells.length !== value.tableColumns.length) {
ctx.addIssue({
code: z.ZodIssueCode.custom,
path: ["rows", rowIndex, "cells"],
message: "Each row must contain the same number of cells as tableColumns.",
});
}
});
});
export type SchemaType = z.infer<typeof Schema>;
function getGridTemplateColumns(columnCount: number) {
if (columnCount <= 1) {
return "minmax(0, 1fr)";
}
return `minmax(0, 1.4fr) repeat(${columnCount - 1}, minmax(0, 1fr))`;
}
function renderCell(value: string, isFirstColumn: boolean) {
if (!isFirstColumn && value && value.toLowerCase() === "check") {
return <span className="text-[26px] px-[32px]" style={{ color: "var(--graph-2,#37f08e)" }}></span>;
}
return (
<span
className="text-[18px] px-[32px]"
style={{
color: isFirstColumn
? "var(--background-text,#d5dcff)"
: "var(--background-text,#CAD5E2)",
}}
>
{value}
</span>
);
}
const CodeSlide05ComparisonTable = ({ data }: { data: Partial<SchemaType> }) => {
const tableColumns = data.tableColumns?.length ? data.tableColumns : DEFAULT_TABLE_COLUMNS;
const rows = data.rows?.length ? data.rows : DEFAULT_ROWS;
const gridTemplateColumns = getGridTemplateColumns(tableColumns.length);
return (
<>
<link href="https://fonts.googleapis.com/css2?family=Nunito+Sans:ital,opsz,wght@0,6..12,200..1000;1,6..12,200..1000&display=swap" rel="stylesheet" />
<div
className="relative h-[720px] w-[1280px] overflow-hidden p-[53px]"
style={{
backgroundColor: "var(--background-color,#101B37)",
fontFamily: "var(--body-font-family,Nunito Sans)",
}}
>
<h2 className="text-[64px] font-medium" style={{ color: "var(--background-text,#ffffff)" }}>{data.title}</h2>
<div
className="mt-[22px] min-h-0 flex-1 rounded-[16px] border"
style={{
backgroundColor: "var(--card-color,#0F172BCC)",
borderColor: "var(--stroke,#1D293D80)",
}}
>
<div
className="grid items-center"
style={{
color: "var(--background-text,#8ea1da)",
gridTemplateColumns,
}}
>
{tableColumns.map((column, columnIndex) => (
<p
key={`${column}-${columnIndex}`}
className="px-[32px] py-[16px] text-[18px] text-center border-b border-r"
style={{
color: "var(--background-text,#ffffff)",
borderColor: "var(--stroke,#1D293D80)",
borderRightWidth: columnIndex === tableColumns.length - 1 ? "0px" : undefined,
}}
>
{column}
</p>
))}
</div>
<div className="">
{rows.map((row, rowIndex) => (
<div
key={`row-${rowIndex}`}
className="grid"
style={{
gridTemplateColumns,
}}
>
{row.cells.map((cell, cellIndex) => (
<div
key={`row-${rowIndex}-cell-${cellIndex}`}
className="flex items-center justify-center border-b border-r px-[20px] py-[20px] text-center"
style={{
borderColor: "var(--stroke,#1D293D80)",
borderRightWidth: cellIndex === row.cells.length - 1 ? "0px" : undefined,
}}
>
{renderCell(cell, cellIndex === 0)}
</div>
))}
</div>
))}
</div>
</div>
</div>
</>
);
};
export default CodeSlide05ComparisonTable;