From 436686eed1d2cf8f61f32dcc506dd01240c76d54 Mon Sep 17 00:00:00 2001 From: mkelvers Date: Mon, 20 Apr 2026 16:36:14 +0200 Subject: [PATCH] feat(shared): add centralized helper functions for templates --- web/shared/format.go | 43 +++++++++++++++++++++++++++++++++++++++++++ web/shared/studio.go | 13 +++++++++++++ web/shared/ui.go | 10 ++++++++++ 3 files changed, 66 insertions(+) create mode 100644 web/shared/format.go create mode 100644 web/shared/studio.go create mode 100644 web/shared/ui.go diff --git a/web/shared/format.go b/web/shared/format.go new file mode 100644 index 0000000..db8155f --- /dev/null +++ b/web/shared/format.go @@ -0,0 +1,43 @@ +package shared + +import ( + "fmt" + "net/url" +) + +// BuildStreamURL constructs a stream URL from mode and token +func BuildStreamURL(mode string, token string) string { + if token == "" { + return "" + } + return fmt.Sprintf("/watch/proxy/stream?mode=%s&token=%s", url.QueryEscape(mode), url.QueryEscape(token)) +} + +// FormatProgressTime formats seconds into MM:SS format +func FormatProgressTime(seconds float64) string { + total := int(seconds) + if total < 0 { + total = 0 + } + minutes := total / 60 + remainingSeconds := total % 60 + return fmt.Sprintf("%02d:%02d", minutes, remainingSeconds) +} + +// FormatEstablishedDate extracts YYYY-MM-DD from ISO date string +func FormatEstablishedDate(date string) string { + if len(date) >= 10 { + return date[:10] + } + return date +} + +// WatchlistURL builds the watchlist URL with query parameters +func WatchlistURL(view string, status string, sortBy string, sortOrder string) string { + return fmt.Sprintf("/watchlist?view=%s&status=%s&sort=%s&order=%s", view, status, sortBy, sortOrder) +} + +// AnimeURL builds the anime detail URL +func AnimeURL(animeID int) string { + return fmt.Sprintf("/anime/%d", animeID) +} diff --git a/web/shared/studio.go b/web/shared/studio.go new file mode 100644 index 0000000..d5ba77f --- /dev/null +++ b/web/shared/studio.go @@ -0,0 +1,13 @@ +package shared + +import "mal/integrations/jikan" + +// GetProducerName extracts the default title from producer response +func GetProducerName(producer jikan.ProducerResponse) string { + for _, title := range producer.Data.Titles { + if title.Type == "Default" { + return title.Title + } + } + return "Studio" +} diff --git a/web/shared/ui.go b/web/shared/ui.go new file mode 100644 index 0000000..7ba3276 --- /dev/null +++ b/web/shared/ui.go @@ -0,0 +1,10 @@ +package shared + +// TabClass returns the CSS class for watchlist filter tabs +func TabClass(active bool) string { + base := "shrink-0 whitespace-nowrap bg-(--panel-soft) px-2 py-1 text-xs text-(--text-muted) no-underline hover:bg-(--surface-tab-hover) hover:text-(--text) hover:no-underline" + if active { + return "shrink-0 whitespace-nowrap bg-(--surface-tab-active) px-2 py-1 text-xs text-(--accent) no-underline hover:no-underline" + } + return base +}