1package components
2
3import (
4 "strings"
5
6 "github.com/bnema/gordon/internal/adapters/in/cli/ui/styles"
7
8 "github.com/charmbracelet/lipgloss"
9)
10
11// Status represents a status type for rendering.
12type Status int
13
14const (
15 StatusSuccess Status = iota
16 StatusError
17 StatusWarning
18 StatusInfo
19 StatusPending
20 StatusRunning
21 StatusStopped
22 StatusPaused
23 StatusRestarting
24 StatusExited
25 StatusUnknown
26)
27
28// StatusConfig holds configuration for status rendering.
29type StatusConfig struct {
30 Status Status
31 Label string
32 Icon string
33 Style lipgloss.Style
34 Badge bool // If true, render as a badge with background
35 Compact bool // If true, render icon only
36}
37
38// DefaultStatusConfigs provides default configurations for each status type.
39var DefaultStatusConfigs = map[Status]StatusConfig{
40 StatusSuccess: {
41 Icon: styles.IconSuccess,
42 Style: styles.Theme.Success,
43 },
44 StatusError: {
45 Icon: styles.IconError,
46 Style: styles.Theme.Error,
47 },
48 StatusWarning: {
49 Icon: styles.IconWarning,
50 Style: styles.Theme.Warning,
51 },
52 StatusInfo: {
53 Icon: styles.IconInfo,
54 Style: styles.Theme.Info,
55 },
56 StatusPending: {
57 Icon: styles.IconPending,
58 Style: styles.Theme.Muted,
59 },
60 StatusRunning: {
61 Icon: styles.IconRunning,
62 Style: styles.Theme.Success,
63 },
64 StatusStopped: {
65 Icon: styles.IconStopped,
66 Style: styles.Theme.Error,
67 },
68 StatusPaused: {
69 Icon: styles.IconPaused,
70 Style: styles.Theme.Warning,
71 },
72 StatusRestarting: {
73 Icon: styles.IconRestarting,
74 Style: styles.Theme.Warning,
75 },
76 StatusExited: {
77 Icon: styles.IconExited,
78 Style: styles.Theme.Error,
79 },
80 StatusUnknown: {
81 Icon: styles.IconUnknown,
82 Style: styles.Theme.Muted,
83 },
84}
85
86// RenderStatus renders a status with icon and optional label.
87func RenderStatus(status Status, label string) string {
88 config := DefaultStatusConfigs[status]
89 if label == "" {
90 return config.Style.Render(config.Icon)
91 }
92 return config.Style.Render(config.Icon + " " + label)
93}
94
95// RenderStatusBadge renders a status as a compact icon badge with background.
96// It displays only the icon (no label) for minimal width in table columns.
97func RenderStatusBadge(status Status) string {
98 config := DefaultStatusConfigs[status]
99 var badgeStyle lipgloss.Style
100 switch status {
101 case StatusSuccess, StatusRunning:
102 badgeStyle = styles.Theme.BadgeSuccess
103 case StatusError, StatusStopped, StatusExited:
104 badgeStyle = styles.Theme.BadgeError
105 case StatusWarning, StatusPaused, StatusRestarting:
106 badgeStyle = styles.Theme.BadgeWarning
107 case StatusPending:
108 badgeStyle = styles.Theme.BadgePending
109 case StatusUnknown:
110 badgeStyle = styles.Theme.Muted
111 default:
112 badgeStyle = styles.Theme.BadgeInfo
113 }
114 return badgeStyle.Render(config.Icon)
115}
116
117// ParseStatus converts a string status to Status type.
118func ParseStatus(s string) Status {
119 switch strings.ToLower(s) {
120 case "success", "ok", "active", "healthy":
121 return StatusSuccess
122 case "error", "failed", "unhealthy":
123 return StatusError
124 case "warning", "degraded":
125 return StatusWarning
126 case "info":
127 return StatusInfo
128 case "pending", "starting", "waiting", "created":
129 return StatusPending
130 case "running", "up":
131 return StatusRunning
132 case "stopped", "down":
133 return StatusStopped
134 case "paused":
135 return StatusPaused
136 case "restarting":
137 return StatusRestarting
138 case "exited", "dead":
139 return StatusExited
140 case "unknown":
141 return StatusUnknown
142 default:
143 return StatusUnknown
144 }
145}
146
147// StatusIndicator is a simple status indicator component.
148type StatusIndicator struct {
149 Status Status
150 Label string
151 Badge bool
152}
153
154// NewStatusIndicator creates a new status indicator.
155func NewStatusIndicator(status Status, label string) StatusIndicator {
156 return StatusIndicator{
157 Status: status,
158 Label: label,
159 Badge: false,
160 }
161}
162
163// NewStatusBadge creates a new status badge (with background).
164func NewStatusBadge(status Status, label string) StatusIndicator {
165 return StatusIndicator{
166 Status: status,
167 Label: label,
168 Badge: true,
169 }
170}
171
172// View renders the status indicator.
173func (s StatusIndicator) View() string {
174 if s.Badge {
175 return RenderStatusBadge(s.Status)
176 }
177 return RenderStatus(s.Status, s.Label)
178}
179
180// ContainerStatusIndicator renders container status with appropriate styling.
181func ContainerStatusIndicator(status string) string {
182 parsed := ParseStatus(status)
183 return RenderStatus(parsed, status)
184}
185
186// ContainerStatusBadge renders container status as a badge.
187func ContainerStatusBadge(status string) string {
188 parsed := ParseStatus(status)
189 return RenderStatusBadge(parsed)
190}