Refactor Site Builder Integration and Update Docker Configuration

- Merged the site builder functionality into the main app, enhancing the SiteBuilderWizard component with new steps and improved UI.
- Updated the Docker Compose configuration by removing the separate site builder service and integrating its functionality into the igny8_sites service.
- Enhanced Vite configuration to support code-splitting for builder routes, optimizing loading times.
- Updated package dependencies to include new libraries for state management and form handling.
This commit is contained in:
IGNY8 VPS (Salman)
2025-11-18 10:35:30 +00:00
parent 8508af37c7
commit 3ea519483d
19 changed files with 1637 additions and 91 deletions

View File

@@ -1,16 +1,52 @@
import { BrowserRouter, Routes, Route } from 'react-router-dom';
import SiteRenderer from './pages/SiteRenderer';
import { lazy, Suspense } from 'react';
import { BrowserRouter, Routes, Route, Navigate } from 'react-router-dom';
import ProtectedRoute from './shared/ProtectedRoute';
import BuilderLayout from './builder/components/layout/BuilderLayout';
// Lazy load builder pages (code-split to avoid loading in public sites)
const WizardPage = lazy(() => import('./builder/pages/wizard/WizardPage'));
const PreviewCanvas = lazy(() => import('./builder/pages/preview/PreviewCanvas'));
const SiteDashboard = lazy(() => import('./builder/pages/dashboard/SiteDashboard'));
// Renderer pages (load immediately for public sites)
const SiteRenderer = lazy(() => import('./renderer/pages/SiteRenderer'));
// Loading component
const LoadingFallback = () => (
<div style={{ display: 'flex', justifyContent: 'center', alignItems: 'center', minHeight: '100vh' }}>
<div>Loading...</div>
</div>
);
function App() {
return (
<BrowserRouter>
<Routes>
<Route path="/:siteId/*" element={<SiteRenderer />} />
<Route path="/" element={<div>IGNY8 Sites Renderer</div>} />
</Routes>
<Suspense fallback={<LoadingFallback />}>
<Routes>
{/* Public Site Renderer Routes (No Auth) */}
<Route path="/:siteId/*" element={<SiteRenderer />} />
<Route path="/" element={<div>IGNY8 Sites Renderer</div>} />
{/* Builder Routes (Auth Required) */}
<Route
path="/builder/*"
element={
<ProtectedRoute>
<BuilderLayout>
<Routes>
<Route path="/" element={<WizardPage />} />
<Route path="preview" element={<PreviewCanvas />} />
<Route path="dashboard" element={<SiteDashboard />} />
<Route path="*" element={<Navigate to="/builder" replace />} />
</Routes>
</BuilderLayout>
</ProtectedRoute>
}
/>
</Routes>
</Suspense>
</BrowserRouter>
);
}
export default App;

View File

@@ -1,29 +1,28 @@
:root {
font-family: Inter, system-ui, Avenir, Helvetica, Arial, sans-serif;
line-height: 1.5;
font-weight: 400;
color-scheme: light dark;
color: rgba(255, 255, 255, 0.87);
background-color: #242424;
font-family: 'Inter', 'Inter var', system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
color: #0f172a;
background-color: #f5f7fb;
font-synthesis: none;
text-rendering: optimizeLegibility;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}
*,
*::before,
*::after {
box-sizing: border-box;
}
body {
margin: 0;
display: flex;
place-items: center;
min-width: 320px;
min-height: 100vh;
background: #f5f7fb;
}
#root {
width: 100%;
margin: 0 auto;
text-align: center;
button {
font-family: inherit;
}
a {
color: inherit;
}

View File

@@ -1,11 +1,10 @@
import { StrictMode } from 'react'
import { createRoot } from 'react-dom/client'
import App from './App.tsx'
import './index.css'
import { StrictMode } from 'react';
import { createRoot } from 'react-dom/client';
import App from './App.tsx';
import './index.css';
createRoot(document.getElementById('root')!).render(
<StrictMode>
<App />
</StrictMode>,
)
);

View File

@@ -0,0 +1,44 @@
import { useEffect, useState } from 'react';
import { Navigate, useLocation } from 'react-router-dom';
/**
* ProtectedRoute component that checks for authentication token.
* Redirects to login if not authenticated.
*/
interface ProtectedRouteProps {
children: React.ReactNode;
}
export default function ProtectedRoute({ children }: ProtectedRouteProps) {
const [isAuthenticated, setIsAuthenticated] = useState<boolean | null>(null);
const location = useLocation();
useEffect(() => {
// Check for JWT token in localStorage
const token = localStorage.getItem('auth-storage');
if (token) {
try {
const authData = JSON.parse(token);
setIsAuthenticated(!!authData?.state?.token);
} catch {
setIsAuthenticated(false);
}
} else {
setIsAuthenticated(false);
}
}, []);
if (isAuthenticated === null) {
// Still checking authentication
return <div>Checking authentication...</div>;
}
if (!isAuthenticated) {
// Redirect to login (or main app login page)
// In production, this might redirect to app.igny8.com/login
return <Navigate to="/login" state={{ from: location }} replace />;
}
return <>{children}</>;
}