UX safety: confirm destructive deletes, scope dice clear, back up sessionLog, add 404

- New themed useConfirm() hook (no native dialogs). World deletes (notes, quests,
  homebrew, maps) now confirm before removing.
- Dice 'Clear history' is disabled with no active campaign (it used to wipe EVERY
  campaign's rolls) and now confirms; only ever clears the active campaign.
- sessionLog is included in backup/restore and the campaign cascade-delete — it was
  silently dropped on backup and orphaned on campaign delete.
- Unknown URLs render a themed 'Page not found' with a link home instead of a blank shell.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
2026-06-09 17:37:52 +02:00
parent 3e39e44a8a
commit f2e4259c84
10 changed files with 99 additions and 11 deletions
+2 -1
View File
@@ -65,7 +65,7 @@ export const campaignsRepo = {
async remove(id: string): Promise<void> {
await db.transaction(
'rw',
[db.campaigns, db.characters, db.encounters, db.diceRolls, db.notes, db.npcs, db.quests, db.calendars, db.maps, db.homebrew],
[db.campaigns, db.characters, db.encounters, db.diceRolls, db.notes, db.npcs, db.quests, db.calendars, db.maps, db.homebrew, db.sessionLog],
async () => {
await db.characters.where('campaignId').equals(id).delete();
await db.encounters.where('campaignId').equals(id).delete();
@@ -75,6 +75,7 @@ export const campaignsRepo = {
await db.quests.where('campaignId').equals(id).delete();
await db.maps.where('campaignId').equals(id).delete();
await db.homebrew.where('campaignId').equals(id).delete();
await db.sessionLog.where('campaignId').equals(id).delete();
await db.calendars.delete(id);
await db.campaigns.delete(id);
},