- Refactored ManagementPortalPage, MultiUploadPage, ModerationGroupImagesPage - Created reusable modular components with mode support: * ImageDescriptionManager (manage/moderate modes) * GroupMetadataEditor (edit/upload/moderate modes) * ConsentManager (edit/upload modes) - Replaced Material-UI Buttons with HTML buttons + CSS classes - Fixed image descriptions upload (preview ID to filename mapping) - Reduced ModerationGroupImagesPage from 281 to 107 lines - Updated ModerationGroupsPage and GroupsOverviewPage button styles - All pages now use consistent Paper boxes with headings - Inline Material-UI Alerts instead of SweetAlert2 popups (except destructive actions) - Icons: 💾 save, ↩ discard, 🗑️ delete consistently used
154 lines
4.5 KiB
JavaScript
154 lines
4.5 KiB
JavaScript
import { useState, useEffect } from 'react';
|
||
import { useNavigate } from 'react-router-dom';
|
||
import { Helmet } from 'react-helmet';
|
||
import {
|
||
Container,
|
||
Card,
|
||
Typography,
|
||
Box,
|
||
CircularProgress
|
||
} from '@mui/material';
|
||
|
||
|
||
|
||
// Components
|
||
import Navbar from '../ComponentUtils/Headers/Navbar';
|
||
import Footer from '../ComponentUtils/Footer';
|
||
import ImageGallery from '../ComponentUtils/ImageGallery';
|
||
|
||
// Utils
|
||
import { fetchAllGroups } from '../../Utils/batchUpload';
|
||
|
||
// Styles
|
||
import '../../App.css';
|
||
|
||
function GroupsOverviewPage() {
|
||
// use CSS classes from GroupsOverviewPage.css
|
||
const navigate = useNavigate();
|
||
|
||
const [groups, setGroups] = useState([]);
|
||
const [loading, setLoading] = useState(true);
|
||
const [error, setError] = useState(null);
|
||
|
||
useEffect(() => {
|
||
loadGroups();
|
||
}, []);
|
||
|
||
const loadGroups = async () => {
|
||
try {
|
||
setLoading(true);
|
||
const response = await fetchAllGroups();
|
||
setGroups(response.groups || []);
|
||
setError(null);
|
||
} catch (err) {
|
||
setError(err.message);
|
||
console.error('Error loading groups:', err);
|
||
} finally {
|
||
setLoading(false);
|
||
}
|
||
};
|
||
|
||
// previously had handleViewSlideshow but it was not used; removed to satisfy ESLint
|
||
|
||
const handleViewGroup = (groupId) => {
|
||
navigate(`/groups/${groupId}`);
|
||
};
|
||
|
||
const handleCreateNew = () => {
|
||
navigate('/multi-upload');
|
||
};
|
||
// removed unused local helpers (formatDate, handleGoHome) to clear ESLint warnings
|
||
|
||
if (loading) {
|
||
return (
|
||
<div className="allContainer">
|
||
<Navbar />
|
||
<Container maxWidth="lg" className="page-container">
|
||
<div className="loading-container">
|
||
<CircularProgress size={60} color="primary" />
|
||
<Typography variant="h6" style={{ marginTop: '20px', color: '#666666' }}>
|
||
Slideshows werden geladen...
|
||
</Typography>
|
||
</div>
|
||
</Container>
|
||
<Footer />
|
||
</div>
|
||
);
|
||
}
|
||
|
||
return (
|
||
<div className="allContainer">
|
||
<Helmet>
|
||
<title>Gruppenübersicht - Interne Verwaltung</title>
|
||
<meta name="robots" content="noindex, nofollow, nosnippet, noarchive" />
|
||
<meta name="googlebot" content="noindex, nofollow" />
|
||
<meta name="description" content="Interne Gruppenübersicht - Nicht öffentlich zugänglich" />
|
||
</Helmet>
|
||
<Navbar />
|
||
|
||
<Container maxWidth="lg" className="page-container">
|
||
{/* Header */}
|
||
<Card className="header-card">
|
||
<Typography className="header-title">
|
||
Alle Slideshows
|
||
</Typography>
|
||
<Typography className="header-subtitle">
|
||
Übersicht aller erstellten Slideshows.
|
||
</Typography>
|
||
</Card>
|
||
|
||
{/* Groups Grid */}
|
||
{error ? (
|
||
<div className="empty-state">
|
||
<Typography variant="h6" style={{ color: '#f44336', marginBottom: '20px' }}>
|
||
😕 Fehler beim Laden
|
||
</Typography>
|
||
<Typography variant="body1" style={{ color: '#666666', marginBottom: '30px' }}>
|
||
{error}
|
||
</Typography>
|
||
<button onClick={loadGroups} className="btn btn-secondary">
|
||
🔄 Erneut versuchen
|
||
</button>
|
||
</div>
|
||
) : groups.length === 0 ? (
|
||
<div className="empty-state">
|
||
<Typography variant="h4" style={{ color: '#666666', marginBottom: '20px' }}>
|
||
📸 Keine Slideshows vorhanden
|
||
</Typography>
|
||
<Typography variant="body1" style={{ color: '#999999', marginBottom: '30px' }}>
|
||
Erstellen Sie Ihre erste Slideshow, indem Sie mehrere Bilder hochladen.
|
||
</Typography>
|
||
<button
|
||
className="btn btn-success"
|
||
onClick={handleCreateNew}
|
||
style={{ fontSize: '16px', padding: '12px 24px' }}
|
||
>
|
||
➕ Erste Slideshow erstellen
|
||
</button>
|
||
</div>
|
||
) : (
|
||
<>
|
||
<Box marginBottom={2}>
|
||
<Typography variant="h6" style={{ color: '#666666' }}>
|
||
📊 {groups.length} Slideshow{groups.length !== 1 ? 's' : ''} gefunden
|
||
</Typography>
|
||
</Box>
|
||
<ImageGallery
|
||
items={groups}
|
||
onViewImages={(group) => handleViewGroup(group.groupId)}
|
||
isPending={false}
|
||
showActions={false}
|
||
mode="group"
|
||
/>
|
||
</>
|
||
)}
|
||
</Container>
|
||
|
||
<div className="footerContainer">
|
||
<Footer />
|
||
</div>
|
||
</div>
|
||
);
|
||
}
|
||
|
||
export default GroupsOverviewPage; |