feat: change gallery filter to toggleable tabs
This commit is contained in:
1 parent
d304beeba1
commit
696f2ef50a
2 files changed
+56
-33
No files matched your search
@@ -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[] = [];
|
||||||
|
|||||||
@@ -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' } : {}}>
|
||||||
|
|||||||
Reference in new issue
Block a user