```
### Additional Layout Improvements:
```typescript
// File: frontend/src/pages/GalleryPage.tsx
// Update the header section for better visual balance (around line 275):
{galleryInfo?.event_name}
{/* Event type instead of date */}
{galleryInfo?.event_type && (
{t(`events.types.${galleryInfo.event_type}`)}
)}
```
---
## 3. Analytics Umami Configuration Check
**Problem:** Analytics page shows "Umami Analytics Not Configured" even when configured in settings.
**Current State:**
- File: `frontend/src/pages/admin/AnalyticsPage.tsx` (lines 67-87)
- Check logic may not be working correctly
**Implementation:**
### Frontend Fix:
```typescript
// File: frontend/src/pages/admin/AnalyticsPage.tsx
// Fix the Umami configuration check (around lines 67-87):
// REPLACE the useEffect:
useEffect(() => {
const fetchUmamiConfig = async () => {
try {
const response = await fetch(`${import.meta.env.VITE_API_URL}/api/public/settings`);
const settings = await response.json();
// Check if Umami is properly configured
const isConfigured = settings.analytics_umami_enabled &&
settings.analytics_umami_url &&
settings.analytics_umami_website_id;
if (isConfigured) {
setUmamiConfig({
url: settings.analytics_umami_url,
shareUrl: settings.analytics_umami_share_url,
websiteId: settings.analytics_umami_website_id,
enabled: true
});
} else {
// Fall back to environment variables
const envConfigured = import.meta.env.VITE_UMAMI_URL &&
import.meta.env.VITE_UMAMI_WEBSITE_ID;
setUmamiConfig({
url: import.meta.env.VITE_UMAMI_URL,
shareUrl: import.meta.env.VITE_UMAMI_SHARE_URL,
websiteId: import.meta.env.VITE_UMAMI_WEBSITE_ID,
enabled: envConfigured
});
}
} catch (error) {
console.error('Failed to fetch Umami config:', error);
setUmamiConfig({ enabled: false });
}
};
fetchUmamiConfig();
}, []);
// Update the configuration notice condition (around line 441):
{!umamiConfig.enabled && (
{t('analytics.notConfigured')}
{t('analytics.configureInstructions')}
)}
```
---
## 4. Analytics Numbers Accuracy Fix
**Problem:** Dashboard shows correct numbers but analytics page shows different numbers.
**Current State:**
- Dashboard: `frontend/src/services/admin.service.ts` `getDashboardStats()`
- Analytics: `frontend/src/services/admin.service.ts` `getAnalytics()`
- Backend: Different endpoints with potentially different calculation logic
**Implementation:**
### Backend Investigation and Fix:
```javascript
// File: backend/src/routes/adminDashboard.js
// Ensure consistent calculation logic in both /stats and /analytics endpoints
// Update the analytics endpoint (around line 216) to use the same calculation as stats:
router.get('/analytics', adminAuth, async (req, res) => {
try {
const days = sanitizeDays(req.query.days || 7);
// Use same calculation logic as /stats endpoint
const thirtyDaysAgo = new Date();
thirtyDaysAgo.setDate(thirtyDaysAgo.getDate() - days);
// Get total downloads - SAME logic as /stats
const totalDownloads = await db('access_logs')
.whereIn('action', ['download', 'download_all'])
.where('timestamp', '>=', thirtyDaysAgo.toISOString())
.count('id as count')
.first();
// Get total views - SAME logic as /stats
const totalViews = await db('access_logs')
.where('action', 'view')
.where('timestamp', '>=', thirtyDaysAgo.toISOString())
.count('id as count')
.first();
// ... rest of the analytics logic
// Add totals to response for verification
res.json({
chartData: dates,
topGalleries,
devices,
totals: {
totalViews: totalViews.count,
totalDownloads: totalDownloads.count,
period: `${days} days`
}
});
} catch (error) {
console.error('Analytics error:', error);
res.status(500).json({ error: 'Failed to fetch analytics data' });
}
});
```
### Frontend Verification:
```typescript
// File: frontend/src/pages/admin/AnalyticsPage.tsx
// Add debug information in development (around line 107):
const analytics: ComponentAnalyticsData | undefined = React.useMemo(() => {
if (!apiData) return undefined;
// Calculate totals from chart data
const totalViews = apiData.chartData.reduce((sum, day) => sum + day.views, 0);
const totalDownloads = apiData.chartData.reduce((sum, day) => sum + day.downloads, 0);
// Debug: Compare with API totals in development
if (process.env.NODE_ENV === 'development' && apiData.totals) {
console.log('Analytics Debug:', {
calculatedViews: totalViews,
apiTotalViews: apiData.totals.totalViews,
calculatedDownloads: totalDownloads,
apiTotalDownloads: apiData.totals.totalDownloads,
period: apiData.totals.period
});
}
// ... rest of the calculation
}, [apiData]);
```
---
## 5. Missing Translation Key Fix
**Problem:** Missing translation key `admin.activities.analytics_settings_updated` in recent activities.
**Current State:**
- Key not found in `frontend/src/i18n/locales/en.json` or `de.json`
**Implementation:**
### Translation Updates:
```json
// File: frontend/src/i18n/locales/en.json
// Add to admin.activities section (around line 785):
"analytics_settings_updated": "Analytics settings updated"
// File: frontend/src/i18n/locales/de.json
// Add to admin.activities section (around line 710):
"analytics_settings_updated": "Analytik-Einstellungen aktualisiert"
```
### Backend Activity Logging:
```javascript
// File: backend/src/routes/adminSettings.js (or wherever analytics settings are updated)
// Ensure activity is logged with correct key:
await logActivity(req.admin.id, 'analytics_settings_updated', {
settingsUpdated: Object.keys(updateData).filter(key => key.startsWith('analytics_')),
timestamp: new Date()
});
```
---
## 6. Complete Translation Audit
**Problem:** Need to check all recent activity types for missing translations.
**Current State:**
- Activity types defined in backend, translations in frontend
**Implementation:**
### Audit Script:
```bash
# Create a script to find missing translation keys
# File: scripts/audit-translations.js
const fs = require('fs');
const path = require('path');
// Read translation files
const enTranslations = JSON.parse(fs.readFileSync('frontend/src/i18n/locales/en.json', 'utf8'));
const deTranslations = JSON.parse(fs.readFileSync('frontend/src/i18n/locales/de.json', 'utf8'));
// Common activity types that should exist
const requiredActivityKeys = [
'event_created', 'event_updated', 'event_deleted', 'event_archived',
'photos_uploaded', 'photo_deleted', 'photos_bulk_deleted',
'archive_downloaded', 'archive_deleted', 'archive_restored',
'email_config_updated', 'email_template_updated',
'branding_updated', 'theme_updated', 'analytics_settings_updated',
'general_settings_updated', 'security_settings_updated',
'category_created', 'category_updated', 'category_deleted',
'cms_page_updated', 'favicon_uploaded',
'bulk_download', 'gallery_password_entry', 'expiration_warning_viewed'
];
console.log('Missing English translations:');
requiredActivityKeys.forEach(key => {
if (!enTranslations.admin?.activities?.[key]) {
console.log(`- admin.activities.${key}`);
}
});
console.log('\nMissing German translations:');
requiredActivityKeys.forEach(key => {
if (!deTranslations.admin?.activities?.[key]) {
console.log(`- admin.activities.${key}`);
}
});
```
### Missing Translations to Add:
```json
// File: frontend/src/i18n/locales/en.json
// Add any missing keys to admin.activities:
"analytics_settings_updated": "Analytics settings updated",
"cms_page_updated": "CMS page updated: {{page}}",
"security_settings_updated": "Security settings updated",
"password_reset": "Password reset for: {{eventName}}",
"admin_logout": "Admin {{actorName}} logged out",
"system_activity": "System activity: {{type}}"
// File: frontend/src/i18n/locales/de.json
// German equivalents:
"analytics_settings_updated": "Analytik-Einstellungen aktualisiert",
"cms_page_updated": "CMS-Seite aktualisiert: {{page}}",
"security_settings_updated": "Sicherheitseinstellungen aktualisiert",
"password_reset": "Passwort zurückgesetzt für: {{eventName}}",
"admin_logout": "Admin {{actorName}} abgemeldet",
"system_activity": "Systemaktivität: {{type}}"
```
---
## 7. CMS Page Long German Text Formatting
**Problem:** Long German text like "Datenschutzerklärung" pushes image to left and looks ugly.
**Current State:**
- File: `frontend/src/pages/admin/CMSPageEnhanced.tsx` (lines 130-170)
- File: `frontend/src/pages/admin/CMSPage.tsx` (lines 90-110)
**Implementation:**
### CSS Fix:
```typescript
// File: frontend/src/pages/admin/CMSPageEnhanced.tsx
// Update the page selection buttons (around line 130):
```
### Alternative - Responsive Layout:
```typescript
// File: frontend/src/pages/admin/CMSPageEnhanced.tsx
// Alternative: Use responsive text sizing
{/* For very long German words, show abbreviated version */}
{t(`legal.${page.slug}`).length > 15
? `${t(`legal.${page.slug}`).substring(0, 12)}...`
: t(`legal.${page.slug}`)
}
```
---
## 8. Event Creation Date Format Fix
**Problem:** Event creation page uses browser English format instead of saved admin settings date format.
**Current State:**
- Files: `frontend/src/pages/admin/CreateEventPageEnhanced.tsx`, `CreateEventPage.tsx`
- Uses browser locale instead of admin date format settings
**Implementation:**
### Hook Enhancement:
```typescript
// File: frontend/src/hooks/useLocalizedDate.ts
// Add admin settings integration:
import { useTranslation } from 'react-i18next';
import { format as dateFnsFormat, formatDistanceToNow as dateFnsFormatDistanceToNow } from 'date-fns';
import { de, enUS, enGB } from 'date-fns/locale';
import { useQuery } from '@tanstack/react-query';
import { settingsService } from '../services/settings.service';
export const useLocalizedDate = () => {
const { i18n } = useTranslation();
// Fetch admin date format settings
const { data: settings } = useQuery({
queryKey: ['admin-date-settings'],
queryFn: () => settingsService.getAllSettings(),
staleTime: 10 * 60 * 1000, // Cache for 10 minutes
});
const getLocale = () => {
// Use admin settings if available, otherwise fall back to i18n language
const savedFormat = settings?.general_date_format;
if (savedFormat?.locale) {
switch (savedFormat.locale) {
case 'en-US': return enUS;
case 'en-GB': return enGB;
case 'de': return de;
default: return i18n.language === 'de' ? de : enUS;
}
}
return i18n.language === 'de' ? de : enUS;
};
const getDateFormat = () => {
const savedFormat = settings?.general_date_format?.format;
if (savedFormat) {
// Convert admin format to date-fns format
switch (savedFormat) {
case 'DD/MM/YYYY': return 'dd/MM/yyyy';
case 'MM/DD/YYYY': return 'MM/dd/yyyy';
case 'YYYY-MM-DD': return 'yyyy-MM-dd';
case 'DD.MM.YYYY': return 'dd.MM.yyyy';
default: return 'dd/MM/yyyy';
}
}
return i18n.language === 'de' ? 'dd.MM.yyyy' : 'MM/dd/yyyy';
};
const format = (date: Date | string, formatStr?: string) => {
const dateObj = typeof date === 'string' ? new Date(date) : date;
const finalFormat = formatStr || getDateFormat();
return dateFnsFormat(dateObj, finalFormat, { locale: getLocale() });
};
// ... rest of the hook
};
```
### Event Creation Page Fix:
```typescript
// File: frontend/src/pages/admin/CreateEventPageEnhanced.tsx
// Update the expiration date display (around line 495):
{formData.event_date && (
);
};
```
### Alternative - Image Flags:
```typescript
// Alternative solution using flag images:
const languages = [
{ code: 'en', name: 'English', flag: '/flags/gb.svg' },
{ code: 'de', name: 'Deutsch', flag: '/flags/de.svg' },
];
// Add images to public/flags/ directory
// Use:
```
---
## 🔍 Testing Instructions
### After implementing each fix:
1. **Password Complexity**: Test different complexity levels in admin settings
2. **Gallery Login**: Verify event date is hidden on gallery login pages
3. **Analytics Check**: Verify "Not Configured" message appears/disappears correctly
4. **Analytics Numbers**: Compare dashboard vs analytics page numbers
5. **Translations**: Check recent activities display correct translations
6. **CMS Formatting**: Test with long German page names
7. **Date Format**: Test event creation with different admin date settings
8. **Language Flags**: Test language selector in Chrome on Windows
### Regression Testing:
- [ ] Gallery login still works correctly
- [ ] Analytics page displays correctly when Umami is configured
- [ ] Admin settings save and load correctly
- [ ] Event creation works with all date formats
- [ ] Language switching works in all browsers
---
## 📝 Notes
- All changes maintain backward compatibility
- No database schema changes required
- Frontend changes are non-breaking
- Can be deployed incrementally
- All text is properly internationalized
**⚠️ Important**: Test each fix in isolation before combining, especially the analytics changes as they affect production data display.