fix(frontend): surface upload errors, push ban/lock, route guards (WS8)

H11: UploadSheet now honors the modal contract — role=dialog/aria-modal +
accessible name, a focus-trap/Escape/focus-restore $effect mirroring
ContextSheet, and inert + pointer-events-none when closed so its controls leave
the tab order and AT tree.

H12: a layout-level $effect toasts each upload-queue item the first time it
transitions to 'error', so a banned/locked/over-quota guest is actually told
why their photo didn't post instead of the composer silently closing.

M10: api.ts now redirects to /join after clearAuth() on a 401 (guarded against
loops on the auth screens), so a 401 no longer strands the user on a dead page.

M11: ban and event-lock are pushed to guests. A new uploadsLocked store is
seeded from /me/context (now exposes uploads_locked) and kept live by
event-closed/opened SSE; the feed shows a banner and the FAB is disabled when
locked. A user-banned SSE event force-logs-out the targeted user.

M19: feed and export pages track a distinct loadError and render an "Erneut
versuchen" retry card instead of collapsing a fetch failure into "empty" /
"not released". Light-mode empty-state text bumped to gray-500 for contrast.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
MechaCat02
2026-06-27 16:16:01 +02:00
parent cf428725b9
commit 5bd008591b
9 changed files with 169 additions and 10 deletions

View File

@@ -1,3 +1,5 @@
import { goto } from '$app/navigation';
import { browser } from '$app/environment';
import { getToken, clearAuth } from './auth';
const BASE = '/api/v1';
@@ -42,6 +44,11 @@ async function request<T>(
if (!res.ok) {
if (res.status === 401) {
clearAuth();
// Don't strand the user on a now-unauthenticated page with no nav —
// send them to /join. Guard against loops on the auth screens.
if (browser && !/^\/(join|recover|admin\/login)/.test(window.location.pathname)) {
void goto('/join');
}
}
throw new ApiError(res.status, data.error ?? 'unknown', data.message ?? 'Fehler');
}