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.
This commit is contained in:
Niklas Ye
2026-05-21 13:28:13 +02:00
commit 55ee64530b
14 changed files with 849 additions and 0 deletions
+89
View File
@@ -0,0 +1,89 @@
package tui
import (
"time"
"github.com/charmbracelet/bubbles/help"
tea "github.com/charmbracelet/bubbletea"
"github.com/yeniklas/terdut-tui/internal/api"
)
type section int
const (
sectionAlerts section = iota
sectionSchedule
sectionUsers
)
type mode int
const (
modeDashboard mode = iota
modeDetail
modeSchedule
modeUsers
)
// tea.Msg types
type connectedMsg struct{ serverURL string }
type connectErrMsg struct{ err error }
type tickMsg time.Time
type clearStatusMsg struct{}
// Model holds all UI state.
type Model struct {
client *api.Client
serverURL string
refreshInterval time.Duration
activeSection section
mode mode
width int
height int
connected bool
err error
statusMsg string
help help.Model
keys keyMap
}
func NewModel(client *api.Client, serverURL string, refreshInterval time.Duration) Model {
return Model{
client: client,
serverURL: serverURL,
refreshInterval: refreshInterval,
activeSection: sectionAlerts,
mode: modeDashboard,
help: help.New(),
keys: keys,
}
}
func (m Model) Init() tea.Cmd {
return connectCmd(m.client)
}
func connectCmd(client *api.Client) tea.Cmd {
return func() tea.Msg {
if err := client.HealthCheck(); err != nil {
return connectErrMsg{err}
}
return connectedMsg{}
}
}
func tickCmd(interval time.Duration) tea.Cmd {
return tea.Tick(interval, func(t time.Time) tea.Msg {
return tickMsg(t)
})
}
func clearStatusCmd() tea.Cmd {
return tea.Tick(3*time.Second, func(time.Time) tea.Msg {
return clearStatusMsg{}
})
}