feat: change gallery filter to toggleable tabs

This commit is contained in:
Jannik committed 2026-09-24 04:18:58 +02:00
1 parent d304beeba1
commit 696f2ef50a
2 files changed
+56 -33

No files matched your search

+6 -1
View File
@@ -28,7 +28,12 @@ export async function GET(request: NextRequest) {
where.published = true; where.published = true;
} }
if (directoryParam) { 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[] = []; let itemsRaw: any[] = [];
+50 -32
View File
@@ -41,23 +41,37 @@ export default function MediaWall({
const [loading, setLoading] = useState(false); const [loading, setLoading] = useState(false);
const [hasMore, setHasMore] = useState(!!initialCursor); const [hasMore, setHasMore] = useState(!!initialCursor);
const [votingOpen, setVotingOpen] = useState(initialVotingOpen); const [votingOpen, setVotingOpen] = useState(initialVotingOpen);
const [selectedDir, setSelectedDir] = useState<string>(''); const [selectedDirs, setSelectedDirs] = useState<string[]>(directories);
const handleDirChange = async (e: React.ChangeEvent<HTMLSelectElement>) => { const handleDirToggle = async (dir: string) => {
const dir = e.target.value; let newSelected = [...selectedDirs];
setSelectedDir(dir); 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); setItems(initialItems);
setCursor(initialCursor); setCursor(initialCursor);
setHasMore(!!initialCursor); setHasMore(!!initialCursor);
return; return;
} }
if (newSelected.length === 0) {
setItems([]);
setCursor(null);
setHasMore(false);
return;
}
setLoading(true); setLoading(true);
setItems([]); setItems([]);
try { 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) { if (res.ok) {
const data = await res.json(); const data = await res.json();
setItems(data.items); setItems(data.items);
@@ -79,10 +93,13 @@ export default function MediaWall({
const wallRef = useRef<HTMLDivElement>(null); const wallRef = useRef<HTMLDivElement>(null);
const loadMore = useCallback(async () => { const loadMore = useCallback(async () => {
if (loading || !hasMore || !cursor) return; if (loading || !hasMore || !cursor || selectedDirs.length === 0) return;
setLoading(true); setLoading(true);
try { 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}`); const res = await fetch(`/api/media?limit=50&cursor=${cursor}${dirParam}`);
if (res.ok) { if (res.ok) {
const data = await res.json(); const data = await res.json();
@@ -104,7 +121,7 @@ export default function MediaWall({
} finally { } finally {
setLoading(false); setLoading(false);
} }
}, [loading, hasMore, cursor, selectedDir]); }, [loading, hasMore, cursor, selectedDirs, directories.length]);
// Infinite scroll observer // Infinite scroll observer
useEffect(() => { useEffect(() => {
@@ -142,29 +159,30 @@ export default function MediaWall({
return ( return (
<> <>
{directories.length > 0 && ( {directories.length > 0 && (
<div style={{ padding: '80px 20px 0', maxWidth: '1920px', margin: '0 auto', display: 'flex', justifyContent: 'center' }}> <div style={{ padding: '80px 20px 0', maxWidth: '1920px', margin: '0 auto', display: 'flex', justifyContent: 'center', gap: '10px', flexWrap: 'wrap' }}>
<select {directories.map(dir => {
value={selectedDir} const isActive = selectedDirs.includes(dir);
onChange={handleDirChange} return (
style={{ <button
padding: '10px 20px', key={dir}
borderRadius: '20px', onClick={() => handleDirToggle(dir)}
border: '1px solid var(--color-border)', style={{
background: 'var(--color-surface)', padding: '8px 16px',
fontFamily: 'var(--font-body)', borderRadius: '20px',
fontSize: '1rem', border: `1px solid ${isActive ? 'var(--color-primary)' : 'var(--color-border)'}`,
outline: 'none', background: isActive ? 'var(--color-primary)' : 'var(--color-surface)',
cursor: 'pointer', color: isActive ? 'white' : 'var(--color-text)',
boxShadow: 'var(--shadow)', fontFamily: 'var(--font-body)',
color: 'var(--color-text)', fontSize: '0.9rem',
minWidth: '200px' cursor: 'pointer',
}} transition: 'all 0.2s ease',
> boxShadow: isActive ? 'var(--shadow)' : 'none',
<option value="">Alle Fotos</option> }}
{directories.map(dir => ( >
<option key={dir} value={dir}>{dir}</option> {dir}
))} </button>
</select> );
})}
</div> </div>
)} )}
<div className="media-wall" ref={wallRef} style={directories.length > 0 ? { paddingTop: '20px' } : {}}> <div className="media-wall" ref={wallRef} style={directories.length > 0 ? { paddingTop: '20px' } : {}}>