diff options
Diffstat (limited to 'internal/handlers/handlers.go')
| -rw-r--r-- | internal/handlers/handlers.go | 58 |
1 files changed, 30 insertions, 28 deletions
diff --git a/internal/handlers/handlers.go b/internal/handlers/handlers.go index 1e376b5..a1a12e7 100644 --- a/internal/handlers/handlers.go +++ b/internal/handlers/handlers.go @@ -1179,7 +1179,8 @@ func (h *Handler) HandleShoppingToggle(w http.ResponseWriter, r *http.Request) { source := r.FormValue("source") checked := r.FormValue("checked") == "true" - if source == "user" { + switch source { + case "user": var userID int64 if _, err := fmt.Sscanf(id, "user-%d", &userID); err != nil { JSONError(w, http.StatusBadRequest, "Invalid user item ID", err) @@ -1189,35 +1190,30 @@ func (h *Handler) HandleShoppingToggle(w http.ResponseWriter, r *http.Request) { JSONError(w, http.StatusInternalServerError, "Failed to toggle item", err) return } + case "trello", "plantoeat": + // Store checked state locally for external sources + if err := h.store.SetShoppingItemChecked(source, id, checked); err != nil { + JSONError(w, http.StatusInternalServerError, "Failed to toggle item", err) + return + } + default: + JSONError(w, http.StatusBadRequest, "Unknown source", nil) + return } - // Note: Trello and PlanToEat toggle would need their own API calls - - // Return updated item HTML - checkedClass := "" - checkedAttr := "" - textClass := "text-white" - if checked { - checkedClass = "opacity-50" - checkedAttr = "checked" - textClass = "line-through text-white/40" - } - html := fmt.Sprintf(`<li class="flex items-center gap-3 p-3 bg-white/5 hover:bg-white/10 transition-colors rounded-lg border border-white/5 %s"> - <input type="checkbox" %s - hx-post="/shopping/toggle" - hx-vals='{"id":"%s","source":"%s","checked":%t}' - hx-target="closest li" - hx-swap="outerHTML" - class="h-5 w-5 rounded bg-black/40 border-white/30 text-green-500 focus:ring-white/30 cursor-pointer flex-shrink-0"> - <span class="flex-1 %s">%s</span> - <span class="text-xs px-2 py-0.5 rounded bg-purple-900/50 text-purple-300">user</span> - </li>`, checkedClass, checkedAttr, template.HTMLEscapeString(id), template.HTMLEscapeString(source), !checked, textClass, template.HTMLEscapeString(r.FormValue("name"))) - HTMLString(w, html) + + // Return refreshed shopping tab + stores := h.aggregateShoppingLists(r.Context()) + HTMLResponse(w, h.templates, "shopping-tab", struct{ Stores []models.ShoppingStore }{stores}) } // aggregateShoppingLists combines Trello, PlanToEat, and user shopping items by store func (h *Handler) aggregateShoppingLists(ctx context.Context) []models.ShoppingStore { storeMap := make(map[string]map[string][]models.UnifiedShoppingItem) + // Fetch locally stored checked states for external sources + trelloChecks, _ := h.store.GetShoppingItemChecks("trello") + plantoeatChecks, _ := h.store.GetShoppingItemChecks("plantoeat") + // 1. Fetch Trello "Shopping" board cards boards, err := h.store.GetBoards() if err != nil { @@ -1237,10 +1233,11 @@ func (h *Handler) aggregateShoppingLists(ctx context.Context) []models.ShoppingS } item := models.UnifiedShoppingItem{ - ID: card.ID, - Name: card.Name, - Store: storeName, - Source: "trello", + ID: card.ID, + Name: card.Name, + Store: storeName, + Source: "trello", + Checked: trelloChecks[card.ID], } storeMap[storeName][""] = append(storeMap[storeName][""], item) } @@ -1265,6 +1262,11 @@ func (h *Handler) aggregateShoppingLists(ctx context.Context) []models.ShoppingS storeMap[storeName] = make(map[string][]models.UnifiedShoppingItem) } + // Use locally stored check state if available, otherwise use scraped state + checked := item.Checked + if localChecked, ok := plantoeatChecks[item.ID]; ok { + checked = localChecked + } unified := models.UnifiedShoppingItem{ ID: item.ID, Name: item.Name, @@ -1272,7 +1274,7 @@ func (h *Handler) aggregateShoppingLists(ctx context.Context) []models.ShoppingS Category: item.Category, Store: storeName, Source: "plantoeat", - Checked: item.Checked, + Checked: checked, } storeMap[storeName][item.Category] = append(storeMap[storeName][item.Category], unified) } |
