diff --git a/backend/src/utils/dateFormatter.js b/backend/src/utils/dateFormatter.js index ffcc7dc..02f1485 100644 --- a/backend/src/utils/dateFormatter.js +++ b/backend/src/utils/dateFormatter.js @@ -11,7 +11,21 @@ async function formatDate(date, language = 'en') { try { // Get date format setting from database const setting = await db('app_settings').where('setting_key', 'general_date_format').first(); - const dateConfig = setting ? JSON.parse(setting.setting_value) : DEFAULT_FORMAT; + let dateConfig = DEFAULT_FORMAT; + + if (setting && setting.setting_value) { + // Handle both string and object values + if (typeof setting.setting_value === 'string') { + try { + dateConfig = JSON.parse(setting.setting_value); + } catch (e) { + console.warn('Failed to parse date format setting:', e.message); + dateConfig = DEFAULT_FORMAT; + } + } else { + dateConfig = setting.setting_value; + } + } const dateObj = date instanceof Date ? date : new Date(date); diff --git a/docs/picpeak-logo.png b/docs/picpeak-logo.png new file mode 100644 index 0000000..8ce30c9 Binary files /dev/null and b/docs/picpeak-logo.png differ diff --git a/docs/screenshot-analytics.png b/docs/screenshot-analytics.png new file mode 100644 index 0000000..1668459 Binary files /dev/null and b/docs/screenshot-analytics.png differ diff --git a/docs/screenshot-dashboard.png b/docs/screenshot-dashboard.png new file mode 100644 index 0000000..7d91494 Binary files /dev/null and b/docs/screenshot-dashboard.png differ diff --git a/docs/screenshots-events.png b/docs/screenshots-events.png new file mode 100644 index 0000000..f907561 Binary files /dev/null and b/docs/screenshots-events.png differ diff --git a/frontend/src/components/admin/PhotoUpload.tsx b/frontend/src/components/admin/PhotoUpload.tsx index c8c7042..b117357 100644 --- a/frontend/src/components/admin/PhotoUpload.tsx +++ b/frontend/src/components/admin/PhotoUpload.tsx @@ -32,6 +32,20 @@ export const PhotoUpload: React.FC = ({ eventId, onUploadCompl const imageFiles = files.filter(file => ['image/jpeg', 'image/png', 'image/webp'].includes(file.type) ); + + // Check total file count with existing files + const totalFiles = selectedFiles.length + imageFiles.length; + if (totalFiles > 20) { + const allowedNewFiles = 20 - selectedFiles.length; + if (allowedNewFiles <= 0) { + toast.error(t('upload.maxFilesReached') || 'Maximum 20 files allowed'); + return; + } + toast.warning(t('upload.someFilesSkipped') || `Only ${allowedNewFiles} more files can be added (20 max)`); + setSelectedFiles(prev => [...prev, ...imageFiles.slice(0, allowedNewFiles)]); + return; + } + setSelectedFiles(prev => [...prev, ...imageFiles]); }; @@ -41,6 +55,12 @@ export const PhotoUpload: React.FC = ({ eventId, onUploadCompl const handleUpload = async () => { if (selectedFiles.length === 0) return; + + // Validate file count + if (selectedFiles.length > 20) { + toast.error(t('upload.tooManyFiles') || 'Maximum 20 files can be uploaded at once'); + return; + } setIsUploading(true); setUploadProgress(0); diff --git a/frontend/src/i18n/locales/en.json b/frontend/src/i18n/locales/en.json index de93b07..fc8a0dc 100644 --- a/frontend/src/i18n/locales/en.json +++ b/frontend/src/i18n/locales/en.json @@ -47,7 +47,10 @@ "uploadComplete": "Upload complete!", "uploadFailed": "Upload failed", "someFilesFailed": "Some files failed to upload", - "uploadPhotos": "Upload Photos" + "uploadPhotos": "Upload Photos", + "maxFilesReached": "Maximum 20 files allowed", + "someFilesSkipped": "Some files were skipped (20 file limit)", + "tooManyFiles": "Maximum 20 files can be uploaded at once" }, "navigation": { "dashboard": "Dashboard",