diff --git a/servers/fastapi/chroma/chroma.sqlite3 b/servers/fastapi/chroma/chroma.sqlite3 index 1b3a19a3..e0e73d71 100644 Binary files a/servers/fastapi/chroma/chroma.sqlite3 and b/servers/fastapi/chroma/chroma.sqlite3 differ diff --git a/servers/nextjs/app/(presentation-generator)/custom-template/components/EachSlide/HtmlEditor.tsx b/servers/nextjs/app/(presentation-generator)/custom-template/components/EachSlide/HtmlEditor.tsx index 284e7b4a..39152d49 100644 --- a/servers/nextjs/app/(presentation-generator)/custom-template/components/EachSlide/HtmlEditor.tsx +++ b/servers/nextjs/app/(presentation-generator)/custom-template/components/EachSlide/HtmlEditor.tsx @@ -1,7 +1,6 @@ 'use client' import React, { useState, useEffect } from "react"; import { Button } from "@/components/ui/button"; -import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card"; import { Save, X, Code } from "lucide-react"; import { ProcessedSlide } from "../../types"; import Editor from 'react-simple-code-editor'; @@ -10,6 +9,7 @@ import 'prismjs/components/prism-clike'; import 'prismjs/components/prism-javascript'; import 'prismjs/components/prism-markup'; import 'prismjs/components/prism-jsx'; +import { Sheet, SheetContent, SheetFooter, SheetHeader, SheetTitle } from "@/components/ui/sheet"; interface HtmlEditorProps { slide: ProcessedSlide; @@ -42,58 +42,56 @@ export const HtmlEditor: React.FC = ({ }; return ( - - - -
- - HTML Editor -
-
- - - -
-
-
- -
-

Edit the HTML code to customize the slide layout.

- {/* Render code editor */} -
+ { if (!open) handleCancel(); }}> + + + + + + HTML Editor + + + + - setHtmlContent(htmlContent)} - highlight={htmlContent => highlight(htmlContent, languages.jsx!,'jsx')} - padding={10} - id="html-editor" - name="html-editor" - - className="container__editor" - /> -
- - - - +
+
+ setHtmlContent(html)} + highlight={code => highlight(code, languages.jsx!, 'jsx')} + padding={10} + id="html-editor" + name="html-editor" + className="container__editor" + /> +
+
+ + +
+
+ + +
+
+
+ + ); }; \ No newline at end of file diff --git a/servers/nextjs/app/(presentation-generator)/outline/components/LayoutSelection.tsx b/servers/nextjs/app/(presentation-generator)/outline/components/LayoutSelection.tsx index e5538cff..de7e79a1 100644 --- a/servers/nextjs/app/(presentation-generator)/outline/components/LayoutSelection.tsx +++ b/servers/nextjs/app/(presentation-generator)/outline/components/LayoutSelection.tsx @@ -56,6 +56,21 @@ const LayoutSelection: React.FC = ({ }); } }, [layoutGroups, selectedLayoutGroup, onSelectLayoutGroup]); + useEffect(() => { + if (loading) { + return; + } + const existingScript = document.querySelector( + 'script[src*="tailwindcss.com"]' + ); + if (!existingScript) { + const script = document.createElement("script"); + script.src = "https://cdn.tailwindcss.com"; + script.async = true; + document.head.appendChild(script); + } + + }, []); if (loading) { return ( diff --git a/servers/nextjs/app/(presentation-generator)/presentation/components/SlideContent.tsx b/servers/nextjs/app/(presentation-generator)/presentation/components/SlideContent.tsx index 6fb374f8..fa5bb4a7 100644 --- a/servers/nextjs/app/(presentation-generator)/presentation/components/SlideContent.tsx +++ b/servers/nextjs/app/(presentation-generator)/presentation/components/SlideContent.tsx @@ -104,7 +104,7 @@ const SlideContent = ({ slide, index, presentationId }: SlideContentProps) => { }, [renderSlideContent, slide, isStreaming]); useEffect(() => { - if (isStreaming || loading) { + if (loading) { return; } if (slide.layout_group.includes("custom")) { diff --git a/servers/nextjs/app/(presentation-generator)/template-preview/[slug]/backup.tsx b/servers/nextjs/app/(presentation-generator)/template-preview/[slug]/backup.tsx deleted file mode 100644 index 4cc4055a..00000000 --- a/servers/nextjs/app/(presentation-generator)/template-preview/[slug]/backup.tsx +++ /dev/null @@ -1,399 +0,0 @@ - "use client"; - - import React, { useEffect, useState, useRef } from "react"; - import { useParams, useRouter } from "next/navigation"; - // import { useGroupLayoutLoader } from '../hooks/useGroupLayoutLoader' - import LoadingStates from "../components/LoadingStates"; - import { Card } from "@/components/ui/card"; - import { Button } from "@/components/ui/button"; - import { ArrowLeft, Edit, Home, Trash2 } from "lucide-react"; - import { useLayout } from "@/app/(presentation-generator)/context/LayoutContext"; - - import html2canvas from "html2canvas"; -import { EditControls } from "../../custom-template/components/EachSlide/EditControls"; -import { useDrawingCanvas } from "../../custom-template/hooks/useDrawingCanvas"; - const GroupLayoutPreview = () => { - const params = useParams(); - const router = useRouter(); - const slug = params.slug as string; - // const isCustom = slug.includes("custom-"); - const isCustom = true; - // Custom hooks - const { - canvasRef, - slideDisplayRef, - strokeWidth, - strokeColor, - eraserMode, - isDrawing, - canvasDimensions, - setCanvasDimensions, - didYourDraw, - handleMouseDown, - handleMouseMove, - handleMouseUp, - handleTouchStart, - handleTouchMove, - handleTouchEnd, - handleClearCanvas, - handleEraserModeChange, - handleStrokeColorChange, - handleStrokeWidthChange, - } = useDrawingCanvas(); - - const slideContentRef = useRef(null); - - const { getFullDataByGroup, loading,refetch } = useLayout(); - const layoutGroup = getFullDataByGroup(slug); - const [isEditMode, setIsEditMode] = useState(false); - const [selectedIndex, setSelectedIndex] = useState(null); - const [prompt, setPrompt] = useState(""); - const [isUpdating, setIsUpdating] = useState(false); - - useEffect(() => { - const existingScript = document.querySelector( - 'script[src*="tailwindcss.com"]' - ); - if (!existingScript) { - const script = document.createElement("script"); - script.src = "https://cdn.tailwindcss.com"; - script.async = true; - document.head.appendChild(script); - } - }, [slug]); - - // Size canvas to content when entering edit mode - useEffect(() => { - if (isEditMode && slideContentRef.current) { - const rect = slideContentRef.current.getBoundingClientRect(); - setCanvasDimensions({ - width: Math.max(rect.width, 800), - height: Math.max(rect.height, 600), - }); - } - }, [isEditMode, setCanvasDimensions]); - - // Handle loading state - if (loading) { - return ; - } - - // Handle empty state - if (!layoutGroup || layoutGroup.length === 0) { - return ; - } - const deleteLayouts = async () => { - const presentationId = slug.replace('custom-',''); - refetch(); - router.back(); - const response = await fetch(`/api/v1/ppt/layout-management/delete-layouts/${presentationId}`, { - method: "DELETE", - }); - if (response.ok) { - router.push("/template-preview"); - } - } - - const handleSave = async ( - slideDisplayRef: React.RefObject, - didYourDraw: boolean - ) => { - if ( - !slideContentRef.current || - !slideDisplayRef.current - ) - return; - - if (!prompt.trim()) { - alert("Please enter a prompt before saving."); - return; - } - - setIsUpdating(true); - - try { - // Take screenshot of the slide display area (slide only) - const slideOnly = await html2canvas(slideDisplayRef.current, { - backgroundColor: "#ffffff", - scale: 1, - logging: false, - useCORS: true, - ignoreElements: (element) => { - return element.tagName === "CANVAS"; - }, - }); - let slideWithCanvas; - if (didYourDraw) { - // Take screenshot of the entire slide display area including canvas - slideWithCanvas = await html2canvas(slideDisplayRef.current, { - backgroundColor: "#ffffff", - scale: 1, - logging: false, - useCORS: true, - }); - } - - - - const currentUiImageBlob = dataURLToBlob( - slideOnly.toDataURL("image/png") - ); - let sketchImageBlob; - if (didYourDraw && slideWithCanvas) { - sketchImageBlob = dataURLToBlob(slideWithCanvas.toDataURL("image/png")); - } - - // download the images - - const currentUiImageUrl = URL.createObjectURL(currentUiImageBlob); - if (currentUiImageUrl) { - const a = document.createElement("a"); - a.href = currentUiImageUrl; - a.download = `slide-current.png`; - a.click(); - } - if (sketchImageBlob) { - const sketchImageUrl = URL.createObjectURL(sketchImageBlob); - if (sketchImageUrl) { - const b = document.createElement("a"); - b.href = sketchImageUrl; - b.download = `slide-sketch.png`; - b.click(); - } - } - - - - - // const formData = new FormData(); - // formData.append( - // "current_ui_image", - // currentUiImageBlob, - // `slide--current.png` - // ); - // if (didYourDraw && slideWithCanvas && sketchImageBlob) { - // formData.append( - // "sketch_image", - // sketchImageBlob, - // `slide-sketch.png` - // ); - // } - // formData.append("html", ''); - // formData.append("prompt", prompt); - - // const response = await fetch("/api/v1/ppt/html-edit/", { - // method: "POST", - // body: formData, - // }); - - // if (!response.ok) { - // throw new Error(`API call failed: ${response.statusText}`); - // } - - // const data = await response.json(); - - - // Exit edit mode - setIsEditMode(false); - setPrompt(""); - } catch (error) { - console.error("Error updating slide:", error); - alert( - `Error updating slide: ${ - error instanceof Error ? error.message : "Unknown error" - }` - ); - } finally { - setIsUpdating(false); - } - }; - const dataURLToBlob = (dataURL: string): Blob => { - const parts = dataURL.split(","); - const contentType = parts[0].match(/:(.*?);/)?.[1] || "image/png"; - const raw = window.atob(parts[1]); - const rawLength = raw.length; - const uInt8Array = new Uint8Array(rawLength); - - for (let i = 0; i < rawLength; ++i) { - uInt8Array[i] = raw.charCodeAt(i); - } - - return new Blob([uInt8Array], { type: contentType }); - }; - - return ( -
- {/* Header */} -
-
- {/* Navigation */} -
- - - {isCustom && } -
- -
-

- {layoutGroup[0].groupName} Layouts -

-

- {layoutGroup.length} layout{layoutGroup.length !== 1 ? "s" : ""} •{" "} - {layoutGroup[0].groupName} -

-
- -
-
- - -
- {/* Edit Controls (no HTML editor) */} - {isCustom && ( - { - setIsUpdating(true); - setTimeout(() => { - setIsUpdating(false); - setIsEditMode(false); - setSelectedIndex(null); - }, 300); - }} - onCancel={() => { - setIsEditMode(false); - setSelectedIndex(null); - handleClearCanvas(); - }} - onStrokeWidthChange={handleStrokeWidthChange} - onStrokeColorChange={handleStrokeColorChange} - onEraserModeChange={handleEraserModeChange} - onClearCanvas={handleClearCanvas} - /> - )} -
- {layoutGroup.map((layout: any, index: number) => { - const { - component: LayoutComponent, - sampleData, - name, - fileName, - } = layout; - - const isSelected = isCustom && isEditMode && selectedIndex === index; - - return ( - - {/* Layout Header */} -
-
-
-

- {name} -

-
- - {fileName} - - - {layoutGroup[0].groupName} - -
-
-
- {isCustom && ( - - )} -
-
-
- - {/* Layout Content */} -
-
- - {isSelected && ( - e.preventDefault()} - /> - )} -
-
-
- ); - })} -
-
- - {/* Footer */} -
-
-
-

- {layoutGroup[0].groupName} • {layoutGroup.length} components -

-
-
-
-
- ); - }; - - export default GroupLayoutPreview; diff --git a/servers/nextjs/app/(presentation-generator)/template-preview/hooks/useGroupLayoutLoader.ts b/servers/nextjs/app/(presentation-generator)/template-preview/hooks/useGroupLayoutLoader.ts deleted file mode 100644 index 7e556239..00000000 --- a/servers/nextjs/app/(presentation-generator)/template-preview/hooks/useGroupLayoutLoader.ts +++ /dev/null @@ -1,361 +0,0 @@ -"use client"; -import React, { useState, useEffect, useRef } from "react"; -import * as Babel from "@babel/standalone"; -import * as z from "zod"; - -import { - LayoutInfo, - LayoutGroup, - GroupedLayoutsResponse, - GroupSetting, -} from "../types"; -import { toast } from "sonner"; - -interface UseGroupLayoutLoaderReturn { - layoutGroup: LayoutGroup | null; - loading: boolean; - error: string | null; - retry: () => void; -} - -// Global cache to store layout groups and avoid re-fetching -const layoutGroupCache = new Map(); -const loadingGroupsCache = new Set(); - -// Extract Babel compilation logic into a utility function -const compileCustomLayout = (layoutCode: string, React: any, z: any) => { - const cleanCode = layoutCode - .replace(/import\s+React\s+from\s+'react';?/g, "") - .replace(/import\s*{\s*z\s*}\s*from\s+'zod';?/g, ""); - - const compiled = Babel.transform(cleanCode, { - presets: [ - ["react", { runtime: "classic" }], - ["typescript", { isTSX: true, allExtensions: true }], - ], - sourceType: "script", - }).code; - - const factory = new Function( - "React", - "z", - ` - ${compiled} - - /* everything declared in the string is in scope here */ - return { - __esModule: true, - default: dynamicSlideLayout, - layoutName, - layoutId, - layoutDescription, - Schema - }; - ` - ); - - return factory(React, z); -}; - -export const useGroupLayoutLoader = ( - groupSlug: string -): UseGroupLayoutLoaderReturn => { - const [layoutGroup, setLayoutGroup] = useState(null); - const [loading, setLoading] = useState(true); - const [error, setError] = useState(null); - const hasMountedRef = useRef(false); - - const loadCustomLayouts = async () => { - try { - // Check if this is a custom group (starts with 'custom-') - if (!groupSlug.startsWith("custom-")) { - return null; - } - - const presentationId = groupSlug.replace("custom-", ""); - - const customLayoutResponse = await fetch( - `/api/v1/ppt/layout-management/get-layouts/${presentationId}` - ); - - if (!customLayoutResponse.ok) { - throw new Error( - `Failed to fetch custom layouts: ${customLayoutResponse.statusText}` - ); - } - - const customLayoutsData = await customLayoutResponse.json(); - const allLayouts = customLayoutsData.layouts; - - const groupLayouts: LayoutInfo[] = []; - const settings: GroupSetting = { - description: `Custom presentation layouts`, - ordered: false, - default: false, - }; - - for (const layoutData of allLayouts) { - try { - // Compile custom layout code - const module = compileCustomLayout(layoutData.layout_code, React, z); - - if (!module.default) { - toast.error(`Custom Layout has no default export`, { - description: - "Please ensure the layout file exports a default component", - }); - console.warn(`❌ Custom Layout has no default export`); - continue; - } - - if (!module.Schema) { - toast.error(`Custom Layout has no Schema export`, { - description: "Please ensure the layout file exports a Schema", - }); - console.warn(`❌ Custom Layout has no Schema export`); - continue; - } - - // Use empty object to let schema apply its default values - const sampleData = module.Schema.parse({}); - - const originalLayoutId = - module.layoutId || - layoutData.layout_name.toLowerCase().replace(/layout$/, ""); - const layoutName = - module.layoutName || - layoutData.layout_name.replace(/([A-Z])/g, " $1").trim(); - - const layoutInfo: LayoutInfo = { - name: layoutName, - component: module.default, - schema: module.Schema, - sampleData, - fileName: layoutData.layout_name, - groupName: groupSlug, - layoutId: originalLayoutId, - }; - - groupLayouts.push(layoutInfo); - } catch (compilationError) { - console.error( - `Failed to compile custom layout ${layoutData.layout_name}:`, - compilationError - ); - toast.error(`Failed to compile ${layoutData.layout_name}`, { - description: "There was an error compiling the custom layout code", - }); - } - } - - if (groupLayouts.length === 0) { - throw new Error( - `No valid custom layouts found in "${groupSlug}" group.` - ); - } - - return { - groupName: groupSlug, - layouts: groupLayouts, - settings, - }; - } catch (error) { - console.error("Error loading custom layouts:", error); - throw error; - } - }; - - const loadGroupLayouts = async () => { - // Check cache first - if (layoutGroupCache.has(groupSlug)) { - setLayoutGroup(layoutGroupCache.get(groupSlug)!); - setLoading(false); - setError(null); - return; - } - - // Prevent multiple simultaneous requests for the same group - if (loadingGroupsCache.has(groupSlug)) { - return; - } - - try { - setLoading(true); - setError(null); - loadingGroupsCache.add(groupSlug); - - // Check if this is a custom group - if (groupSlug.startsWith("custom-")) { - const customGroup = await loadCustomLayouts(); - if (customGroup) { - // Cache the result - layoutGroupCache.set(groupSlug, customGroup); - setLayoutGroup(customGroup); - setError(null); - return; - } - } - - // Load standard layouts - const response = await fetch("/api/layouts"); - if (!response.ok) { - toast.error("Error loading layouts", { - description: response.statusText, - }); - return; - } - const groupedLayoutsData: GroupedLayoutsResponse[] = - await response.json(); - - // Find the specific group by slug - const targetGroupData = groupedLayoutsData.find( - (group) => group.groupName.toLowerCase() === groupSlug.toLowerCase() - ); - - if (!targetGroupData) { - setError(`Group "${groupSlug}" not found`); - return; - } - - const groupLayouts: LayoutInfo[] = []; - - // Use settings from settings.json or provide defaults - const groupSettings: GroupSetting = targetGroupData.settings - ? targetGroupData.settings - : { - description: `${targetGroupData.groupName} presentation layouts`, - ordered: false, - default: false, - }; - - for (const fileName of targetGroupData.files) { - try { - const layoutName = fileName.replace(".tsx", "").replace(".ts", ""); - const module = await import( - `@/presentation-layouts/${targetGroupData.groupName}/${layoutName}` - ); - - if (!module.default) { - toast.error(`${layoutName} has no default export`, { - description: - "Please ensure the layout file exports a default component", - }); - - console.warn(`${layoutName} has no default export`); - return; - } - - if (!module.Schema) { - toast.error(`${layoutName} is missing required Schema export`, { - description: "Please ensure the layout file exports a Schema", - }); - console.error(`${layoutName} is missing required Schema export`); - return; - } - - // Use empty object to let schema apply its default values - const sampleData = module.Schema.parse({}); - const layoutId = - module.layoutId || layoutName.toLowerCase().replace(/layout$/, ""); - - const layoutInfo: LayoutInfo = { - name: layoutName, - component: module.default, - schema: module.Schema, - sampleData, - fileName, - groupName: targetGroupData.groupName, - layoutId, - }; - - groupLayouts.push(layoutInfo); - } catch (importError) { - console.error( - `Failed to import ${fileName} from ${targetGroupData.groupName}:`, - importError - ); - - // Try alternative import path - try { - const layoutName = fileName.replace(".tsx", "").replace(".ts", ""); - const module = await import( - `@/presentation-layouts/${targetGroupData.groupName}/${layoutName}` - ); - - if (module.default && module.Schema) { - const sampleData = module.Schema.parse({}); - // if layoutId is not provided, use the layoutName - const layoutId = - module.layoutId || - layoutName.toLowerCase().replace(/layout$/, ""); - const layoutInfo: LayoutInfo = { - name: layoutName, - component: module.default, - schema: module.Schema, - sampleData, - fileName, - groupName: targetGroupData.groupName, - layoutId, - }; - groupLayouts.push(layoutInfo); - } else { - console.error( - `${layoutName} is missing required exports (default component or Schema)` - ); - } - } catch (altError) { - console.error( - `Alternative import also failed for ${fileName} from ${targetGroupData.groupName}:`, - altError - ); - } - } - } - - if (groupLayouts.length === 0) { - toast.error("No valid layouts found", { - description: `No valid layouts found in "${groupSlug}" group.`, - }); - setError(`No valid layouts found in "${groupSlug}" group.`); - } else { - const group: LayoutGroup = { - groupName: targetGroupData.groupName, - layouts: groupLayouts, - settings: groupSettings, - }; - - // Cache the result - layoutGroupCache.set(groupSlug, group); - setLayoutGroup(group); - setError(null); - } - } catch (error) { - console.error("Error loading group layouts:", error); - setError( - error instanceof Error ? error.message : "Failed to load group layouts" - ); - } finally { - setLoading(false); - loadingGroupsCache.delete(groupSlug); - } - }; - - const retry = () => { - hasMountedRef.current = false; - loadGroupLayouts(); - }; - - useEffect(() => { - if (groupSlug && !hasMountedRef.current) { - hasMountedRef.current = true; - loadGroupLayouts(); - } - }, [groupSlug]); - - return { - layoutGroup, - loading, - error, - retry, - }; -}; diff --git a/servers/nextjs/app/(presentation-generator)/template-preview/hooks/useLayoutLoader.ts b/servers/nextjs/app/(presentation-generator)/template-preview/hooks/useLayoutLoader.ts deleted file mode 100644 index 014e8514..00000000 --- a/servers/nextjs/app/(presentation-generator)/template-preview/hooks/useLayoutLoader.ts +++ /dev/null @@ -1,157 +0,0 @@ -'use client' -import { useState, useEffect } from 'react' - -import { LayoutInfo, LayoutGroup, GroupedLayoutsResponse, GroupSetting } from '../types' -import { toast } from 'sonner' - -interface UseLayoutLoaderReturn { - layoutGroups: LayoutGroup[] - layouts: LayoutInfo[] - loading: boolean - error: string | null - retry: () => void -} - -export const useLayoutLoader = (): UseLayoutLoaderReturn => { - const [layoutGroups, setLayoutGroups] = useState([]) - const [layouts, setLayouts] = useState([]) - const [loading, setLoading] = useState(true) - const [error, setError] = useState(null) - - const loadAllLayouts = async () => { - try { - setLoading(true) - setError(null) - - const response = await fetch('/api/templates') - if (!response.ok) { - toast.error('Error loading templates', { - description: response.statusText, - }) - return - } - const groupedLayoutsData: GroupedLayoutsResponse[] = await response.json() - const loadedGroups: LayoutGroup[] = [] - const allLayouts: LayoutInfo[] = [] - - for (const groupData of groupedLayoutsData) { - const groupLayouts: LayoutInfo[] = [] - - const groupSettings: GroupSetting = groupData.settings ? groupData.settings : { - description: `${groupData.groupName} presentation templates`, - ordered: false, - default: false - } - - for (const fileName of groupData.files) { - try { - const layoutName = fileName.replace('.tsx', '').replace('.ts', '') - const module = await import(`@/presentation-layouts/${groupData.groupName}/${layoutName}`) - - if (!module.default) { - toast.error(`${layoutName} has no default export`, { - description: 'Please ensure the template file exports a default component', - }) - console.warn(`${layoutName} has no default export`) - throw new Error(`${layoutName} has no default export`) - } - - if (!module.Schema) { - toast.error(`${layoutName} is missing required Schema export`, { - description: 'Please ensure the template file exports a Schema', - }) - console.error(`${layoutName} is missing required Schema export`) - throw new Error(`${layoutName} is missing required Schema export`) - } - - const sampleData = module.Schema.parse({}) - const layoutId = module.layoutId || layoutName.toLowerCase().replace(/layout$/, '') - - const layoutInfo: LayoutInfo = { - name: layoutName, - component: module.default, - schema: module.Schema, - sampleData, - fileName, - groupName: groupData.groupName, - layoutId - } - - groupLayouts.push(layoutInfo) - allLayouts.push(layoutInfo) - - } catch (importError) { - console.error(`Failed to import ${fileName} from ${groupData.groupName}:`, importError) - - try { - const layoutName = fileName.replace('.tsx', '').replace('.ts', '') - const module = await import(`@/presentation-layouts/${groupData.groupName}/${layoutName}`) - - if (module.default && module.Schema) { - const sampleData = module.Schema.parse({}) - const layoutId = module.layoutId || layoutName.toLowerCase().replace(/layout$/, '') - - const layoutInfo: LayoutInfo = { - name: layoutName, - component: module.default, - schema: module.Schema, - sampleData, - fileName, - groupName: groupData.groupName, - layoutId - } - groupLayouts.push(layoutInfo) - allLayouts.push(layoutInfo) - } else { - console.error(`${layoutName} is missing required exports (default component or Schema)`) - } - } catch (altError) { - console.error(`Alternative import also failed for ${fileName} from ${groupData.groupName}:`, altError) - } - } - } - - if (groupLayouts.length > 0) { - loadedGroups.push({ - groupName: groupData.groupName, - layouts: groupLayouts, - settings: groupSettings - }) - } - } - - if (allLayouts.length === 0) { - toast.error('No valid templates found', { - description: 'Make sure your template files export both a default component and a Schema.', - }) - setError('No valid templates found. Make sure your template files export both a default component and a Schema.') - } else { - setLayoutGroups(loadedGroups) - setLayouts(allLayouts) - setError(null) - } - - } catch (error) { - console.error('Error loading templates:', error) - setError(error instanceof Error ? error.message : 'Failed to load templates') - } finally { - setLoading(false) - } - } - - const retry = () => { - loadAllLayouts() - } - - useEffect(() => { - loadAllLayouts() - }, []) - - return { - layoutGroups, - layouts, - loading, - error, - retry - } -} \ No newline at end of file diff --git a/servers/nextjs/app/(presentation-generator)/template-preview/page.tsx b/servers/nextjs/app/(presentation-generator)/template-preview/page.tsx index 2938de74..1aadf884 100644 --- a/servers/nextjs/app/(presentation-generator)/template-preview/page.tsx +++ b/servers/nextjs/app/(presentation-generator)/template-preview/page.tsx @@ -108,7 +108,7 @@ const LayoutPreview = () => { ))} router.push(`/custom-layout`)} + onClick={() => router.push(`/custom-template`)} >
diff --git a/servers/nextjs/app/globals.css b/servers/nextjs/app/globals.css index 4f8e4ba1..5b890cba 100644 --- a/servers/nextjs/app/globals.css +++ b/servers/nextjs/app/globals.css @@ -443,7 +443,7 @@ thead { .container__content_area { tab-size: 4ch; - max-height: 400px; + /* max-height: 600px; */ overflow: auto; margin: 1.67em 0; }