diff --git a/servers/nextjs/app/(presentation-generator)/context/LayoutContext.tsx b/servers/nextjs/app/(presentation-generator)/context/LayoutContext.tsx index 20f2c292..59476f2d 100644 --- a/servers/nextjs/app/(presentation-generator)/context/LayoutContext.tsx +++ b/servers/nextjs/app/(presentation-generator)/context/LayoutContext.tsx @@ -3,7 +3,8 @@ import React, { createContext, useContext, useEffect, useState, ReactNode } from import dynamic from 'next/dynamic'; import { toast } from "sonner"; import * as z from 'zod'; - +import { useDispatch } from 'react-redux'; +import { setLayoutLoading } from '@/store/slices/presentationGeneration'; export interface LayoutInfo { id: string; name?: string; @@ -60,6 +61,7 @@ export const LayoutProvider: React.FC<{ children: ReactNode }> = ({ children }) const [loading, setLoading] = useState(false); const [error, setError] = useState(null); const [isPreloading, setIsPreloading] = useState(false); + const dispatch = useDispatch(); const buildData = async (groupedLayoutsData: GroupedLayoutsResponse[]) => { const layouts: LayoutInfo[] = []; @@ -171,6 +173,7 @@ export const LayoutProvider: React.FC<{ children: ReactNode }> = ({ children }) try { setLoading(true); setError(null); + dispatch(setLayoutLoading(true)); const layoutResponse = await fetch('/api/layouts'); @@ -197,6 +200,7 @@ export const LayoutProvider: React.FC<{ children: ReactNode }> = ({ children }) setError(errorMessage); console.error('💥 Error loading layouts:', err); } finally { + dispatch(setLayoutLoading(false)); setLoading(false); } }; diff --git a/servers/nextjs/app/(presentation-generator)/hooks/useGroupLayouts.tsx b/servers/nextjs/app/(presentation-generator)/hooks/useGroupLayouts.tsx index 3624ea76..05e0a3ff 100644 --- a/servers/nextjs/app/(presentation-generator)/hooks/useGroupLayouts.tsx +++ b/servers/nextjs/app/(presentation-generator)/hooks/useGroupLayouts.tsx @@ -36,7 +36,6 @@ export const useGroupLayouts = () => { // Render slide content with group validation, automatic Tiptap text editing, and editable images/icons const renderSlideContent = useMemo(() => { return (slide: any, isEditMode: boolean) => { - console.time("renderSlideContent"); const Layout = getGroupLayout(slide.layout, slide.layout_group); if (!Layout) { return ( @@ -76,7 +75,6 @@ export const useGroupLayouts = () => { ); } - console.timeEnd("renderSlideContent"); return ; }; diff --git a/servers/nextjs/app/(presentation-generator)/presentation/hooks/useAutoSave.tsx b/servers/nextjs/app/(presentation-generator)/presentation/hooks/useAutoSave.tsx index 963b17cc..75e9273d 100644 --- a/servers/nextjs/app/(presentation-generator)/presentation/hooks/useAutoSave.tsx +++ b/servers/nextjs/app/(presentation-generator)/presentation/hooks/useAutoSave.tsx @@ -13,7 +13,7 @@ export const useAutoSave = ({ debounceMs = 2000, enabled = true, }: UseAutoSaveOptions = {}) => { - const { presentationData, isStreaming, isLoading } = useSelector( + const { presentationData, isStreaming, isLoading, isLayoutLoading } = useSelector( (state: RootState) => state.presentationGeneration ); @@ -61,7 +61,7 @@ export const useAutoSave = ({ // Effect to trigger auto-save when presentation data changes useEffect(() => { - if (!enabled || !presentationData || isStreaming || isLoading) return; + if (!enabled || !presentationData || isStreaming || isLoading || isLayoutLoading) return; // Trigger debounced save debouncedSave(presentationData); diff --git a/servers/nextjs/app/layout.tsx b/servers/nextjs/app/layout.tsx index a90f163d..39aab20f 100644 --- a/servers/nextjs/app/layout.tsx +++ b/servers/nextjs/app/layout.tsx @@ -87,6 +87,7 @@ export default function RootLayout({ className={`${inter.variable} ${roboto.variable} ${instrument_sans.variable} antialiased`} > + {children} diff --git a/servers/nextjs/app/page.tsx b/servers/nextjs/app/page.tsx index 6f38ab3d..fff5d4b2 100644 --- a/servers/nextjs/app/page.tsx +++ b/servers/nextjs/app/page.tsx @@ -1,9 +1,9 @@ -import Home from '../components/Home' +import Home from "@/components/Home" const page = () => { - return ( - - ) + return ( + + ) } -export default page +export default page \ No newline at end of file diff --git a/servers/nextjs/app/settings/SettingPage.tsx b/servers/nextjs/app/settings/SettingPage.tsx index ecc6ee64..ece5f16b 100644 --- a/servers/nextjs/app/settings/SettingPage.tsx +++ b/servers/nextjs/app/settings/SettingPage.tsx @@ -62,9 +62,9 @@ const SettingsPage = () => { isDisabled: true, text: "Saving Configuration..." })); - + await handleSaveLLMConfig(llmConfig); - + if (llmConfig.LLM === "ollama" && llmConfig.OLLAMA_MODEL) { const isPulled = await checkIfSelectedOllamaModelIsPulled(llmConfig.OLLAMA_MODEL); if (!isPulled) { @@ -72,7 +72,7 @@ const SettingsPage = () => { await handleModelDownload(); } } - + toast.info("Configuration saved successfully"); setIsLoading(false); setButtonState(prev => ({ diff --git a/servers/nextjs/presentation-layouts/classic/Type10SlideLayout.tsx b/servers/nextjs/presentation-layouts/classic/Type10SlideLayout.tsx index 409d7213..a0b68ade 100644 --- a/servers/nextjs/presentation-layouts/classic/Type10SlideLayout.tsx +++ b/servers/nextjs/presentation-layouts/classic/Type10SlideLayout.tsx @@ -112,8 +112,8 @@ interface Type10SlideLayoutProps { } const Type10SlideLayout: React.FC = ({ data: slideData }) => { - const { title, items, chartData, chartType = 'line', color = '#3b82f6', dataKey = 'value', categoryKey = 'name', showLegend = false, showTooltip = true } = slideData; - + const { title, items, data, chartType = 'line', color = '#3b82f6', dataKey = 'value', categoryKey = 'name', showLegend = false, showTooltip = true } = slideData; + const chartData = data || []; const renderChart = () => { const commonProps = { data: chartData, @@ -171,7 +171,7 @@ const Type10SlideLayout: React.FC = ({ data: slideData } case 'pie': return ( - + {showTooltip && } />} {showLegend && } />} = ({ dat key={`timeline-${index}`} className="relative z-10 w-12 h-12 rounded-full bg-blue-600 px-1 text-white flex items-center justify-center font-bold text-lg" > - `0${index + 1}` + {index + 1} ))} diff --git a/servers/nextjs/presentation-layouts/classic/Type4SlideLayout.tsx b/servers/nextjs/presentation-layouts/classic/Type4SlideLayout.tsx index 7b863ff1..da9ac603 100644 --- a/servers/nextjs/presentation-layouts/classic/Type4SlideLayout.tsx +++ b/servers/nextjs/presentation-layouts/classic/Type4SlideLayout.tsx @@ -142,7 +142,7 @@ const Type4SlideLayout: React.FC = ({ data: slideData }) case 'pie': return ( - + {showTooltip && } />} {showLegend && } />} = ({ data: slideData }) => { - const { title, items, chartData, chartType = 'line', color = '#3b82f6', dataKey = 'value', categoryKey = 'name', showLegend = false, showTooltip = true } = slideData; + const { title, items, data, chartType = 'line', color = '#3b82f6', dataKey = 'value', categoryKey = 'name', showLegend = false, showTooltip = true } = slideData; + const chartData = data || []; const renderChart = () => { const commonProps = { data: chartData, @@ -159,23 +160,27 @@ const Type9SlideLayout: React.FC = ({ data: slideData }) case 'pie': return ( - - {showTooltip && } />} - {showLegend && } />} - `${name} ${(percent * 100).toFixed(0)}%`} - > - {chartData.map((entry: any, index: number) => ( - - ))} - - + + + {showTooltip && } />} + {showLegend && } />} + `${name} ${(percent * 100).toFixed(0)}%`} + > + {chartData && chartData.map((entry: any, index: number) => ( + + ))} + + + ); case 'scatter': diff --git a/servers/nextjs/presentation-layouts/professional/AboutUsSlide.tsx b/servers/nextjs/presentation-layouts/professional/AboutUsSlide.tsx index b19ac0e9..5b6d9465 100644 --- a/servers/nextjs/presentation-layouts/professional/AboutUsSlide.tsx +++ b/servers/nextjs/presentation-layouts/professional/AboutUsSlide.tsx @@ -1,17 +1,10 @@ import * as z from "zod"; -// Note: -// If you want to use Image and Icon Must Use these Schemas. -// Image and icons are only media support for PDF and PPTX. + import { ImageSchema, IconSchema } from "../defaultSchemes"; // Schema definition export const Schema = z.object({ - // Note: - // Schema fields - // Each fields must have a default value (this is important for Layout-preview) - // Each fields must have a meta description - // Each fields must have a min and max length, length must support the layout design. - // Each Array fields must have a min and max length + sectionTitle: z.string() .min(3) diff --git a/servers/nextjs/presentation-layouts/professional/OurServiceSlide.tsx b/servers/nextjs/presentation-layouts/professional/OurServiceSlide.tsx index 15c9dedf..10e6b520 100644 --- a/servers/nextjs/presentation-layouts/professional/OurServiceSlide.tsx +++ b/servers/nextjs/presentation-layouts/professional/OurServiceSlide.tsx @@ -21,6 +21,16 @@ export const Schema = z.object({ 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" @@ -47,7 +57,7 @@ type SchemaType = z.infer; // Component definition const OurServiceSlide = ({ data }: { data: Partial }) => { - const { sectionTitle, sectionSubtitle, serviceHighlight, showVisualAccents, showColorBlocks } = data; + const { sectionTitle, sectionSubtitle, serviceHighlight, showVisualAccents, showColorBlocks, bulletPoints } = data; return (
@@ -67,6 +77,18 @@ const OurServiceSlide = ({ data }: { data: Partial }) => {

)} +
+ + {bulletPoints && bulletPoints.map((point, index) => ( +
+
+
+

{point}

+
+
+ ))} +
+ {/* Visual Accents */} {showVisualAccents && ( <> diff --git a/servers/nextjs/store/slices/presentationGeneration.ts b/servers/nextjs/store/slices/presentationGeneration.ts index d049d18c..f16cbfe3 100644 --- a/servers/nextjs/store/slices/presentationGeneration.ts +++ b/servers/nextjs/store/slices/presentationGeneration.ts @@ -30,12 +30,14 @@ interface PresentationGenerationState { error: string | null; presentationData: PresentationData | null; isSlidesRendered: boolean; + isLayoutLoading: boolean; } const initialState: PresentationGenerationState = { presentation_id: null, outlines: [], isSlidesRendered: false, + isLayoutLoading: false, isLoading: false, isStreaming: null, error: null, @@ -53,6 +55,9 @@ const presentationGenerationSlice = createSlice({ setLoading: (state, action: PayloadAction) => { state.isLoading = action.payload; }, + setLayoutLoading: (state, action: PayloadAction) => { + state.isLayoutLoading = action.payload; + }, // Presentation ID setPresentationId: (state, action: PayloadAction) => { state.presentation_id = action.payload; @@ -365,6 +370,7 @@ const presentationGenerationSlice = createSlice({ export const { setStreaming, setLoading, + setLayoutLoading, setPresentationId, setSlidesRendered, setError,