feat: add prerendering support and improve component imports
- Introduced a new PrerenderHome component for development testing. - Updated App.js to conditionally render the PrerenderHome based on the route. - Refactored several components to use ES6 import/export syntax for consistency. - Enhanced AppContent to manage dynamic theming and added a development-only FAB for prerender testing. - Minor adjustments to props in PrerenderCategory for clarity.
This commit is contained in:
64
src/App.js
64
src/App.js
@@ -1,4 +1,5 @@
|
|||||||
import React, { useState, useEffect, lazy, Suspense } from "react";
|
import React, { useState, useEffect, lazy, Suspense } from "react";
|
||||||
|
import { createTheme } from "@mui/material/styles";
|
||||||
import {
|
import {
|
||||||
Routes,
|
Routes,
|
||||||
Route,
|
Route,
|
||||||
@@ -14,6 +15,7 @@ import Fab from "@mui/material/Fab";
|
|||||||
import Tooltip from "@mui/material/Tooltip";
|
import Tooltip from "@mui/material/Tooltip";
|
||||||
import SmartToyIcon from "@mui/icons-material/SmartToy";
|
import SmartToyIcon from "@mui/icons-material/SmartToy";
|
||||||
import PaletteIcon from "@mui/icons-material/Palette";
|
import PaletteIcon from "@mui/icons-material/Palette";
|
||||||
|
import ScienceIcon from "@mui/icons-material/Science";
|
||||||
|
|
||||||
import { CarouselProvider } from "./contexts/CarouselContext.js";
|
import { CarouselProvider } from "./contexts/CarouselContext.js";
|
||||||
import config from "./config.js";
|
import config from "./config.js";
|
||||||
@@ -60,11 +62,13 @@ const ThcTestPage = lazy(() => import(/* webpackChunkName: "thc-test" */ "./page
|
|||||||
// Lazy load payment success page
|
// Lazy load payment success page
|
||||||
const PaymentSuccess = lazy(() => import(/* webpackChunkName: "payment" */ "./components/PaymentSuccess.js"));
|
const PaymentSuccess = lazy(() => import(/* webpackChunkName: "payment" */ "./components/PaymentSuccess.js"));
|
||||||
|
|
||||||
|
// Lazy load prerender component (development testing only)
|
||||||
|
const PrerenderHome = lazy(() => import(/* webpackChunkName: "prerender-home" */ "./PrerenderHome.js"));
|
||||||
|
|
||||||
// Import theme from separate file to reduce main bundle size
|
// Import theme from separate file to reduce main bundle size
|
||||||
import defaultTheme from "./theme.js";
|
import defaultTheme from "./theme.js";
|
||||||
// Lazy load theme customizer for development only
|
// Lazy load theme customizer for development only
|
||||||
const ThemeCustomizerDialog = lazy(() => import(/* webpackChunkName: "theme-customizer" */ "./components/ThemeCustomizerDialog.js"));
|
const ThemeCustomizerDialog = lazy(() => import(/* webpackChunkName: "theme-customizer" */ "./components/ThemeCustomizerDialog.js"));
|
||||||
import { createTheme } from "@mui/material/styles";
|
|
||||||
|
|
||||||
const deleteMessages = () => {
|
const deleteMessages = () => {
|
||||||
console.log("Deleting messages");
|
console.log("Deleting messages");
|
||||||
@@ -72,13 +76,16 @@ const deleteMessages = () => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
const AppContent = ({ currentTheme, onThemeChange }) => {
|
const AppContent = ({ currentTheme, dynamicTheme, onThemeChange }) => {
|
||||||
// State to manage chat visibility
|
// State to manage chat visibility
|
||||||
const [isChatOpen, setChatOpen] = useState(false);
|
const [isChatOpen, setChatOpen] = useState(false);
|
||||||
const [authVersion, setAuthVersion] = useState(0);
|
const [authVersion, setAuthVersion] = useState(0);
|
||||||
// @note Theme customizer state for development mode
|
// @note Theme customizer state for development mode
|
||||||
const [isThemeCustomizerOpen, setThemeCustomizerOpen] = useState(false);
|
const [isThemeCustomizerOpen, setThemeCustomizerOpen] = useState(false);
|
||||||
|
|
||||||
|
// Remove duplicate theme state since it's passed as prop
|
||||||
|
// const [dynamicTheme, setDynamicTheme] = useState(createTheme(defaultTheme));
|
||||||
|
|
||||||
// Get current location
|
// Get current location
|
||||||
const location = useLocation();
|
const location = useLocation();
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
@@ -138,6 +145,35 @@ const AppContent = ({ currentTheme, onThemeChange }) => {
|
|||||||
// Check if we're in development mode
|
// Check if we're in development mode
|
||||||
const isDevelopment = process.env.NODE_ENV === "development";
|
const isDevelopment = process.env.NODE_ENV === "development";
|
||||||
|
|
||||||
|
// Check if current route is a prerender test route
|
||||||
|
const isPrerenderTestRoute = isDevelopment && location.pathname === "/prerenderTest/home";
|
||||||
|
|
||||||
|
// If it's a prerender test route, render it standalone without app layout
|
||||||
|
if (isPrerenderTestRoute) {
|
||||||
|
return (
|
||||||
|
<LanguageProvider i18n={i18n}>
|
||||||
|
<ThemeProvider theme={dynamicTheme}>
|
||||||
|
<CssBaseline />
|
||||||
|
<Suspense fallback={
|
||||||
|
<Box
|
||||||
|
sx={{
|
||||||
|
display: "flex",
|
||||||
|
justifyContent: "center",
|
||||||
|
alignItems: "center",
|
||||||
|
minHeight: "100vh",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<CircularProgress color="primary" />
|
||||||
|
</Box>
|
||||||
|
}>
|
||||||
|
<PrerenderHome />
|
||||||
|
</Suspense>
|
||||||
|
</ThemeProvider>
|
||||||
|
</LanguageProvider>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Regular app layout for all other routes
|
||||||
return (
|
return (
|
||||||
<Box
|
<Box
|
||||||
sx={{
|
sx={{
|
||||||
@@ -208,10 +244,10 @@ const AppContent = ({ currentTheme, onThemeChange }) => {
|
|||||||
|
|
||||||
{/* Admin page */}
|
{/* Admin page */}
|
||||||
<Route path="/admin" element={<AdminPage/>} />
|
<Route path="/admin" element={<AdminPage/>} />
|
||||||
|
|
||||||
{/* Admin Users page */}
|
{/* Admin Users page */}
|
||||||
<Route path="/admin/users" element={<UsersPage/>} />
|
<Route path="/admin/users" element={<UsersPage/>} />
|
||||||
|
|
||||||
{/* Admin Server Logs page */}
|
{/* Admin Server Logs page */}
|
||||||
<Route path="/admin/logs" element={<ServerLogsPage/>} />
|
<Route path="/admin/logs" element={<ServerLogsPage/>} />
|
||||||
|
|
||||||
@@ -312,6 +348,25 @@ const AppContent = ({ currentTheme, onThemeChange }) => {
|
|||||||
</Tooltip>
|
</Tooltip>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
|
{/* Development-only Prerender Test FAB */}
|
||||||
|
{isDevelopment && (
|
||||||
|
<Tooltip title="Test Prerender Home" placement="left">
|
||||||
|
<Fab
|
||||||
|
color="warning"
|
||||||
|
aria-label="prerender test"
|
||||||
|
size="small"
|
||||||
|
sx={{
|
||||||
|
position: "fixed",
|
||||||
|
bottom: 31,
|
||||||
|
right: 75,
|
||||||
|
}}
|
||||||
|
onClick={() => navigate('/prerenderTest/home')}
|
||||||
|
>
|
||||||
|
<ScienceIcon sx={{ fontSize: "1.2rem" }} />
|
||||||
|
</Fab>
|
||||||
|
</Tooltip>
|
||||||
|
)}
|
||||||
|
|
||||||
{/* Development-only Theme Customizer Dialog */}
|
{/* Development-only Theme Customizer Dialog */}
|
||||||
{isDevelopment && isThemeCustomizerOpen && (
|
{isDevelopment && isThemeCustomizerOpen && (
|
||||||
<Suspense fallback={
|
<Suspense fallback={
|
||||||
@@ -361,6 +416,7 @@ const App = () => {
|
|||||||
<CssBaseline />
|
<CssBaseline />
|
||||||
<AppContent
|
<AppContent
|
||||||
currentTheme={currentTheme}
|
currentTheme={currentTheme}
|
||||||
|
dynamicTheme={dynamicTheme}
|
||||||
onThemeChange={handleThemeChange}
|
onThemeChange={handleThemeChange}
|
||||||
/>
|
/>
|
||||||
</ThemeProvider>
|
</ThemeProvider>
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ import { Box, AppBar, Toolbar, Container, Typography, Grid, Card, CardMedia, Car
|
|||||||
import Footer from './components/Footer.js';
|
import Footer from './components/Footer.js';
|
||||||
import { Logo, SearchBar, CategoryList } from './components/header/index.js';
|
import { Logo, SearchBar, CategoryList } from './components/header/index.js';
|
||||||
|
|
||||||
const PrerenderCategory = ({ categoryId, categoryName, categorySeoName, productData }) => {
|
const PrerenderCategory = ({ categoryId, categoryName, categorySeoName: _categorySeoName, productData }) => {
|
||||||
const products = productData?.products || [];
|
const products = productData?.products || [];
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
|||||||
@@ -1,13 +1,12 @@
|
|||||||
const React = require('react');
|
import React from 'react';
|
||||||
const {
|
import {
|
||||||
Box,
|
Box,
|
||||||
AppBar,
|
AppBar,
|
||||||
Toolbar,
|
Toolbar,
|
||||||
Container
|
Container
|
||||||
} = require('@mui/material');
|
} from '@mui/material';
|
||||||
const Footer = require('./components/Footer.js').default;
|
import Footer from './components/Footer.js';
|
||||||
const { Logo, CategoryList } = require('./components/header/index.js');
|
import { Logo, CategoryList } from './components/header/index.js';
|
||||||
const MainPageLayout = require('./components/MainPageLayout.js').default;
|
|
||||||
|
|
||||||
|
|
||||||
class PrerenderHome extends React.Component {
|
class PrerenderHome extends React.Component {
|
||||||
@@ -65,4 +64,4 @@ class PrerenderHome extends React.Component {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
module.exports = { default: PrerenderHome };
|
export default PrerenderHome;
|
||||||
@@ -1,13 +1,13 @@
|
|||||||
const React = require('react');
|
import React from 'react';
|
||||||
const {
|
import {
|
||||||
Box,
|
Box,
|
||||||
AppBar,
|
AppBar,
|
||||||
Toolbar,
|
Toolbar,
|
||||||
Container
|
Container
|
||||||
} = require('@mui/material');
|
} from '@mui/material';
|
||||||
const Footer = require('./components/Footer.js').default;
|
import Footer from './components/Footer.js';
|
||||||
const { Logo } = require('./components/header/index.js');
|
import { Logo } from './components/header/index.js';
|
||||||
const NotFound404 = require('./pages/NotFound404.js').default;
|
import NotFound404 from './pages/NotFound404.js';
|
||||||
|
|
||||||
class PrerenderNotFound extends React.Component {
|
class PrerenderNotFound extends React.Component {
|
||||||
render() {
|
render() {
|
||||||
@@ -89,4 +89,4 @@ class PrerenderNotFound extends React.Component {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
module.exports = { default: PrerenderNotFound };
|
export default PrerenderNotFound;
|
||||||
@@ -1,20 +1,17 @@
|
|||||||
const React = require('react');
|
import React from 'react';
|
||||||
const {
|
import {
|
||||||
Container,
|
Container,
|
||||||
Typography,
|
Typography,
|
||||||
Card,
|
|
||||||
CardMedia,
|
|
||||||
Grid,
|
|
||||||
Box,
|
Box,
|
||||||
Chip,
|
Chip,
|
||||||
Stack,
|
Stack,
|
||||||
AppBar,
|
AppBar,
|
||||||
Toolbar,
|
Toolbar,
|
||||||
Button
|
Button
|
||||||
} = require('@mui/material');
|
} from '@mui/material';
|
||||||
const Footer = require('./components/Footer.js').default;
|
import Footer from './components/Footer.js';
|
||||||
const { Logo } = require('./components/header/index.js');
|
import { Logo } from './components/header/index.js';
|
||||||
const ProductImage = require('./components/ProductImage.js').default;
|
import ProductImage from './components/ProductImage.js';
|
||||||
|
|
||||||
// Utility function to clean product names by removing trailing number in parentheses
|
// Utility function to clean product names by removing trailing number in parentheses
|
||||||
const cleanProductName = (name) => {
|
const cleanProductName = (name) => {
|
||||||
@@ -46,9 +43,6 @@ class PrerenderProduct extends React.Component {
|
|||||||
|
|
||||||
const product = productData.product;
|
const product = productData.product;
|
||||||
const attributes = productData.attributes || [];
|
const attributes = productData.attributes || [];
|
||||||
const mainImage = product.pictureList && product.pictureList.trim()
|
|
||||||
? `/assets/images/prod${product.pictureList.split(',')[0].trim()}.jpg`
|
|
||||||
: '/assets/images/nopicture.jpg';
|
|
||||||
|
|
||||||
// Format price with tax
|
// Format price with tax
|
||||||
const priceWithTax = new Intl.NumberFormat("de-DE", {
|
const priceWithTax = new Intl.NumberFormat("de-DE", {
|
||||||
@@ -563,4 +557,4 @@ class PrerenderProduct extends React.Component {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
module.exports = { default: PrerenderProduct };
|
export default PrerenderProduct;
|
||||||
@@ -1,17 +1,11 @@
|
|||||||
const React = require('react');
|
import React from 'react';
|
||||||
const {
|
import {
|
||||||
Box,
|
|
||||||
AppBar,
|
|
||||||
Toolbar,
|
|
||||||
Container,
|
|
||||||
Typography,
|
Typography,
|
||||||
List,
|
List,
|
||||||
ListItem,
|
ListItem,
|
||||||
ListItemText
|
ListItemText
|
||||||
} = require('@mui/material');
|
} from '@mui/material';
|
||||||
const Footer = require('./components/Footer.js').default;
|
import LegalPage from './pages/LegalPage.js';
|
||||||
const { Logo, CategoryList } = require('./components/header/index.js');
|
|
||||||
const LegalPage = require('./pages/LegalPage.js').default;
|
|
||||||
|
|
||||||
const PrerenderSitemap = ({ categoryData }) => {
|
const PrerenderSitemap = ({ categoryData }) => {
|
||||||
// Process category data to flatten the hierarchy
|
// Process category data to flatten the hierarchy
|
||||||
@@ -134,4 +128,4 @@ const PrerenderSitemap = ({ categoryData }) => {
|
|||||||
return React.createElement(LegalPage, { title: 'Sitemap', content: content });
|
return React.createElement(LegalPage, { title: 'Sitemap', content: content });
|
||||||
};
|
};
|
||||||
|
|
||||||
module.exports = { default: PrerenderSitemap };
|
export default PrerenderSitemap;
|
||||||
292
src/pages/PrerenderTestPage.js
Normal file
292
src/pages/PrerenderTestPage.js
Normal file
@@ -0,0 +1,292 @@
|
|||||||
|
import React, { useState, lazy, Suspense } from 'react';
|
||||||
|
import { useParams, useNavigate } from 'react-router-dom';
|
||||||
|
import {
|
||||||
|
Box,
|
||||||
|
Container,
|
||||||
|
Typography,
|
||||||
|
Paper,
|
||||||
|
Button,
|
||||||
|
Grid,
|
||||||
|
Card,
|
||||||
|
CardContent,
|
||||||
|
CardActions,
|
||||||
|
Chip,
|
||||||
|
Alert,
|
||||||
|
CircularProgress
|
||||||
|
} from '@mui/material';
|
||||||
|
import { styled } from '@mui/material/styles';
|
||||||
|
import ScienceIcon from '@mui/icons-material/Science';
|
||||||
|
|
||||||
|
// Lazy load prerender components for testing
|
||||||
|
const PrerenderHome = lazy(() => import('../PrerenderHome.js'));
|
||||||
|
const PrerenderCategory = lazy(() => import('../PrerenderCategory.js'));
|
||||||
|
const PrerenderProduct = lazy(() => import('../PrerenderProduct.js'));
|
||||||
|
const PrerenderKonfigurator = lazy(() => import('../PrerenderKonfigurator.js'));
|
||||||
|
const PrerenderProfile = lazy(() => import('../PrerenderProfile.js'));
|
||||||
|
const PrerenderSitemap = lazy(() => import('../PrerenderSitemap.js'));
|
||||||
|
|
||||||
|
const StyledPaper = styled(Paper)(({ theme }) => ({
|
||||||
|
padding: theme.spacing(3),
|
||||||
|
margin: theme.spacing(2, 0),
|
||||||
|
backgroundColor: theme.palette.background.paper,
|
||||||
|
}));
|
||||||
|
|
||||||
|
const ComponentCard = styled(Card)(({ theme }) => ({
|
||||||
|
height: '100%',
|
||||||
|
display: 'flex',
|
||||||
|
flexDirection: 'column',
|
||||||
|
transition: 'transform 0.2s ease-in-out, box-shadow 0.2s ease-in-out',
|
||||||
|
'&:hover': {
|
||||||
|
transform: 'translateY(-2px)',
|
||||||
|
boxShadow: theme.shadows[4],
|
||||||
|
},
|
||||||
|
}));
|
||||||
|
|
||||||
|
const PrerenderTestPage = () => {
|
||||||
|
const { componentName } = useParams();
|
||||||
|
const navigate = useNavigate();
|
||||||
|
const [selectedComponent, setSelectedComponent] = useState(componentName || 'home');
|
||||||
|
const [componentProps, setComponentProps] = useState({});
|
||||||
|
|
||||||
|
// Available components for testing - memoized to prevent re-renders
|
||||||
|
const availableComponents = React.useMemo(() => ({
|
||||||
|
// Prerender components
|
||||||
|
home: {
|
||||||
|
component: PrerenderHome,
|
||||||
|
name: 'Home Page',
|
||||||
|
description: 'Main homepage component',
|
||||||
|
category: 'Prerender',
|
||||||
|
props: {}
|
||||||
|
},
|
||||||
|
category: {
|
||||||
|
component: PrerenderCategory,
|
||||||
|
name: 'Category Page',
|
||||||
|
description: 'Category listing with products',
|
||||||
|
category: 'Prerender',
|
||||||
|
props: {
|
||||||
|
categoryId: 209,
|
||||||
|
categoryName: 'Test Category',
|
||||||
|
categorySeoName: 'test-category',
|
||||||
|
productData: null
|
||||||
|
}
|
||||||
|
},
|
||||||
|
product: {
|
||||||
|
component: PrerenderProduct,
|
||||||
|
name: 'Product Page',
|
||||||
|
description: 'Individual product detail page',
|
||||||
|
category: 'Prerender',
|
||||||
|
props: {
|
||||||
|
productData: {
|
||||||
|
product: {
|
||||||
|
id: 1,
|
||||||
|
name: 'Test Product',
|
||||||
|
seoName: 'test-product',
|
||||||
|
description: 'This is a test product for prerender testing',
|
||||||
|
price: 99.99
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
konfigurator: {
|
||||||
|
component: PrerenderKonfigurator,
|
||||||
|
name: 'Konfigurator',
|
||||||
|
description: 'Grow tent configurator',
|
||||||
|
category: 'Prerender',
|
||||||
|
props: {}
|
||||||
|
},
|
||||||
|
profile: {
|
||||||
|
component: PrerenderProfile,
|
||||||
|
name: 'Profile Page',
|
||||||
|
description: 'User profile page',
|
||||||
|
category: 'Prerender',
|
||||||
|
props: {}
|
||||||
|
},
|
||||||
|
sitemap: {
|
||||||
|
component: PrerenderSitemap,
|
||||||
|
name: 'Sitemap',
|
||||||
|
description: 'Site navigation map',
|
||||||
|
category: 'Prerender',
|
||||||
|
props: {
|
||||||
|
categoryData: null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}), []);
|
||||||
|
|
||||||
|
React.useEffect(() => {
|
||||||
|
if (componentName && availableComponents[componentName]) {
|
||||||
|
setSelectedComponent(componentName);
|
||||||
|
setComponentProps(availableComponents[componentName].props);
|
||||||
|
}
|
||||||
|
}, [componentName, availableComponents]);
|
||||||
|
|
||||||
|
const handleComponentChange = (componentKey) => {
|
||||||
|
setSelectedComponent(componentKey);
|
||||||
|
setComponentProps(availableComponents[componentKey].props);
|
||||||
|
navigate(`/prerenderTest/${componentKey}`);
|
||||||
|
};
|
||||||
|
|
||||||
|
const renderComponent = () => {
|
||||||
|
const componentConfig = availableComponents[selectedComponent];
|
||||||
|
if (!componentConfig) return null;
|
||||||
|
|
||||||
|
const Component = componentConfig.component;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Suspense fallback={
|
||||||
|
<Box sx={{
|
||||||
|
display: 'flex',
|
||||||
|
justifyContent: 'center',
|
||||||
|
alignItems: 'center',
|
||||||
|
minHeight: '200px'
|
||||||
|
}}>
|
||||||
|
<CircularProgress />
|
||||||
|
</Box>
|
||||||
|
}>
|
||||||
|
<Component {...componentProps} />
|
||||||
|
</Suspense>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
const getCategories = () => {
|
||||||
|
const categories = {};
|
||||||
|
Object.keys(availableComponents).forEach(key => {
|
||||||
|
const category = availableComponents[key].category;
|
||||||
|
if (!categories[category]) {
|
||||||
|
categories[category] = [];
|
||||||
|
}
|
||||||
|
categories[category].push(key);
|
||||||
|
});
|
||||||
|
return categories;
|
||||||
|
};
|
||||||
|
|
||||||
|
const categories = getCategories();
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Container maxWidth="xl" sx={{ py: 4 }}>
|
||||||
|
<Typography variant="h3" component="h1" gutterBottom align="center">
|
||||||
|
Prerender Preview Environment
|
||||||
|
</Typography>
|
||||||
|
|
||||||
|
<Typography variant="body1" align="center" sx={{ mb: 4, color: 'text.secondary' }}>
|
||||||
|
Preview prerender components dynamically during development
|
||||||
|
</Typography>
|
||||||
|
|
||||||
|
<Alert severity="info" sx={{ mb: 3 }}>
|
||||||
|
This page allows you to preview prerender components in a development environment.
|
||||||
|
The actual prerender components remain unchanged and are used for static generation.
|
||||||
|
</Alert>
|
||||||
|
|
||||||
|
{/* Component Selection */}
|
||||||
|
<StyledPaper elevation={2}>
|
||||||
|
<Typography variant="h5" gutterBottom>
|
||||||
|
Select Component to Preview
|
||||||
|
</Typography>
|
||||||
|
|
||||||
|
<Grid container spacing={2} sx={{ mb: 3 }}>
|
||||||
|
{Object.keys(categories).map(category => (
|
||||||
|
<Grid item xs={12} key={category}>
|
||||||
|
<Typography variant="h6" sx={{ mb: 2, mt: 2 }}>
|
||||||
|
{category} Components
|
||||||
|
</Typography>
|
||||||
|
<Grid container spacing={2}>
|
||||||
|
{categories[category].map(componentKey => {
|
||||||
|
const config = availableComponents[componentKey];
|
||||||
|
return (
|
||||||
|
<Grid item xs={12} sm={6} md={4} lg={3} key={componentKey}>
|
||||||
|
<ComponentCard
|
||||||
|
onClick={() => handleComponentChange(componentKey)}
|
||||||
|
sx={{
|
||||||
|
cursor: 'pointer',
|
||||||
|
border: selectedComponent === componentKey ? '2px solid' : '1px solid',
|
||||||
|
borderColor: selectedComponent === componentKey ? 'primary.main' : 'divider'
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<CardContent sx={{ flexGrow: 1 }}>
|
||||||
|
<Typography variant="h6" component="div" gutterBottom>
|
||||||
|
{config.name}
|
||||||
|
</Typography>
|
||||||
|
<Typography variant="body2" color="text.secondary" sx={{ mb: 1 }}>
|
||||||
|
{config.description}
|
||||||
|
</Typography>
|
||||||
|
<Chip
|
||||||
|
label={category}
|
||||||
|
size="small"
|
||||||
|
color={category === 'Prerender' ? 'primary' : 'secondary'}
|
||||||
|
variant="outlined"
|
||||||
|
/>
|
||||||
|
</CardContent>
|
||||||
|
<CardActions>
|
||||||
|
<Button
|
||||||
|
size="small"
|
||||||
|
variant={selectedComponent === componentKey ? 'contained' : 'outlined'}
|
||||||
|
fullWidth
|
||||||
|
startIcon={<ScienceIcon />}
|
||||||
|
>
|
||||||
|
{selectedComponent === componentKey ? 'Previewing' : 'Preview'}
|
||||||
|
</Button>
|
||||||
|
</CardActions>
|
||||||
|
</ComponentCard>
|
||||||
|
</Grid>
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
</Grid>
|
||||||
|
</Grid>
|
||||||
|
))}
|
||||||
|
</Grid>
|
||||||
|
|
||||||
|
{/* Current Selection Info */}
|
||||||
|
<Box sx={{ mb: 3 }}>
|
||||||
|
<Typography variant="h6" gutterBottom>
|
||||||
|
Currently Previewing: {availableComponents[selectedComponent]?.name}
|
||||||
|
</Typography>
|
||||||
|
<Typography variant="body2" color="text.secondary">
|
||||||
|
Component: {selectedComponent} | Category: {availableComponents[selectedComponent]?.category}
|
||||||
|
</Typography>
|
||||||
|
</Box>
|
||||||
|
</StyledPaper>
|
||||||
|
|
||||||
|
{/* Component Preview Area */}
|
||||||
|
<StyledPaper elevation={1}>
|
||||||
|
<Typography variant="h5" gutterBottom>
|
||||||
|
Component Preview
|
||||||
|
</Typography>
|
||||||
|
|
||||||
|
<Alert severity="warning" sx={{ mb: 3 }}>
|
||||||
|
The component below is rendered dynamically for development preview.
|
||||||
|
In production, this would be prerendered as static HTML.
|
||||||
|
</Alert>
|
||||||
|
|
||||||
|
<Box sx={{
|
||||||
|
border: '1px solid',
|
||||||
|
borderColor: 'divider',
|
||||||
|
borderRadius: 1,
|
||||||
|
minHeight: '400px',
|
||||||
|
backgroundColor: 'background.default',
|
||||||
|
p: 2,
|
||||||
|
overflow: 'auto'
|
||||||
|
}}>
|
||||||
|
{renderComponent()}
|
||||||
|
</Box>
|
||||||
|
</StyledPaper>
|
||||||
|
|
||||||
|
{/* Navigation */}
|
||||||
|
<Box sx={{ mt: 4, textAlign: 'center' }}>
|
||||||
|
<Button
|
||||||
|
variant="outlined"
|
||||||
|
onClick={() => navigate('/')}
|
||||||
|
sx={{ mr: 2 }}
|
||||||
|
>
|
||||||
|
Back to Home
|
||||||
|
</Button>
|
||||||
|
<Button
|
||||||
|
variant="contained"
|
||||||
|
onClick={() => window.location.reload()}
|
||||||
|
>
|
||||||
|
Refresh Preview
|
||||||
|
</Button>
|
||||||
|
</Box>
|
||||||
|
</Container>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default PrerenderTestPage;
|
||||||
Reference in New Issue
Block a user