package tui import ( "fmt" "strings" "github.com/charmbracelet/bubbles/viewport" "github.com/charmbracelet/lipgloss" "git.unkin.net/unkin/forgebot/pkg/models" ) type detailView struct { task *models.Task viewport viewport.Model ready bool } func newDetailView() detailView { return detailView{} } func (d *detailView) setTask(task *models.Task, width, height int) { d.task = task d.viewport = viewport.New(width, height-2) d.viewport.SetContent(d.renderContent(width)) d.ready = true } func (d *detailView) renderContent(width int) string { t := d.task if t == nil { return "" } var b strings.Builder titleStyle := lipgloss.NewStyle().Bold(true).Foreground(statusColors[t.Status]) b.WriteString(titleStyle.Render(fmt.Sprintf("Task: %s", t.ID))) b.WriteString("\n\n") row := func(label, value string) { b.WriteString(detailLabelStyle.Render(label)) b.WriteString(detailValueStyle.Render(value)) b.WriteString("\n") } row("Status:", string(t.Status)) row("Command:", t.Command) row("Repository:", t.Repository) row("Ref:", t.Ref) row("Author:", t.Author) if t.PoolRef != "" { row("Pool:", t.PoolRef) } if t.IssueNumber > 0 { row("Issue:", fmt.Sprintf("#%d", t.IssueNumber)) } if t.PRNumber > 0 { row("PR:", fmt.Sprintf("#%d", t.PRNumber)) } if t.Skill != "" { row("Skill:", t.Skill) } if t.JobName != "" { row("Job:", t.JobName) } if t.ParentTaskID != "" { row("Parent:", t.ParentTaskID) } b.WriteString("\n") row("Created:", t.CreatedAt.Format("2006-01-02 15:04:05")) if t.StartedAt != nil { row("Started:", t.StartedAt.Format("2006-01-02 15:04:05")) } if t.CompletedAt != nil { row("Completed:", t.CompletedAt.Format("2006-01-02 15:04:05")) } if t.Body != "" { b.WriteString("\n") b.WriteString(lipgloss.NewStyle().Bold(true).Render("Body:")) b.WriteString("\n") b.WriteString(t.Body) b.WriteString("\n") } if t.Result != "" { b.WriteString("\n") b.WriteString(lipgloss.NewStyle().Bold(true).Render("Result:")) b.WriteString("\n") b.WriteString(t.Result) b.WriteString("\n") } if t.ErrorMessage != "" { b.WriteString("\n") b.WriteString(errStyle.Bold(true).Render("Error:")) b.WriteString("\n") b.WriteString(errStyle.Render(t.ErrorMessage)) b.WriteString("\n") } return b.String() } func (d *detailView) view() string { if !d.ready { return "" } header := lipgloss.NewStyle().Bold(true).Render("Task Detail") + " " + helpStyle.Render("esc=back e=edit j/k=scroll") return header + "\n" + d.viewport.View() }