summaryrefslogtreecommitdiff
path: root/internal/handlers/handlers.go
diff options
context:
space:
mode:
authorPeter Stone <thepeterstone@gmail.com>2026-01-19 09:11:04 -1000
committerPeter Stone <thepeterstone@gmail.com>2026-01-19 09:11:04 -1000
commit2215aaa458b318edb16337ab56cf658117023eb4 (patch)
tree73dc62cb8ed385e8ab5d255825b03ffb8845b27e /internal/handlers/handlers.go
parent791034f1b588bf679f45a0f89168515fcbde66d5 (diff)
Implement Unified Quick Add for Tasks tab (Phase 3 Step 8)
Add Quick Add form to create Todoist tasks or Trello cards directly from the Tasks tab with optional due date support. Features: - HandleUnifiedAdd handler with due date parsing - HandleGetListsOptions for dynamic Trello list loading - Quick Add form with source toggle (Todoist/Trello) - Date picker for due dates - HX-Trigger refresh after successful creation - Pass boards to tasks-tab template for board selector Cleanup: - Remove resolved issue tracking files Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Diffstat (limited to 'internal/handlers/handlers.go')
-rw-r--r--internal/handlers/handlers.go87
1 files changed, 87 insertions, 0 deletions
diff --git a/internal/handlers/handlers.go b/internal/handlers/handlers.go
index b3bc8e4..20095fe 100644
--- a/internal/handlers/handlers.go
+++ b/internal/handlers/handlers.go
@@ -3,6 +3,7 @@ package handlers
import (
"context"
"encoding/json"
+ "fmt"
"html/template"
"log"
"net/http"
@@ -727,3 +728,89 @@ func (h *Handler) HandleCompleteAtom(w http.ResponseWriter, r *http.Request) {
// Return 200 OK with empty body to remove the element from DOM
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()
+
+ if err := r.ParseForm(); err != nil {
+ http.Error(w, "Failed to parse form", http.StatusBadRequest)
+ return
+ }
+
+ title := r.FormValue("title")
+ source := r.FormValue("source")
+ dueDateStr := r.FormValue("due_date")
+
+ if title == "" {
+ http.Error(w, "Title is required", http.StatusBadRequest)
+ return
+ }
+
+ // Parse due date if provided
+ var dueDate *time.Time
+ if dueDateStr != "" {
+ parsed, err := time.Parse("2006-01-02", dueDateStr)
+ if err == nil {
+ dueDate = &parsed
+ }
+ }
+
+ switch source {
+ case "todoist":
+ _, err := h.todoistClient.CreateTask(ctx, title, "", dueDate, 1)
+ if err != nil {
+ http.Error(w, "Failed to create Todoist task", http.StatusInternalServerError)
+ log.Printf("Error creating Todoist task: %v", err)
+ return
+ }
+ // Invalidate cache so fresh data is fetched
+ h.store.InvalidateCache("todoist_tasks")
+
+ case "trello":
+ listID := r.FormValue("list_id")
+ if listID == "" {
+ http.Error(w, "List is required for Trello", http.StatusBadRequest)
+ return
+ }
+ _, err := h.trelloClient.CreateCard(ctx, listID, title, "", dueDate)
+ if err != nil {
+ http.Error(w, "Failed to create Trello card", http.StatusInternalServerError)
+ log.Printf("Error creating Trello card: %v", err)
+ return
+ }
+ // Invalidate cache so fresh data is fetched
+ h.store.InvalidateCache("trello_boards")
+
+ default:
+ http.Error(w, "Invalid source", http.StatusBadRequest)
+ return
+ }
+
+ // Trigger a refresh of the tasks tab via HTMX
+ w.Header().Set("HX-Trigger", "refresh-tasks")
+ w.WriteHeader(http.StatusOK)
+}
+
+// HandleGetListsOptions returns HTML options for lists in a given board
+func (h *Handler) HandleGetListsOptions(w http.ResponseWriter, r *http.Request) {
+ ctx := r.Context()
+ boardID := r.URL.Query().Get("board_id")
+
+ if boardID == "" {
+ http.Error(w, "board_id is required", http.StatusBadRequest)
+ return
+ }
+
+ lists, err := h.trelloClient.GetLists(ctx, boardID)
+ if err != nil {
+ http.Error(w, "Failed to fetch lists", http.StatusInternalServerError)
+ log.Printf("Error fetching lists for board %s: %v", boardID, err)
+ return
+ }
+
+ w.Header().Set("Content-Type", "text/html")
+ for _, list := range lists {
+ fmt.Fprintf(w, `<option value="%s">%s</option>`, list.ID, list.Name)
+ }
+}