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:
+85
-49
@@ -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>
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user