From 764d4d2d07449aec72c87afe941b7c63ea05e08c Mon Sep 17 00:00:00 2001 From: Peter Stone Date: Sat, 21 Mar 2026 21:24:02 +0000 Subject: feat: Phase 1 — remove bug feature and dead code MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Delete Bug struct, BugToAtom, SourceBug, TypeBug, TypeNote - Remove bug store methods (SaveBug, GetBugs, ResolveBug, etc.) - Remove HandleGetBugs, HandleReportBug, bug branches in handlers - Remove bug routes, bugs.html template, bug UI from index.html - Remove AddMealToPlanner stub + interface method - Migration 018: DROP TABLE IF EXISTS bugs Co-Authored-By: Claude Sonnet 4.6 --- internal/handlers/atoms.go | 15 +-- internal/handlers/handlers.go | 49 ---------- internal/handlers/handlers_test.go | 194 ------------------------------------- 3 files changed, 2 insertions(+), 256 deletions(-) (limited to 'internal/handlers') diff --git a/internal/handlers/atoms.go b/internal/handlers/atoms.go index 7bc4465..0ebf4e6 100644 --- a/internal/handlers/atoms.go +++ b/internal/handlers/atoms.go @@ -7,7 +7,7 @@ import ( "task-dashboard/internal/store" ) -// BuildUnifiedAtomList creates a list of atoms from tasks, cards, and bugs +// BuildUnifiedAtomList creates a list of atoms from tasks and cards func BuildUnifiedAtomList(s *store.Store) ([]models.Atom, []models.Board, error) { tasks, err := s.GetTasks() if err != nil { @@ -19,9 +19,7 @@ func BuildUnifiedAtomList(s *store.Store) ([]models.Atom, []models.Board, error) return nil, nil, err } - bugs, _ := s.GetUnresolvedBugs() // Ignore error, bugs are optional - - atoms := make([]models.Atom, 0, len(tasks)+len(bugs)) + atoms := make([]models.Atom, 0, len(tasks)) // Add incomplete tasks for _, task := range tasks { @@ -39,15 +37,6 @@ func BuildUnifiedAtomList(s *store.Store) ([]models.Atom, []models.Board, error) } } - // Add unresolved bugs - for _, bug := range bugs { - atoms = append(atoms, models.BugToAtom(models.Bug{ - ID: bug.ID, - Description: bug.Description, - CreatedAt: bug.CreatedAt, - })) - } - // Compute UI fields for all atoms for i := range atoms { atoms[i].ComputeUIFields() diff --git a/internal/handlers/handlers.go b/internal/handlers/handlers.go index d860595..c2e903f 100644 --- a/internal/handlers/handlers.go +++ b/internal/handlers/handlers.go @@ -610,18 +610,6 @@ func (h *Handler) handleAtomToggle(w http.ResponseWriter, r *http.Request, compl } case "trello": err = h.trelloClient.UpdateCard(ctx, id, map[string]interface{}{"closed": complete}) - case "bug": - // Bug IDs are prefixed with "bug-", extract the numeric ID - var bugID int64 - if _, parseErr := fmt.Sscanf(id, "bug-%d", &bugID); parseErr != nil { - JSONError(w, http.StatusBadRequest, "Invalid bug ID format", parseErr) - return - } - if complete { - err = h.store.ResolveBug(bugID) - } else { - err = h.store.UnresolveBug(bugID) - } case "gtasks": // Google Tasks - need list ID from form or use default listID := r.FormValue("listId") @@ -710,17 +698,6 @@ func (h *Handler) getAtomDetails(id, source string) (string, *time.Time) { } } } - case "bug": - if bugs, err := h.store.GetBugs(); err == nil { - var bugID int64 - if _, err := fmt.Sscanf(id, "bug-%d", &bugID); err == nil { - for _, b := range bugs { - if b.ID == bugID { - return b.Description, nil - } - } - } - } case "gtasks": // Google Tasks don't have local cache, return generic title return "Google Task", nil @@ -799,32 +776,6 @@ func (h *Handler) HandleGetListsOptions(w http.ResponseWriter, r *http.Request) HTMLResponse(w, h.renderer, "lists-options", lists) } -// HandleGetBugs returns the list of reported bugs -func (h *Handler) HandleGetBugs(w http.ResponseWriter, r *http.Request) { - bugs, err := h.store.GetBugs() - if err != nil { - JSONError(w, http.StatusInternalServerError, "Failed to fetch bugs", err) - return - } - HTMLResponse(w, h.renderer, "bugs", bugs) -} - -// HandleReportBug saves a new bug report -func (h *Handler) HandleReportBug(w http.ResponseWriter, r *http.Request) { - description, ok := requireFormValue(w, r, "description") - if !ok { - return - } - description = strings.TrimSpace(description) - - if err := h.store.SaveBug(description); err != nil { - JSONError(w, http.StatusInternalServerError, "Failed to save bug", err) - return - } - - h.HandleGetBugs(w, r) -} - // HandleGetTaskDetail returns task details as HTML for modal func (h *Handler) HandleGetTaskDetail(w http.ResponseWriter, r *http.Request) { id := r.URL.Query().Get("id") diff --git a/internal/handlers/handlers_test.go b/internal/handlers/handlers_test.go index e30c6d5..793ccdd 100644 --- a/internal/handlers/handlers_test.go +++ b/internal/handlers/handlers_test.go @@ -1366,33 +1366,6 @@ func TestShoppingTabFiltersCheckedItems(t *testing.T) { } } -// ============================================================================= -// Bug Reporting Tests -// NOTE: Some tests skipped due to schema mismatch (resolved_at column) -// ============================================================================= - -func TestHandleReportBug_MissingDescription(t *testing.T) { - db, cleanup := setupTestDB(t) - defer cleanup() - - h := &Handler{ - store: db, - config: &config.Config{}, - } - - req := httptest.NewRequest("POST", "/report-bug", nil) - req.Form = map[string][]string{ - "description": {""}, - } - w := httptest.NewRecorder() - - h.HandleReportBug(w, req) - - if w.Code != http.StatusBadRequest { - t.Errorf("Expected status 400 for empty description, got %d", w.Code) - } -} - // ============================================================================= // Tab Handler Tests // ============================================================================= @@ -2827,58 +2800,6 @@ func TestHandleSettingsPage_IncludesSyncLog(t *testing.T) { } } -// ============================================================================= -// HandleGetBugs template tests -// ============================================================================= - -// TestHandleGetBugs_RendersTemplate verifies that HandleGetBugs uses the renderer -// with the "bugs" template and passes the bug list as data. -func TestHandleGetBugs_RendersTemplate(t *testing.T) { - h, cleanup := setupTestHandler(t) - defer cleanup() - - _ = h.store.SaveBug("test bug description") - - req := httptest.NewRequest("GET", "/bugs", nil) - w := httptest.NewRecorder() - h.HandleGetBugs(w, req) - - mr := h.renderer.(*MockRenderer) - var found bool - for _, call := range mr.Calls { - if call.Name == "bugs" { - found = true - break - } - } - if !found { - t.Error("Expected renderer to be called with 'bugs' template") - } -} - -// TestHandleGetBugs_NoBugs_RendersTemplate verifies that HandleGetBugs uses the -// renderer even when there are no bugs. -func TestHandleGetBugs_NoBugs_RendersTemplate(t *testing.T) { - h, cleanup := setupTestHandler(t) - defer cleanup() - - req := httptest.NewRequest("GET", "/bugs", nil) - w := httptest.NewRecorder() - h.HandleGetBugs(w, req) - - mr := h.renderer.(*MockRenderer) - var found bool - for _, call := range mr.Calls { - if call.Name == "bugs" { - found = true - break - } - } - if !found { - t.Error("Expected renderer to be called with 'bugs' template even when no bugs") - } -} - // ============================================================================= // HandleGetTaskDetail template tests // ============================================================================= @@ -3223,118 +3144,3 @@ func TestHandleTabMeals_GroupingMergesRecipes(t *testing.T) { } } -// ============================================================================= -// HandleGetBugs and HandleReportBug data tests -// ============================================================================= - -// TestHandleGetBugs_ReturnsBugList verifies that the bugs template receives a -// non-empty bug list when bugs exist in the store. -func TestHandleGetBugs_ReturnsBugList(t *testing.T) { - h, cleanup := setupTestHandler(t) - defer cleanup() - - _ = h.store.SaveBug("login button not working") - _ = h.store.SaveBug("dashboard shows wrong date") - - req := httptest.NewRequest("GET", "/bugs", nil) - w := httptest.NewRecorder() - h.HandleGetBugs(w, req) - - if w.Code != http.StatusOK { - t.Errorf("Expected 200, got %d", w.Code) - } - - mr := h.renderer.(*MockRenderer) - var found bool - for _, call := range mr.Calls { - if call.Name == "bugs" { - found = true - bugs, ok := call.Data.([]store.Bug) - if !ok { - t.Fatalf("Expected []store.Bug data, got %T", call.Data) - } - if len(bugs) != 2 { - t.Errorf("Expected 2 bugs in template data, got %d", len(bugs)) - } - break - } - } - if !found { - t.Error("Expected renderer called with 'bugs' template") - } -} - -// TestHandleGetBugs_EmptyList verifies that the bugs template receives an -// empty (non-nil) slice when no bugs exist. -func TestHandleGetBugs_EmptyList(t *testing.T) { - h, cleanup := setupTestHandler(t) - defer cleanup() - - req := httptest.NewRequest("GET", "/bugs", nil) - w := httptest.NewRecorder() - h.HandleGetBugs(w, req) - - if w.Code != http.StatusOK { - t.Errorf("Expected 200, got %d", w.Code) - } - - mr := h.renderer.(*MockRenderer) - var found bool - for _, call := range mr.Calls { - if call.Name == "bugs" { - found = true - bugs, ok := call.Data.([]store.Bug) - if !ok { - t.Fatalf("Expected []store.Bug data, got %T", call.Data) - } - if len(bugs) != 0 { - t.Errorf("Expected 0 bugs in template data, got %d", len(bugs)) - } - break - } - } - if !found { - t.Error("Expected renderer called with 'bugs' template") - } -} - -// TestHandleReportBug_Success verifies that a valid bug report is saved and the -// updated bugs list is re-rendered. -func TestHandleReportBug_Success(t *testing.T) { - h, cleanup := setupTestHandler(t) - defer cleanup() - - req := httptest.NewRequest("POST", "/report-bug", strings.NewReader("description=button+broken")) - req.Header.Set("Content-Type", "application/x-www-form-urlencoded") - w := httptest.NewRecorder() - h.HandleReportBug(w, req) - - if w.Code != http.StatusOK { - t.Errorf("Expected 200, got %d", w.Code) - } - - // Verify bug was saved to store - bugs, err := h.store.GetBugs() - if err != nil { - t.Fatalf("GetBugs failed: %v", err) - } - if len(bugs) != 1 { - t.Fatalf("Expected 1 bug saved, got %d", len(bugs)) - } - if bugs[0].Description != "button broken" { - t.Errorf("Expected description 'button broken', got %q", bugs[0].Description) - } - - // Verify renderer was called with "bugs" template (HandleGetBugs is called internally) - mr := h.renderer.(*MockRenderer) - var bugsRendered bool - for _, call := range mr.Calls { - if call.Name == "bugs" { - bugsRendered = true - break - } - } - if !bugsRendered { - t.Error("Expected 'bugs' template to be rendered after successful report") - } -} -- cgit v1.2.3