docs(09-01): complete frequency picker rework plan
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -34,7 +34,7 @@ See `milestones/v1.1-ROADMAP.md` for full phase details.
|
|||||||
**v1.2 Polish & Task Management (Phases 8-10):**
|
**v1.2 Polish & Task Management (Phases 8-10):**
|
||||||
|
|
||||||
- [x] **Phase 8: Task Delete** - Add smart delete action to tasks — hard delete if never completed, soft delete (deactivate) if completed at least once (completed 2026-03-18)
|
- [x] **Phase 8: Task Delete** - Add smart delete action to tasks — hard delete if never completed, soft delete (deactivate) if completed at least once (completed 2026-03-18)
|
||||||
- [ ] **Phase 9: Task Creation UX** - Rework the frequency picker from flat preset chips to an intuitive "Every N units" interface with quick-select shortcuts
|
- [x] **Phase 9: Task Creation UX** - Rework the frequency picker from flat preset chips to an intuitive "Every N units" interface with quick-select shortcuts (completed 2026-03-18)
|
||||||
- [ ] **Phase 10: Dead Code Cleanup** - Remove orphaned v1.0 daily plan files and verify no regressions
|
- [ ] **Phase 10: Dead Code Cleanup** - Remove orphaned v1.0 daily plan files and verify no regressions
|
||||||
|
|
||||||
## Phase Details
|
## Phase Details
|
||||||
@@ -58,7 +58,7 @@ Plans:
|
|||||||
**Goal**: Users can set any recurring frequency intuitively without hunting through a grid of preset chips — common frequencies are one tap away, custom intervals are freeform
|
**Goal**: Users can set any recurring frequency intuitively without hunting through a grid of preset chips — common frequencies are one tap away, custom intervals are freeform
|
||||||
**Depends on**: Phase 8
|
**Depends on**: Phase 8
|
||||||
**Requirements**: TCX-01, TCX-02, TCX-03, TCX-04
|
**Requirements**: TCX-01, TCX-02, TCX-03, TCX-04
|
||||||
**Plans:** 1 plan
|
**Plans:** 1/1 plans complete
|
||||||
Plans:
|
Plans:
|
||||||
- [ ] 09-01-PLAN.md — Rework frequency picker: 4 shortcut chips + freeform "Every N units" picker
|
- [ ] 09-01-PLAN.md — Rework frequency picker: 4 shortcut chips + freeform "Every N units" picker
|
||||||
**Success Criteria** (what must be TRUE):
|
**Success Criteria** (what must be TRUE):
|
||||||
@@ -90,5 +90,5 @@ Plans:
|
|||||||
| 6. Task History | v1.1 | 1/1 | Complete | 2026-03-16 |
|
| 6. Task History | v1.1 | 1/1 | Complete | 2026-03-16 |
|
||||||
| 7. Task Sorting | v1.1 | 2/2 | Complete | 2026-03-16 |
|
| 7. Task Sorting | v1.1 | 2/2 | Complete | 2026-03-16 |
|
||||||
| 8. Task Delete | 2/2 | Complete | 2026-03-18 | - |
|
| 8. Task Delete | 2/2 | Complete | 2026-03-18 | - |
|
||||||
| 9. Task Creation UX | v1.2 | 0/1 | Planned | - |
|
| 9. Task Creation UX | 1/1 | Complete | 2026-03-18 | - |
|
||||||
| 10. Dead Code Cleanup | v1.2 | - | Planned | - |
|
| 10. Dead Code Cleanup | v1.2 | - | Planned | - |
|
||||||
|
|||||||
@@ -3,14 +3,14 @@ gsd_state_version: 1.0
|
|||||||
milestone: v1.0
|
milestone: v1.0
|
||||||
milestone_name: milestone
|
milestone_name: milestone
|
||||||
status: "Ready for /gsd:plan-phase 8"
|
status: "Ready for /gsd:plan-phase 8"
|
||||||
stopped_at: Completed 08-task-delete 08-02-PLAN.md
|
stopped_at: Completed 09-task-creation-ux 09-01-PLAN.md
|
||||||
last_updated: "2026-03-18T20:08:14.841Z"
|
last_updated: "2026-03-18T21:46:51.068Z"
|
||||||
last_activity: 2026-03-18 — Created v1.2 milestone
|
last_activity: 2026-03-18 — Created v1.2 milestone
|
||||||
progress:
|
progress:
|
||||||
total_phases: 3
|
total_phases: 3
|
||||||
completed_phases: 1
|
completed_phases: 2
|
||||||
total_plans: 2
|
total_plans: 3
|
||||||
completed_plans: 2
|
completed_plans: 3
|
||||||
percent: 0
|
percent: 0
|
||||||
---
|
---
|
||||||
|
|
||||||
@@ -44,6 +44,7 @@ Progress: [░░░░░░░░░░] 0% (0/3 phases)
|
|||||||
| Tests | 89 | 108 | TBD |
|
| Tests | 89 | 108 | TBD |
|
||||||
| Phase 08-task-delete P01 | 9 | 2 tasks | 11 files |
|
| Phase 08-task-delete P01 | 9 | 2 tasks | 11 files |
|
||||||
| Phase 08-task-delete P02 | 2 | 2 tasks | 3 files |
|
| Phase 08-task-delete P02 | 2 | 2 tasks | 3 files |
|
||||||
|
| Phase 09-task-creation-ux P01 | 2 | 1 tasks | 4 files |
|
||||||
|
|
||||||
## Accumulated Context
|
## Accumulated Context
|
||||||
|
|
||||||
@@ -55,6 +56,7 @@ Decisions archived to PROJECT.md Key Decisions table.
|
|||||||
- [Phase 08-task-delete]: Migration tests updated to only test v1->v3 and v2->v3 paths since AppDatabase.schemaVersion=3 always migrates to v3
|
- [Phase 08-task-delete]: Migration tests updated to only test v1->v3 and v2->v3 paths since AppDatabase.schemaVersion=3 always migrates to v3
|
||||||
- [Phase 08-task-delete]: smartDeleteTask kept separate from deleteTask to preserve existing hard-delete path for cascade/other uses
|
- [Phase 08-task-delete]: smartDeleteTask kept separate from deleteTask to preserve existing hard-delete path for cascade/other uses
|
||||||
- [Phase 08-task-delete]: Delete button placed after history section with divider, visible only in edit mode
|
- [Phase 08-task-delete]: Delete button placed after history section with divider, visible only in edit mode
|
||||||
|
- [Phase 09-task-creation-ux]: Picker is single source of truth: _resolveFrequency() reads from picker always; _ShortcutFrequency enum handles bidirectional sync via toPickerValues()/fromPickerValues()
|
||||||
|
|
||||||
### Pending Todos
|
### Pending Todos
|
||||||
|
|
||||||
@@ -66,7 +68,7 @@ None.
|
|||||||
|
|
||||||
## Session Continuity
|
## Session Continuity
|
||||||
|
|
||||||
Last session: 2026-03-18T20:03:07.081Z
|
Last session: 2026-03-18T21:46:51.066Z
|
||||||
Stopped at: Completed 08-task-delete 08-02-PLAN.md
|
Stopped at: Completed 09-task-creation-ux 09-01-PLAN.md
|
||||||
Resume file: None
|
Resume file: None
|
||||||
Next action: /gsd:plan-phase 8
|
Next action: /gsd:plan-phase 8
|
||||||
|
|||||||
105
.planning/phases/09-task-creation-ux/09-01-SUMMARY.md
Normal file
105
.planning/phases/09-task-creation-ux/09-01-SUMMARY.md
Normal file
@@ -0,0 +1,105 @@
|
|||||||
|
---
|
||||||
|
phase: 09-task-creation-ux
|
||||||
|
plan: 01
|
||||||
|
subsystem: ui
|
||||||
|
tags: [flutter, dart, l10n, frequency-picker, choice-chip, segmented-button]
|
||||||
|
|
||||||
|
# Dependency graph
|
||||||
|
requires: []
|
||||||
|
provides:
|
||||||
|
- Reworked frequency picker with 4 shortcut chips (Täglich, Wöchentlich, Alle 2 Wochen, Monatlich)
|
||||||
|
- Always-visible freeform "Alle [N] [unit]" picker replacing hidden Custom mode
|
||||||
|
- Bidirectional chip/picker sync via _ShortcutFrequency enum
|
||||||
|
- Unified _resolveFrequency() reading exclusively from picker (single source of truth)
|
||||||
|
- Edit mode loading for all 8 IntervalType values including quarterly and yearly
|
||||||
|
affects: []
|
||||||
|
|
||||||
|
# Tech tracking
|
||||||
|
tech-stack:
|
||||||
|
added: []
|
||||||
|
patterns:
|
||||||
|
- "Shortcut chip + freeform picker: ChoiceChip row above always-visible SegmentedButton picker"
|
||||||
|
- "Bidirectional sync: chip tapped populates picker; picker edited recalculates chip highlight via fromPickerValues()"
|
||||||
|
- "Single source of truth: _resolveFrequency() always reads from picker, never from a preset reference"
|
||||||
|
|
||||||
|
key-files:
|
||||||
|
created: []
|
||||||
|
modified:
|
||||||
|
- lib/features/tasks/presentation/task_form_screen.dart
|
||||||
|
- lib/l10n/app_de.arb
|
||||||
|
- lib/l10n/app_localizations.dart
|
||||||
|
- lib/l10n/app_localizations_de.dart
|
||||||
|
|
||||||
|
key-decisions:
|
||||||
|
- "Picker is single source of truth: _resolveFrequency() reads from _customIntervalController + _customUnit always"
|
||||||
|
- "_ShortcutFrequency enum with toPickerValues() and fromPickerValues() handles bidirectional sync without manual mapping"
|
||||||
|
- "Named IntervalTypes (daily/weekly/biweekly/monthly) used for canonical values; only everyNDays for 3+ weeks"
|
||||||
|
- "Quarterly (3 months) and yearly (12 months) displayed correctly in picker with no chip highlighted"
|
||||||
|
|
||||||
|
patterns-established:
|
||||||
|
- "Shortcut chip pattern: enum with toPickerValues() / fromPickerValues() for bidirectional picker sync"
|
||||||
|
|
||||||
|
requirements-completed: [TCX-01, TCX-02, TCX-03, TCX-04]
|
||||||
|
|
||||||
|
# Metrics
|
||||||
|
duration: 2min
|
||||||
|
completed: 2026-03-18
|
||||||
|
---
|
||||||
|
|
||||||
|
# Phase 9 Plan 01: Task Creation UX — Frequency Picker Rework Summary
|
||||||
|
|
||||||
|
**4 shortcut chips (Täglich/Wöchentlich/Alle 2 Wochen/Monatlich) + always-visible freeform picker replacing the 10-chip grid with hidden Custom mode**
|
||||||
|
|
||||||
|
## Performance
|
||||||
|
|
||||||
|
- **Duration:** 2 min
|
||||||
|
- **Started:** 2026-03-18T21:43:24Z
|
||||||
|
- **Completed:** 2026-03-18T21:45:30Z
|
||||||
|
- **Tasks:** 1 (+ 1 auto-approved checkpoint)
|
||||||
|
- **Files modified:** 4
|
||||||
|
|
||||||
|
## Accomplishments
|
||||||
|
- Replaced 10-chip preset grid and hidden "Benutzerdefiniert" mode with 4 shortcut chips + always-visible freeform picker
|
||||||
|
- Implemented bidirectional sync: tapping a chip populates the picker; editing the picker recalculates chip highlight
|
||||||
|
- Simplified _resolveFrequency() to read exclusively from the picker (single source of truth), using named IntervalTypes for canonical values
|
||||||
|
- Edit mode correctly loads all 8 IntervalType values (daily, everyNDays, weekly, biweekly, monthly, everyNMonths, quarterly, yearly) into the picker and highlights the matching shortcut chip where applicable
|
||||||
|
|
||||||
|
## Task Commits
|
||||||
|
|
||||||
|
Each task was committed atomically:
|
||||||
|
|
||||||
|
1. **Task 1: Rework frequency picker — shortcut chips + freeform picker** - `8a0b69b` (feat)
|
||||||
|
2. **Task 2: Verify frequency picker UX** - auto-approved (checkpoint:human-verify, auto_advance=true)
|
||||||
|
|
||||||
|
**Plan metadata:** (docs commit follows)
|
||||||
|
|
||||||
|
## Files Created/Modified
|
||||||
|
- `lib/features/tasks/presentation/task_form_screen.dart` - Reworked frequency picker: removed _selectedPreset and _isCustomFrequency fields; added _ShortcutFrequency enum and _activeShortcut state; replaced _buildFrequencySelector() with shortcut chips + always-visible picker; renamed _buildCustomFrequencyInput to _buildFrequencyPickerRow with bidirectional sync; simplified _resolveFrequency() to picker-only
|
||||||
|
- `lib/l10n/app_de.arb` - Added frequencyShortcutDaily/Weekly/Biweekly/Monthly keys
|
||||||
|
- `lib/l10n/app_localizations.dart` - Regenerated to include new shortcut string getters
|
||||||
|
- `lib/l10n/app_localizations_de.dart` - Regenerated with German translations (Täglich, Wöchentlich, Alle 2 Wochen, Monatlich)
|
||||||
|
|
||||||
|
## Decisions Made
|
||||||
|
- Picker is single source of truth: _resolveFrequency() reads from _customIntervalController + _customUnit always, regardless of which chip is highlighted
|
||||||
|
- _ShortcutFrequency enum with toPickerValues() and static fromPickerValues() cleanly handles bidirectional sync without manual if-chain mapping in each callback
|
||||||
|
- Named IntervalTypes (daily/weekly/biweekly/monthly) used for canonical values (e.g., weekly has days=1, biweekly has days=14) matching existing DB records; only everyNDays used for 3+ weeks
|
||||||
|
- Quarterly (3 months) and yearly (12 months) round-trip correctly: loaded as "3 Monate" / "12 Monate" in picker with no chip highlighted
|
||||||
|
|
||||||
|
## Deviations from Plan
|
||||||
|
|
||||||
|
None - plan executed exactly as written.
|
||||||
|
|
||||||
|
## Issues Encountered
|
||||||
|
None.
|
||||||
|
|
||||||
|
## User Setup Required
|
||||||
|
None - no external service configuration required.
|
||||||
|
|
||||||
|
## Next Phase Readiness
|
||||||
|
- Frequency picker rework complete; TaskFormScreen is ready for further UX improvements
|
||||||
|
- All 144 existing tests pass, dart analyze is clean
|
||||||
|
- No changes to frequency.dart, no DB migration, no new screens
|
||||||
|
|
||||||
|
---
|
||||||
|
*Phase: 09-task-creation-ux*
|
||||||
|
*Completed: 2026-03-18*
|
||||||
Reference in New Issue
Block a user