215 lines
9.7 KiB
Markdown
215 lines
9.7 KiB
Markdown
---
|
|
phase: 07-task-sorting
|
|
plan: 02
|
|
type: execute
|
|
wave: 2
|
|
depends_on: ["07-01"]
|
|
files_modified:
|
|
- lib/features/tasks/presentation/sort_dropdown.dart
|
|
- lib/features/home/presentation/home_screen.dart
|
|
- lib/features/tasks/presentation/task_list_screen.dart
|
|
- test/features/home/presentation/home_screen_test.dart
|
|
autonomous: true
|
|
requirements: [SORT-01, SORT-02, SORT-03]
|
|
|
|
must_haves:
|
|
truths:
|
|
- "A sort dropdown is visible in the HomeScreen AppBar showing the current sort label"
|
|
- "A sort dropdown is visible in the TaskListScreen AppBar showing the current sort label"
|
|
- "Tapping the dropdown shows three options: A-Z, Intervall, Aufwand"
|
|
- "Selecting a sort option updates the task list order immediately"
|
|
- "The sort preference persists across screen navigations and app restarts"
|
|
artifacts:
|
|
- path: "lib/features/tasks/presentation/sort_dropdown.dart"
|
|
provides: "Reusable SortDropdown ConsumerWidget"
|
|
exports: ["SortDropdown"]
|
|
- path: "lib/features/home/presentation/home_screen.dart"
|
|
provides: "HomeScreen with AppBar containing SortDropdown"
|
|
contains: "SortDropdown"
|
|
- path: "lib/features/tasks/presentation/task_list_screen.dart"
|
|
provides: "TaskListScreen AppBar with SortDropdown alongside edit/delete"
|
|
contains: "SortDropdown"
|
|
key_links:
|
|
- from: "lib/features/tasks/presentation/sort_dropdown.dart"
|
|
to: "sortPreferenceProvider"
|
|
via: "ref.watch for display, ref.read for mutation"
|
|
pattern: "ref\\.watch\\(sortPreferenceProvider\\)"
|
|
- from: "lib/features/home/presentation/home_screen.dart"
|
|
to: "lib/features/tasks/presentation/sort_dropdown.dart"
|
|
via: "SortDropdown widget in AppBar actions"
|
|
pattern: "SortDropdown"
|
|
- from: "lib/features/tasks/presentation/task_list_screen.dart"
|
|
to: "lib/features/tasks/presentation/sort_dropdown.dart"
|
|
via: "SortDropdown widget in AppBar actions"
|
|
pattern: "SortDropdown"
|
|
---
|
|
|
|
<objective>
|
|
Build the sort dropdown widget and wire it into both task list screens (HomeScreen and TaskListScreen), adding an AppBar to HomeScreen.
|
|
|
|
Purpose: Gives users visible access to the sort controls. The data layer from Plan 01 already sorts reactively; this plan adds the UI trigger.
|
|
|
|
Output: SortDropdown reusable widget, updated HomeScreen with AppBar, updated TaskListScreen with dropdown in existing AppBar, updated tests.
|
|
</objective>
|
|
|
|
<execution_context>
|
|
@/home/jlmak/.claude/get-shit-done/workflows/execute-plan.md
|
|
@/home/jlmak/.claude/get-shit-done/templates/summary.md
|
|
</execution_context>
|
|
|
|
<context>
|
|
@.planning/PROJECT.md
|
|
@.planning/ROADMAP.md
|
|
@.planning/STATE.md
|
|
@.planning/phases/07-task-sorting/07-CONTEXT.md
|
|
@.planning/phases/07-task-sorting/07-01-SUMMARY.md
|
|
|
|
<interfaces>
|
|
<!-- Interfaces from Plan 01 that this plan depends on -->
|
|
|
|
From lib/features/tasks/domain/task_sort_option.dart (created in 07-01):
|
|
```dart
|
|
enum TaskSortOption { alphabetical, interval, effort }
|
|
```
|
|
|
|
From lib/features/tasks/presentation/sort_preference_notifier.dart (created in 07-01):
|
|
```dart
|
|
@riverpod
|
|
class SortPreferenceNotifier extends _$SortPreferenceNotifier {
|
|
TaskSortOption build(); // returns alphabetical by default
|
|
Future<void> setSortOption(TaskSortOption option);
|
|
}
|
|
// Generated as: sortPreferenceProvider
|
|
```
|
|
|
|
From lib/l10n/app_de.arb (strings added in 07-01):
|
|
```
|
|
sortAlphabetical: "A-Z"
|
|
sortInterval: "Intervall"
|
|
sortEffort: "Aufwand"
|
|
sortLabel: "Sortierung"
|
|
```
|
|
|
|
<!-- Existing interfaces being modified -->
|
|
|
|
From lib/features/home/presentation/home_screen.dart:
|
|
```dart
|
|
class HomeScreen extends ConsumerStatefulWidget {
|
|
// Currently: Stack with CalendarStrip + CalendarDayList + floating Today FAB
|
|
// No AppBar — body sits directly inside AppShell's Scaffold
|
|
}
|
|
```
|
|
|
|
From lib/features/tasks/presentation/task_list_screen.dart:
|
|
```dart
|
|
class TaskListScreen extends ConsumerWidget {
|
|
// Has its own Scaffold with AppBar containing edit + delete IconButtons
|
|
// AppBar actions: [edit, delete]
|
|
}
|
|
```
|
|
|
|
From lib/features/home/presentation/calendar_strip.dart:
|
|
```dart
|
|
class CalendarStrip extends StatefulWidget {
|
|
const CalendarStrip({super.key, required this.controller, this.onTodayVisibilityChanged});
|
|
final CalendarStripController controller;
|
|
final ValueChanged<bool>? onTodayVisibilityChanged;
|
|
}
|
|
```
|
|
</interfaces>
|
|
</context>
|
|
|
|
<tasks>
|
|
|
|
<task type="auto">
|
|
<name>Task 1: Build SortDropdown widget and integrate into HomeScreen and TaskListScreen</name>
|
|
<files>
|
|
lib/features/tasks/presentation/sort_dropdown.dart,
|
|
lib/features/home/presentation/home_screen.dart,
|
|
lib/features/tasks/presentation/task_list_screen.dart
|
|
</files>
|
|
<action>
|
|
1. Create `lib/features/tasks/presentation/sort_dropdown.dart`:
|
|
- A `ConsumerWidget` named `SortDropdown`
|
|
- Uses `PopupMenuButton<TaskSortOption>` (Material 3, better than DropdownButton for AppBar trailing actions — it opens a menu overlay rather than inline expansion)
|
|
- `ref.watch(sortPreferenceProvider)` to get current sort option
|
|
- The button child shows the current sort label as a Text widget using l10n strings:
|
|
- `alphabetical` -> `l10n.sortAlphabetical` (A-Z)
|
|
- `interval` -> `l10n.sortInterval` (Intervall)
|
|
- `effort` -> `l10n.sortEffort` (Aufwand)
|
|
- Style the button child as a Row with `Icon(Icons.sort)` + `SizedBox(width: 4)` + label Text. Use `theme.textTheme.labelLarge` for the text.
|
|
- `itemBuilder` returns 3 `PopupMenuItem<TaskSortOption>` entries with check marks: for each option, show a Row with `Icon(Icons.check, size: 18)` (visible only when selected, invisible when not via `Opacity(opacity: isSelected ? 1 : 0)`) + `SizedBox(width: 8)` + label Text
|
|
- `onSelected`: `ref.read(sortPreferenceProvider.notifier).setSortOption(value)`
|
|
- Helper method `String _label(TaskSortOption option, AppLocalizations l10n)` that maps enum to l10n string
|
|
|
|
2. Edit `lib/features/home/presentation/home_screen.dart`:
|
|
- HomeScreen currently returns a `Stack` with `Column(CalendarStrip, Expanded(CalendarDayList))` + optional floating Today button
|
|
- Wrap the entire current Stack in a `Scaffold` with an `AppBar`:
|
|
- `AppBar(title: Text(l10n.tabHome), actions: [const SortDropdown()])`
|
|
- The `tabHome` l10n string already exists ("Ubersicht") — reuse it as the AppBar title for the home screen
|
|
- body: the existing Stack content
|
|
- Keep CalendarStrip, CalendarDayList, and floating Today FAB exactly as they are
|
|
- Import `sort_dropdown.dart`
|
|
- Note: HomeScreen is inside AppShell's Scaffold body. Adding a nested Scaffold is fine and standard for per-tab AppBars in StatefulShellRoute.indexedStack. The AppShell Scaffold provides the bottom nav; the inner Scaffold provides the AppBar.
|
|
|
|
3. Edit `lib/features/tasks/presentation/task_list_screen.dart`:
|
|
- In the existing `AppBar.actions` list, add `const SortDropdown()` BEFORE the edit and delete IconButtons. Order: [SortDropdown, edit, delete].
|
|
- Import `sort_dropdown.dart`
|
|
- No other changes to TaskListScreen
|
|
</action>
|
|
<verify>
|
|
<automated>cd /home/jlmak/Projects/jlmak/HouseHoldKeaper && flutter analyze --no-fatal-infos</automated>
|
|
</verify>
|
|
<done>SortDropdown widget exists showing current sort label with sort icon. HomeScreen has AppBar with title "Ubersicht" and SortDropdown. TaskListScreen AppBar has SortDropdown before edit/delete buttons. dart analyze clean.</done>
|
|
</task>
|
|
|
|
<task type="auto">
|
|
<name>Task 2: Update tests for HomeScreen AppBar and sort dropdown</name>
|
|
<files>
|
|
test/features/home/presentation/home_screen_test.dart
|
|
</files>
|
|
<action>
|
|
1. Edit `test/features/home/presentation/home_screen_test.dart`:
|
|
- Add import for `sort_preference_notifier.dart` and `task_sort_option.dart`
|
|
- In the `_buildApp` helper, add a provider override for `sortPreferenceProvider`:
|
|
```dart
|
|
sortPreferenceProvider.overrideWith(SortPreferenceNotifier.new),
|
|
```
|
|
This will use the real notifier with mock SharedPreferences (already set up in setUp).
|
|
- Add a new test group `'HomeScreen sort dropdown'`:
|
|
- Test: "shows sort dropdown in AppBar" — pump the app with tasks, verify `find.byType(PopupMenuButton<TaskSortOption>)` findsOneWidget
|
|
- Test: "shows AppBar with title" — verify `find.text('Ubersicht')` findsOneWidget (the tabHome l10n string)
|
|
- Verify all existing tests still pass. The addition of an AppBar wrapping the existing content should not break existing assertions since they look for specific widgets/text within the tree.
|
|
|
|
2. Run full test suite to confirm no regressions.
|
|
</action>
|
|
<verify>
|
|
<automated>cd /home/jlmak/Projects/jlmak/HouseHoldKeaper && flutter test && flutter analyze --no-fatal-infos</automated>
|
|
</verify>
|
|
<done>Home screen tests verify AppBar with sort dropdown is present. All 108+ tests pass (106 existing + 2+ new). dart analyze clean.</done>
|
|
</task>
|
|
|
|
</tasks>
|
|
|
|
<verification>
|
|
- `flutter test` — all tests pass including new sort dropdown tests
|
|
- `flutter analyze --no-fatal-infos` — zero issues
|
|
- HomeScreen has AppBar with SortDropdown visible
|
|
- TaskListScreen has SortDropdown in AppBar actions
|
|
- Tapping dropdown shows 3 options with check mark on current selection
|
|
- Selecting a different sort option reorders the task list reactively
|
|
</verification>
|
|
|
|
<success_criteria>
|
|
- SortDropdown widget is reusable and shows current sort with icon
|
|
- HomeScreen has AppBar titled "Ubersicht" with SortDropdown in trailing actions
|
|
- TaskListScreen has SortDropdown before edit/delete buttons in AppBar
|
|
- Sort selection updates task list order immediately (reactive via provider)
|
|
- Sort preference persists (set in one screen, visible in another after navigation)
|
|
- All tests pass, analyze clean
|
|
</success_criteria>
|
|
|
|
<output>
|
|
After completion, create `.planning/phases/07-task-sorting/07-02-SUMMARY.md`
|
|
</output>
|