xtablo-source/.planning/phases/16-tablo-detail/16-03-SUMMARY.md
Arthur Belleville 3a5a26c5c8
docs(16-03): complete kanban restyle + etape grouping plan summary
Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
2026-05-16 23:43:44 +02:00

8.1 KiB

phase plan subsystem tags dependency_graph tech_stack key_files decisions metrics
16-tablo-detail 03 templates
htmx
templ
kanban
etape-grouping
design-tokens
requires provides affects
16-01
16-02
kanban-etape-grouping
tasks-section-layout
task-row-layout
etape-strip-removed
16-04-files-templ
added patterns
groupTasksByEtape helper
EtapeGroup type
EtapeGroupHeader component
tasks-section kanban layout
task-row card pattern
created modified
backend/templates/tasks.templ
backend/templates/tablos.templ
backend/internal/web/handlers_tasks.go
EtapeGroup.EtapeColor always set to empty string — sqlc.Etape struct has no Color field in this schema (no etape color in DB migration)
uuid.UUID(t.EtapeID.Bytes).String() used for pgtype.UUID → string conversion — matches existing taskEtapeIDString helper in tasks_forms.go
tablos.templ KanbanBoard call updated in Task 2 (not Task 1) — build would fail if tasks.templ committed alone; treated as atomic with handlers_tasks.go updates
duration completed tasks_completed files_modified
~20min 2026-05-16T22:30:00Z 2 3

Phase 16 Plan 03: Kanban Restyle + Etape Grouping Summary

One-liner: Added groupTasksByEtape helper and EtapeGroupHeader component to tasks.templ; restyled KanbanColumn to tasks-section layout, TaskCard to task-row layout, AddTaskTrigger to tasks-add-button; removed @EtapeStrip OOB calls from TaskCardGone/TaskCardOOB; updated all three KanbanBoard call sites to accept etapes []sqlc.Etape as 5th parameter.

Tasks Completed

Task Name Commit Files
1 Add groupTasksByEtape helper, EtapeGroup type, EtapeGroupHeader component; update KanbanBoard/Column signatures and restyled column/card/trigger 084fc0e backend/templates/tasks.templ
2 Update all three KanbanBoard call sites (tablos.templ + handlers_tasks.go) and verify full test suite e2ee434 backend/internal/web/handlers_tasks.go, backend/templates/tablos.templ

What Was Built

Task 1 — tasks.templ:

  • EtapeGroup type: Struct with EtapeID string, EtapeTitle string, EtapeColor string, Tasks []sqlc.Task. EtapeColor always empty (schema has no color field).

  • groupTasksByEtape helper: Iterates tasks, uses !t.EtapeID.Valid to detect unassigned (pgtype.UUID nil check), converts valid UUIDs via uuid.UUID(t.EtapeID.Bytes).String() (same pattern as taskEtapeIDString in tasks_forms.go). Iterates etapes in declaration order, only adds groups with tasks. Appends unassigned group last only if any unassigned tasks exist.

  • EtapeGroupHeader component: Renders div class="etape-group-header". If EtapeColor != "" renders color dot span with inline style. Renders span class="etape-group-label is-unassigned" for unassigned group (EtapeID == ""), plain etape-group-label otherwise.

  • KanbanBoard signature: Added etapes []sqlc.Etape as 5th parameter. Passes etapes through to each @KanbanColumn(...) call.

  • KanbanColumn restyled: Outer div class="kanban-column" wraps div class="tasks-section". Header: div class="tasks-section-header" with left side (h3 + badge) and right side (div id="add-task-slot-{status}" containing @AddTaskTrigger). Body: div class="task-list sortable-column" — empty state uses p class="task-list-empty", else computes groups := groupTasksByEtape(tasks, etapes) and renders @EtapeGroupHeader(group) + task loop.

  • TaskCard restyled: Inner div changed from task-card bg-white rounded border... to task-row task-card. Drag handle removed. HTMX edit attributes moved to the outer task-row div (making the whole row clickable). Children: div class="task-check" (round checkbox), div class="task-body" (task title p), @ui.IconButton with trash/danger/ghost for delete confirm.

  • AddTaskTrigger restyled: Button class changed from ui-button ui-button-soft ui-button-neutral ui-button-md w-full text-left text-sm mt-2 to tasks-add-button. All HTMX attributes preserved unchanged.

  • EtapeStrip OOB removal: Deleted @EtapeStrip(tabloID, etapes, counts, filter, csrfToken, true) from both TaskCardGone and TaskCardOOB. Kept etapes []sqlc.Etape and counts EtapeTaskCounts params on both signatures (avoids handler signature changes that would break tests). Added // TODO: remove etapes and counts params after Phase 16 cleanup comments.

Task 2 — call site updates:

  • backend/templates/tablos.templ TasksTabFragment: @KanbanBoard(tablo.ID, csrfToken, tasks, filter)@KanbanBoard(tablo.ID, csrfToken, tasks, filter, etapes). etapes is already a parameter of TasksTabFragment.

  • backend/internal/web/handlers_tasks.go line 589 (single reorder path): tasks, _, _, filter, oktasks, etapes, _, filter, ok; KanbanBoard call updated to pass etapes.

  • backend/internal/web/handlers_tasks.go line 639 (batch reorder path): same change.

Verification

grep -c "groupTasksByEtape" tasks.templ → 3 (func decl + call inside KanbanColumn)
grep -c "EtapeGroupHeader" tasks.templ → 3 (templ decl + usage in KanbanColumn)
grep -c "kanban-column" tasks.templ → 1
grep -c "tasks-section" tasks.templ → 2 (tasks-section + tasks-section-header)
grep -c "task-row" tasks.templ → 1
grep -c "EtapeStrip" tasks.templ → 0
grep -c "KanbanBoard.*etapes" handlers_tasks.go → 2
grep -c "KanbanBoard.*etapes" tablos.templ → 1
go build ./backend/... → exit 0
go test ./backend/internal/web/... -count=1 → ok (all tests pass)

Deviations from Plan

Auto-fixed Issues

1. [Rule 1 - Bug] sqlc.Etape has no Color field

  • Found during: Task 1 — first build attempt
  • Issue: Plan specified etape.Color.Valid and etape.Color.String field access on sqlc.Etape. The actual schema type Etape struct has no Color field — only ID, TabloID, Title, Description, Position, CreatedAt, UpdatedAt.
  • Fix: Set EtapeGroup.EtapeColor to "" unconditionally in groupTasksByEtape. EtapeGroupHeader will not render a color dot for any group (since EtapeColor is always empty). The is-unassigned label logic still works correctly.
  • Files modified: backend/templates/tasks.templ
  • Commit: 084fc0e

2. [Rule 3 - Blocking] tablos.templ KanbanBoard call updated in Task 2 (not deferred)

  • Found during: Task 1 — go build ./backend/... fails after tasks_templ.go regeneration because tablos_templ.go still calls old 4-arg KanbanBoard
  • Issue: Plan intended tablos.templ to be updated in Task 2, but the templ compiler regenerates tablos_templ.go from tablos.templ immediately, causing a compile-time argument count mismatch.
  • Fix: Updated @KanbanBoard(tablo.ID, csrfToken, tasks, filter)@KanbanBoard(tablo.ID, csrfToken, tasks, filter, etapes) in tablos.templ during the Task 1/Task 2 boundary (before the first commit), then committed tasks.templ alone and tablos.templ + handlers_tasks.go together. The work was still split into two commits as planned.
  • Files modified: backend/templates/tablos.templ
  • Commit: e2ee434

Known Stubs

  • EtapeGroup color dot: EtapeColor is always "" because sqlc.Etape has no Color field. The etape-group-color-dot CSS and EtapeGroupHeader color dot rendering are wired but will never fire unless a Color field is added to the schema in a future phase.

Threat Flags

No new trust boundaries introduced. All changes are HTML/CSS restructuring of existing authenticated routes. T-16-03-01 through T-16-03-04 dispositions unchanged (accept).

Self-Check: PASSED

  • backend/templates/tasks.templ — FOUND, contains groupTasksByEtape, EtapeGroupHeader, kanban-column, tasks-section, task-row task-card, tasks-add-button, zero EtapeStrip
  • backend/templates/tablos.templ — FOUND, contains KanbanBoard.*etapes
  • backend/internal/web/handlers_tasks.go — FOUND, contains 2x KanbanBoard.*etapes
  • Commit 084fc0e — FOUND (Task 1)
  • Commit e2ee434 — FOUND (Task 2)
  • go build ./backend/... — exit 0
  • go test ./backend/internal/web/... -count=1 — PASSED (ok backend/internal/web + ok backend/internal/web/ui)