--- phase: 08-task-delete plan: 02 type: execute wave: 2 depends_on: ["08-01"] files_modified: - lib/features/tasks/presentation/task_providers.dart - lib/features/tasks/presentation/task_form_screen.dart autonomous: true requirements: [DEL-01, DEL-04] must_haves: truths: - "User sees a red delete button at the bottom of the task edit form" - "Tapping delete shows a confirmation dialog before any action" - "Confirming delete on a task with no completions removes it from the database" - "Confirming delete on a task with completions deactivates it (hidden from views)" - "After deletion the user is navigated back to the room task list" artifacts: - path: "lib/features/tasks/presentation/task_form_screen.dart" provides: "Delete button and confirmation dialog in edit mode" contains: "taskDeleteConfirmTitle" - path: "lib/features/tasks/presentation/task_providers.dart" provides: "Smart delete method using getCompletionCount" contains: "softDeleteTask" key_links: - from: "lib/features/tasks/presentation/task_form_screen.dart" to: "lib/features/tasks/presentation/task_providers.dart" via: "TaskActions.smartDeleteTask call from delete button callback" pattern: "smartDeleteTask" - from: "lib/features/tasks/presentation/task_providers.dart" to: "lib/features/tasks/data/tasks_dao.dart" via: "getCompletionCount + conditional deleteTask or softDeleteTask" pattern: "getCompletionCount.*softDeleteTask|deleteTask" --- Add the delete button and confirmation dialog to the task edit form, with smart delete logic in the provider layer. Purpose: Users can remove tasks they no longer need. The smart behavior (hard vs soft delete) is invisible to the user -- they just see "delete" with a confirmation. Output: Working delete flow on the task edit form: red button -> confirmation dialog -> smart delete -> navigate back. @/home/jlmak/.claude/get-shit-done/workflows/execute-plan.md @/home/jlmak/.claude/get-shit-done/templates/summary.md @.planning/PROJECT.md @.planning/ROADMAP.md @.planning/STATE.md @.planning/phases/08-task-delete/08-CONTEXT.md @.planning/phases/08-task-delete/08-01-SUMMARY.md From lib/features/tasks/presentation/task_providers.dart (existing TaskActions): ```dart @riverpod class TaskActions extends _$TaskActions { @override FutureOr build() {} Future createTask({...}) async { ... } Future updateTask(Task task) async { ... } Future deleteTask(int taskId) async { ... } // calls DAO hard delete Future completeTask(int taskId) async { ... } } ``` From lib/features/tasks/data/tasks_dao.dart (after Plan 01): ```dart class TasksDao { Future deleteTask(int taskId); // hard delete (cascade) Future softDeleteTask(int taskId); // sets isActive = false Future getCompletionCount(int taskId); // count completions } ``` From lib/features/tasks/presentation/task_form_screen.dart (edit mode section): ```dart // History section (edit mode only) — delete button goes AFTER this if (widget.isEditing) ...[ const SizedBox(height: 24), const Divider(), ListTile( leading: const Icon(Icons.history), title: Text(l10n.taskHistoryTitle), trailing: const Icon(Icons.chevron_right), onTap: () => showTaskHistorySheet( context: context, taskId: widget.taskId!, ), ), ], ``` From lib/l10n/app_de.arb (existing delete l10n strings): ```json "taskDeleteConfirmTitle": "Aufgabe l\u00f6schen?", "taskDeleteConfirmMessage": "Die Aufgabe wird unwiderruflich gel\u00f6scht.", "taskDeleteConfirmAction": "L\u00f6schen" ``` Room delete dialog pattern (from lib/features/rooms/presentation/rooms_screen.dart:165-189): ```dart showDialog( context: context, builder: (ctx) => AlertDialog( title: Text(l10n.roomDeleteConfirmTitle), content: Text(l10n.roomDeleteConfirmMessage), actions: [ TextButton( onPressed: () => Navigator.pop(ctx), child: Text(l10n.cancel), ), FilledButton( style: FilledButton.styleFrom( backgroundColor: Theme.of(ctx).colorScheme.error, ), onPressed: () { ... }, child: Text(l10n.roomDeleteConfirmAction), ), ], ), ); ``` Task 1: Add smartDeleteTask to TaskActions provider lib/features/tasks/presentation/task_providers.dart Add a `smartDeleteTask` method to the `TaskActions` class in task_providers.dart. This method checks the completion count and routes to hard delete or soft delete accordingly: ```dart /// Smart delete: hard-deletes tasks with no completions, soft-deletes tasks with completions. Future smartDeleteTask(int taskId) async { final db = ref.read(appDatabaseProvider); final completionCount = await db.tasksDao.getCompletionCount(taskId); if (completionCount == 0) { await db.tasksDao.deleteTask(taskId); } else { await db.tasksDao.softDeleteTask(taskId); } } ``` Keep the existing `deleteTask` method unchanged (it is still a valid hard delete for other uses like room cascade delete). Run `dart run build_runner build --delete-conflicting-outputs` to regenerate the provider code. cd /home/jlmak/Projects/jlmak/HouseHoldKeaper && dart analyze --fatal-infos lib/features/tasks/presentation/task_providers.dart - smartDeleteTask method exists on TaskActions - Method checks completion count and routes to hard or soft delete - dart analyze passes with zero issues Task 2: Add delete button and confirmation dialog to TaskFormScreen lib/features/tasks/presentation/task_form_screen.dart 1. In the TaskFormScreen build method's ListView children, AFTER the history section (the existing `if (widget.isEditing) ...` block ending at line ~204), add the delete button section inside the same `if (widget.isEditing)` block: ```dart if (widget.isEditing) ...[ const SizedBox(height: 24), const Divider(), // History ListTile (existing) ListTile( leading: const Icon(Icons.history), title: Text(l10n.taskHistoryTitle), trailing: const Icon(Icons.chevron_right), onTap: () => showTaskHistorySheet( context: context, taskId: widget.taskId!, ), ), // DELETE BUTTON — new const Divider(), const SizedBox(height: 8), SizedBox( width: double.infinity, child: FilledButton.icon( style: FilledButton.styleFrom( backgroundColor: theme.colorScheme.error, foregroundColor: theme.colorScheme.onError, ), onPressed: _isLoading ? null : _onDelete, icon: const Icon(Icons.delete_outline), label: Text(l10n.taskDeleteConfirmAction), ), ), ], ``` 2. Add a `_onDelete` method to _TaskFormScreenState: ```dart Future _onDelete() async { final l10n = AppLocalizations.of(context); final confirmed = await showDialog( context: context, builder: (ctx) => AlertDialog( title: Text(l10n.taskDeleteConfirmTitle), content: Text(l10n.taskDeleteConfirmMessage), actions: [ TextButton( onPressed: () => Navigator.pop(ctx, false), child: Text(l10n.cancel), ), FilledButton( style: FilledButton.styleFrom( backgroundColor: Theme.of(ctx).colorScheme.error, ), onPressed: () => Navigator.pop(ctx, true), child: Text(l10n.taskDeleteConfirmAction), ), ], ), ); if (confirmed != true || !mounted) return; setState(() => _isLoading = true); try { await ref.read(taskActionsProvider.notifier).smartDeleteTask(widget.taskId!); if (mounted) { context.pop(); } } finally { if (mounted) { setState(() => _isLoading = false); } } } ``` Note: The `l10n.cancel` string should already exist from the room delete dialog. If not, use `MaterialLocalizations.of(context).cancelButtonLabel`. 3. Verify `cancel` l10n key exists. If it does not exist in app_de.arb, check for the existing cancel button pattern in rooms_screen.dart and use the same approach. cd /home/jlmak/Projects/jlmak/HouseHoldKeaper && flutter test --reporter compact && dart analyze --fatal-infos - Red delete button visible at bottom of task edit form (below history, separated by divider) - Delete button only shows in edit mode (not create mode) - Tapping delete shows AlertDialog with title "Aufgabe loschen?" and error-colored confirm button - Canceling dialog does nothing - Confirming dialog calls smartDeleteTask and pops back to room task list - Button is disabled while loading (_isLoading) - All existing tests pass, dart analyze clean - Task edit form shows red delete button below history section with divider separator - Delete button is NOT shown in create mode - Tapping delete shows confirmation dialog matching room delete dialog pattern - Confirming deletes/deactivates the task and navigates back - Canceling returns to the form without changes - All tests pass: `flutter test --reporter compact` - Code quality: `dart analyze --fatal-infos` reports zero issues - Complete delete flow works: open task -> scroll to bottom -> tap delete -> confirm -> back to room task list - Smart delete is invisible to user: tasks with completions are deactivated, tasks without are removed - Delete button follows Material 3 error color pattern - Confirmation dialog uses existing German l10n strings - All 137+ tests pass After completion, create `.planning/phases/08-task-delete/08-02-SUMMARY.md`