focus-flow/Codex Documentation/Completed Plans/UI Plan 2 - Backlog Board Implementation/UI_PLAN_2_SUMMARY.md

345 lines
15 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<!-- SPDX-FileCopyrightText: 2026 FocusFlow contributors -->
<!-- SPDX-License-Identifier: AGPL-3.0-only -->
# UI Plan 2 — Backlog Board Tab Implementation
**Status:** Proposed plan.
**Primary target:** Implement the finalized Backlog tab shown in the two supplied mockups.
**Default mockup:** `mockups/backlog_board_default.png`.
**Drawer mockup:** `mockups/backlog_task_drawer.png`.
**Execution mode:** Feed this folder to Codex and execute block files in numeric order. Use `xhigh` reasoning for all chunks unless Ashley explicitly says otherwise.
**Implementation branch suggestion:** `block-ui-backlog-board` or the repos closest existing branch convention.
---
## 1. Purpose
Build the desktop-first Backlog tab for FocusFlow as a real Flutter screen, not a throwaway static mockup. The final state should provide:
1. Sidebar navigation with `Backlog` active.
2. Backlog title, task count, search, filters, sort, group, board/compact toggle, settings button, and `New Task` primary action.
3. Four-column backlog board:
- `Do Next`
- `Need Time Block`
- `Break Up First`
- `Not Now`
4. Backlog task cards with project, priority, duration, difficulty bars, reward icons, child-task previews, and selection styling.
5. Right-side Backlog summary panel in the default state.
6. Right-anchored task detail drawer when a backlog card is selected.
7. Suggested slots and task actions in the drawer.
8. New task / add task entry points wired to backlog-safe capture.
9. Tests and validation that preserve the existing backend-source-of-truth rule.
This plan intentionally treats the mockups as finalized visual direction and uses the current repo architecture as implementation truth.
---
## 2. Source truth and constraints
Use sources in this order:
1. Repo files, especially `AGENTS.md`, package boundaries, existing app structure, and tests.
2. This plan folder.
3. The two mockups in `mockups/`.
4. Existing completed UI Plan 1 files.
5. Human documentation and UX flow documents already in the repo.
Hard constraints:
- V1 is SQLite-first. Do not add MongoDB runtime work.
- `scheduler_core` remains pure Dart and is the scheduling/application source of truth.
- Flutter must not import scheduler `src/`, Drift/SQLite adapters, notification platform packages, backup/export internals, or OS APIs directly.
- UI may own local visual selection state, menu open/closed state, scroll position, text controller state, and drawer open/closed state.
- UI must not own canonical scheduling rules, placement rules, task lifecycle rules, or persistence mutations.
- Any scheduling/task mutation must go through public scheduler application commands/controllers.
- New Dart files require file-level Dartdoc library docs plus Dartdoc for every public/private class, enum, enum value, constructor, method, field, and top-level declaration, following `AGENTS.md`.
- New project files require SPDX metadata.
---
## 3. Confirmed repo observations from this planning pass
The supplied repo already contains:
- Flutter app target: `apps/focus_flow_flutter/`.
- Current provisional/Plan 1 Today UI with sidebar, app shell, theme tokens, top bar, timeline cards, difficulty bars, reward icons, and selected-task modal pieces.
- Current simple `BacklogPane` and `BacklogRow` that are not visually aligned with the finalized board mockup.
- Existing public scheduler application/query concepts:
- `V1ApplicationManagementUseCases.getBacklog`.
- `BacklogQueryResult`.
- `BacklogItemReadModel`.
- `GetBacklogRequest`.
- `BacklogView`, `BacklogFilter`, and `BacklogSortKey`.
- `V1ApplicationCommandUseCases.quickCaptureToBacklog`.
- `V1ApplicationCommandUseCases.scheduleBacklogItemToNextAvailableSlot`.
- `V1ApplicationCommandUseCases.breakUpTask`.
- Existing domain `Task` supports core scheduling fields, project id, duration, priority, reward, difficulty, backlog tags, parent task id, stats, timestamps, scheduled/actual/completed intervals, status, and type.
- Current domain `Task` does **not** appear to include freeform notes or general tags, which the drawer mockup shows.
- Current application commands do **not** appear to include a general update/edit-backlog-task command, push-to-someday command, or remove/archive backlog command.
Plan implication: this is a UI implementation plus a small application/domain read-model expansion, not only a widget rewrite.
---
## 4. Product assumptions to implement unless Ashley changes them
These assumptions unblock Codex without inventing broad product scope:
1. **Backlog columns are a V1 read-model policy.** The Flutter board consumes a `BacklogBoardReadModel`; it does not independently decide canonical task grouping.
2. **Column assignment is deterministic and explainable.** Each item exposes `bucket`, `bucketReason`, and optional `reasonMetadata` so the UI can show why it is in that column.
3. **General tags and notes are V1 task metadata.** Add minimal domain/persistence/application support needed for the drawer and create/edit flows.
4. **Remove means archive from active backlog, not physical delete.** Use an application-level remove/archive transition that hides the task from backlog. Prefer `TaskStatus.noLongerRelevant` unless a repo-local convention already says otherwise.
5. **Push to Someday means mark the task as a someday/wishlist backlog item.** Use existing `BacklogTag.wishlist` where possible. This should move or keep the task in `Not Now`.
6. **Suggested slots are non-mutating previews.** They must be generated by application/core read logic or by calling scheduler logic against cloned/current state. They must not save anything until the user presses `Schedule`.
7. **Schedule button chooses a suggested slot only through backend intent.** If the current command only supports “next available slot,” wire the primary button to that command and label suggested rows as preview-only until a slot-specific command exists.
8. **Compact mode can remain a non-primary visual affordance.** Board mode is the acceptance target because only Board has a finalized mockup. If a low-risk compact list already exists, it may be reused behind the toggle, but do not invent a second finalized design.
9. **Settings remains visible and inert for this plan** unless a settings surface already exists.
10. **Project dropdown and tag controls in the drawer should support inline edits only after the relevant update command exists.** If the command is not completed in the same block, render them as disabled/read-only with active visual styling deferred only at the final polish pass.
Non-blocking clarification items for Ashley after plan review:
- Exact board bucket policy thresholds for `Do Next`, `Need Time Block`, `Break Up First`, and `Not Now`.
- Whether `Remove` should be reversible archive, cancellation, no-longer-relevant, or hard delete.
- Whether slot rows should support picking a specific slot in V1 or only preview the result of next-available scheduling.
- Whether freeform tags should be global reusable tags or simple task-local strings in V1.
Do not stop implementation on those questions unless Ashley explicitly requests a policy change before coding.
---
## 5. Visual target summary
### App shell and sidebar
- Keep the dark rounded app frame and left sidebar style from UI Plan 1.
- Sidebar width remains approximately 250 px.
- `Backlog` nav item is active with magenta-tinted fill and outline.
- `Today`, `Projects`, `Reports`, and `Settings` remain visible.
- Bottom-left status card shows:
- green check icon,
- `Schedule up to date`,
- `All changes are saved.`
### Backlog default state
At desktop width around 1672×941:
- Main content has a left board region and a right summary panel.
- Header row:
- `Backlog` title,
- `24 tasks` count pill,
- subtitle: `Choose work that fits your current energy.`
- right controls: `Compact`, `Board` active, `Settings`.
- Control row:
- search field with placeholder `Search backlog...`,
- `Filters` button,
- `Sort: Custom` dropdown,
- `Group: None` dropdown,
- magenta `+ New Task` button with trailing chevron.
- Board columns:
- each column has an icon, title, count pill, subtitle, add icon, card stack, and `+ Add task` footer.
- Summary panel:
- `Backlog summary` header with sparkle icon and collapse chevron,
- total tasks and total estimated time,
- priority counts,
- project counts,
- duration distribution donut/list,
- planning tip card.
### Selected-card drawer state
- Selecting/clicking a backlog card opens a right-side drawer.
- Drawer is anchored to the right edge of the app content/window.
- Drawer overlays existing content and does **not** shift columns, header controls, or summary panel.
- No heavy scrim; underlying board remains visible.
- Selected card remains highlighted with magenta outline behind the drawer.
- Drawer width should be approximately 460470 px at mockup width, clamped for smaller desktop windows.
- Drawer sections:
- header with bucket/status icon, title, sparkle icon, close icon,
- subtitle and age/created metadata,
- notes panel,
- project selector and tag chips,
- duration/reward/difficulty metric tiles,
- suggested slots list,
- action buttons: `Schedule`, `Break Up`, `Push to Someday`, `Remove`.
---
## 6. Feature scope
### In scope
- Backlog route/tab under current Flutter app.
- Sidebar nav state and Backlog active rendering.
- Backlog-specific controllers/read state.
- Backlog board read models in public scheduler/application API.
- Demo seed data sufficient to render the exact mockup composition.
- Four board columns with counts and card ordering.
- Default summary panel.
- Drawer open/close/select-another behavior.
- Search/filter/sort/group controls with at least deterministic basic behavior.
- New Task and Add Task entry points with backlog-safe capture.
- Schedule action for a selected backlog item.
- Break Up action path if the existing `breakUpTask` command can be surfaced safely; otherwise the drawer button may open a non-persisting placeholder form until Block 8 completes the command wiring.
- Push to Someday command using `BacklogTag.wishlist` or equivalent.
- Remove/archive command using the chosen non-destructive lifecycle transition.
- Notes and tags support needed for drawer/create/edit read and persistence.
- Responsive handling for desktop width reductions.
- Widget tests and core/application tests.
### Out of scope
- Week/month views.
- Drag-and-drop card movement.
- Reports implementation.
- Shield/Recovery flows.
- Calendar sync.
- OS notifications.
- Backup/restore UI.
- Export/import UI.
- Full settings implementation.
- Perfect pixel golden tests.
- Mobile-first layout.
---
## 7. Target data/read-model shape
Codex may adjust exact names to match repo conventions, but preserve the information architecture.
```dart
enum BacklogBoardBucket {
doNext,
needTimeBlock,
breakUpFirst,
notNow,
}
class BacklogBoardQueryResult {
final String ownerId;
final CivilDate localDate;
final BacklogBoardSummaryReadModel summary;
final List<BacklogBoardColumnReadModel> columns;
final List<ProjectOptionReadModel> projectOptions;
}
class BacklogBoardColumnReadModel {
final BacklogBoardBucket bucket;
final String title;
final String subtitle;
final String accentToken;
final int count;
final List<BacklogBoardItemReadModel> items;
}
class BacklogBoardItemReadModel {
final String taskId;
final String title;
final String? subtitle;
final String projectId;
final String projectName;
final String projectColorToken;
final int? durationMinutes;
final PriorityLevel? priority;
final RewardLevel reward;
final DifficultyLevel difficulty;
final BacklogBoardBucket bucket;
final String bucketReason;
final DateTime createdAt;
final DateTime updatedAt;
final bool hasChildren;
final List<BacklogChildPreviewReadModel> childPreview;
final List<String> tags;
}
class BacklogTaskDetailReadModel {
final BacklogBoardItemReadModel item;
final String? notes;
final String addedLabel;
final List<String> tags;
final List<ProjectOptionReadModel> projectOptions;
final List<SuggestedSlotReadModel> suggestedSlots;
}
```
Summary should include:
- total tasks,
- total estimated minutes,
- priority distribution,
- project distribution,
- duration distribution buckets: `030`, `3060`, `60120`, `120+`,
- planning tip string.
Suggested slots should include:
- stable id,
- local date label,
- start/end display text,
- duration minutes,
- fit label (`Great Fit`, `Okay`, no-fit/conflict if relevant),
- fit severity token,
- whether it is the primary/default scheduling target.
---
## 8. Block list
Execute these files in order:
1. `UI_PLAN_2_BLOCK_01_REPO_SCOPE_AND_ASSETS.md`
2. `UI_PLAN_2_BLOCK_02_BACKLOG_READ_MODELS_AND_METADATA.md`
3. `UI_PLAN_2_BLOCK_03_NAVIGATION_AND_SCREEN_SHELL.md`
4. `UI_PLAN_2_BLOCK_04_BOARD_COLUMNS_AND_CARDS.md`
5. `UI_PLAN_2_BLOCK_05_SEARCH_FILTER_SORT_GROUP.md`
6. `UI_PLAN_2_BLOCK_06_SUMMARY_PANEL.md`
7. `UI_PLAN_2_BLOCK_07_TASK_DETAIL_DRAWER.md`
8. `UI_PLAN_2_BLOCK_08_COMMANDS_CREATE_AND_ACTIONS.md`
9. `UI_PLAN_2_BLOCK_09_TESTING_VALIDATION_HANDOFF.md`
---
## 9. Expected final changed areas
Likely changed or added areas:
```text
packages/scheduler_core/lib/src/domain/models/entities/task.dart
packages/scheduler_core/lib/src/application/application_management/**
packages/scheduler_core/lib/src/application/application_commands/**
packages/scheduler_core/lib/src/persistence/document_mapping/tasks/**
packages/scheduler_core/lib/src/persistence/persistence_contract/fields/tasks/**
packages/scheduler_persistence/lib/persistence/repositories/task_repository.dart
packages/scheduler_persistence_memory/**
packages/scheduler_persistence_sqlite/lib/src/scheduler_db/tables/tasks/tasks.dart
packages/scheduler_persistence_sqlite/lib/src/scheduler_db/daos/task_dao.dart
packages/scheduler_persistence_sqlite/lib/src/sqlite_repositories/sqlite_task_repository.dart
apps/focus_flow_flutter/lib/app/**
apps/focus_flow_flutter/lib/controllers/**
apps/focus_flow_flutter/lib/models/backlog/**
apps/focus_flow_flutter/lib/widgets/backlog/**
apps/focus_flow_flutter/lib/widgets/sidebar.dart
apps/focus_flow_flutter/lib/theme/**
apps/focus_flow_flutter/test/**
```
Do not modify unrelated packages unless tests prove a required boundary update.
---
## 10. Final acceptance criteria
The plan is complete when:
- Backlog sidebar item opens/renders the Backlog tab and is visually active.
- Default Backlog board state closely matches `backlog_board_default.png`.
- Selecting `Review Q3 budget` or any task card opens a right-side drawer matching `backlog_task_drawer.png`.
- Drawer overlays content without moving columns or summary.
- Search/filter/sort/group controls are visible and do not break board state.
- Board columns, cards, summary, and drawer are all driven by scheduler/application read models or controller-level display models derived from those read models.
- Schedule action uses scheduler application command(s); UI does not compute canonical placement.
- New task capture creates backlog tasks through scheduler application command(s).
- Push to Someday and Remove are non-destructive domain/application commands, not Flutter-only state deletion.
- Tests cover default render, navigation, controls, card selection, drawer close, summary data, and command callbacks.
- `flutter analyze` and `flutter test` pass under `apps/focus_flow_flutter`.
- Root/package tests touched by domain/persistence changes pass or are explicitly reported if environment prevents full validation.