4.4 KiB
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:
- Define
PlanningDeps{Queries *sqlc.Queries, Now func() time.Time}. - In
PlanningPageHandler, defaultNowtotime.Nowwhen nil. - Read the authenticated user from context after
auth.RequireAuth; no request parameter should identify the user. - Parse
start=YYYY-MM-DD; blank or invalid values fall back to today's local date. - Compute inclusive range
startthroughstart.AddDate(0, 0, 13). - Call
ListUserEventsRangewith authenticateduser.ID,pgDateFromTime(start), andpgDateFromTime(end). - 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-mdandui-button ui-button-solid-default-mdfor Today when appropriate. - Agenda rows: one continuous
ul/lilist with borders, not nested cards. - Link URL:
/tablos/{tablo_id}/events?month=YYYY-MMderived from the event date. - Color dot: inline span only when
tablo_coloris 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)anddefer cleanup().q := sqlc.New(pool)andstore := auth.NewStore(q).- Use
preInsertUser,insertEventTestTablo,insertEventTestEvent, andsessionCookieForUserpatterns fromhandlers_events_test.go. - Route through the full
NewRouterso 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.RequireAuthandListUserEventsRangefiltering bytablos.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.