78881e1b07
Extract CreateRecurringTask into engine package for reuse by both CLI and API. Add POST /tasks/parse endpoint for CLI-style input parsing. Remove FK constraint on change_log to preserve history after task deletion. Update web frontend to filter completed tasks from view and add mock mode support for development. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
291 lines
13 KiB
Markdown
291 lines
13 KiB
Markdown
# Opal Web — PWA Requirements
|
||
|
||
## 1. Problem Statement
|
||
|
||
The current opal-web PWA uses a conventional form-based UI for task management.
|
||
This is misaligned with how opal actually works — opal is a CLI-first tool with
|
||
a rich, expressive text syntax for creating, filtering, and modifying tasks.
|
||
|
||
The new design replaces the form-based approach with a **CLI-passthrough
|
||
interface**: a single text input that accepts the same syntax as the opal CLI,
|
||
making the web UI a thin, mobile-friendly shell over the existing command
|
||
language.
|
||
|
||
**Target users:** Existing opal CLI users who want quick mobile/web access
|
||
without learning a separate UI paradigm.
|
||
|
||
---
|
||
|
||
## 2. User Stories
|
||
|
||
### US-1: Quick-add a task from mobile
|
||
**As a** user, **I want** to type `Buy groceries due:tomorrow +errand` into the
|
||
input and have it create a task, **so that** I can capture tasks as fast as I do
|
||
from the terminal.
|
||
|
||
**Acceptance Criteria:**
|
||
- Given the input is focused and I type a description with modifiers
|
||
- When I submit (Enter / tap send)
|
||
- Then the raw input string is sent to the API, which parses it server-side
|
||
- And a task is created with the parsed description, due date, and tags
|
||
- And the input clears
|
||
- And the new task appears in the list
|
||
|
||
### US-2: Use property pills to build a command
|
||
**As a** user, **I want** to tap a `Due` pill above the input to insert `due:`
|
||
at my cursor position, **so that** I don't have to remember every modifier name
|
||
on mobile.
|
||
|
||
**Acceptance Criteria:**
|
||
- Given the input is focused
|
||
- When I tap the `Due` pill
|
||
- Then `due:` is inserted at the cursor position in the input
|
||
- And the keyboard stays open / input retains focus
|
||
- And the cursor is placed immediately after the inserted text
|
||
|
||
### US-3: View my pending tasks
|
||
**As a** user, **I want** to see my pending tasks in a list above the input,
|
||
**so that** I have context for what I'm working on.
|
||
|
||
**Acceptance Criteria:**
|
||
- Given I open the app
|
||
- When the task list loads
|
||
- Then I see pending tasks displayed in a compact list, sorted by urgency
|
||
- And each task shows its description with inline metadata (project, priority,
|
||
due date, tags) using subtle color coding
|
||
|
||
### US-4: Complete a task via swipe
|
||
**As a** user, **I want** to swipe a task to the right to mark it done, **so
|
||
that** I can quickly clear completed work.
|
||
|
||
**Acceptance Criteria:**
|
||
- Given I see a task in the list
|
||
- When I swipe the task to the right
|
||
- Then a green background with a checkmark is revealed during the swipe
|
||
- And on release past the threshold, the task is marked as completed
|
||
- And the task animates out of the list
|
||
|
||
### US-5: Complete a task via checkbox
|
||
**As a** user, **I want** to tap a checkbox on a task to mark it done, **so
|
||
that** I have a familiar fallback when swiping is inconvenient.
|
||
|
||
**Acceptance Criteria:**
|
||
- Given I see a task in the list
|
||
- When I tap the checkbox/circle on the left side of the task
|
||
- Then the task is marked as completed and animates out of the list
|
||
|
||
### US-6: Filter tasks by report
|
||
**As a** user, **I want** to switch between different task views (pending, next,
|
||
active, overdue, completed, etc.), **so that** I can focus on what's relevant.
|
||
|
||
**Acceptance Criteria:**
|
||
- Given I am on the main task view
|
||
- When I tap the filter/report button
|
||
- Then a dropdown opens showing available reports
|
||
- And selecting a report filters the task list accordingly
|
||
|
||
### US-7: Access settings
|
||
**As a** user, **I want** to access a settings page, **so that** I can
|
||
configure API connection, view sync status, and log out.
|
||
|
||
**Acceptance Criteria:**
|
||
- Given I am on the main task view
|
||
- When I tap the gear icon in the top-right corner
|
||
- Then I navigate to a settings page
|
||
- And I can navigate back to the task list
|
||
|
||
---
|
||
|
||
## 3. Functional Requirements
|
||
|
||
### App Structure
|
||
|
||
| ID | Priority | Requirement |
|
||
|------|----------|-------------|
|
||
| F-00 | MUST | The app is a single-screen design: one main view with task list + input bar |
|
||
| F-01 | MUST | A separate settings page is accessible via a gear icon in the top-right corner |
|
||
| F-02 | MUST | No bottom navigation bar — the input bar occupies the bottom of the screen |
|
||
|
||
### Header
|
||
|
||
| ID | Priority | Requirement |
|
||
|------|----------|-------------|
|
||
| F-05 | MUST | The header contains the current report name (e.g., "Pending", "Next", "Overdue") |
|
||
| F-06 | MUST | The header contains a filter/report button that opens a dropdown of available reports |
|
||
| F-07 | MUST | The header contains a gear icon (top-right) linking to the settings page |
|
||
|
||
### Report Picker
|
||
|
||
| ID | Priority | Requirement |
|
||
|------|----------|-------------|
|
||
| F-08 | MUST | A dropdown/popover triggered by the filter button in the header |
|
||
| F-09 | MUST | Lists all available reports (see table below) |
|
||
| F-0A | MUST | Selecting a report reloads the task list with the corresponding filter |
|
||
| F-0B | MUST | The currently active report is visually indicated in the dropdown |
|
||
| F-0C | SHOULD | Default report on app open is "Pending" |
|
||
|
||
**Reports (all CLI reports):**
|
||
|
||
| Report | Description |
|
||
|------------|------------------------------------------|
|
||
| Pending | All pending tasks (default) |
|
||
| Next | Most urgent ready tasks (top N) |
|
||
| Active | Currently started tasks |
|
||
| Ready | Tasks with no future wait/scheduled date |
|
||
| Overdue | Tasks past their due date |
|
||
| Completed | Completed tasks |
|
||
| Waiting | Tasks hidden until their wait date |
|
||
| Recurring | Pending recurring task instances |
|
||
| Template | Recurring template tasks |
|
||
| Newest | Most recently created pending tasks |
|
||
| Oldest | Oldest pending tasks |
|
||
|
||
### Input Bar
|
||
|
||
| ID | Priority | Requirement |
|
||
|------|----------|-------------|
|
||
| F-10 | MUST | A single-line text input is fixed to the bottom of the visible viewport, always visible |
|
||
| F-11 | MUST | The input accepts opal CLI syntax for the `add` command: description words, `+tag`, `project:`, `due:`, `priority:`, `scheduled:`, `wait:`, `until:`, `recur:` |
|
||
| F-12 | MUST | Submitting the input sends the raw string to the API for server-side parsing and task creation |
|
||
| F-13 | MUST | The input clears after successful submission |
|
||
| F-14 | SHOULD | The input bar remains above the mobile keyboard when the keyboard is open |
|
||
| F-15 | MUST | The input is add-only — it does not parse other CLI commands (done, modify, delete, etc.) |
|
||
|
||
### Property Pills
|
||
|
||
| ID | Priority | Requirement |
|
||
|------|----------|-------------|
|
||
| F-20 | MUST | When the input is focused, a row of tappable pills appears directly above the input |
|
||
| F-21 | MUST | Tapping a pill inserts its text at the current cursor position in the input |
|
||
| F-22 | MUST | After inserting, the input retains focus and the cursor is placed after the inserted text |
|
||
| F-23 | MUST | Pills disappear when the input loses focus |
|
||
| F-24 | SHOULD | The pill row is horizontally scrollable if it overflows |
|
||
|
||
**Pills (display order):**
|
||
|
||
| Pill label | Inserts | Notes |
|
||
|--------------|---------------|-------|
|
||
| `Due` | `due:` | Date: tomorrow, mon, eod, 2025-03-15, 3d, etc. |
|
||
| `Pri` | `priority:` | H, M, L |
|
||
| `Project` | `project:` | Project name |
|
||
| `Tag` | `+` | Tag prefix — user types tag name after |
|
||
| `Recur` | `recur:` | Duration: 1d, 1w, 2w, 1m, daily, weekly, etc. |
|
||
| `Scheduled` | `scheduled:` | Same date format as due: |
|
||
| `Wait` | `wait:` | Same date format as due: |
|
||
| `Until` | `until:` | Same date format as due: |
|
||
|
||
### Task List
|
||
|
||
| ID | Priority | Requirement |
|
||
|------|----------|-------------|
|
||
| F-30 | MUST | The main view displays a scrollable list of tasks above the input bar, filtered by the active report |
|
||
| F-31 | MUST | Each task row shows: description, and inline metadata where set (project, priority, due date, tags) |
|
||
| F-32 | MUST | Task rows are compact — hybrid density with subtle color coding for priority and due dates, no full cards |
|
||
| F-33 | MUST | Swiping a task to the right marks it as completed |
|
||
| F-34 | MUST | Each task has a small checkbox/circle on the left that also completes the task on tap |
|
||
| F-35 | MUST | Swipe-to-complete reveals a green background with a checkmark icon during the swipe |
|
||
| F-36 | SHOULD | Tasks are sorted by urgency (matching the CLI's urgency calculation) |
|
||
| F-37 | SHOULD | Overdue due dates are visually distinct (red/warm color) |
|
||
| F-38 | SHOULD | Completed tasks animate out of the list (brief fade/slide) |
|
||
| F-39 | COULD | Pull-to-refresh to reload task list |
|
||
|
||
---
|
||
|
||
## 4. Non-Functional Requirements
|
||
|
||
| ID | Category | Requirement |
|
||
|-------|---------------|-------------|
|
||
| NF-01 | Mobile-first | The UI must work well on 375px–428px viewport widths (iPhone SE through Pro Max) |
|
||
| NF-02 | Performance | Task list should render within 100ms of data availability |
|
||
| NF-03 | PWA | The app must remain installable as a PWA with offline shell caching |
|
||
| NF-04 | Keyboard | The input bar must not be obscured by the mobile keyboard |
|
||
| NF-05 | Touch | Swipe gestures must have clear thresholds (no accidental triggers from scrolling) |
|
||
|
||
---
|
||
|
||
## 5. Constraints & Assumptions
|
||
|
||
### Constraints
|
||
- Must use the existing SvelteKit + Vite + static adapter stack
|
||
- Must work with the existing opal REST API (or mock mode for dev)
|
||
- The opal API can be extended or reworked during the design phase to better
|
||
support the new functionality
|
||
|
||
### Assumptions
|
||
- Users are familiar with opal CLI syntax or will learn it through the pills
|
||
- The `add` command is the only command handled by the input bar
|
||
- **Parsing happens server-side** — the frontend sends the raw input string to
|
||
a new or updated API endpoint; no client-side replication of the opal parser
|
||
- Completion is handled via swipe gesture or checkbox, not via the input bar
|
||
|
||
---
|
||
|
||
## 6. Open Questions
|
||
|
||
All previously open questions have been resolved:
|
||
|
||
| # | Question | Resolution |
|
||
|----|----------|------------|
|
||
| Q1 | How should the task list handle filtering/views? | Reports are available via a filter button/dropdown in the header |
|
||
| Q2 | Where should the settings link live? | Top-right gear icon |
|
||
| Q3 | Should swipe-to-complete show a visual indicator? | Yes — green background with checkmark revealed during swipe |
|
||
| Q4 | Should completed tasks be viewable? | Yes — included as a report option in the filter dropdown |
|
||
| Q5 | Which reports should the API support? | All CLI reports (see Report Picker section) |
|
||
|
||
### Open for Design Phase
|
||
|
||
| # | Question | Impact |
|
||
|----|----------|--------|
|
||
| Q6 | **What new API endpoint is needed for raw-string task creation?** e.g., `POST /tasks/parse` accepting `{ "input": "Buy groceries due:tomorrow +errand" }`. | Affects backend and frontend contract |
|
||
| Q7 | **How should the API expose report-based queries?** e.g., `GET /tasks?report=next` vs. dedicated endpoints per report. Some reports (next, ready, overdue) require server-side urgency/date logic. | Affects API design |
|
||
|
||
---
|
||
|
||
## 7. Design Notes
|
||
|
||
Items for the design phase to pay attention to:
|
||
|
||
### Swipe vs. Scroll Conflict
|
||
Horizontal swipe-to-complete on a vertically scrolling list is a known UX
|
||
challenge on mobile. The designer should define a clear gesture model:
|
||
- Minimum horizontal displacement before the swipe "locks in" (vs. being
|
||
interpreted as a scroll)
|
||
- Whether the swipe requires a threshold to trigger, or if releasing mid-swipe
|
||
cancels it
|
||
- Consider a slight delay or angle detection to disambiguate
|
||
|
||
### Input Bar and Mobile Keyboard
|
||
When the mobile keyboard opens, the input bar must stay visible above it. This
|
||
is notoriously inconsistent across browsers/OS versions. Design should account
|
||
for:
|
||
- `visualViewport` API for keyboard-aware positioning
|
||
- iOS Safari's quirks with `position: fixed` and the virtual keyboard
|
||
- Whether the task list should shrink or scroll when the keyboard opens
|
||
|
||
### Error Feedback from Parse Endpoint
|
||
If the server rejects the raw input string (e.g., invalid date `due:neverday`),
|
||
how is the error communicated? Options:
|
||
- Inline error message below the input bar (toast-style or persistent)
|
||
- The input should NOT clear on failure (so the user can fix and retry)
|
||
|
||
### Empty States
|
||
Each report may return zero results. Design should define empty states for:
|
||
- First-time use (no tasks at all — should guide user toward the input)
|
||
- Report with no matches (e.g., "No overdue tasks" — brief, non-alarming)
|
||
|
||
### Report Picker Density
|
||
With 11 reports in the dropdown, the designer should consider whether all fit
|
||
comfortably on a mobile screen without scrolling, or if grouping/sectioning
|
||
is needed (e.g., "Active views" vs. "Archive views").
|
||
|
||
---
|
||
|
||
## 8. Out of Scope
|
||
|
||
- OAuth/authentication flow redesign (handled separately; mock mode for dev)
|
||
- Sync infrastructure changes
|
||
- Offline task creation queue (existing implementation stays as-is)
|
||
- Full CLI command passthrough (modify, delete, start, stop — add-only for now)
|
||
- Task detail/edit view
|
||
- Projects and Tags dedicated pages
|