summaryrefslogtreecommitdiff
path: root/issues
diff options
context:
space:
mode:
Diffstat (limited to 'issues')
-rw-r--r--issues/001-hide-future-tasks-behind-fold.md51
-rw-r--r--issues/002-modal-menu-quick-add-bug-report.md47
-rw-r--r--issues/003-fix-tap-to-expand.md48
-rw-r--r--issues/005-visual-task-timing-differentiation.md61
-rw-r--r--issues/006-reorder-tasks-by-urgency.md63
-rw-r--r--issues/007-fix-outdated-todoist-link.md54
-rw-r--r--issues/009-keep-completed-tasks-visible.md54
-rw-r--r--issues/010-fix-quick-add-timestamp.md76
-rw-r--r--issues/015-random-landscape-background.md77
-rw-r--r--issues/016-click-task-edit-details.md80
10 files changed, 0 insertions, 611 deletions
diff --git a/issues/001-hide-future-tasks-behind-fold.md b/issues/001-hide-future-tasks-behind-fold.md
deleted file mode 100644
index f6012fe..0000000
--- a/issues/001-hide-future-tasks-behind-fold.md
+++ /dev/null
@@ -1,51 +0,0 @@
-# [FEATURE] Hide future tasks behind a fold
-
-## Description
-Hide tasks more than 3-7 days out behind a fold.
-
-## User Story
-As a user, I want tasks more than N days out hidden by default so that I can focus on immediate priorities.
-
-## Technical Context
-- Affects: `internal/handlers/handlers.go` (task filtering), `web/templates/partials/todoist-tasks.html` or `tasks-tab.html`
-- Data already has `due_date`; filtering is a presentation concern
-
-## Test Strategy
-
-### Unit Test (Red)
-**File:** `internal/handlers/handlers_test.go`
-
-Test a new filter function `FilterTasksByHorizon(tasks []Task, days int)` returns only tasks within range.
-
-```go
-func TestFilterTasksByHorizon(t *testing.T) {
- // Given tasks with varying due dates
- // When filtered with horizon of 7 days
- // Then only tasks within 7 days are in "visible" slice
- // And remaining tasks are in "deferred" slice
-}
-```
-
-### E2E Test (Red)
-Verify collapsed section renders with count badge; click expands to show deferred tasks.
-
-## Proposed Approach
-
-1. Add config param `task_horizon_days` (default 7)
-2. Partition tasks in handler into "visible" vs "deferred"
-3. Render deferred in a collapsible `<details>` element with HTMX swap
-4. Show count badge on collapsed header (e.g., "+12 later")
-
-## Affected Components
-- `internal/handlers/handlers.go`
-- `internal/config/config.go`
-- `web/templates/partials/todoist-tasks.html`
-- `web/templates/partials/tasks-tab.html`
-
-## Definition of Done
-- [ ] Tasks beyond horizon hidden by default
-- [ ] Collapsible UI shows count of hidden tasks
-- [ ] Click to expand shows all deferred tasks
-- [ ] Horizon days configurable
-- [ ] Unit tests pass
-- [ ] E2E test confirms behavior
diff --git a/issues/002-modal-menu-quick-add-bug-report.md b/issues/002-modal-menu-quick-add-bug-report.md
deleted file mode 100644
index b518cf3..0000000
--- a/issues/002-modal-menu-quick-add-bug-report.md
+++ /dev/null
@@ -1,47 +0,0 @@
-# [FEATURE] Quick add & bug report in modal menu
-
-## Description
-Put quick add (rename "add" to "quick add") and bug report in a unified modal menu.
-
-## User Story
-As a user, I want quick-add and bug-report behind a unified modal so the UI is cleaner.
-
-## Technical Context
-- Affects: `web/templates/index.html` (modal container), new partial `partials/modal-menu.html`
-- Existing handlers for quick-add and bug already exist; this is UI consolidation
-- Note: Issue #14 is a duplicate of this
-
-## Test Strategy
-
-### E2E/Integration Test (Red)
-Test modal opens on trigger, contains both forms, submits correctly.
-
-```
-1. Click menu trigger -> modal opens
-2. Assert "Add Task" and "Report Bug" tabs/options visible
-3. Fill quick-add form -> submit -> task created
-4. Switch to bug tab -> fill -> submit -> bug created
-5. Modal closes after successful submit
-```
-
-## Proposed Approach
-
-1. Create shared modal partial with tab/toggle between "Add Task" and "Report Bug"
-2. Use HTMX `hx-get` to lazy-load modal content
-3. Add keyboard shortcut (e.g., `Cmd+K` or `Ctrl+K`) to invoke
-4. Rename "Add" button to "Quick Add" throughout UI
-5. Single FAB or menu button replaces separate add/bug buttons
-
-## Affected Components
-- `web/templates/index.html`
-- `web/templates/partials/modal-menu.html` (new)
-- `web/static/` (JS for keyboard shortcut)
-- Existing quick-add and bug handlers (no changes, just UI consolidation)
-
-## Definition of Done
-- [ ] Single modal contains both forms
-- [ ] Tab/toggle switches between quick-add and bug report
-- [ ] Keyboard shortcut opens modal
-- [ ] Both forms submit correctly
-- [ ] Modal closes on successful submit
-- [ ] Old separate UI elements removed
diff --git a/issues/003-fix-tap-to-expand.md b/issues/003-fix-tap-to-expand.md
deleted file mode 100644
index a1cfd8c..0000000
--- a/issues/003-fix-tap-to-expand.md
+++ /dev/null
@@ -1,48 +0,0 @@
-# [BUG] Tap to expand doesn't work
-
-## Description
-Tap to expand doesn't work on task items.
-
-## Technical Context
-- Likely a JS/HTMX event binding issue in task list items
-- Affects: `partials/todoist-tasks.html` or `tasks-tab.html`, possibly JS in `web/static/`
-- May be related to event delegation on dynamically-loaded content
-
-## Test Strategy
-
-### E2E Test (Red)
-Playwright/browser test: click task row -> assert expanded content visible.
-
-```
-1. Load tasks page
-2. Click on a task row
-3. Assert expanded details section becomes visible
-4. Assert expanded content contains expected task details
-```
-
-## Proposed Approach
-
-1. Inspect current expand trigger mechanism:
- - Is it `hx-get` with `hx-trigger="click"`?
- - Is it a JS click handler?
- - Is it a `<details>` element?
-2. Check for missing `hx-trigger` or event delegation issues on dynamically-loaded content
-3. Ensure `htmx:afterSwap` rebinds event listeners if needed
-4. Test on both desktop (click) and mobile (tap)
-
-## Debugging Steps
-1. Open browser dev tools -> check for JS errors on click
-2. Inspect element -> verify HTMX attributes present
-3. Check Network tab -> see if request fires on click
-4. If using JS handlers, verify they're attached after HTMX swaps
-
-## Affected Components
-- `web/templates/partials/todoist-tasks.html`
-- `web/templates/partials/tasks-tab.html`
-- `web/static/` (if JS-based)
-
-## Definition of Done
-- [ ] Clicking/tapping a task expands its details
-- [ ] Works on desktop and mobile
-- [ ] Works on initial load and after HTMX swaps
-- [ ] E2E test confirms behavior
diff --git a/issues/005-visual-task-timing-differentiation.md b/issues/005-visual-task-timing-differentiation.md
deleted file mode 100644
index 4cc40b4..0000000
--- a/issues/005-visual-task-timing-differentiation.md
+++ /dev/null
@@ -1,61 +0,0 @@
-# [FEATURE] Visual differentiation for task timing
-
-## Description
-Tasks after today should be grayed out, past deadline should be emphasized.
-
-## User Story
-As a user, I want past-due tasks highlighted and future tasks dimmed so urgency is immediately visible.
-
-## Technical Context
-- Pure presentation logic in template
-- Affects: `partials/todoist-tasks.html`, `partials/tasks-tab.html`
-- Requires comparing task `due_date` against current date
-
-## Test Strategy
-
-### Unit Test (Red)
-**File:** `internal/handlers/handlers_test.go`
-
-Test helper function returns correct urgency class.
-
-```go
-func TestTaskUrgencyClass(t *testing.T) {
- tests := []struct {
- name string
- dueDate time.Time
- expected string
- }{
- {"overdue yesterday", yesterday, "overdue"},
- {"due today", today, "today"},
- {"due tomorrow", tomorrow, "future"},
- {"no due date", zeroTime, "none"},
- }
- // ...
-}
-```
-
-### E2E Test (Red)
-Assert CSS classes applied correctly to tasks based on due date.
-
-## Proposed Approach
-
-1. Add template helper or compute urgency class in handler
-2. Return struct with `UrgencyClass` field for each task
-3. Apply Tailwind classes based on urgency:
- - `text-red-600 font-bold` (overdue)
- - `text-inherit` or default (today)
- - `text-gray-400` (future)
-4. Consider adding visual indicator icon (e.g., warning for overdue)
-
-## Affected Components
-- `internal/handlers/handlers.go`
-- `internal/models/types.go` (if adding field to view model)
-- `web/templates/partials/todoist-tasks.html`
-- `web/templates/partials/tasks-tab.html`
-
-## Definition of Done
-- [ ] Overdue tasks visually emphasized (red/bold)
-- [ ] Future tasks grayed out
-- [ ] Today's tasks normal styling
-- [ ] Unit tests for urgency calculation
-- [ ] E2E test verifies correct classes applied
diff --git a/issues/006-reorder-tasks-by-urgency.md b/issues/006-reorder-tasks-by-urgency.md
deleted file mode 100644
index 8a5f968..0000000
--- a/issues/006-reorder-tasks-by-urgency.md
+++ /dev/null
@@ -1,63 +0,0 @@
-# [FEATURE] Reorder task list by urgency
-
-## Description
-List past due tasks, then tasks with a specific time today, then 12am (all-day) tasks today, then future tasks.
-
-## User Story
-As a user, I want tasks sorted by urgency tiers so I see what needs attention first.
-
-## Technical Context
-- Affects: `internal/handlers/handlers.go` — sorting logic before template render
-- Requires distinguishing "has specific time" vs "all-day" (midnight/00:00)
-- Todoist API may return all-day tasks with time set to 00:00:00
-
-## Test Strategy
-
-### Unit Test (Red)
-**File:** `internal/handlers/handlers_test.go`
-
-```go
-func TestSortTasksByUrgency(t *testing.T) {
- tasks := []Task{
- {Name: "future", DueDate: tomorrow},
- {Name: "overdue", DueDate: yesterday},
- {Name: "today-timed", DueDate: todayAt(14, 30)},
- {Name: "today-allday", DueDate: todayAt(0, 0)},
- }
-
- sorted := SortTasksByUrgency(tasks)
-
- // Expected order: overdue, today-timed, today-allday, future
- assert.Equal(t, "overdue", sorted[0].Name)
- assert.Equal(t, "today-timed", sorted[1].Name)
- assert.Equal(t, "today-allday", sorted[2].Name)
- assert.Equal(t, "future", sorted[3].Name)
-}
-```
-
-## Proposed Approach
-
-1. Define sort buckets with priority:
- - Priority 0: Overdue (due_date < today)
- - Priority 1: Today with specific time (due_date == today && time != 00:00)
- - Priority 2: Today all-day (due_date == today && time == 00:00)
- - Priority 3: Future (due_date > today)
-2. Within each bucket, sort by due_date ascending
-3. Implement stable sort to preserve original order within equal items
-
-## Traps to Avoid
-- **Timezone handling:** Ensure consistent timezone (user's local or UTC?) for date comparisons
-- **Null due dates:** Decide where tasks with no due date should appear (suggest: after future tasks)
-- **All-day detection:** Todoist may use different conventions; verify API response format
-
-## Affected Components
-- `internal/handlers/handlers.go`
-- `internal/handlers/handlers_test.go`
-
-## Definition of Done
-- [ ] Tasks sorted in specified order
-- [ ] Overdue tasks appear first
-- [ ] Timed tasks today before all-day tasks today
-- [ ] Future tasks appear last
-- [ ] Null due date tasks handled gracefully
-- [ ] Unit tests cover all buckets and edge cases
diff --git a/issues/007-fix-outdated-todoist-link.md b/issues/007-fix-outdated-todoist-link.md
deleted file mode 100644
index 5d628f2..0000000
--- a/issues/007-fix-outdated-todoist-link.md
+++ /dev/null
@@ -1,54 +0,0 @@
-# [BUG] Fix outdated Todoist task link
-
-## Description
-Fix outdated Todoist task link.
-
-## Technical Context
-- Affects: `internal/api/todoist.go` (URL construction) or stored `url` field in DB
-- Todoist may have changed their URL scheme
-- Current URLs may be returning 404 or redirecting incorrectly
-
-## Test Strategy
-
-### Unit Test (Red)
-**File:** `internal/api/todoist_test.go`
-
-```go
-func TestBuildTaskURL(t *testing.T) {
- taskID := "123456789"
- url := BuildTaskURL(taskID)
-
- // Assert current Todoist URL format
- // Option A: https://todoist.com/showTask?id=123456789
- // Option B: https://todoist.com/app/task/123456789
- assert.Equal(t, "https://todoist.com/app/task/123456789", url)
-}
-```
-
-## Proposed Approach
-
-1. Research current Todoist web URL format:
- - Check Todoist docs or inspect working links in browser
- - Likely format: `https://todoist.com/app/task/{task_id}` or `https://todoist.com/showTask?id={task_id}`
-2. Update URL builder in `internal/api/todoist.go`
-3. Consider migration for existing cached URLs in database:
- - Option A: Update on read (lazy migration)
- - Option B: Run migration script to update all stored URLs
-4. If URL comes from API response directly, verify we're using the correct field
-
-## Debugging Steps
-1. Find a task ID in the database
-2. Try current URL format in browser
-3. Try alternative formats to find working one
-4. Check Todoist API response for canonical URL field
-
-## Affected Components
-- `internal/api/todoist.go`
-- `internal/api/todoist_test.go`
-- Potentially `internal/store/sqlite.go` (if migration needed)
-
-## Definition of Done
-- [ ] Task links open correct Todoist page
-- [ ] URL builder uses current format
-- [ ] Existing cached URLs updated or migrated
-- [ ] Unit test validates URL format
diff --git a/issues/009-keep-completed-tasks-visible.md b/issues/009-keep-completed-tasks-visible.md
deleted file mode 100644
index b80eaca..0000000
--- a/issues/009-keep-completed-tasks-visible.md
+++ /dev/null
@@ -1,54 +0,0 @@
-# [FEATURE] Keep completed tasks visible until refresh
-
-## Description
-Leave completed tasks in view until refresh and don't confirm completion.
-
-## User Story
-As a user, I want completed tasks to stay visible (struck through) until I refresh so I can see my progress and undo mistakes.
-
-## Technical Context
-- Affects: `partials/todoist-tasks.html` (HTMX swap behavior), possibly JS state
-- Currently completion likely removes item via `hx-swap="delete"` or similar
-- Need to change to in-place update with completed styling
-
-## Test Strategy
-
-### E2E Test (Red)
-```
-1. Load tasks page with uncompleted task
-2. Click complete button on task
-3. Assert task still visible with .completed class (strikethrough)
-4. Assert no confirmation dialog appeared
-5. Refresh page
-6. Assert completed task no longer visible
-```
-
-## Proposed Approach
-
-1. **Change completion endpoint response:**
- - Instead of empty response (for delete), return updated task HTML
- - Task HTML includes completed styling (strikethrough, muted colors)
-
-2. **Update HTMX swap:**
- - Change from `hx-swap="delete"` or `hx-swap="outerHTML"` with empty
- - To `hx-swap="outerHTML"` with completed task HTML
-
-3. **Remove confirmation:**
- - Remove any `hx-confirm` attribute on complete button
- - Or remove JS confirmation dialog if present
-
-4. **Completed task styling:**
- - Add `.completed` class with `line-through text-gray-400`
- - Optionally add "undo" button that appears on completed tasks
-
-## Affected Components
-- `internal/handlers/handlers.go` (completion endpoint response)
-- `web/templates/partials/todoist-tasks.html`
-- `web/templates/partials/task-item.html` (if exists, for completed variant)
-
-## Definition of Done
-- [ ] Completing a task keeps it visible with strikethrough
-- [ ] No confirmation dialog on completion
-- [ ] Task disappears on page refresh
-- [ ] Optional: Undo button on completed tasks
-- [ ] E2E test confirms behavior
diff --git a/issues/010-fix-quick-add-timestamp.md b/issues/010-fix-quick-add-timestamp.md
deleted file mode 100644
index 3c59325..0000000
--- a/issues/010-fix-quick-add-timestamp.md
+++ /dev/null
@@ -1,76 +0,0 @@
-# [BUG] Quick add date defaults to tomorrow in evening
-
-## Description
-The date pre-filled in quick add defaults to tomorrow when used during the evening.
-
-## Symptom
-When adding a task in the evening, the date field pre-fills with tomorrow's date instead of today.
-
-## Technical Context
-- Likely a timezone or date boundary issue
-- Server may be using UTC while user expects local time
-- Or JavaScript date handling crossing midnight boundary incorrectly
-
-## Test Strategy
-
-### Unit Test (Red)
-**File:** `internal/handlers/handlers_test.go`
-
-```go
-func TestQuickAddDefaultDate(t *testing.T) {
- tests := []struct {
- name string
- serverTime time.Time
- userTZ string
- expectedDate string
- }{
- {
- name: "evening in US Eastern",
- serverTime: time.Date(2026, 1, 21, 23, 0, 0, 0, time.UTC), // 6pm ET
- userTZ: "America/New_York",
- expectedDate: "2026-01-21", // Should be today, not tomorrow
- },
- {
- name: "late night edge case",
- serverTime: time.Date(2026, 1, 22, 4, 0, 0, 0, time.UTC), // 11pm ET
- userTZ: "America/New_York",
- expectedDate: "2026-01-21",
- },
- }
- // ...
-}
-```
-
-## Proposed Approach
-
-1. **Identify the source:**
- - Check quick-add handler: how is default date determined?
- - Check template: is date set server-side or client-side JS?
- - Check if using `time.Now()` (server's timezone) vs user's timezone
-
-2. **Likely fix:**
- - If server-side: pass user's timezone preference and convert
- - If client-side: use `new Date()` which uses browser's local time
- - Ensure consistent timezone handling throughout
-
-3. **Verify date calculation:**
- - `today` should be based on user's local date, not UTC date
- - Evening in US Eastern (UTC-5) at 8pm = UTC next day 1am
-
-## Debugging Steps
-1. Check current time on server vs browser
-2. Inspect what value is sent in quick-add form
-3. Check JavaScript date initialization if client-side
-4. Check Go `time.Now()` usage if server-side
-
-## Affected Components
-- `internal/handlers/handlers.go` (quick-add endpoint/template data)
-- `web/templates/partials/` (quick-add form)
-- `web/static/` (if JS sets date)
-- Potentially user preferences for timezone
-
-## Definition of Done
-- [ ] Quick add defaults to user's local today, regardless of time
-- [ ] Works correctly in evening hours
-- [ ] Works across timezone boundaries
-- [ ] Unit test covers evening edge case
diff --git a/issues/015-random-landscape-background.md b/issues/015-random-landscape-background.md
deleted file mode 100644
index 4f65c98..0000000
--- a/issues/015-random-landscape-background.md
+++ /dev/null
@@ -1,77 +0,0 @@
-# [FEATURE] Random landscape background image
-
-## Description
-Use a random open licensed landscape image as the background, and replace it with a new one each refresh.
-
-## User Story
-As a user, I want a fresh landscape background on each visit for visual variety.
-
-## Technical Context
-- Affects page container/body styling
-- Needs external image source with open license
-- Consider performance and loading states
-
-## Test Strategy
-
-### Integration Test (Red)
-Test image endpoint returns valid image URL with appropriate license.
-
-```go
-func TestGetRandomBackgroundURL(t *testing.T) {
- url := GetRandomBackgroundURL()
-
- assert.NotEmpty(t, url)
- assert.Contains(t, url, "unsplash") // or other source
-
- // Verify URL is accessible
- resp, err := http.Head(url)
- assert.NoError(t, err)
- assert.Equal(t, 200, resp.StatusCode)
-}
-```
-
-## Proposed Approach
-
-1. **Image Source Options:**
- - **Unsplash Source API:** `https://source.unsplash.com/1920x1080/?landscape,nature`
- - Free, no API key needed for basic use
- - Redirects to random image
- - **Pexels API:** Requires API key
- - **Local curated set:** Bundle images, no external dependency
-
-2. **Implementation:**
- - Set CSS `background-image` on body or main container
- - Add loading state (solid color) while image loads
- - Use `background-size: cover` and `background-position: center`
-
-3. **Template change:**
- ```html
- <body style="background-image: url('{{.BackgroundURL}}'); background-size: cover;">
- ```
-
- Or with CSS class and CSS variable.
-
-4. **Handler:**
- - Generate/fetch random URL on each page load
- - Pass to template context
-
-## Traps to Avoid
-- **Slow loads:** Large images can delay page render
- - Use appropriate resolution (1920x1080 max)
- - Consider lazy loading or progressive enhancement
-- **Image fails to load:** Have solid color fallback
-- **Caching:** Browser may cache image; ensure URL changes per request
-- **Dark text visibility:** May need overlay or text shadow for readability
-
-## Affected Components
-- `internal/handlers/handlers.go` (add background URL to context)
-- `web/templates/index.html` (apply background style)
-- `web/static/css/` (fallback and loading styles)
-
-## Definition of Done
-- [ ] Background image displays on page load
-- [ ] Different image on each refresh
-- [ ] Images are openly licensed
-- [ ] Fallback color while loading
-- [ ] Text remains readable over images
-- [ ] Integration test verifies URL validity
diff --git a/issues/016-click-task-edit-details.md b/issues/016-click-task-edit-details.md
deleted file mode 100644
index a1687c9..0000000
--- a/issues/016-click-task-edit-details.md
+++ /dev/null
@@ -1,80 +0,0 @@
-# [FEATURE] Click task to open editable details
-
-## Description
-When I click a task, open details and let me update description.
-
-## User Story
-As a user, I want to click a task to view and edit its description inline.
-
-## Technical Context
-- Extends existing task display with detail view
-- Requires new endpoints for fetching and updating task details
-- HTMX-powered modal or slide-out panel
-
-## Test Strategy
-
-### Unit Test (Red)
-**File:** `internal/handlers/handlers_test.go`
-
-```go
-func TestUpdateTaskDescription(t *testing.T) {
- // Setup mock Todoist client
- mockClient := &MockTodoistClient{}
- handler := NewHandler(mockClient)
-
- // Call update endpoint
- req := httptest.NewRequest("PUT", "/tasks/123",
- strings.NewReader(`{"description": "Updated desc"}`))
-
- // Assert Todoist API called with correct params
- mockClient.AssertCalled(t, "UpdateTask", "123", "Updated desc")
-}
-```
-
-### E2E Test (Red)
-```
-1. Click on a task row
-2. Assert modal/drawer opens with task details
-3. Assert description field is editable
-4. Edit description and save
-5. Assert modal closes
-6. Assert description persisted (re-open to verify)
-```
-
-## Proposed Approach
-
-1. **Endpoints:**
- - `GET /tasks/{id}/detail` — fetch task with full details
- - `PUT /tasks/{id}` — update task (description, etc.)
-
-2. **UI Flow:**
- - Click task row triggers `hx-get="/tasks/{id}/detail"`
- - Response loads into modal or slide-out panel
- - Form with editable description (textarea)
- - Save button triggers `hx-put="/tasks/{id}"`
- - On success, close modal and optionally update task row
-
-3. **Template:**
- - New partial: `partials/task-detail.html`
- - Contains: title (read-only or editable), description (editable), due date, labels, save/cancel buttons
-
-4. **API Integration:**
- - Update Todoist via API when saving
- - Update local cache
-
-## Affected Components
-- `internal/handlers/handlers.go` (new endpoints)
-- `internal/handlers/handlers_test.go`
-- `internal/api/todoist.go` (UpdateTask method if not exists)
-- `web/templates/partials/task-detail.html` (new)
-- `web/templates/partials/todoist-tasks.html` (add click handler)
-- `web/templates/index.html` (modal container if needed)
-
-## Definition of Done
-- [ ] Clicking task opens detail view
-- [ ] Description field is editable
-- [ ] Save persists to Todoist
-- [ ] Local cache updated
-- [ ] Modal/drawer closes on save
-- [ ] Unit tests for update handler
-- [ ] E2E test for full flow