191 lines
5 KiB
Go
191 lines
5 KiB
Go
package views
|
|
|
|
import (
|
|
"net/url"
|
|
"strings"
|
|
|
|
"github.com/a-h/templ"
|
|
"xtablo-backend/internal/web/ui"
|
|
)
|
|
|
|
type TabloCardView struct {
|
|
ID string
|
|
Name string
|
|
Color string
|
|
Status string
|
|
StatusLabel string
|
|
StatusClass string
|
|
StatusTone string
|
|
Progress int
|
|
CreatedAtLabel string
|
|
CardDateLabel string
|
|
ProgressLabel string
|
|
DeleteURL string
|
|
DeleteRequestURL string
|
|
EditRequestURL string
|
|
IconKind string
|
|
IconBgClass string
|
|
IconFgClass string
|
|
Accent string
|
|
Initial string
|
|
}
|
|
|
|
type TablosPageViewModel struct {
|
|
DisplayName string
|
|
View string
|
|
Status string
|
|
ModalKind string
|
|
EditingTabloID string
|
|
FormName string
|
|
FormColor string
|
|
ErrorMessage string
|
|
Tablos []TabloCardView
|
|
}
|
|
|
|
func NewTablosPageViewModel(displayName string, view string, status string, modalKind string, editingTabloID string, formName string, formColor string, errorMessage string, tablos []TabloCardView) TablosPageViewModel {
|
|
return TablosPageViewModel{
|
|
DisplayName: displayName,
|
|
View: normalizedView(view),
|
|
Status: normalizedStatus(status),
|
|
ModalKind: normalizedModalKind(modalKind),
|
|
EditingTabloID: strings.TrimSpace(editingTabloID),
|
|
FormName: strings.TrimSpace(formName),
|
|
FormColor: normalizedFormColor(modalKind, formColor),
|
|
ErrorMessage: strings.TrimSpace(errorMessage),
|
|
Tablos: tablos,
|
|
}
|
|
}
|
|
|
|
func (vm TablosPageViewModel) IsGridView() bool {
|
|
return vm.View != "list"
|
|
}
|
|
|
|
func (vm TablosPageViewModel) HasTablos() bool {
|
|
return len(vm.Tablos) > 0
|
|
}
|
|
|
|
func (vm TablosPageViewModel) HasModal() bool {
|
|
return vm.ModalKind != ""
|
|
}
|
|
|
|
func (vm TablosPageViewModel) IsCreateModal() bool {
|
|
return vm.ModalKind == "create"
|
|
}
|
|
|
|
func (vm TablosPageViewModel) IsEditModal() bool {
|
|
return vm.ModalKind == "edit"
|
|
}
|
|
|
|
func (vm TablosPageViewModel) StatusHref(status string) string {
|
|
values := vm.baseValues()
|
|
values.Set("status", normalizedStatus(status))
|
|
return "/tablos?" + values.Encode()
|
|
}
|
|
|
|
func (vm TablosPageViewModel) ViewHref(view string) string {
|
|
values := vm.baseValues()
|
|
values.Set("view", normalizedView(view))
|
|
return "/tablos?" + values.Encode()
|
|
}
|
|
|
|
func (vm TablosPageViewModel) CreateModalHref() string {
|
|
values := vm.baseValues()
|
|
values.Set("modal", "create")
|
|
return "/tablos?" + values.Encode()
|
|
}
|
|
|
|
func (vm TablosPageViewModel) EditModalHref(tabloID string) string {
|
|
values := vm.baseValues()
|
|
return "/tablos/" + strings.TrimSpace(tabloID) + "/edit?" + values.Encode()
|
|
}
|
|
|
|
func (vm TablosPageViewModel) CloseModalHref() string {
|
|
values := vm.baseValues()
|
|
return "/tablos?" + values.Encode()
|
|
}
|
|
|
|
func (vm TablosPageViewModel) EditSubmitHref() string {
|
|
return "/tablos/" + vm.EditingTabloID
|
|
}
|
|
|
|
func normalizedView(view string) string {
|
|
if view == "list" {
|
|
return "list"
|
|
}
|
|
return "grid"
|
|
}
|
|
|
|
func normalizedStatus(status string) string {
|
|
switch status {
|
|
case "todo", "in_progress", "done":
|
|
return status
|
|
default:
|
|
return "all"
|
|
}
|
|
}
|
|
|
|
func normalizedModalKind(kind string) string {
|
|
switch kind {
|
|
case "create", "edit":
|
|
return kind
|
|
default:
|
|
return ""
|
|
}
|
|
}
|
|
|
|
func normalizedFormColor(modalKind string, color string) string {
|
|
trimmed := strings.TrimSpace(color)
|
|
if trimmed != "" {
|
|
return trimmed
|
|
}
|
|
if normalizedModalKind(modalKind) == "create" {
|
|
return "#3B82F6"
|
|
}
|
|
return ""
|
|
}
|
|
|
|
func (vm TablosPageViewModel) baseValues() url.Values {
|
|
values := url.Values{}
|
|
values.Set("view", vm.View)
|
|
values.Set("status", vm.Status)
|
|
return values
|
|
}
|
|
|
|
func gridToggleClass(active bool) string {
|
|
if active {
|
|
return "flex items-center gap-2 pb-3 border-b-2 transition-colors border-purple-600 text-purple-600 dark:border-purple-400 dark:text-purple-400 font-semibold"
|
|
}
|
|
return "flex items-center gap-2 pb-3 border-b-2 transition-colors border-transparent text-gray-500 dark:text-gray-400 hover:text-gray-700 dark:hover:text-gray-200"
|
|
}
|
|
|
|
func listToggleClass(gridActive bool) string {
|
|
return gridToggleClass(!gridActive)
|
|
}
|
|
|
|
func statusPillClass(active bool) string {
|
|
if active {
|
|
return "flex items-center gap-1.5 px-4 py-2.5 border rounded-[8px] font-medium text-sm transition-colors border-purple-600 bg-purple-50 dark:bg-purple-950/30 text-purple-600 dark:text-purple-400"
|
|
}
|
|
return "flex items-center gap-1.5 px-4 py-2.5 border rounded-[8px] font-medium text-sm transition-colors border-[#EAECF0] dark:border-gray-700 hover:bg-gray-50 dark:hover:bg-gray-800 text-gray-700 dark:text-gray-300"
|
|
}
|
|
|
|
func badgeVariantForTone(tone string) ui.BadgeVariant {
|
|
switch tone {
|
|
case "warning":
|
|
return ui.BadgeVariantWarning
|
|
case "success":
|
|
return ui.BadgeVariantSuccess
|
|
case "danger":
|
|
return ui.BadgeVariantDanger
|
|
default:
|
|
return ui.BadgeVariantInfo
|
|
}
|
|
}
|
|
|
|
func projectColorVariableStyle(color string) templ.SafeCSS {
|
|
return templ.SanitizeCSS("--project-color", templ.SafeCSSProperty(strings.TrimSpace(color)))
|
|
}
|
|
|
|
func backgroundColorStyle(color string) templ.SafeCSS {
|
|
return templ.SanitizeCSS("background-color", templ.SafeCSSProperty(strings.TrimSpace(color)))
|
|
}
|