feat(manacore/web): add undo toasts to all 14 DetailViews + task completion

Extend undo toast coverage to all modules:
- Delete undo in cards, storage, presi, planta, inventar, skilltree,
  memoro, questions, uload, mukke, citycorners DetailViews
- Task completion toggle in todo ListView shows undo toast

All deletions can now be reversed within 5 seconds via "Rückgängig".

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
Till JS 2026-04-03 14:55:30 +02:00
parent 81716725f2
commit 543e7055b9
12 changed files with 84 additions and 11 deletions

View file

@ -6,6 +6,7 @@
import { liveQuery } from 'dexie';
import { db } from '$lib/data/database';
import { deckStore } from '../stores/decks.svelte';
import { toastStore } from '@manacore/shared-ui/toast';
import { Trash } from '@manacore/shared-icons';
import type { ViewProps } from '$lib/app-registry';
import type { LocalDeck, LocalCard } from '../types';
@ -78,8 +79,12 @@
}
async function deleteDeck() {
await deckStore.deleteDeck(deckId);
const id = deckId;
await deckStore.deleteDeck(id);
goBack();
toastStore.undo('Deck gelöscht', () => {
db.table('decks').update(id, { deletedAt: undefined, updatedAt: new Date().toISOString() });
});
}
</script>

View file

@ -6,6 +6,7 @@
import { liveQuery } from 'dexie';
import { db } from '$lib/data/database';
import { favoritesStore } from '../stores/favorites.svelte';
import { toastStore } from '@manacore/shared-ui/toast';
import { Star, Trash } from '@manacore/shared-icons';
import type { ViewProps } from '$lib/app-registry';
import type { LocalLocation, LocalFavorite } from '../types';
@ -80,11 +81,18 @@
}
async function deleteLocation() {
await db.table('ccLocations').update(locationId, {
const id = locationId;
await db.table('ccLocations').update(id, {
deletedAt: new Date().toISOString(),
updatedAt: new Date().toISOString(),
});
goBack();
toastStore.undo('Ort gelöscht', () => {
db.table('ccLocations').update(id, {
deletedAt: undefined,
updatedAt: new Date().toISOString(),
});
});
}
const categoryLabels: Record<LocalLocation['category'], string> = {

View file

@ -6,6 +6,7 @@
import { liveQuery } from 'dexie';
import { db } from '$lib/data/database';
import { collectionsStore } from '../stores/collections.svelte';
import { toastStore } from '@manacore/shared-ui/toast';
import { Trash } from '@manacore/shared-icons';
import type { ViewProps } from '$lib/app-registry';
import type { LocalCollection, LocalItem } from '../types';
@ -71,8 +72,15 @@
}
async function deleteCollection() {
await collectionsStore.delete(collectionId);
const id = collectionId;
await collectionsStore.delete(id);
goBack();
toastStore.undo('Sammlung gelöscht', () => {
db.table('invCollections').update(id, {
deletedAt: undefined,
updatedAt: new Date().toISOString(),
});
});
}
</script>

View file

@ -6,6 +6,7 @@
import { liveQuery } from 'dexie';
import { db } from '$lib/data/database';
import { memosStore } from '../stores/memos.svelte';
import { toastStore } from '@manacore/shared-ui/toast';
import { Trash, PushPin } from '@manacore/shared-icons';
import type { ViewProps } from '$lib/app-registry';
import type { LocalMemo, ProcessingStatus } from '../types';
@ -60,8 +61,12 @@
}
async function deleteMemo() {
await memosStore.delete(memoId);
const id = memoId;
await memosStore.delete(id);
goBack();
toastStore.undo('Memo gelöscht', () => {
db.table('memos').update(id, { deletedAt: undefined, updatedAt: new Date().toISOString() });
});
}
function formatDuration(ms: number | null): string {

View file

@ -6,6 +6,7 @@
import { liveQuery } from 'dexie';
import { db } from '$lib/data/database';
import { libraryStore } from '../stores/library.svelte';
import { toastStore } from '@manacore/shared-ui/toast';
import { Heart, Trash } from '@manacore/shared-icons';
import type { ViewProps } from '$lib/app-registry';
import type { LocalSong } from '../types';
@ -64,8 +65,12 @@
}
async function deleteSong() {
await libraryStore.delete(songId);
const id = songId;
await libraryStore.delete(id);
goBack();
toastStore.undo('Song gelöscht', () => {
db.table('songs').update(id, { deletedAt: undefined, updatedAt: new Date().toISOString() });
});
}
function formatDuration(sec?: number | null): string {

View file

@ -5,6 +5,7 @@
<script lang="ts">
import { liveQuery } from 'dexie';
import { db } from '$lib/data/database';
import { toastStore } from '@manacore/shared-ui/toast';
import { Trash } from '@manacore/shared-icons';
import type { ViewProps } from '$lib/app-registry';
import type { LocalPlant, HealthStatus, LightLevel } from '../types';
@ -74,11 +75,15 @@
}
async function deletePlant() {
await db.table('plants').update(plantId, {
const id = plantId;
await db.table('plants').update(id, {
deletedAt: new Date().toISOString(),
updatedAt: new Date().toISOString(),
});
goBack();
toastStore.undo('Pflanze gelöscht', () => {
db.table('plants').update(id, { deletedAt: undefined, updatedAt: new Date().toISOString() });
});
}
const healthLabels: Record<HealthStatus, string> = {

View file

@ -6,6 +6,7 @@
import { liveQuery } from 'dexie';
import { db } from '$lib/data/database';
import { decksStore } from '../stores/decks.svelte';
import { toastStore } from '@manacore/shared-ui/toast';
import { Trash } from '@manacore/shared-icons';
import type { ViewProps } from '$lib/app-registry';
import type { LocalDeck, LocalSlide } from '../types';
@ -71,8 +72,15 @@
}
async function deleteDeck() {
await decksStore.deleteDeck(deckId);
const id = deckId;
await decksStore.deleteDeck(id);
goBack();
toastStore.undo('Präsentation gelöscht', () => {
db.table('presiDecks').update(id, {
deletedAt: undefined,
updatedAt: new Date().toISOString(),
});
});
}
</script>

View file

@ -5,6 +5,7 @@
<script lang="ts">
import { liveQuery } from 'dexie';
import { db } from '$lib/data/database';
import { toastStore } from '@manacore/shared-ui/toast';
import { Trash } from '@manacore/shared-icons';
import type { ViewProps } from '$lib/app-registry';
import type { LocalQuestion, QuestionStatus, QuestionPriority, ResearchDepth } from '../types';
@ -68,11 +69,18 @@
}
async function deleteQuestion() {
await db.table('questions').update(questionId, {
const id = questionId;
await db.table('questions').update(id, {
deletedAt: new Date().toISOString(),
updatedAt: new Date().toISOString(),
});
goBack();
toastStore.undo('Frage gelöscht', () => {
db.table('questions').update(id, {
deletedAt: undefined,
updatedAt: new Date().toISOString(),
});
});
}
const statusLabels: Record<QuestionStatus, string> = {

View file

@ -6,6 +6,7 @@
import { liveQuery } from 'dexie';
import { db } from '$lib/data/database';
import { skillStore } from '../stores/skills.svelte';
import { toastStore } from '@manacore/shared-ui/toast';
import { Trash, Lightning } from '@manacore/shared-icons';
import type { ViewProps } from '$lib/app-registry';
import type { LocalSkill, SkillBranch } from '../types';
@ -82,8 +83,12 @@
}
async function deleteSkill() {
await skillStore.deleteSkill(skillId);
const id = skillId;
await skillStore.deleteSkill(id);
goBack();
toastStore.undo('Skill gelöscht', () => {
db.table('skills').update(id, { deletedAt: undefined, updatedAt: new Date().toISOString() });
});
}
</script>

View file

@ -6,6 +6,7 @@
import { liveQuery } from 'dexie';
import { db } from '$lib/data/database';
import { filesStore } from '../stores/files.svelte';
import { toastStore } from '@manacore/shared-ui/toast';
import { Heart, Trash } from '@manacore/shared-icons';
import type { ViewProps } from '$lib/app-registry';
import type { LocalFile } from '../types';
@ -48,8 +49,12 @@
}
async function deleteFile() {
await filesStore.deleteFile(fileId);
const id = fileId;
await filesStore.deleteFile(id);
goBack();
toastStore.undo('Datei gelöscht', () => {
db.table('files').update(id, { deletedAt: undefined, updatedAt: new Date().toISOString() });
});
}
function formatSize(bytes: number): string {

View file

@ -13,6 +13,7 @@
getTaskStats,
} from './queries';
import { tasksStore } from './stores/tasks.svelte';
import { toastStore } from '@manacore/shared-ui/toast';
import { Circle, Check } from '@manacore/shared-icons';
import type { ViewProps } from '$lib/app-registry';
import { dropTarget, dragSource } from '@manacore/shared-ui/dnd';
@ -75,7 +76,12 @@
async function toggleComplete(e: Event, id: string) {
e.stopPropagation();
const task = tasks.find((t) => t.id === id);
const wasCompleted = task?.isCompleted ?? false;
await tasksStore.toggleComplete(id);
toastStore.undo(wasCompleted ? 'Aufgabe wiederhergestellt' : 'Aufgabe erledigt', () =>
tasksStore.toggleComplete(id)
);
}
</script>

View file

@ -5,6 +5,7 @@
<script lang="ts">
import { liveQuery } from 'dexie';
import { db } from '$lib/data/database';
import { toastStore } from '@manacore/shared-ui/toast';
import { Trash } from '@manacore/shared-icons';
import type { ViewProps } from '$lib/app-registry';
import type { LocalLink } from '../types';
@ -67,11 +68,15 @@
}
async function deleteLink() {
await db.table('links').update(linkId, {
const id = linkId;
await db.table('links').update(id, {
deletedAt: new Date().toISOString(),
updatedAt: new Date().toISOString(),
});
goBack();
toastStore.undo('Link gelöscht', () => {
db.table('links').update(id, { deletedAt: undefined, updatedAt: new Date().toISOString() });
});
}
</script>