xtablo-source/backend/templates/app_layout_helpers.go
Arthur Belleville 3a864aa84e
feat(19): revamp tablos page — filter tabs, view toggle, card click nav
- 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>
2026-05-17 22:11:31 +02:00

73 lines
2.5 KiB
Go

package templates
import "strings"
// BreadcrumbItem represents one crumb in the top header breadcrumb trail.
// If Href is empty, the item renders as plain text (current page — no link).
type BreadcrumbItem struct {
Label string
Href string
}
// sidebarNavItem describes one entry in the sidebar primary navigation list.
type sidebarNavItem struct {
Href string
Label string
Icon string
Active bool
DividerBefore bool
}
// navItemWrapperClass returns the Tailwind class string for a nav item wrapper.
func navItemWrapperClass(active bool) string {
if active {
return "flex w-full px-2.5 py-2 rounded-md cursor-pointer bg-purple-100 font-semibold"
}
return "flex w-full px-2.5 py-2 rounded-md cursor-pointer hover:bg-gray-100 font-medium"
}
// navItemLabelClass returns the Tailwind class string for a nav item text label.
func navItemLabelClass(active bool) string {
if active {
return "text-base font-normal text-[#804EEC]"
}
return "text-base font-normal text-gray-500"
}
// navItemIconClass returns the Tailwind class string for a nav item icon wrapper.
func navItemIconClass(active bool) string {
if active {
return "[&>svg]:w-5 [&>svg]:h-5 text-[#804EEC]"
}
return "[&>svg]:w-5 [&>svg]:h-5 text-gray-500"
}
// isActivePath reports whether activePath matches href.
func isActivePath(activePath string, href string) bool {
return strings.TrimSpace(activePath) != "" && activePath == href
}
// tabloDisplayStatus derives a display status from progress for client-side filtering.
// "pas-commence" = 0% (no tasks or none done), "en-cours" = 1-99%, "termine" = 100%.
func tabloDisplayStatus(progress, totalTasks int) string {
if totalTasks == 0 || progress == 0 {
return "pas-commence"
}
if progress >= 100 {
return "termine"
}
return "en-cours"
}
// sidebarPrimaryNavItems returns the ordered sidebar nav items.
// French labels match the production app. DividerBefore adds an <hr> separator before the item.
func sidebarPrimaryNavItems(activePath string) []sidebarNavItem {
return []sidebarNavItem{
{Href: "/", Label: "Aperçu", Icon: "panels", Active: isActivePath(activePath, "/")},
{Href: "#", Label: "Tâches", Icon: "tasks", Active: false, DividerBefore: true},
{Href: "/", Label: "Projets", Icon: "layers", Active: false},
{Href: "/planning", Label: "Planning", Icon: "planning", Active: isActivePath(activePath, "/planning"), DividerBefore: true},
{Href: "#", Label: "Discussions", Icon: "chat", Active: false},
{Href: "#", Label: "Fichiers", Icon: "files", Active: false},
}
}