diff options
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() |
