From 4b254e95274b09628ea143e55db6250418adaad9 Mon Sep 17 00:00:00 2001 From: Arthur Belleville Date: Sun, 17 May 2026 16:30:32 +0200 Subject: [PATCH] feat(19-02): rebuild TabloProjectCard with dual card+row structure - 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 --- backend/templates/tablos.templ | 101 +++++++++++++++++++++++---------- 1 file changed, 72 insertions(+), 29 deletions(-) diff --git a/backend/templates/tablos.templ b/backend/templates/tablos.templ index 19b7c79..0a8510c 100644 --- a/backend/templates/tablos.templ +++ b/backend/templates/tablos.templ @@ -4,6 +4,8 @@ import ( "backend/internal/auth" "backend/internal/db/sqlc" "backend/internal/web/ui" + "strconv" + "strings" ) // TablosDashboard renders the root authenticated dashboard with sidebar AppLayout. @@ -63,27 +65,27 @@ templ TablosEmptyState() { }) } -// TabloProjectCard renders a single tablo as a project-card in the dashboard grid. -// Follows D-C02 design: colored avatar circle, title zone (with inline-edit support), -// creation date, and edit/delete icon buttons. +// TabloProjectCard renders a single tablo as a dual-element card+row wrapper. +// The outer article.tablo-card-wrapper contains both a .project-card (grid view) +// and a .tablo-list-row (list view, hidden by default). +// Matches production design: status badge top-left, delete button top-right, +// colored avatar with initial letter, title, date, and progress bar. +// Uses display:contents on the wrapper so it is transparent to grid/flex layout. // Guards color rendering against null pgtype.Text values (Pitfall 6). // Uses .Time accessor on pgtype.Timestamptz (Pitfall 6). templ TabloProjectCard(card TabloCardView, csrfToken string) { -
-
-
- @ui.IconButton(ui.IconButtonProps{ - Label: "Edit title", - Icon: "pencil", - Variant: ui.IconButtonVariantNeutral, - Tone: ui.IconButtonToneGhost, - Type: "button", - Attrs: templ.Attributes{ - "hx-get": "/tablos/" + card.Tablo.ID.String() + "/edit-title", - "hx-target": "closest .tablo-title-zone", - "hx-swap": "outerHTML", - }, - }) +
+ +
+
+ + if len(card.Tablo.Status) > 0 { + @ui.Badge(ui.BadgeProps{ + Label: strings.ToUpper(card.Tablo.Status[:1]) + card.Tablo.Status[1:], + Variant: ui.BadgeVariantPrimary, + }) + } +
@ui.IconButton(ui.IconButtonProps{ Label: "Delete tablo", @@ -99,19 +101,60 @@ templ TabloProjectCard(card TabloCardView, csrfToken string) { })
-
-
- if card.Tablo.Color.Valid && card.Tablo.Color.String != "" { - - } else { - - } -
-

{ card.Tablo.Title }

+
+ if card.Tablo.Color.Valid && card.Tablo.Color.String != "" { + + if len(card.Tablo.Title) > 0 { + { string([]rune(card.Tablo.Title)[0:1]) } + } + + } else { + + if len(card.Tablo.Title) > 0 { + { string([]rune(card.Tablo.Title)[0:1]) } + } + + } +
+

{ card.Tablo.Title }

+
+
+
+ + { card.Tablo.CreatedAt.Time.Format("Jan 2, 2006") } +
+
+ Progression: { strconv.Itoa(card.Progress) }% +
+
+
-
- { card.Tablo.CreatedAt.Time.Format("Jan 2, 2006") } + +
+ if len(card.Tablo.Status) > 0 { + @ui.Badge(ui.BadgeProps{ + Label: strings.ToUpper(card.Tablo.Status[:1]) + card.Tablo.Status[1:], + Variant: ui.BadgeVariantPrimary, + }) + } + { card.Tablo.Title } + { card.Tablo.CreatedAt.Time.Format("Jan 2, 2006") } + { strconv.Itoa(card.Progress) }% +
+ @ui.IconButton(ui.IconButtonProps{ + Label: "Delete tablo", + Icon: "trash", + Variant: ui.IconButtonVariantDanger, + Tone: ui.IconButtonToneGhost, + Type: "button", + Attrs: templ.Attributes{ + "hx-get": "/tablos/" + card.Tablo.ID.String() + "/delete-confirm", + "hx-target": "closest .tablo-delete-zone", + "hx-swap": "outerHTML", + }, + }) +
}