Errungenschaften: Abzeichen fuer erreichte Meilensteine
CI / pruefen (pull_request) Canceled after 0s

Zwanzig feste Abzeichen plus dynamische fuer vollstaendig gesehene Filmreihen
und abgeschlossene Universen. Sie tauchen auf, wenn etwas erreicht ist, und
bleiben — auch wenn die Bedingung spaeter wegfaellt. Eine zurueckgenommene
Sichtung soll kein Abzeichen kosten.

Alle Regeln arbeiten auf *einem* Datensatz, der einmal geholt wird. Sonst
stellte jede Regel ihre eigene Abfrage, und aus zwanzig Abzeichen wuerden
zwanzig Abfragen bei jedem Abhaken. Ausgewertet wird nach Sichtungsaktionen
und einmal taeglich; der erste Lauf eines Kontos ist stumm, weil eine
gewachsene Bibliothek sonst zwei Dutzend Meldungen auf einmal ausloest.

Fuer Filmreihen braucht es keine gepflegte Liste: TMDB gruppiert sie selbst,
und tmdbCollectionId liegt beim Import schon am Titel. Eigennamen wie
"Spider Bro" kommen aus einer kleinen Datendatei obendrauf; fehlt ein Eintrag,
greift der generische Name.

Die kuratierten Eintraege tragen jeweils ein Stueck des erwarteten
TMDB-Namens. Ich habe die Collection-Kennungen aus dem Gedaechtnis
geschrieben und kann sie hier nicht gegen TMDB pruefen — passt der Name
nicht, wird der Eintrag ignoriert und der generische greift. Eine falsch
abgeschriebene Kennung bleibt damit folgenlos statt jemandem das falsche
Abzeichen zu geben.

Die Uhrzeit-Regel liest die Stunde ueber formatToParts statt ueber die
formatierte Zeichenkette: auf Deutsch liefert Intl fuer eine einzelne Stunde
"03 Uhr", und daraus wird beim Umwandeln NaN. Ein Test hat das aufgedeckt.

Beim ersten Oeffnen der Uebersicht wird einmal ausgewertet — sonst bliebe sie
bei einem Bestandskonto leer, bis nachts der Hintergrundlauf kommt.

Zehn Tests, Anleitung mit Screenshot. Symbole als eigene SVG auf einem
gemeinsamen Raster; erreicht und offen unterscheiden sich nicht nur durch
Farbe, sondern auch im Text.

Refs #15
This commit is contained in:
Florian Wilde
2026-09-02 12:09:51 +02:00
parent 3671fbdc40
commit b560ee9c51
21 changed files with 1457 additions and 22 deletions
+16 -3
View File
@@ -16,7 +16,7 @@ import type { ActionResult } from "@/app/actions/library";
type Toast = {
id: number;
message: string;
tone: "info" | "error";
tone: "info" | "error" | "erfolg";
undo?: () => Promise<void> | void;
};
@@ -58,6 +58,12 @@ export function ToastProvider({ children }: { children: React.ReactNode }) {
show(result.message, {
undo: undo && ids.length > 0 ? () => void undo(ids) : undefined,
});
// Errungenschaften bekommen eine eigene Einblendung — sie sollen nicht
// in der Meldung über das Abhaken untergehen.
for (const name of result.achievements ?? []) {
show(`Errungenschaft: ${name}`, { tone: "erfolg" });
}
},
[show],
);
@@ -96,8 +102,15 @@ function ToastItem({ toast, onDismiss }: { toast: Toast; onDismiss: () => void }
borderColor:
toast.tone === "error"
? "color-mix(in oklab, var(--fl-danger) 50%, transparent)"
: "var(--fl-border)",
color: toast.tone === "error" ? "var(--fl-danger)" : "var(--fl-text)",
: toast.tone === "erfolg"
? "color-mix(in oklab, var(--fl-success) 50%, transparent)"
: "var(--fl-border)",
color:
toast.tone === "error"
? "var(--fl-danger)"
: toast.tone === "erfolg"
? "var(--fl-success)"
: "var(--fl-text)",
}}
>
<span className="flex-1">{toast.message}</span>