diff --git a/frontend/src/Components/ComponentUtils/DeletionLogSection.js b/frontend/src/Components/ComponentUtils/DeletionLogSection.js index 4649919..9edf2a0 100644 --- a/frontend/src/Components/ComponentUtils/DeletionLogSection.js +++ b/frontend/src/Components/ComponentUtils/DeletionLogSection.js @@ -21,6 +21,7 @@ import InfoIcon from '@mui/icons-material/Info'; // Services import { adminGet } from '../../services/adminApi'; +import { handleAdminError } from '../../services/adminErrorHandler'; const DeletionLogSection = () => { const [deletions, setDeletions] = useState([]); @@ -46,7 +47,7 @@ const DeletionLogSection = () => { setDeletions(data.deletions || []); setError(null); } catch (error) { - console.error('Fehler beim Laden des Lösch-Logs:', error); + await handleAdminError(error, 'Lösch-Log laden'); setError('Fehler beim Laden des Lösch-Logs'); } finally { setLoading(false); @@ -58,7 +59,7 @@ const DeletionLogSection = () => { const data = await adminGet('/api/admin/deletion-log/stats'); setStatistics(data.statistics || null); } catch (error) { - console.error('Fehler beim Laden der Statistiken:', error); + await handleAdminError(error, 'Statistiken laden'); } }; diff --git a/frontend/src/Components/ComponentUtils/MultiUpload/ConsentCheckboxes.js b/frontend/src/Components/ComponentUtils/MultiUpload/ConsentCheckboxes.js index b653009..0a51c3d 100644 --- a/frontend/src/Components/ComponentUtils/MultiUpload/ConsentCheckboxes.js +++ b/frontend/src/Components/ComponentUtils/MultiUpload/ConsentCheckboxes.js @@ -11,6 +11,7 @@ import { // Services import { adminGet } from '../../../services/adminApi'; +import { handleAdminError } from '../../../services/adminErrorHandler'; import InfoIcon from '@mui/icons-material/Info'; import FacebookIcon from '@mui/icons-material/Facebook'; import InstagramIcon from '@mui/icons-material/Instagram'; @@ -59,7 +60,7 @@ function ConsentCheckboxes({ setPlatforms(data); setError(null); } catch (error) { - console.error('Error loading platforms:', error); + await handleAdminError(error, 'Plattformen laden'); setError('Plattformen konnten nicht geladen werden'); } finally { setLoading(false); diff --git a/frontend/src/Components/Pages/ModerationGroupImagesPage.js b/frontend/src/Components/Pages/ModerationGroupImagesPage.js index 31beed1..3fee085 100644 --- a/frontend/src/Components/Pages/ModerationGroupImagesPage.js +++ b/frontend/src/Components/Pages/ModerationGroupImagesPage.js @@ -4,6 +4,7 @@ import { Container, Box } from '@mui/material'; // Services import { adminGet, adminRequest } from '../../services/adminApi'; +import { handleAdminError } from '../../services/adminErrorHandler'; // Components import Navbar from '../ComponentUtils/Headers/Navbar'; @@ -51,6 +52,7 @@ const ModerationGroupImagesPage = () => { setGroup(transformedData); } catch (e) { + await handleAdminError(e, 'Gruppe laden'); setError('Fehler beim Laden der Gruppe'); } finally { setLoading(false); diff --git a/frontend/src/Components/Pages/ModerationGroupsPage.js b/frontend/src/Components/Pages/ModerationGroupsPage.js index d255d7d..131b38f 100644 --- a/frontend/src/Components/Pages/ModerationGroupsPage.js +++ b/frontend/src/Components/Pages/ModerationGroupsPage.js @@ -7,6 +7,7 @@ import Swal from 'sweetalert2/dist/sweetalert2.js'; // Services import { adminGet, adminRequest, adminDownload } from '../../services/adminApi'; +import { handleAdminError } from '../../services/adminErrorHandler'; // Components import Navbar from '../ComponentUtils/Headers/Navbar'; @@ -40,7 +41,7 @@ const ModerationGroupsPage = () => { const data = await adminGet('/api/admin/social-media/platforms'); setPlatforms(data); } catch (error) { - console.error('Fehler beim Laden der Plattformen:', error); + await handleAdminError(error, 'Plattformen laden'); } }; @@ -68,7 +69,7 @@ const ModerationGroupsPage = () => { const data = await adminGet(url); setGroups(data.groups); } catch (error) { - console.error('Fehler beim Laden der Moderations-Gruppen:', error); + await handleAdminError(error, 'Moderations-Gruppen laden'); setError('Fehler beim Laden der Gruppen'); } finally { setLoading(false); @@ -101,7 +102,7 @@ const ModerationGroupsPage = () => { showConfirmButton: false }); } catch (error) { - console.error('Fehler beim Freigeben der Gruppe:', error); + await handleAdminError(error, 'Gruppe freigeben'); await Swal.fire({ icon: 'error', title: 'Fehler', @@ -139,9 +140,7 @@ const ModerationGroupsPage = () => { )); } catch (error) { - console.error('Fehler beim Löschen des Bildes:', error); - console.error('Error details:', error.message, error.stack); - alert('Fehler beim Löschen des Bildes: ' + error.message); + await handleAdminError(error, 'Bild löschen'); } }; @@ -159,8 +158,7 @@ const ModerationGroupsPage = () => { setShowImages(false); } } catch (error) { - console.error('Fehler beim Löschen der Gruppe:', error); - alert('Fehler beim Löschen der Gruppe'); + await handleAdminError(error, 'Gruppe löschen'); } }; @@ -190,11 +188,7 @@ const ModerationGroupsPage = () => { showConfirmButton: false }); } catch (error) { - console.error('Fehler beim Export:', error); - await Swal.fire({ - icon: 'error', - title: 'Fehler', - text: 'Fehler beim Export der Consent-Daten: ' + error.message + await handleAdminError(error, 'Consent-Export'); }); } }; diff --git a/frontend/src/services/adminErrorHandler.js b/frontend/src/services/adminErrorHandler.js new file mode 100644 index 0000000..508cfd5 --- /dev/null +++ b/frontend/src/services/adminErrorHandler.js @@ -0,0 +1,94 @@ +import Swal from 'sweetalert2/dist/sweetalert2.js'; + +/** + * Zentrale Error-Handler für Admin API Fehler + */ + +/** + * Behandelt Admin API Fehler mit benutzerfreundlichen Meldungen + * @param {Error} error - Der aufgetretene Fehler + * @param {string} context - Kontext der Operation (z.B. "Gruppe laden") + * @returns {Promise} + */ +export const handleAdminError = async (error, context = 'Operation') => { + console.error(`Admin API Error [${context}]:`, error); + + // 403 Unauthorized - Admin Token fehlt oder ungültig + if (error.message.includes('Unauthorized') || error.message.includes('403')) { + await Swal.fire({ + icon: 'error', + title: 'Authentifizierung fehlgeschlagen', + html: ` +

Admin-Token fehlt oder ist ungültig.

+

Bitte kontaktieren Sie den Administrator.

+
+ + Technische Details:
+ - Prüfen Sie die REACT_APP_ADMIN_API_KEY Variable
+ - Token muss mit Backend ADMIN_API_KEY übereinstimmen
+ - Kontext: ${context} +
+ `, + confirmButtonText: 'OK', + confirmButtonColor: '#d33' + }); + return; + } + + // 429 Rate Limit + if (error.message.includes('Too many requests') || error.message.includes('429')) { + await Swal.fire({ + icon: 'warning', + title: 'Zu viele Anfragen', + text: 'Bitte warten Sie einen Moment und versuchen Sie es erneut.', + timer: 3000, + showConfirmButton: false + }); + return; + } + + // 404 Not Found + if (error.message.includes('404')) { + await Swal.fire({ + icon: 'error', + title: 'Nicht gefunden', + text: `Die angeforderte Ressource wurde nicht gefunden.`, + confirmButtonText: 'OK' + }); + return; + } + + // 500 Server Error + if (error.message.includes('500')) { + await Swal.fire({ + icon: 'error', + title: 'Server-Fehler', + text: 'Ein interner Server-Fehler ist aufgetreten. Bitte versuchen Sie es später erneut.', + confirmButtonText: 'OK' + }); + return; + } + + // Generischer Fehler + await Swal.fire({ + icon: 'error', + title: `Fehler: ${context}`, + text: error.message || 'Ein unbekannter Fehler ist aufgetreten.', + confirmButtonText: 'OK' + }); +}; + +/** + * Wrapper für async Operationen mit automatischem Error-Handling + * @param {Function} operation - Die auszuführende async Operation + * @param {string} context - Kontext der Operation + * @returns {Promise} - Ergebnis der Operation oder null bei Fehler + */ +export const withErrorHandling = async (operation, context) => { + try { + return await operation(); + } catch (error) { + await handleAdminError(error, context); + return null; + } +};