Project-Image-Uploader/frontend/src/Components/Pages/PublicGroupImagesPage.js
matthias.lotz cb640576f4 feat(frontend): Migrate all API routes to new structure with admin auth
Phase 1: Route Structure & Admin Authentication

 Route Prefix Fixes:
- All routes now use consistent /api prefix
- Public: /groups/* → /api/groups/*
- Admin: /groups/*, /moderation/* → /api/admin/*
- Social Media: /api/social-media/* → /api/admin/social-media/*

 Admin API Authentication:
- Created adminApi.js service with Bearer Token helpers
  * adminFetch() - Base fetch with Authorization header
  * adminGet() - GET with auto error handling
  * adminRequest() - POST/PUT/PATCH/DELETE with JSON
  * adminDownload() - For Blob downloads (CSV exports)
- Added frontend/.env.example with REACT_APP_ADMIN_API_KEY
- All /api/admin/* calls now use admin helpers

 Updated Components:
- ModerationGroupsPage.js: All admin endpoints migrated
- ModerationGroupImagesPage.js: Group loading + image deletion
- PublicGroupImagesPage.js: Fixed public group route
- DeletionLogSection.js: Deletion log endpoints
- ConsentCheckboxes.js: Platform loading

⚠️ Next Steps:
- Add user-friendly 403 error handling
- Test all affected pages
- Configure REACT_APP_ADMIN_API_KEY in deployment
2025-11-16 18:39:40 +01:00

80 lines
2.6 KiB
JavaScript

import React, { useState, useEffect } from 'react';
import { useParams } from 'react-router-dom';
import { Container } from '@mui/material';
import Navbar from '../ComponentUtils/Headers/Navbar';
import Footer from '../ComponentUtils/Footer';
import ImageGalleryCard from '../ComponentUtils/ImageGalleryCard';
import ImageGallery from '../ComponentUtils/ImageGallery';
const PublicGroupImagesPage = () => {
const { groupId } = useParams();
const [group, setGroup] = useState(null);
const [loading, setLoading] = useState(true);
const [error, setError] = useState(null);
useEffect(() => {
loadGroup();
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [groupId]);
const loadGroup = async () => {
try {
setLoading(true);
// Public endpoint (no moderation controls)
const res = await fetch(`/api/groups/${groupId}`);
if (!res.ok) throw new Error('Nicht gefunden');
const data = await res.json();
setGroup(data);
} catch (e) {
setError('Fehler beim Laden der Gruppe');
} finally {
setLoading(false);
}
};
if (loading) return <div className="moderation-loading">Lade Gruppe...</div>;
if (error) return <div className="moderation-error">{error}</div>;
if (!group) return <div className="moderation-error">Gruppe nicht gefunden</div>;
return (
<div className="allContainer">
<Navbar />
<Container maxWidth="lg" className="page-container" style={{ marginTop: '40px' }}>
<ImageGalleryCard
item={group}
showActions={false}
isPending={!group.approved}
mode="group"
hidePreview={true}
/>
<ImageGallery
items={group.images && group.images.length > 0 ? group.images.map(img => ({
...img, // Pass all image fields including previewPath and imageDescription
remoteUrl: `/download/${img.fileName}`, // Keep for backward compatibility
originalName: img.originalName || img.fileName,
id: img.id
})) : []}
showActions={false}
enableReordering={false}
mode="single-image"
emptyMessage="Keine Bilder in dieser Gruppe."
imageDescriptions={group.images && group.images.length > 0 ?
group.images.reduce((acc, img) => {
if (img.imageDescription) {
acc[img.id] = img.imageDescription;
}
return acc;
}, {}) : {}}
/>
</Container>
<div className="footerContainer"><Footer /></div>
</div>
);
};
export default PublicGroupImagesPage;