feat: add folder filter to admin panel
This commit is contained in:
1 parent
7191a8fbf0
commit
77e8876a07
1 file changed
+61
-19
+61
-19
@@ -21,6 +21,7 @@ export default function AdminDashboard() {
|
|||||||
const [votingOpen, setVotingOpen] = useState(false);
|
const [votingOpen, setVotingOpen] = useState(false);
|
||||||
const [directoryOrder, setDirectoryOrder] = useState<string[]>([]);
|
const [directoryOrder, setDirectoryOrder] = useState<string[]>([]);
|
||||||
const [loading, setLoading] = useState(true);
|
const [loading, setLoading] = useState(true);
|
||||||
|
const [selectedFolder, setSelectedFolder] = useState<string>('');
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
@@ -121,21 +122,23 @@ export default function AdminDashboard() {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const handleBulkAction = async (action: 'publish' | 'unpublish') => {
|
const handleBulkAction = async (action: 'publish' | 'unpublish') => {
|
||||||
if (!confirm(`Möchtest du wirklich alle ${action === 'publish' ? 'freigeben' : 'aufheben'}?`)) return;
|
if (!confirm(`Möchtest du wirklich alle ${selectedFolder ? 'in diesem Ordner ' : ''}${action === 'publish' ? 'freigeben' : 'aufheben'}?`)) return;
|
||||||
|
|
||||||
const isPublished = action === 'publish';
|
const isPublished = action === 'publish';
|
||||||
const idsToUpdate = items.filter(i => i.published !== isPublished).map(i => i.id);
|
const itemsToProcess = selectedFolder ? items.filter(i => i.directory === selectedFolder) : items;
|
||||||
|
const idsToUpdate = itemsToProcess.filter(i => i.published !== isPublished).map(i => i.id);
|
||||||
|
|
||||||
if (idsToUpdate.length === 0) return;
|
if (idsToUpdate.length === 0) return;
|
||||||
|
|
||||||
// Optimistic UI
|
// Optimistic UI
|
||||||
setItems((prev) =>
|
setItems((prev) => {
|
||||||
prev.map((i) => ({ ...i, published: isPublished }))
|
const next = prev.map((i) => idsToUpdate.includes(i.id) ? { ...i, published: isPublished } : i);
|
||||||
);
|
setStats({
|
||||||
setStats({
|
total: next.length,
|
||||||
total: items.length,
|
published: next.filter((i) => i.published).length,
|
||||||
published: isPublished ? items.length : 0,
|
unpublished: next.filter((i) => !i.published).length,
|
||||||
unpublished: isPublished ? 0 : items.length,
|
});
|
||||||
|
return next;
|
||||||
});
|
});
|
||||||
|
|
||||||
try {
|
try {
|
||||||
@@ -183,6 +186,8 @@ export default function AdminDashboard() {
|
|||||||
|
|
||||||
if (!authChecked) return <div style={{ padding: '20px' }}>Prüfe Berechtigung...</div>;
|
if (!authChecked) return <div style={{ padding: '20px' }}>Prüfe Berechtigung...</div>;
|
||||||
|
|
||||||
|
const displayedItems = selectedFolder ? items.filter(i => i.directory === selectedFolder) : items;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="admin-content" style={{ padding: '20px', maxWidth: '1200px', margin: '0 auto' }}>
|
<div className="admin-content" style={{ padding: '20px', maxWidth: '1200px', margin: '0 auto' }}>
|
||||||
<div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', marginBottom: '20px', flexWrap: 'wrap', gap: '10px' }}>
|
<div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', marginBottom: '20px', flexWrap: 'wrap', gap: '10px' }}>
|
||||||
@@ -247,14 +252,51 @@ export default function AdminDashboard() {
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', marginBottom: '15px', flexWrap: 'wrap', gap: '10px' }}>
|
<div style={{ marginBottom: '20px' }}>
|
||||||
<h3 style={{ fontSize: '1.2rem' }}>Alle Medien</h3>
|
<h3 style={{ fontSize: '1.2rem', marginBottom: '10px' }}>Filter</h3>
|
||||||
<div style={{ display: 'flex', gap: '10px' }}>
|
<div style={{ display: 'flex', gap: '10px', flexWrap: 'wrap' }}>
|
||||||
<button className="btn-secondary" onClick={() => handleBulkAction('publish')} disabled={loading || items.length === 0}>
|
<button
|
||||||
Alle freigeben
|
onClick={() => setSelectedFolder('')}
|
||||||
|
style={{
|
||||||
|
padding: '8px 16px',
|
||||||
|
borderRadius: '20px',
|
||||||
|
border: `1px solid ${selectedFolder === '' ? 'var(--color-primary)' : 'var(--color-border)'}`,
|
||||||
|
background: selectedFolder === '' ? 'var(--color-primary)' : 'var(--color-surface)',
|
||||||
|
color: selectedFolder === '' ? 'white' : 'var(--color-text)',
|
||||||
|
cursor: 'pointer',
|
||||||
|
transition: 'all 0.2s'
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
Alle Ordner
|
||||||
</button>
|
</button>
|
||||||
<button className="btn-secondary" onClick={() => handleBulkAction('unpublish')} disabled={loading || items.length === 0}>
|
{orderedFolders.map(folder => (
|
||||||
Alle aufheben
|
<button
|
||||||
|
key={folder}
|
||||||
|
onClick={() => setSelectedFolder(folder)}
|
||||||
|
style={{
|
||||||
|
padding: '8px 16px',
|
||||||
|
borderRadius: '20px',
|
||||||
|
border: `1px solid ${selectedFolder === folder ? 'var(--color-primary)' : 'var(--color-border)'}`,
|
||||||
|
background: selectedFolder === folder ? 'var(--color-primary)' : 'var(--color-surface)',
|
||||||
|
color: selectedFolder === folder ? 'white' : 'var(--color-text)',
|
||||||
|
cursor: 'pointer',
|
||||||
|
transition: 'all 0.2s'
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{folder}
|
||||||
|
</button>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', marginBottom: '15px', flexWrap: 'wrap', gap: '10px' }}>
|
||||||
|
<h3 style={{ fontSize: '1.2rem' }}>Medien {selectedFolder ? `(${selectedFolder})` : ''}</h3>
|
||||||
|
<div style={{ display: 'flex', gap: '10px' }}>
|
||||||
|
<button className="btn-secondary" onClick={() => handleBulkAction('publish')} disabled={loading || displayedItems.length === 0}>
|
||||||
|
{selectedFolder ? 'Sichtbare freigeben' : 'Alle freigeben'}
|
||||||
|
</button>
|
||||||
|
<button className="btn-secondary" onClick={() => handleBulkAction('unpublish')} disabled={loading || displayedItems.length === 0}>
|
||||||
|
{selectedFolder ? 'Sichtbare aufheben' : 'Alle aufheben'}
|
||||||
</button>
|
</button>
|
||||||
<button className="btn-secondary" onClick={fetchData} disabled={loading}>
|
<button className="btn-secondary" onClick={fetchData} disabled={loading}>
|
||||||
{loading ? 'Lädt...' : 'Aktualisieren'}
|
{loading ? 'Lädt...' : 'Aktualisieren'}
|
||||||
@@ -263,7 +305,7 @@ export default function AdminDashboard() {
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div style={{ display: 'grid', gridTemplateColumns: 'repeat(auto-fill, minmax(150px, 1fr))', gap: '15px' }}>
|
<div style={{ display: 'grid', gridTemplateColumns: 'repeat(auto-fill, minmax(150px, 1fr))', gap: '15px' }}>
|
||||||
{items.map(item => (
|
{displayedItems.map(item => (
|
||||||
<div
|
<div
|
||||||
key={item.id}
|
key={item.id}
|
||||||
style={{
|
style={{
|
||||||
@@ -305,9 +347,9 @@ export default function AdminDashboard() {
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
))}
|
))}
|
||||||
{items.length === 0 && !loading && (
|
{displayedItems.length === 0 && !loading && (
|
||||||
<div style={{ gridColumn: '1 / -1', padding: '40px', textAlign: 'center', color: 'var(--color-text-light)' }}>
|
<div style={{ gridColumn: '1 / -1', padding: '40px', textAlign: 'center', color: 'var(--color-text-light)' }}>
|
||||||
Keine Medien gefunden. Bitte einen Scan durchführen.
|
Keine Medien gefunden. Bitte einen Scan durchführen oder anderen Filter wählen.
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
Reference in new issue
Block a user