Fix brand theme application and add comprehensive translations

- Fixed theme not being reflected on gallery and admin login pages
- Created GlobalThemeProvider to apply themes globally
- Updated gallery and admin login pages to use dynamic CSS variables
- Added complete translations for all admin sections in English and German:
  - Notifications management
  - Event view and creation
  - Photo upload functionality
  - Category management
  - Archive page view
  - Analytics dashboard
  - Branding and theme settings
  - System settings
  - CMS page management
  - Email configuration
- Fixed admin photo management display issues
- Fixed photo upload category assignment
- Added password reset functionality for galleries
- Improved error handling and user feedback

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

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
2025-07-08 17:07:40 +02:00
parent 2012b0bab9
commit d594d00227
79 changed files with 4570 additions and 329 deletions
+3 -3
View File
@@ -16,7 +16,7 @@ interface GalleryEvent {
interface GalleryAuthContextType {
isAuthenticated: boolean;
event: GalleryEvent | null;
login: (slug: string, password: string) => Promise<void>;
login: (slug: string, password: string, recaptchaToken?: string | null) => Promise<void>;
logout: () => void;
isLoading: boolean;
error: string | null;
@@ -62,11 +62,11 @@ export const GalleryAuthProvider: React.FC<GalleryAuthProviderProps> = ({ childr
setIsLoading(false);
}, []);
const login = async (slug: string, password: string) => {
const login = async (slug: string, password: string, recaptchaToken?: string | null) => {
try {
setError(null);
setIsLoading(true);
const response = await authService.verifyGalleryPassword(slug, password);
const response = await authService.verifyGalleryPassword(slug, password, recaptchaToken);
setEvent(response.event);
setIsAuthenticated(true);
@@ -0,0 +1,74 @@
import React, { createContext, useContext, useState, useEffect, ReactNode } from 'react';
import { useQuery } from '@tanstack/react-query';
import { setMaintenanceModeCallback } from '../config/api';
interface MaintenanceContextType {
isMaintenanceMode: boolean;
setMaintenanceMode: (enabled: boolean) => void;
}
const MaintenanceContext = createContext<MaintenanceContextType | undefined>(undefined);
export const useMaintenanceMode = () => {
const context = useContext(MaintenanceContext);
if (!context) {
throw new Error('useMaintenanceMode must be used within MaintenanceProvider');
}
return context;
};
interface MaintenanceProviderProps {
children: ReactNode;
}
export const MaintenanceProvider: React.FC<MaintenanceProviderProps> = ({ children }) => {
const [isMaintenanceMode, setIsMaintenanceMode] = useState(false);
// Check maintenance mode status on mount
const { data: settings } = useQuery({
queryKey: ['public-settings-maintenance'],
queryFn: async () => {
try {
const response = await fetch(`${import.meta.env.VITE_API_URL || 'http://localhost:3001'}/api/public/settings`);
if (response.status === 503) {
setIsMaintenanceMode(true);
return null;
}
return response.json();
} catch (error) {
// If we can't reach the server, don't assume maintenance mode
return null;
}
},
staleTime: 30 * 1000, // Check every 30 seconds
refetchInterval: 30 * 1000,
});
// Update maintenance mode based on settings
useEffect(() => {
if (settings?.maintenance_mode !== undefined) {
setIsMaintenanceMode(settings.maintenance_mode);
}
}, [settings]);
// Set up the callback for API interceptor
useEffect(() => {
setMaintenanceModeCallback((enabled: boolean) => {
setIsMaintenanceMode(enabled);
});
return () => {
setMaintenanceModeCallback(null as any);
};
}, []);
const setMaintenanceMode = (enabled: boolean) => {
setIsMaintenanceMode(enabled);
};
return (
<MaintenanceContext.Provider value={{ isMaintenanceMode, setMaintenanceMode }}>
{children}
</MaintenanceContext.Provider>
);
};
+2 -1
View File
@@ -1,4 +1,5 @@
export { GalleryAuthProvider, useGalleryAuth } from './GalleryAuthContext';
export { AdminAuthProvider, useAdminAuth } from './AdminAuthContext';
export { ThemeProvider, useTheme, PRESET_THEMES } from './ThemeContext';
export type { ThemeConfig, EventTheme } from './ThemeContext';
export type { ThemeConfig, EventTheme } from './ThemeContext';
export { MaintenanceProvider, useMaintenanceMode } from './MaintenanceContext';