From f08f06bef47aac2c9effb4cec650d99c2deb2dd7 Mon Sep 17 00:00:00 2001 From: Peter Stone Date: Sat, 18 Jul 2026 00:14:45 +0000 Subject: Rework Tasks tab: Chains section, checklist modal, project visibility The flat Tasks-tab atom list was silently dumping every chain step (locked and unlocked) and dormant bucket-pool items in as ordinary undated cards, with no chain/project context and no protection against completing a locked step out of order. - CompleteNativeTask now rejects completing a locked chain task (ErrChainTaskLocked), mapped to 400 in both the widget and web complete-atom handlers. - Chain tasks and dormant bucket items are excluded from the flat atom list; a new "Chains" section shows one card per active/paused chain with the current step and N/M progress. - New chain checklist modal (GET /chains/{id}) lists every position in order with pause/resume/abandon -- the web view originally deferred as Android-only. - Fixed a real bug this surfaced: resuming a paused chain only flipped the status flag, never unlocking the deferred successor, so a chain paused right after a completion stayed stuck forever. SetChainStatus now catches up the deferred advancement on resume, idempotently. - Atom cards gained a project-name chip for general visibility. Co-Authored-By: Claude Sonnet 5 Claude-Session: https://claude.ai/code/session_01EZ7ikw2ukGJFTHE3bJS7zL --- internal/handlers/handlers.go | 13 +++++++++++++ 1 file changed, 13 insertions(+) (limited to 'internal/handlers/handlers.go') diff --git a/internal/handlers/handlers.go b/internal/handlers/handlers.go index 343d0b1..54c6a70 100644 --- a/internal/handlers/handlers.go +++ b/internal/handlers/handlers.go @@ -3,6 +3,7 @@ package handlers import ( "context" "crypto/rand" + "errors" "fmt" "html/template" "log" @@ -46,6 +47,7 @@ func New(s *store.Store, trello api.TrelloAPI, planToEat api.PlanToEatAPI, googl // Template functions funcMap := template.FuncMap{ "subtract": func(a, b int) int { return a - b }, + "add": func(a, b int) int { return a + b }, // multiDayLabel returns the "(starts/ends HH:MM)" suffix for a // multi-day calendar event's row on the day it's rendered, or "" // for a normal item or a "spans" (pass-through) day, which shows @@ -580,6 +582,10 @@ func (h *Handler) handleAtomToggle(w http.ResponseWriter, r *http.Request, compl } if err != nil { + if errors.Is(err, store.ErrChainTaskLocked) { + JSONError(w, http.StatusBadRequest, "Task is locked in its chain", err) + return + } action := "complete" if !complete { action = "reopen" @@ -858,6 +864,11 @@ func (h *Handler) HandleTabTasks(w http.ResponseWriter, r *http.Request) { return } + chainSummaries, err := BuildChainSummaries(h.store) + if err != nil { + log.Printf("Warning: failed to build chain summaries: %v", err) + } + SortAtomsByUrgency(atoms) currentAtoms, futureAtoms := PartitionAtomsByTime(atoms) @@ -865,11 +876,13 @@ func (h *Handler) HandleTabTasks(w http.ResponseWriter, r *http.Request) { Atoms []models.Atom FutureAtoms []models.Atom Boards []models.Board + Chains []models.ChainSummary Today string }{ Atoms: currentAtoms, FutureAtoms: futureAtoms, Boards: boards, + Chains: chainSummaries, Today: config.Now().Format("2006-01-02"), } -- cgit v1.2.3