Files
terdut-tui/internal/tui/view.go
T
Niklas Ye 55ee64530b feat: Stage 1 scaffold — config, API client, placeholder TUI
Sets up the full project structure following the hactl/gokapi-tui
architecture: strict Elm-pattern Bubbletea TUI, YAML config at
~/.config/terdut-tui/config.yaml, REST API client with Bearer auth,
self-update via GitHub Releases, and a three-section tab placeholder
(Alerts / Schedule / Users) that verifies server connectivity on startup.
2026-05-21 13:28:13 +02:00

88 lines
2.0 KiB
Go

package tui
import (
"fmt"
"strings"
"github.com/charmbracelet/lipgloss"
)
var sectionNames = []string{"Alerts", "Schedule", "Users"}
func (m Model) View() string {
if m.width == 0 {
return ""
}
header := m.renderHeader()
tabs := m.renderTabs()
body := m.renderBody()
footer := m.renderFooter()
return lipgloss.JoinVertical(lipgloss.Left, header, tabs, body, footer)
}
func (m Model) renderHeader() string {
title := styleHeader.Render("terdut-tui")
right := ""
if m.serverURL != "" {
right = styleMuted.Render(m.serverURL)
}
gap := m.width - lipgloss.Width(title) - lipgloss.Width(right)
if gap < 0 {
gap = 0
}
return title + strings.Repeat(" ", gap) + right
}
func (m Model) renderTabs() string {
var tabs []string
for i, name := range sectionNames {
if section(i) == m.activeSection {
tabs = append(tabs, styleTabActive.Render(name))
} else {
tabs = append(tabs, styleTabInactive.Render(name))
}
}
line := strings.Repeat("─", m.width)
return strings.Join(tabs, "") + "\n" + styleMuted.Render(line)
}
func (m Model) renderBody() string {
bodyHeight := m.height - 5 // header + tabs + separator + footer + help
if bodyHeight < 1 {
bodyHeight = 1
}
var content string
if m.err != nil {
content = styleError.Render(fmt.Sprintf("Error: %v", m.err))
} else if !m.connected {
content = styleMuted.Render("Connecting…")
} else if m.statusMsg != "" {
content = styleStatus.Render(m.statusMsg)
} else {
switch m.activeSection {
case sectionAlerts:
content = styleMuted.Render("Alert dashboard — coming in Stage 2")
case sectionSchedule:
content = styleMuted.Render("On-call schedule — coming in Stage 4")
case sectionUsers:
content = styleMuted.Render("User management — coming in Stage 5")
}
}
lines := strings.Split(content, "\n")
padding := (bodyHeight - len(lines)) / 2
if padding < 0 {
padding = 0
}
return strings.Repeat("\n", padding) + content
}
func (m Model) renderFooter() string {
helpView := m.help.ShortHelpView(m.keys.ShortHelp())
return "\n" + styleFooter.Render(helpView)
}