From 696f2ef50ace6ab1591bdb813d3c6f9278909e2a Mon Sep 17 00:00:00 2001 From: orfelorfel23 Date: Thu, 24 Sep 2026 04:18:58 +0200 Subject: [PATCH] feat: change gallery filter to toggleable tabs --- src/app/api/media/route.ts | 7 ++- src/components/MediaWall.tsx | 82 ++++++++++++++++++++++-------------- 2 files changed, 56 insertions(+), 33 deletions(-) diff --git a/src/app/api/media/route.ts b/src/app/api/media/route.ts index 6a23a1f..bf8441b 100644 --- a/src/app/api/media/route.ts +++ b/src/app/api/media/route.ts @@ -28,7 +28,12 @@ export async function GET(request: NextRequest) { where.published = true; } if (directoryParam) { - where.directory = directoryParam; + const dirs = directoryParam.split(','); + if (dirs.length === 1) { + where.directory = dirs[0]; + } else { + where.directory = { in: dirs }; + } } let itemsRaw: any[] = []; diff --git a/src/components/MediaWall.tsx b/src/components/MediaWall.tsx index c5c976a..5a9cb7d 100644 --- a/src/components/MediaWall.tsx +++ b/src/components/MediaWall.tsx @@ -41,23 +41,37 @@ export default function MediaWall({ const [loading, setLoading] = useState(false); const [hasMore, setHasMore] = useState(!!initialCursor); const [votingOpen, setVotingOpen] = useState(initialVotingOpen); - const [selectedDir, setSelectedDir] = useState(''); + const [selectedDirs, setSelectedDirs] = useState(directories); - const handleDirChange = async (e: React.ChangeEvent) => { - const dir = e.target.value; - setSelectedDir(dir); + const handleDirToggle = async (dir: string) => { + let newSelected = [...selectedDirs]; + if (newSelected.includes(dir)) { + newSelected = newSelected.filter(d => d !== dir); + } else { + newSelected.push(dir); + } - if (dir === '') { + setSelectedDirs(newSelected); + + if (newSelected.length === directories.length) { setItems(initialItems); setCursor(initialCursor); setHasMore(!!initialCursor); return; } + if (newSelected.length === 0) { + setItems([]); + setCursor(null); + setHasMore(false); + return; + } + setLoading(true); setItems([]); try { - const res = await fetch(`/api/media?limit=50&directory=${encodeURIComponent(dir)}`); + const dirParam = newSelected.join(','); + const res = await fetch(`/api/media?limit=50&directory=${encodeURIComponent(dirParam)}`); if (res.ok) { const data = await res.json(); setItems(data.items); @@ -79,10 +93,13 @@ export default function MediaWall({ const wallRef = useRef(null); const loadMore = useCallback(async () => { - if (loading || !hasMore || !cursor) return; + if (loading || !hasMore || !cursor || selectedDirs.length === 0) return; setLoading(true); try { - const dirParam = selectedDir ? `&directory=${encodeURIComponent(selectedDir)}` : ''; + let dirParam = ''; + if (selectedDirs.length > 0 && selectedDirs.length < directories.length) { + dirParam = `&directory=${encodeURIComponent(selectedDirs.join(','))}`; + } const res = await fetch(`/api/media?limit=50&cursor=${cursor}${dirParam}`); if (res.ok) { const data = await res.json(); @@ -104,7 +121,7 @@ export default function MediaWall({ } finally { setLoading(false); } - }, [loading, hasMore, cursor, selectedDir]); + }, [loading, hasMore, cursor, selectedDirs, directories.length]); // Infinite scroll observer useEffect(() => { @@ -142,29 +159,30 @@ export default function MediaWall({ return ( <> {directories.length > 0 && ( -
- +
+ {directories.map(dir => { + const isActive = selectedDirs.includes(dir); + return ( + + ); + })}
)}
0 ? { paddingTop: '20px' } : {}}>