8.6 KiB
phase, plan, type, wave, depends_on, files_modified, autonomous, requirements, must_haves
| phase | plan | type | wave | depends_on | files_modified | autonomous | requirements | must_haves | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 07-quick-add-library | 01 | execute | 1 |
|
true |
|
|
Purpose: Users need a persistent library of saved one-off expense categories (name + icon) that they can reuse across months. This plan creates the database table, Go model, query functions, and HTTP endpoints.
Output: Migration file, QuickAddItem model, CRUD queries, REST handlers at /api/quick-add
<execution_context> @/home/jean-luc-makiola/.claude/get-shit-done/workflows/execute-plan.md @/home/jean-luc-makiola/.claude/get-shit-done/templates/summary.md </execution_context>
@.planning/PROJECT.md @.planning/ROADMAP.md @.planning/STATE.md@backend/internal/models/models.go @backend/internal/db/queries.go @backend/internal/api/handlers.go @backend/internal/api/router.go @backend/migrations/002_templates.sql
From backend/internal/models/models.go:
// Category struct pattern — QuickAddItem should follow same shape
type Category struct {
ID uuid.UUID `json:"id"`
UserID uuid.UUID `json:"user_id"`
Name string `json:"name"`
Type CategoryType `json:"type"`
Icon string `json:"icon"`
SortOrder int `json:"sort_order"`
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"`
}
From backend/internal/api/router.go:
// Route group pattern — quick-add follows same structure
r.Route("/api/template", func(r chi.Router) {
r.Get("/", h.GetTemplate)
r.Put("/", h.UpdateTemplateName)
r.Post("/items", h.CreateTemplateItem)
// ...
})
From backend/internal/api/handlers.go:
// Handler struct — all handlers are methods on this
type Handlers struct {
queries *db.Queries
sessionSecret string
}
// Helper functions available: writeJSON, writeError, auth.UserIDFromContext
-
Add
QuickAddItemstruct tobackend/internal/models/models.go:type QuickAddItem struct { ID uuid.UUID `json:"id"` UserID uuid.UUID `json:"user_id"` Name string `json:"name"` Icon string `json:"icon"` SortOrder int `json:"sort_order"` CreatedAt time.Time `json:"created_at"` UpdatedAt time.Time `json:"updated_at"` } -
Add four query functions to
backend/internal/db/queries.go(append after template section):ListQuickAddItems(ctx, userID) ([]QuickAddItem, error)— SELECT ordered by sort_order, returns empty slice (not nil) when none existCreateQuickAddItem(ctx, userID, name, icon string) (*QuickAddItem, error)— INSERT with sort_order = (SELECT COALESCE(MAX(sort_order),0)+1), RETURNING all columnsUpdateQuickAddItem(ctx, id, userID, name, icon string, sortOrder int) (*QuickAddItem, error)— UPDATE with WHERE id=$1 AND user_id=$2, return error if no rows affectedDeleteQuickAddItem(ctx, id, userID) error— DELETE with WHERE id=$1 AND user_id=$2
Follow existing query patterns: use context parameter, userID scoping in WHERE clause, fmt.Errorf wrapping, pgx row scanning. cd /home/jean-luc-makiola/Development/projects/SimpleFinanceDash/backend && go vet ./... QuickAddItem struct compiles, all four query functions compile, migration file exists with CREATE TABLE statement
ListQuickAddItems(w, r)— GET, extracts userID from context, calls queries.ListQuickAddItems, returns JSON array (200)CreateQuickAddItem(w, r)— POST, accepts JSON{name: string, icon: string}, validates name is non-empty (400 if missing), calls queries.CreateQuickAddItem, returns created item (201)UpdateQuickAddItem(w, r)— PUT, extracts itemId from chi URL param, accepts JSON{name: string, icon: string, sort_order: int}, validates name non-empty, calls queries.UpdateQuickAddItem, returns updated item (200). Return 404 if no rows affected.DeleteQuickAddItem(w, r)— DELETE, extracts itemId from chi URL param, calls queries.DeleteQuickAddItem, returns 204
Follow existing handler patterns:
- Use
auth.UserIDFromContext(r.Context())for userID - Use
chi.URLParam(r, "itemId")for path params - Use
writeJSON(w, status, data)andwriteError(w, status, message) - Parse UUID with
uuid.Parse(), return 400 on invalid
- Register routes in
backend/internal/api/router.goinside the authenticated group (after the template route block):r.Route("/api/quick-add", func(r chi.Router) { r.Get("/", h.ListQuickAddItems) r.Post("/", h.CreateQuickAddItem) r.Put("/{itemId}", h.UpdateQuickAddItem) r.Delete("/{itemId}", h.DeleteQuickAddItem) })
<success_criteria>
- Backend compiles and builds successfully
- Migration creates quick_add_items table with correct schema
- Four REST endpoints exist: GET/POST /api/quick-add, PUT/DELETE /api/quick-add/{itemId}
- All endpoints require authentication (inside authenticated route group)
- All queries scope by user_id </success_criteria>