xtablo-source/.planning/phases/11-individual-planning/11-PATTERNS.md
2026-05-16 07:21:34 +02:00

4.4 KiB

phase slug status created
11 individual-planning complete 2026-05-16

Phase 11 - Pattern Map

Purpose

Map the individual planning implementation to existing Go/HTMX codebase patterns so execution can add a small protected agenda page without inventing parallel routing, data, template, or test conventions.

File Map

New / Modified File Role Closest Existing Analog Pattern to Reuse
backend/internal/web/handlers_planning.go Protected planning page handler backend/internal/web/handlers_events.go, backend/internal/web/handlers_tablos.go Small Deps struct, auth user from request context, query through SQLC, log 500s, no framework state
backend/internal/web/router.go Route mounting Protected route group in router.go Mount GET /planning inside auth.RequireAuth; keep static routes before /tablos/{id}
backend/templates/planning.templ Agenda page template backend/templates/tablos.templ, backend/templates/events.templ Render inside Layout, use Tailwind utilities and local ui-button classes, semantic list output
backend/templates/planning_forms.go Planning view models/helpers backend/templates/events_forms.go Small structs plus URL/date helpers, reuse event date/time formatting
backend/internal/web/handlers_planning_test.go DB-backed planning tests backend/internal/web/handlers_events_test.go setupTestDB, preInsertUser, session cookies, full router requests, response body assertions
backend/cmd/web/main.go Dependency wiring Existing eventDeps, fileDeps, NewRouter call Create planningDeps := web.PlanningDeps{Queries: q} and pass to router
Router call sites/tests Dependency wiring Existing NewRouter(... eventDeps, fileDeps, ...) updates Add PlanningDeps to every NewRouter call with PlanningDeps{Queries: q} or zero value where route is not exercised

Handler Patterns

Planning should mirror existing handler dependencies:

  1. Define PlanningDeps{Queries *sqlc.Queries, Now func() time.Time}.
  2. In PlanningPageHandler, default Now to time.Now when nil.
  3. Read the authenticated user from context after auth.RequireAuth; no request parameter should identify the user.
  4. Parse start=YYYY-MM-DD; blank or invalid values fall back to today's local date.
  5. Compute inclusive range start through start.AddDate(0, 0, 13).
  6. Call ListUserEventsRange with authenticated user.ID, pgDateFromTime(start), and pgDateFromTime(end).
  7. Render templates.PlanningPage(user, csrf.Token(r), agenda).

Template Patterns

Use existing server-rendered conventions:

  • Page shell: @Layout("Planning - Xtablo", user, csrfToken).
  • Heading: text-[28px] font-semibold leading-tight.
  • Range label: text-sm text-slate-600.
  • Navigation links: ui-button ui-button-soft-neutral-md and ui-button ui-button-solid-default-md for Today when appropriate.
  • Agenda rows: one continuous ul/li list with borders, not nested cards.
  • Link URL: /tablos/{tablo_id}/events?month=YYYY-MM derived from the event date.
  • Color dot: inline span only when tablo_color is valid; title text must always render.

Test Patterns

Create backend/internal/web/handlers_planning_test.go and reuse the existing event test style:

  • setupTestDB(t) and defer cleanup().
  • q := sqlc.New(pool) and store := auth.NewStore(q).
  • Use preInsertUser, insertEventTestTablo, insertEventTestEvent, and sessionCookieForUser patterns from handlers_events_test.go.
  • Route through the full NewRouter so auth middleware, CSRF middleware, route mounting, and layout rendering are covered.
  • Assert 404/redirect behavior using status codes already used elsewhere.

Security Patterns

  • Authorization belongs to auth.RequireAuth and ListUserEventsRange filtering by tablos.user_id.
  • Do not fetch by event ID or tablo ID from the planning route.
  • Do not hand-edit generated SQLC files.
  • User strings should render through templ expressions, not templ.Raw.
  • Malformed date input should degrade to the default range.

Anti-Patterns

  • Do not add a migration for this phase.
  • Do not duplicate the Events month calendar.
  • Do not group rows by day or by tablo.
  • Do not show description snippets, edit/delete controls, import/export UI, recurrence UI, or external calendar sync.
  • Do not introduce shadcn, Radix, lucide, custom SVG icons, or a JS framework.