diff options
| author | Peter Stone <thepeterstone@gmail.com> | 2026-01-23 16:10:52 -1000 |
|---|---|---|
| committer | Peter Stone <thepeterstone@gmail.com> | 2026-01-23 16:10:52 -1000 |
| commit | 7828e19501b3ca8b2e86ca7297f580c659e5c9b8 (patch) | |
| tree | e3113af67fcecc459d81b213d7f043630dccae98 /internal/handlers/handlers.go | |
| parent | d11334c0999efb670a8eab93527a50f644fdfceb (diff) | |
Fix bugs #24-27: calendar dedup, uncomplete tasks, planning view
Bug fixes:
- #24: Deduplicate calendar events across multiple calendars using
summary + start time as key
- #25: Change event icon from calendar to clock to avoid confusion
with date display
- #26: Add task uncomplete functionality via ReopenTask API for
Todoist and closed=false for Trello
- #27: Restructure planning view with sections for Scheduled (timed
events/tasks), Today (unscheduled), Quick Add, and Upcoming (3 days)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Diffstat (limited to 'internal/handlers/handlers.go')
| -rw-r--r-- | internal/handlers/handlers.go | 69 |
1 files changed, 63 insertions, 6 deletions
diff --git a/internal/handlers/handlers.go b/internal/handlers/handlers.go index b8fc574..c364188 100644 --- a/internal/handlers/handlers.go +++ b/internal/handlers/handlers.go @@ -827,21 +827,78 @@ func (h *Handler) HandleCompleteAtom(w http.ResponseWriter, r *http.Request) { } } - // Return completed task HTML (stays visible with strikethrough until refresh) + // Return completed task HTML with uncomplete option w.Header().Set("Content-Type", "text/html") - completedHTML := fmt.Sprintf(`<div class="task-item bg-gray-100 rounded-lg shadow-sm border-l-4 border-gray-300 opacity-60"> + completedHTML := fmt.Sprintf(`<div class="bg-white/5 rounded-lg border border-white/5 opacity-60"> <div class="flex items-start gap-2 sm:gap-3 p-3 sm:p-4"> - <input type="checkbox" checked disabled class="mt-1 h-5 w-5 rounded border-gray-300 text-green-600 cursor-not-allowed flex-shrink-0"> + <input type="checkbox" checked + hx-post="/uncomplete-atom" + hx-vals='{"id": "%s", "source": "%s"}' + hx-target="closest div.rounded-lg" + hx-swap="outerHTML" + class="mt-1 h-5 w-5 rounded bg-black/40 border-white/30 text-green-600 cursor-pointer flex-shrink-0"> <span class="text-lg flex-shrink-0">✓</span> <div class="flex-1 min-w-0"> - <h3 class="text-sm font-medium text-gray-400 line-through break-words">%s</h3> - <div class="text-xs text-green-600 mt-1">Completed</div> + <h3 class="text-sm font-medium text-white/40 line-through break-words">%s</h3> + <div class="text-xs text-green-400/70 mt-1">Completed - click to undo</div> </div> </div> - </div>`, template.HTMLEscapeString(title)) + </div>`, template.HTMLEscapeString(id), template.HTMLEscapeString(source), template.HTMLEscapeString(title)) w.Write([]byte(completedHTML)) } +// HandleUncompleteAtom handles reopening a completed task +func (h *Handler) HandleUncompleteAtom(w http.ResponseWriter, r *http.Request) { + ctx := r.Context() + + if err := r.ParseForm(); err != nil { + http.Error(w, "Failed to parse form", http.StatusBadRequest) + log.Printf("Error parsing form: %v", err) + return + } + + id := r.FormValue("id") + source := r.FormValue("source") + + if id == "" || source == "" { + http.Error(w, "Missing id or source", http.StatusBadRequest) + return + } + + var err error + switch source { + case "todoist": + err = h.todoistClient.ReopenTask(ctx, id) + case "trello": + // Reopen the card (closed = false) + updates := map[string]interface{}{ + "closed": false, + } + err = h.trelloClient.UpdateCard(ctx, id, updates) + default: + http.Error(w, "Unknown source: "+source, http.StatusBadRequest) + return + } + + if err != nil { + http.Error(w, "Failed to reopen task", http.StatusInternalServerError) + log.Printf("Error reopening atom (source=%s, id=%s): %v", source, id, err) + return + } + + // Invalidate cache to force refresh + switch source { + case "todoist": + h.store.InvalidateCache(store.CacheKeyTodoistTasks) + case "trello": + h.store.InvalidateCache(store.CacheKeyTrelloBoards) + } + + // Trigger refresh + w.Header().Set("HX-Trigger", "refresh-tasks") + w.WriteHeader(http.StatusOK) +} + // HandleUnifiedAdd creates a task in Todoist or a card in Trello from the Quick Add form func (h *Handler) HandleUnifiedAdd(w http.ResponseWriter, r *http.Request) { ctx := r.Context() |
