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:
@@ -3,6 +3,7 @@ package views
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/charmbracelet/lipgloss"
|
||||
|
||||
@@ -25,12 +26,13 @@ type TicketListStyles struct {
|
||||
|
||||
// TicketList is a custom viewport list of ticket cards.
|
||||
type TicketList struct {
|
||||
Items []ticket.Ticket
|
||||
Cursor int
|
||||
Offset int
|
||||
Width int
|
||||
Height int
|
||||
Styles TicketListStyles
|
||||
Items []ticket.Ticket
|
||||
Cursor int
|
||||
Offset int
|
||||
Width int
|
||||
Height int
|
||||
Styles TicketListStyles
|
||||
SpentByID map[string]time.Duration // optional; shown on selected card
|
||||
}
|
||||
|
||||
// SetSize updates the viewport dimensions.
|
||||
@@ -124,12 +126,16 @@ func (l *TicketList) renderCard(t ticket.Ticket, selected bool) string {
|
||||
|
||||
var content string
|
||||
if selected {
|
||||
// Expanded: headline + glamour-rendered description (fixed dark style).
|
||||
// Expanded: headline + optional spent + glamour description.
|
||||
content = headerLine
|
||||
if spent, ok := l.SpentByID[t.ID]; ok && spent > 0 {
|
||||
content += "\n" + lipgloss.NewStyle().Faint(true).Render(
|
||||
"spent: "+ticket.FormatDurationHuman(spent),
|
||||
)
|
||||
}
|
||||
desc := strings.TrimSpace(t.Description)
|
||||
if desc != "" {
|
||||
content = headerLine + "\n" + RenderMarkdown(desc, innerWidth)
|
||||
} else {
|
||||
content = headerLine
|
||||
content += "\n" + RenderMarkdown(desc, innerWidth)
|
||||
}
|
||||
} else {
|
||||
content = headerLine
|
||||
@@ -190,8 +196,11 @@ func (l *TicketList) estimateHeight(index int) int {
|
||||
if index < 0 || index >= len(l.Items) {
|
||||
return CollapsedCardHeight
|
||||
}
|
||||
if index == l.Cursor && strings.TrimSpace(l.Items[index].Description) != "" {
|
||||
return lipgloss.Height(l.renderCard(l.Items[index], true))
|
||||
if index == l.Cursor {
|
||||
t := l.Items[index]
|
||||
if strings.TrimSpace(t.Description) != "" || (l.SpentByID != nil && l.SpentByID[t.ID] > 0) {
|
||||
return lipgloss.Height(l.renderCard(t, true))
|
||||
}
|
||||
}
|
||||
return CollapsedCardHeight
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user