Phase 20 work was executed against go-backend/ (prototype) instead of
backend/ (production). This commit ports the Figma-aligned restyle to
the correct codebase.
Changes:
- tablos.templ: replace project-card-top header with tablo-detail-header,
tablo-detail-avatar, tablo-detail-title; update tab bar to tablo-tab-bar;
localise tab labels to French (Vue d'ensemble, Tâches, Fichiers,
Discussion, Événements)
- tasks.templ: update KanbanBoard to tablo-kanban-board; KanbanColumn to
tablo-kanban-column with new header/count/empty classes; TaskCard to
card-style layout (task-card-top-row, task-card-title, task-card-delete)
- app.css: add sections 25–27 — tablo detail page, kanban board/columns,
and task card (card appearance, hover states)
Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
- Two separate containers: #tablos-grid (card grid) and #tablos-table (table), toggled via .hidden
- TabloListRow: new templ for <tr> with icon+title, Actif/Archivé badge, date, progress bar, trash
- JS: setTablosView toggles hidden on both containers; filterTablos targets both article and tr elements
- Remove old .tablo-list-row / #tablos-list[data-view] CSS (no longer needed)
Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
- Dashboard: French header "Mes Projets", underline-tab view toggle (grid/list), filter tabs (Tous/Pas commencé/En cours/Terminé) with JS client-side filtering
- Cards: display status derived from progress (À faire/En cours/Terminé), rounded-xl p-6, w-8 h-8 avatar, green-500 progress bar, dashed "Créé le" footer
- Click on card/row navigates to /tablos/{uuid} via event delegation (delete zone stops propagation)
- List view: single-column grid, rows show status + title + date + task count
- CSS: .view-tab and .filter-tab with .is-active state
Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
- TestTablosDashboard_ProgressBar: asserts "Progression:" label and project-card-progress-row class
- TestTablosDashboard_ViewToggle: asserts view-toggle-btn class and data-view="grid" attribute
- TestTablosDashboard_StatusBadge: asserts "Active" badge and tablo-list-row dual-element structure
- All tests use unique email addresses; go build ./... exits 0
- Rewrote TabloProjectCard with outer article.tablo-card-wrapper (display:contents)
- Added .project-card child: status badge top-left, delete button top-right
- Avatar circle now shows initial letter from card.Tablo.Title
- Added calendar icon + formatted date in .project-date-row
- Added .project-card-progress-row with "Progression: X%" label and .project-card-progress-bar
- Added .tablo-list-row sibling (hidden by default) for list view toggle
- Added strconv and strings imports for Itoa and title-casing Status
- Add Progress int field to TabloCardView (D-05)
- Map row.Status into Tablo struct in TabloCardsFromUnreadRows
- Wire ListTabloProgressByIDs batch query in TablosListHandler (no N+1)
- Non-fatal error handling: progress defaults to 0 on query failure
- Add migration 0010_tablo_status.sql with reversible goose Up/Down
- Update all tablo SQL queries to include status column in SELECT/RETURNING/GROUP BY
- Add ListTabloProgressByIDs batch aggregation query (D-06)
- sqlc regenerated locally (files gitignored — regen via sqlc generate)
- Sidebar: Tailwind utilities, French labels (Aperçu/Tâches/Projets/Planning/Discussions/Fichiers), hr separators, collapse button on group hover, tablo list with circle icons, org footer with avatar + "1 membre"
- Header: 75px height, border-b #EAECF0, search input left, bell + avatar-dropdown right (no breadcrumb visible — retained sr-only for a11y + tests)
- Layout: flex instead of grid, dashboard-main no padding, dashboard-main-content wrapper at 2rem
- Tests updated for new search-input assertion
Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
- Add PageHeader templ component with three-zone layout (breadcrumb left, search placeholder center, bell/inbox/avatar right)
- Avatar dropdown uses native details/summary HTML (D-06, no Alpine.js)
- Logout form inside dropdown with CSRF token (T-18-03-01 mitigated)
- Remove Plan 01 breadcrumb/headerActions stubs from AppLayout body
- Wire @PageHeader call inside dashboard-main before children
- Add inline JS for avatar dropdown outside-click close behavior
- Add .dashboard-shell.sidebar-is-collapsed grid-template-columns: 4rem 1fr
- Hide sidebar-brand-title, section labels, nav labels, project labels when collapsed
- Center icons in collapsed state via justify-content: center on sidebar-nav-link-inner
- Hide sidebar-project-list in collapsed state (no icons for project entries)
- Flip collapse button chevron with rotate(180deg) when collapsed
- Regenerate static/tailwind.css via bin/tailwindcss --minify
- Add GENERAL section label above primary nav items list
- Add PROJECTS section label and tablo list inlined directly in DashboardSidebar
- Wire collapse button with inline JS toggling sidebar-is-collapsed on .dashboard-shell
- Remove SidebarOrganizationFooter call (moves to avatar dropdown in Plan 03)
- Remove DividerAfter rendering branch (section labels replace dividers)
- Replace Dashboard/Tasks/Planning/Chat/Files with Home/My Tasks/Projects/Events/Team Members
- Remove DividerAfter from all items (section labels replace dividers per D-08)
- Add "team" case to SidebarNavIcon switch using Lucide users SVG paths
- PlanningShowDaySeparator in planning_forms.go — returns true when date
changes between consecutive events
- PlanningDaySeparator templ: slate-50 header row with date label and
data-day-separator attribute
- PlanningEventListItem: remove redundant DateLabel column (now in separator)
- Loop uses index to call PlanningShowDaySeparator before each event row
Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
- #discussion-messages: max-height 32rem, overflow-y auto, smooth scroll
- Auto-scroll to bottom on initial load, on own message sent (htmx:afterRequest),
and on SSE message received from other users
Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
Remove static/ from exclude_dir, add js to include_ext.
Exclude static/tailwind.css via regex to prevent rebuild loop from
the Tailwind output file triggering its own regeneration.
Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
The server-side flush didn't eliminate the race because browser HTMX and SSE
event processing are inherently async.
Real fix: embed data-current-user-id on #discussion-tab (from DiscussionTabData.
CurrentUserID). The SSE handler now skips any event whose authorUserId matches
the current user — those messages are always delivered via HTMX (IsOwn=true,
right-aligned). SSE only appends messages from other users.
Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
The server was publishing to the SSE broker before writing the HTMX response,
causing a race: if the SSE event (IsOwn=false, left-aligned) arrived at the
browser before HTMX appended the response (IsOwn=true, right-aligned), the
SSE path won and messageExists() then blocked the correct HTMX append.
Fix: write and flush the HTMX response first, then publish to SSE. This ensures
the sender's own message lands in the DOM right-aligned before the SSE event fires.
Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
- CR-01: add id="discussion-message-list" to .divide-y; change hx-target
to #discussion-message-list so HTMX appends inside the list, not after it.
Always render the list div so the target exists even when messages is empty.
- WR-01: SSE broadcast now renders IsOwn=false for all recipients so other
users don't receive the sender's right-aligned bubble
- WR-02: add HX-Retarget/HX-Reswap headers on 422 and 500 error responses
so validation errors reach the composer form in the DOM
- WR-03: replace hardcoded rgba(128,78,236,0.10) with color-mix() using
the --color-brand-primary token
- WR-04: remove hardcoded "1 participant" subtitle (no participant count in data)
- IN-02: DiscussionMessageFromRow now accepts currentUserID uuid.UUID (matching
DiscussionMessagesFromRows) instead of a pre-computed bool
Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
TabloDetailHandler was always rendering the full page regardless of
HX-Request, causing HTMX to swap the entire layout (sidebar, header)
into #tab-content instead of just the overview fragment.
Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
- Add IsOwn bool to DiscussionMessageView; set via user.ID comparison in
DiscussionMessagesFromRows and DiscussionMessageFromRow
- Thread currentUserID through loadDiscussionTabData and all call sites
- discussion.templ: branch message-own vs message-other on message.IsOwn
- Restore .divide-y wrapper inside #discussion-messages (discussion-sse.js
depends on it to locate the message list before appending SSE events)
Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
Phase 16 executor removed the .task-drag-handle div from TaskCard
during restyling. Sortable.js handle: '.task-drag-handle' had no
matching element → dragging completely non-functional.
Restores the grip element with CSS-token styling (no Tailwind).
- Replace <ul>/<li> layout with @ui.Table using fileTableHead/fileTableBody helpers
- Add .overview-section-heading header with "Files" h3 and Upload file button
- Convert FileListRow outer element from <li> to <tr class="file-row-zone">
- Convert FileDeleteConfirmFragment outer element from <div> to <tr class="file-row-zone"> with <td colspan="4">
- Add Download and Delete @ui.IconButton in FileListRow actions column
- Replace FileListEmpty with @ui.EmptyState in FilesTabFragment and UploadErrorFragment
- Convert FileRowGone from <div> to <tr> for DOM consistency
- All 9 file handler tests pass; go build ./... exits 0
- tablos.templ TasksTabFragment: add etapes as 5th argument to @KanbanBoard
- handlers_tasks.go reorder (single): capture etapes from loadTasksTabData; pass to KanbanBoard
- handlers_tasks.go reorder (batch): capture etapes from loadTasksTabData; pass to KanbanBoard
- go build ./backend/... exits 0; go test ./backend/internal/web/... -count=1 passes
- Replace header with project-card-top layout: color avatar with first char, tablo-title-zone
- Replace Discussion link/Invite button/Delete button with @ui.IconButton and @ui.Button using design token variants
- Add inline tablo-delete-zone with trash @ui.IconButton (does not use TabloDeleteButtonFragment)
- Replace metadata row hardcoded flex/hex classes with tablo-metadata-row, @ui.Badge(BadgeVariantPrimary), project-progress-track/bar
- Replace 5 tab nav <a> elements from long inline Tailwind hex classes to tab-nav-item / tab-nav-item is-active
- Wrap tab nav in class="tab-nav" replacing raw flex container
- Move @TabloDescDisplay call from persistent header into TabloOverviewTabFragment
- Remove @EtapeStrip call from TasksTabFragment (D-E01; KanbanBoard call site update deferred to Plan 03)
- Remove last #804EEC hex value from TabloTitleDisplay hover class
- Regenerated tablos_templ.go via templ generate
- insert case "download" with arrow-down SVG (path + polyline + line) before default case
- insert case "chat" with speech-bubble SVG (path) before default case
- icon_button_templ.go regenerated via templ generate (gitignored, regenerated at build time)
Merge conflict resolution had taken the old template signatures (pre-AppLayout).
Restored HEAD~1 signatures then applied the header/tab-nav restyle:
- Title row: md:text-3xl font-bold, Discussion + Invite action buttons
- Metadata row: created date, status badge, 0% progress bar
- Sticky purple-accent tab bar (Overview, Tasks, Files, Discussion, Events)
- All HTMX wiring and AppLayout wrapping preserved
- Replace plain back-link + title with structured header: title row + metadata row
- Title uses larger md:text-3xl font-bold style with inline-edit preserved
- Add Discussion and Invite action buttons in header (purple brand colors)
- Add metadata row: created date, hardcoded En cours status badge, 0% progress bar
- Replace plain slate tab nav with purple-accent tab bar (icon + label per tab)
- Tab active state: text-[#804EEC] border-[#804EEC]; inactive: text-[#667085]
- Tab bar is sticky (top-0 z-40) with horizontal scroll and hidden scrollbar
- Keep all HTMX attributes, hx-push-url, hx-target="#tab-content" logic unchanged
- tablo-title-zone, tablo-desc-zone, tablo-delete-zone elements retained
- Updated TablosDashboard signature to accept activePath and tablos for AppLayout
- Replaced old @Layout call with @AppLayout (sidebar-based shell)
- Added TabloProjectCard component with project-card grid, colored avatar, tablo-title-zone, edit/delete icon buttons
- Replaced TablosEmptyState raw HTML with @ui.EmptyState component (ui-empty-state class)
- Updated TabloDetailPage signature with activePath and sidebarTablos params
- Updated TabloNotFoundPage signature with activePath and sidebarTablos params
- Both detail pages switch from @Layout to @AppLayout