fix(stats): address CodeRabbit review on delete and vocabulary paths

- Plan lexical removals inside each delete transaction. The plan drives a
  subtraction now rather than a recompute, so a snapshot taken before
  BEGIN IMMEDIATE could subtract totals that no longer match the rows
  removed, and only drift reaching <= 0 self-heals.
- Await the active video's pending anime metadata before deleteAnime's
  guard, so a delete issued while the title association is still being
  parsed can't slip past and let the late update recreate the anime row.
- Order vocabulary pages by (frequency, id). The oversample loop re-runs
  with a growing OFFSET, and tied frequencies gave no stable order, so
  rows could be skipped or repeated across pages.
- Clear the delete error when a retry starts, so cancelling leaves no
  stale failure on screen.
- Seed occurrences, kanji, rollups and cover art in the deleteAnime test;
  the empty-table assertions were passing against empty tables.
- Rename both keyframes to kebab-case for stylelint keyframes-name-pattern.
This commit is contained in:
2026-07-28 02:50:36 -07:00
parent 77b7ed1fa1
commit d5f887a834
6 changed files with 160 additions and 53 deletions
@@ -165,6 +165,9 @@ export function AnimeDetailView({
const handleDeleteAnime = async () => {
if (isDeletingAnimeRef.current) return;
isDeletingAnimeRef.current = true;
// Cleared up front so cancelling a retry doesn't leave the previous
// attempt's failure on screen.
setDeleteError(null);
let confirmed = false;
try {
confirmed = await confirmAnimeDelete(detail.canonicalTitle, detail.episodeCount);