package pages import ( "strconv" "strings" "tasksquire/common" "tasksquire/taskwarrior" "github.com/charmbracelet/bubbles/key" "github.com/charmbracelet/bubbles/table" tea "github.com/charmbracelet/bubbletea" "github.com/charmbracelet/lipgloss" ) type ReportPage struct { common *common.Common activeReport *taskwarrior.Report activeContext *taskwarrior.Context activeProject string selectedTask *taskwarrior.Task tasks taskwarrior.Tasks taskTable table.Model tableStyle table.Styles keymap ReportKeys subpage tea.Model subpageActive bool } type ReportKeys struct { Quit key.Binding Up key.Binding Down key.Binding Select key.Binding ToggleFocus key.Binding } func NewReportPage(com *common.Common, report *taskwarrior.Report) *ReportPage { s := table.DefaultStyles() s.Header = s.Header. BorderStyle(lipgloss.NormalBorder()). BorderForeground(lipgloss.Color("240")). BorderBottom(true). Bold(false) s.Selected = s.Selected. Foreground(lipgloss.Color("229")). Background(lipgloss.Color("57")). Bold(false) keys := ReportKeys{ Quit: key.NewBinding( key.WithKeys("q", "ctrl+c"), key.WithHelp("q, ctrl+c", "Quit"), ), Up: key.NewBinding( key.WithKeys("k", "up"), key.WithHelp("↑/k", "Up"), ), Down: key.NewBinding( key.WithKeys("j", "down"), key.WithHelp("↓/j", "Down"), ), Select: key.NewBinding( key.WithKeys("enter"), key.WithHelp("enter", "Select"), ), ToggleFocus: key.NewBinding( key.WithKeys("esc"), key.WithHelp("esc", "Toggle focus"), ), } return &ReportPage{ common: com, activeReport: report, activeContext: com.TW.GetActiveContext(), activeProject: "", tableStyle: s, keymap: keys, } } func (p ReportPage) Init() tea.Cmd { return p.getTasks() } func (p ReportPage) Update(msg tea.Msg) (tea.Model, tea.Cmd) { var cmds []tea.Cmd switch msg := msg.(type) { case BackMsg: p.subpageActive = false case TaskMsg: p.populateTaskTable(msg) case UpdateReportMsg: p.activeReport = msg cmds = append(cmds, p.getTasks()) case UpdateContextMsg: p.activeContext = msg p.common.TW.SetContext(msg) cmds = append(cmds, p.getTasks()) case UpdateProjectMsg: p.activeProject = string(msg) cmds = append(cmds, p.getTasks()) case AddedTaskMsg: cmds = append(cmds, p.getTasks()) case tea.WindowSizeMsg: p.taskTable.SetWidth(msg.Width - 2) p.taskTable.SetHeight(msg.Height - 4) case tea.KeyMsg: switch { case key.Matches(msg, p.common.Keymap.Quit): return p, tea.Quit case key.Matches(msg, p.common.Keymap.SetReport): p.subpage = NewReportPickerPage(p.common, p.activeReport) p.subpage.Init() p.subpageActive = true p.common.PageStack.Push(p) return p.subpage, nil case key.Matches(msg, p.common.Keymap.SetContext): p.subpage = NewContextPickerPage(p.common) p.subpage.Init() p.subpageActive = true p.common.PageStack.Push(p) return p.subpage, nil case key.Matches(msg, p.common.Keymap.Add): p.subpage = NewTaskEditorPage(p.common, taskwarrior.Task{}) p.subpage.Init() p.subpageActive = true p.common.PageStack.Push(p) return p.subpage, nil case key.Matches(msg, p.common.Keymap.SetProject): p.subpage = NewProjectPickerPage(p.common, p.activeProject) p.subpage.Init() p.subpageActive = true p.common.PageStack.Push(p) return p.subpage, nil } } var cmd tea.Cmd p.taskTable, cmd = p.taskTable.Update(msg) cmds = append(cmds, cmd) if p.tasks != nil { p.selectedTask = (*taskwarrior.Task)(p.tasks[p.taskTable.Cursor()]) } return p, tea.Batch(cmds...) } func (p ReportPage) View() string { return p.common.Styles.Main.Render(p.taskTable.View()) + "\n" } func (p *ReportPage) populateTaskTable(tasks []*taskwarrior.Task) { columns := []table.Column{ {Title: "ID", Width: 4}, {Title: "Project", Width: 10}, {Title: "Tags", Width: 10}, {Title: "Prio", Width: 2}, {Title: "Due", Width: 10}, {Title: "Task", Width: 50}, } var rows []table.Row for _, task := range tasks { rows = append(rows, table.Row{ strconv.FormatInt(task.Id, 10), task.Project, strings.Join(task.Tags, ", "), task.Priority, task.Due, task.Description, }) } p.taskTable = table.New( table.WithColumns(columns), table.WithRows(rows), table.WithFocused(true), // table.WithHeight(7), // table.WithWidth(100), ) p.taskTable.SetStyles(p.tableStyle) } func (p *ReportPage) getTasks() tea.Cmd { return func() tea.Msg { filters := []string{} if p.activeProject != "" { filters = append(filters, "project:"+p.activeProject) } p.tasks = p.common.TW.GetTasks(p.activeReport, filters...) return TaskMsg(p.tasks) } } type TaskMsg taskwarrior.Tasks