Add ticket time tracking with reports and entry management.
Support start/stop timer, manual durations, grouped reports, and per-ticket edit/delete of time entries with undo. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -0,0 +1,79 @@
|
||||
package views
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
"unicode"
|
||||
|
||||
"task/internal/ticket"
|
||||
)
|
||||
|
||||
// GroupByMenu renders a report grouping picker.
|
||||
type GroupByMenu struct {
|
||||
Cursor int
|
||||
Width int
|
||||
Styles StatusMenuStyles
|
||||
}
|
||||
|
||||
// NewGroupByMenu creates a menu with the given grouping pre-selected.
|
||||
func NewGroupByMenu(current ticket.GroupBy, width int, styles StatusMenuStyles) GroupByMenu {
|
||||
return GroupByMenu{
|
||||
Cursor: current.Index(),
|
||||
Width: width,
|
||||
Styles: styles,
|
||||
}
|
||||
}
|
||||
|
||||
// MoveDown moves the selection down.
|
||||
func (m *GroupByMenu) MoveDown() {
|
||||
if m.Cursor < len(ticket.AllGroupBys)-1 {
|
||||
m.Cursor++
|
||||
}
|
||||
}
|
||||
|
||||
// MoveUp moves the selection up.
|
||||
func (m *GroupByMenu) MoveUp() {
|
||||
if m.Cursor > 0 {
|
||||
m.Cursor--
|
||||
}
|
||||
}
|
||||
|
||||
// JumpToShortcut moves the cursor to the option whose shortcut matches r.
|
||||
func (m *GroupByMenu) JumpToShortcut(r rune) bool {
|
||||
r = unicode.ToLower(r)
|
||||
for i, g := range ticket.AllGroupBys {
|
||||
if g.Shortcut() == r {
|
||||
m.Cursor = i
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// Selected returns the currently highlighted grouping.
|
||||
func (m GroupByMenu) Selected() ticket.GroupBy {
|
||||
if m.Cursor < 0 || m.Cursor >= len(ticket.AllGroupBys) {
|
||||
return ticket.GroupByProject
|
||||
}
|
||||
return ticket.AllGroupBys[m.Cursor]
|
||||
}
|
||||
|
||||
// View renders the grouping menu.
|
||||
func (m GroupByMenu) View() string {
|
||||
var lines []string
|
||||
lines = append(lines, m.Styles.Title.Render("Group report by"))
|
||||
for i, g := range ticket.AllGroupBys {
|
||||
entry := fmt.Sprintf("%c %s", g.Shortcut(), g.Label())
|
||||
if i == m.Cursor {
|
||||
lines = append(lines, m.Styles.Selected.Render("▸ "+entry))
|
||||
} else {
|
||||
lines = append(lines, m.Styles.Normal.Render(" "+entry))
|
||||
}
|
||||
}
|
||||
body := strings.Join(lines, "\n")
|
||||
w := m.Width
|
||||
if w < 20 {
|
||||
w = 20
|
||||
}
|
||||
return m.Styles.Box.Width(min(40, w-2)).Render(body)
|
||||
}
|
||||
Reference in New Issue
Block a user