feat: implement gallery preview with layout selector

- Add GalleryPreview component that shows simplified gallery layouts
- Update ThemeEditorModal with split view: theme customizer on left, preview on right
- Add grid style selector above preview to switch between layouts
- Update BrandingPage to show live preview alongside theme customizer
- Add preview to CreateEventPageEnhanced when customizing themes
- Support all 6 gallery layouts: grid, masonry, carousel, timeline, hero, mosaic
- Add translation keys for preview layout and live preview

The preview accurately reflects different grid layouts and theme settings,
helping users visualize how their galleries will look before saving.

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <[email protected]>
This commit is contained in:
2025-07-11 08:38:48 +02:00
co-authored by Claude
parent 9006b754a8
commit d89a605579
7 changed files with 326 additions and 31 deletions
+28 -7
View File
@@ -2,7 +2,7 @@ import React, { useState, useEffect, useRef } from 'react';
import { Save, Eye, Palette, Upload } from 'lucide-react';
import { toast } from 'react-toastify';
import { Button, Card, Input, ErrorBoundary, Loading } from '../../components/common';
import { ThemeCustomizer } from '../../components/admin/ThemeCustomizer';
import { ThemeCustomizerEnhanced, GalleryPreview } from '../../components/admin';
import { useTheme, type ThemeConfig, GALLERY_THEME_PRESETS } from '../../contexts/ThemeContext';
import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query';
import { settingsService, type BrandingSettings } from '../../services/settings.service';
@@ -472,12 +472,33 @@ export const BrandingPage: React.FC = () => {
<span className="text-sm text-neutral-700">{t('branding.applyLivePreview')}</span>
</label>
</div>
<ThemeCustomizer
value={currentTheme}
onChange={handleThemeChange}
presetName={currentThemeName}
onPresetChange={handlePresetChange}
/>
<div className="grid grid-cols-1 lg:grid-cols-2 gap-6">
{/* Left side - Theme Customizer */}
<div>
<ThemeCustomizerEnhanced
value={currentTheme}
onChange={handleThemeChange}
presetName={currentThemeName}
onPresetChange={handlePresetChange}
isPreviewMode={isPreviewMode}
showGalleryLayouts={true}
hideActions={true}
/>
</div>
{/* Right side - Gallery Preview */}
<div className="lg:sticky lg:top-4 lg:h-fit">
<Card className="p-4">
<h3 className="text-sm font-medium text-neutral-700 mb-3">
{t('branding.livePreview')}
</h3>
<GalleryPreview
theme={currentTheme}
className="shadow-lg"
/>
</Card>
</div>
</div>
</div>
{/* Event-Specific Themes Info */}
@@ -15,7 +15,7 @@ import { enUS, de } from 'date-fns/locale';
import { toast } from 'react-toastify';
import { Button, Input, Card } from '../../components/common';
import { ThemeCustomizerEnhanced } from '../../components/admin/ThemeCustomizerEnhanced';
import { ThemeCustomizerEnhanced, GalleryPreview } from '../../components/admin';
import { useMutation, useQuery } from '@tanstack/react-query';
import { eventsService } from '../../services/events.service';
import { categoriesService } from '../../services/categories.service';
@@ -375,14 +375,28 @@ export const CreateEventPageEnhanced: React.FC = () => {
{/* Theme Customizer */}
{showThemeCustomizer && (
<ThemeCustomizerEnhanced
value={formData.theme_config}
onChange={handleThemeChange}
presetName={formData.theme_preset}
onPresetChange={handlePresetChange}
isPreviewMode={false}
showGalleryLayouts={true}
/>
<div className="space-y-6">
<div className="grid grid-cols-1 lg:grid-cols-2 gap-6">
{/* Theme Customizer */}
<ThemeCustomizerEnhanced
value={formData.theme_config}
onChange={handleThemeChange}
presetName={formData.theme_preset}
onPresetChange={handlePresetChange}
isPreviewMode={false}
showGalleryLayouts={true}
hideActions={true}
/>
{/* Gallery Preview */}
<div className="lg:sticky lg:top-4 lg:h-fit">
<GalleryPreview
theme={formData.theme_config}
className="shadow-lg"
/>
</div>
</div>
</div>
)}
</div>
</Card>