Implement complete frontend with admin panel and theme system

- Add admin authentication and dashboard
- Create event management pages (list, create, edit, archive)
- Implement gallery enhancements (search, sorting, bulk download)
- Add email configuration and archive management pages
- Integrate Umami analytics with tracking throughout the app
- Add comprehensive error boundaries and loading states
- Implement accessibility features (WCAG 2.1 AA compliance)
- Create theme system with preset themes and customization
- Add branding settings and company information management
- Fix backend database initialization and health check
- Configure proper API URLs and environment variables

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

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
2025-07-06 22:04:45 +02:00
parent 6c82958c79
commit 28632e8970
53 changed files with 13843 additions and 181 deletions
+85 -49
View File
@@ -1,14 +1,26 @@
import { useEffect } from 'react';
import { BrowserRouter as Router, Routes, Route, Navigate } from 'react-router-dom';
import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
import { ToastContainer } from 'react-toastify';
import 'react-toastify/dist/ReactToastify.css';
import { analyticsService } from './services/analytics.service';
import { GalleryAuthProvider, AdminAuthProvider } from './contexts';
import { ThemeProvider } from './contexts/ThemeContext';
import { GalleryPage } from './pages/GalleryPage';
// Page imports (to be created)
// import { AdminLoginPage } from './pages/admin/AdminLoginPage';
// import { AdminDashboard } from './pages/admin/AdminDashboard';
import {
AdminLoginPage,
AdminDashboard,
EventsListPage,
CreateEventPage,
EventDetailsPage,
EmailConfigPage,
ArchivesPage,
AnalyticsPage,
BrandingPage
} from './pages/admin';
import { AdminLayout } from './components/admin';
import { PageErrorBoundary, OfflineIndicator, SkipLink } from './components/common';
// Create a client
const queryClient = new QueryClient({
@@ -21,55 +33,79 @@ const queryClient = new QueryClient({
});
function App() {
// Initialize Umami Analytics
useEffect(() => {
const umamiUrl = import.meta.env.VITE_UMAMI_URL;
const umamiWebsiteId = import.meta.env.VITE_UMAMI_WEBSITE_ID;
if (umamiUrl && umamiWebsiteId) {
analyticsService.initialize({
websiteId: umamiWebsiteId,
hostUrl: umamiUrl,
autoTrack: true,
doNotTrack: true
});
}
}, []);
return (
<QueryClientProvider client={queryClient}>
<Router>
<Routes>
{/* Public gallery routes */}
<Route path="/gallery/:slug" element={
<GalleryAuthProvider>
<GalleryPage />
</GalleryAuthProvider>
} />
<PageErrorBoundary>
<QueryClientProvider client={queryClient}>
<ThemeProvider>
<Router>
<SkipLink />
<Routes>
{/* Public gallery routes */}
<Route path="/gallery/:slug" element={
<GalleryAuthProvider>
<GalleryPage />
</GalleryAuthProvider>
} />
{/* Admin routes */}
<Route path="/admin/*" element={
<AdminAuthProvider>
<Routes>
<Route path="login" element={
<div className="min-h-screen bg-neutral-50">
<h1 className="text-2xl font-bold text-center py-8">Admin Login (To be implemented)</h1>
</div>
} />
<Route path="dashboard" element={
<div className="min-h-screen bg-neutral-50">
<h1 className="text-2xl font-bold text-center py-8">Admin Dashboard (To be implemented)</h1>
</div>
} />
<Route path="/" element={<Navigate to="/admin/dashboard" replace />} />
</Routes>
</AdminAuthProvider>
} />
{/* Admin routes */}
<Route path="/admin/*" element={
<AdminAuthProvider>
<Routes>
<Route path="login" element={<AdminLoginPage />} />
<Route element={<AdminLayout />}>
<Route path="dashboard" element={<AdminDashboard />} />
<Route path="events" element={<EventsListPage />} />
<Route path="events/new" element={<CreateEventPage />} />
<Route path="events/:id" element={<EventDetailsPage />} />
<Route path="archives" element={<ArchivesPage />} />
<Route path="email" element={<EmailConfigPage />} />
<Route path="analytics" element={<AnalyticsPage />} />
<Route path="branding" element={<BrandingPage />} />
<Route path="/" element={<Navigate to="/admin/dashboard" replace />} />
</Route>
</Routes>
</AdminAuthProvider>
} />
{/* Default redirect */}
<Route path="/" element={<Navigate to="/admin/login" replace />} />
</Routes>
</Router>
{/* Default redirect */}
<Route path="/" element={<Navigate to="/admin/login" replace />} />
</Routes>
</Router>
{/* Toast notifications */}
<ToastContainer
position="bottom-right"
autoClose={5000}
hideProgressBar={false}
newestOnTop
closeOnClick
rtl={false}
pauseOnFocusLoss
draggable
pauseOnHover
theme="light"
/>
</QueryClientProvider>
{/* Offline indicator */}
<OfflineIndicator />
{/* Toast notifications */}
<ToastContainer
position="bottom-right"
autoClose={5000}
hideProgressBar={false}
newestOnTop
closeOnClick
rtl={false}
pauseOnFocusLoss
draggable
pauseOnHover
theme="light"
/>
</ThemeProvider>
</QueryClientProvider>
</PageErrorBoundary>
);
}