package views import ( "fmt" "strings" "time" "github.com/a-h/templ" tablomodel "xtablo-backend/internal/tablos" ) const overviewProjectsPreviewLimit = 6 func sidebarNavItemClass(active bool) string { if active { return "sidebar-nav-item is-active" } return "sidebar-nav-item" } func isActivePath(activePath string, href string) bool { return strings.TrimSpace(activePath) != "" && activePath == href } func sidebarNavItemID(href string) string { switch href { case "/": return "sidebar-nav-home" default: slug := strings.Trim(strings.ReplaceAll(href, "/", "-"), "-") if slug == "" { slug = "item" } return "sidebar-nav-" + slug } } type quickAction struct { Title string Description string Icon string } type sidebarNavItem struct { Href string Label string Icon string Active bool DividerAfter bool } type sidebarProjectItem struct { Href string Label string Icon string } type dashboardTask struct { Title string Project string ProjectKey string ProjectHue string Date string Status string StatusTone string Completed bool } func dashboardDateLabel(now time.Time) string { return now.Format("Monday, January 2") } func dashboardTodayLabel() string { return dashboardDateLabel(time.Now()) } func dashboardGreetingName(displayName string) string { displayName = strings.TrimSpace(displayName) if displayName == "" { return "Arthur" } if len(displayName) == 1 { return strings.ToUpper(displayName) } return strings.ToUpper(displayName[:1]) + displayName[1:] } func overviewQuickActions() []quickAction { return []quickAction{ {Title: "Créer un projet", Description: "Définir les objectifs et le périmètre", Icon: "folder-plus"}, {Title: "Créer une tâche", Description: "Découper le travail en actions", Icon: "circle-plus"}, {Title: "Inviter l'équipe", Description: "Ajouter des collaborateurs", Icon: "user-plus"}, {Title: "Envoyer un message", Description: "Communiquer rapidement", Icon: "chat"}, } } func overviewTasks() []dashboardTask { return []dashboardTask{ {Title: "yo", Project: "Hello", ProjectKey: "H", ProjectHue: "blue", Date: "Apr 16, 2026", Status: "À faire", StatusTone: "info", Completed: false}, {Title: "yo", Project: "Hello", ProjectKey: "H", ProjectHue: "blue", Date: "Apr 16, 2026", Status: "Terminé", StatusTone: "success", Completed: true}, {Title: "hello", Project: "margot", ProjectKey: "M", ProjectHue: "red", Date: "Mar 7, 2026", Status: "Terminé", StatusTone: "success", Completed: true}, {Title: "Bonjour", Project: "Jean Macon interet pour le produit de ta mere", ProjectKey: "J", ProjectHue: "purple", Date: "Feb 24, 2026", Status: "Terminé", StatusTone: "success", Completed: true}, {Title: "Bonjour", Project: "Jean Macon interet pour le produit de ta mere", ProjectKey: "J", ProjectHue: "purple", Date: "Feb 21, 2026", Status: "Terminé", StatusTone: "success", Completed: true}, {Title: "Faire ceci", Project: "bikip56648 / Arthur Belleville", ProjectKey: "B", ProjectHue: "blue", Date: "Nov 18, 2025", Status: "Terminé", StatusTone: "success", Completed: true}, {Title: "Hello monsieur", Project: "bikip56648 / Arthur Belleville", ProjectKey: "B", ProjectHue: "blue", Date: "Nov 18, 2025", Status: "Terminé", StatusTone: "success", Completed: true}, } } func OverviewProjectsFromTablos(tablos []tablomodel.Record) []TabloCardView { projects := make([]TabloCardView, 0, len(tablos)) for _, tablo := range tablos { statusLabel, statusTone, progress := overviewProjectStatus(tablo.Status) projects = append(projects, TabloCardView{ ID: tablo.ID.String(), Name: tablo.Name, Status: string(tablo.Status), StatusLabel: statusLabel, StatusTone: statusTone, Initial: projectInitial(tablo.Name), Accent: overviewProjectAccent(tablo.Name), CardDateLabel: tablo.CreatedAt.Format("Jan 02, 2006"), Progress: progress, ProgressLabel: progressPercentLabel(progress), DeleteRequestURL: "/tablos/" + tablo.ID.String(), }) } return projects } func visibleOverviewProjects(projects []TabloCardView, showAll bool) []TabloCardView { if showAll || len(projects) <= overviewProjectsPreviewLimit { return projects } return projects[:overviewProjectsPreviewLimit] } func hiddenOverviewProjectsCount(projects []TabloCardView, showAll bool) int { if showAll || len(projects) <= overviewProjectsPreviewLimit { return 0 } return len(projects) - overviewProjectsPreviewLimit } func sidebarPrimaryNavItems(activePath string) []sidebarNavItem { return []sidebarNavItem{ {Href: "/", Label: "Aperçu", Icon: "panels", Active: isActivePath(activePath, "/"), DividerAfter: true}, {Href: "/tasks", Label: "Tâches", Icon: "tasks", Active: isActivePath(activePath, "/tasks")}, {Href: "/tablos", Label: "Projets", Icon: "layers", Active: isActivePath(activePath, "/tablos"), DividerAfter: true}, {Href: "/planning", Label: "Planning", Icon: "planning", Active: isActivePath(activePath, "/planning")}, {Href: "/chat", Label: "Discussions", Icon: "chat", Active: isActivePath(activePath, "/chat")}, {Href: "/files", Label: "Fichiers", Icon: "files", Active: isActivePath(activePath, "/files")}, } } func sidebarProjectItems() []sidebarProjectItem { return []sidebarProjectItem{ {Href: "/tablos/hello", Label: "Hello", Icon: "bolt"}, {Href: "/tablos/atelier", Label: "Atelier Produit", Icon: "gem"}, {Href: "/tablos/arthur", Label: "Arthur Belleville", Icon: "bolt"}, {Href: "/tablos/equipe", Label: "Equipe Design", Icon: "bolt"}, } } func sidebarFooterNavItems(activePath string) []sidebarNavItem { return []sidebarNavItem{ {Href: "/feedback", Label: "Feedback", Icon: "send", Active: isActivePath(activePath, "/feedback")}, } } func toneClass(tone string) string { switch tone { case "warning": return "tone-warning" case "success": return "tone-success" default: return "tone-info" } } func projectAccentClass(accent string) string { switch accent { case "purple": return "project-accent-purple" case "red": return "project-accent-red" default: return "project-accent-blue" } } func taskRowClass(completed bool) string { if completed { return "task-row is-complete" } return "task-row" } func taskCheckClass(completed bool) string { if completed { return "task-check is-complete" } return "task-check" } func progressPercentLabel(progress int) string { return fmt.Sprintf("%d%%", progress) } func progressInlineStyle(progress int) templ.SafeCSS { return templ.SanitizeCSS("width", templ.SafeCSSProperty(progressPercentLabel(progress))) } func overviewProjectStatus(status tablomodel.Status) (string, string, int) { switch status { case tablomodel.StatusInProgress: return "En cours", "warning", 50 case tablomodel.StatusDone: return "Terminé", "success", 100 default: return "À faire", "info", 0 } } func overviewProjectAccent(name string) string { switch len(strings.TrimSpace(name)) % 3 { case 1: return "purple" case 2: return "red" default: return "blue" } } func projectInitial(name string) string { name = strings.TrimSpace(name) if name == "" { return "P" } return strings.ToUpper(name[:1]) }