package ui import ( "fmt" "strings" "github.com/charmbracelet/lipgloss" "task/internal/config" ) func (m Model) renderHeader() string { brand := m.styles.HeaderBrand.Render(config.CliName) project := m.styles.HeaderMeta.Render(fmt.Sprintf("project: %s", m.cfg.ActiveProject)) board := m.styles.FilterHint.Render(fmt.Sprintf("list: %s", m.boardFilter.Label())) count := m.styles.HeaderMeta.Render(fmt.Sprintf("%d tickets", m.ticketCount())) parts := []string{brand, project, board, count} if label := m.timerHeaderLabel(); label != "" { parts = append(parts, m.styles.FilterHint.Render(label)) } if m.filter != "" { parts = append(parts, m.styles.FilterHint.Render(fmt.Sprintf("filter: %q", m.filter))) } if m.status != "" { style := m.styles.StatusMsg if m.statusIsError { style = m.styles.ErrorMsg } parts = append(parts, style.Render(m.status)) } line := strings.Join(parts, m.styles.HeaderMeta.Render(" │ ")) return m.styles.Header.Width(m.width).Render(line) } func (m Model) renderBody(height int) string { if height < 1 { height = 1 } switch m.mode { case ModeCreate: label := "New ticket:" if m.creatingProject { label = "New project:" } prompt := m.styles.InputPrompt.Render(label) content := prompt + "\n" + m.input.View() return lipgloss.NewStyle().Height(height).Width(m.width).Render(content) case ModeSearch: prompt := m.styles.InputPrompt.Render("Search:") content := prompt + "\n" + m.input.View() return lipgloss.NewStyle().Height(height).Width(m.width).Render(content) case ModeTimeManual: prompt := m.styles.InputPrompt.Render("Log time:") content := prompt + "\n" + m.input.View() return lipgloss.NewStyle().Height(height).Width(m.width).Render(content) case ModeTimeEdit: prompt := m.styles.InputPrompt.Render("Edit duration:") content := prompt + "\n" + m.input.View() return lipgloss.NewStyle().Height(height).Width(m.width).Render(content) case ModeTimeEntries: m.timeEntries.SetSize(m.width, height) return m.timeEntries.View() case ModeReport: m.report.SetSize(m.width, height) return m.report.View() case ModeReportGroup: menu := m.groupByMenu.View() return lipgloss.NewStyle().Height(height).Width(m.width).Render(menu) case ModeProjects, ModeMoveTicket: m.projectList.SetSize(m.width, height) return m.projectList.View() case ModeStatus: menu := m.statusMenu.View() return lipgloss.NewStyle().Height(height).Width(m.width).Render(menu) case ModeBoard: menu := m.boardMenu.View() return lipgloss.NewStyle().Height(height).Width(m.width).Render(menu) case ModeConfirmDelete: title := m.pendingDeleteTitle if title == "" { if m.pendingDeleteProject != "" { title = "this project" } else { title = "this ticket" } } var prompt string if m.pendingDeleteProject != "" { prompt = m.styles.ErrorMsg.Render(fmt.Sprintf("Delete %s?", title)) } else { prompt = m.styles.ErrorMsg.Render(fmt.Sprintf("Delete %q?", title)) } hint := m.styles.StatusMsg.Render("y/enter confirm · esc cancel") content := prompt + "\n" + hint return lipgloss.NewStyle().Height(height).Width(m.width).Render(content) default: m.tickets.SetSize(m.width, height) return m.tickets.View() } }