L7 Offline & PWA: Sync-Seite, Offline-Ansicht, Sync-Badge, Installationshinweis, Logout-Schutz

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
2026-09-14 17:20:44 +02:00
co-authored by Claude Opus 5
parent 4dd330b9fd
commit f0620f9c3b
15 changed files with 1633 additions and 13 deletions
+7 -13
View File
@@ -1,23 +1,17 @@
import { getTranslations } from "next-intl/server";
import { OnlineBadge } from "@/components/field/online-badge";
import { card } from "@/components/field/ui";
import { SyncPanel } from "@/components/offline/sync-panel";
/**
* PLACEHOLDER (lane L4) — `/m/sync` belongs to lane L7 (Offline/PWA), which replaces this page
* with the outbox status, errors and conflicts. Until then it shows the connection state and that
* ops are sent immediately (src/lib/field/client-ops.ts).
* `/m/sync` (lane L7, Spec §22/§23.4, US-012): connection, last sync, pending changes and uploads
* with progress, errors/conflicts in plain language (retry / discard), storage usage, reset. The
* data lives on the device (IndexedDB), so the panel is a client component.
*/
export default async function SyncPlaceholderPage() {
const t = await getTranslations("field.sync");
export default async function SyncPage() {
const t = await getTranslations("offline.sync");
return (
<main className="space-y-4 p-4">
<h1 className="text-[26px]">{t("title")}</h1>
<section className={`${card} space-y-3`}>
<p className="text-[13px] font-semibold text-muted-foreground">{t("status")}</p>
<OnlineBadge large />
<p className="text-[15px]">{t("immediate")}</p>
<p className="text-[14px] text-muted-foreground">{t("offlineHint")}</p>
</section>
<SyncPanel />
</main>
);
}