feat: Bedienelemente für Bibliothek und Episodenfortschritt

Server-Aktionen prüfen die Sitzung jeweils selbst — auf Angaben aus dem
Formular ist beim Zugriffsschutz kein Verlass.

Häkchen reagieren sofort und werden zurückgedreht, wenn der Server
widerspricht: Abhaken soll sich anfühlen wie ein Schalter, nicht wie ein
Formular. Jede Sichtungsaktion meldet sich unten kurz zurück und lässt sich
von dort zurücknehmen — die Wirkung passiert weit weg vom Klick.
This commit is contained in:
Florian Wilde
2026-09-01 19:24:51 +02:00
parent 4c3c878980
commit f613136e8a
13 changed files with 1866 additions and 1 deletions
+69
View File
@@ -0,0 +1,69 @@
"use client";
import { useState, useTransition } from "react";
import { useRouter } from "next/navigation";
import { purgeEntryAction, restoreEntryAction } from "@/app/actions/library";
import { useToasts } from "@/components/Toasts";
/**
* Wiederherstellen oder endgültig löschen.
* Das endgültige Löschen fragt nach — es lässt sich nicht zurücknehmen.
*/
export function TrashActions({ entryId, title }: { entryId: string; title: string }) {
const router = useRouter();
const { report } = useToasts();
const [pending, startTransition] = useTransition();
const [confirming, setConfirming] = useState(false);
return (
<div className="flex flex-wrap items-center gap-2">
<button
type="button"
disabled={pending}
onClick={() =>
startTransition(async () => {
report(await restoreEntryAction(entryId));
router.refresh();
})
}
className="fl-btn fl-btn-ghost px-3 py-1.5 text-sm"
>
Wiederherstellen
</button>
{confirming ? (
<>
<span className="text-sm text-[var(--fl-muted)]">Endgültig löschen?</span>
<button
type="button"
disabled={pending}
onClick={() =>
startTransition(async () => {
report(await purgeEntryAction(entryId));
router.refresh();
})
}
className="fl-btn fl-btn-ghost px-3 py-1.5 text-sm text-[var(--fl-danger)]"
>
Ja, {title} löschen
</button>
<button
type="button"
onClick={() => setConfirming(false)}
className="text-sm text-[var(--fl-faint)] hover:text-[var(--fl-text)]"
>
Abbrechen
</button>
</>
) : (
<button
type="button"
onClick={() => setConfirming(true)}
className="text-sm text-[var(--fl-faint)] underline-offset-4 hover:text-[var(--fl-danger)] hover:underline"
>
Endgültig löschen
</button>
)}
</div>
);
}