summaryrefslogtreecommitdiff
path: root/internal/tui/timer_box.go
diff options
context:
space:
mode:
Diffstat (limited to 'internal/tui/timer_box.go')
-rw-r--r--internal/tui/timer_box.go107
1 files changed, 68 insertions, 39 deletions
diff --git a/internal/tui/timer_box.go b/internal/tui/timer_box.go
index 17781ee..408c3b5 100644
--- a/internal/tui/timer_box.go
+++ b/internal/tui/timer_box.go
@@ -2,56 +2,84 @@ package tui
import (
"fmt"
+ "time"
- tea "github.com/charmbracelet/bubbletea"
+ "punchcard/internal/queries"
)
+// TimerInfo holds information about the current or most recent timer state
+type TimerInfo struct {
+ IsActive bool
+ EntryID int64
+ StartTime time.Time
+ Duration time.Duration
+ ClientID int64
+ ClientName string
+ ProjectID *int64
+ ProjectName string
+ Description *string
+ BillableRate *float64
+}
+
+func (ti *TimerInfo) setNames(clients []queries.Client, projects map[int64][]queries.Project) {
+ for _, cl := range clients {
+ if cl.ID == ti.ClientID {
+ ti.ClientName = cl.Name
+ break
+ }
+ }
+
+ if ti.ProjectID == nil {
+ return
+ }
+ for _, group := range projects {
+ for _, proj := range group {
+ if proj.ID == *ti.ProjectID {
+ ti.ProjectName = proj.Name
+ return
+ }
+ }
+ }
+}
+
+// Box models for the three main components
+type TimerBoxModel struct {
+ timerInfo TimerInfo
+ currentTime time.Time
+}
+
// NewTimerBoxModel creates a new timer box model
func NewTimerBoxModel() TimerBoxModel {
return TimerBoxModel{}
}
-// Update handles messages for the timer box
-func (m TimerBoxModel) Update(msg tea.Msg) (TimerBoxModel, tea.Cmd) {
- return m, nil
-}
-
// View renders the timer box
func (m TimerBoxModel) View(width, height int, isSelected bool) string {
var content string
-
+
if m.timerInfo.IsActive {
content = m.renderActiveTimer()
} else {
- content = m.renderInactiveTimer()
+ content = m.renderInactiveTimer()
}
-
+
// Apply box styling
style := unselectedBoxStyle
if isSelected {
style = selectedBoxStyle
}
-
- var title string
- if m.timerInfo.IsActive {
- title = "⏱ Active Timer"
- } else {
- title = "⚪ Timer (Inactive)"
- }
-
- return style.Width(width).Height(height).Render(
- fmt.Sprintf("%s\n\n%s", title, content),
- )
+
+ return style.Width(width).Height(height).Render(content)
}
// renderActiveTimer renders the active timer display
func (m TimerBoxModel) renderActiveTimer() string {
- var content string
-
+ content := "⏱ Active Timer\n\n"
+
// Timer duration
- timerLine := fmt.Sprintf("Duration: %s", FormatDuration(m.timerInfo.Duration))
+ timerLine := fmt.Sprintf("Duration: %s", FormatDuration(m.currentTime.Sub(m.timerInfo.StartTime)))
content += activeTimerStyle.Render(timerLine) + "\n\n"
-
+
// Project/Client info
if m.timerInfo.ProjectName != "" {
projectLine := fmt.Sprintf("Project: %s / %s", m.timerInfo.ClientName, m.timerInfo.ProjectName)
@@ -60,42 +88,43 @@ func (m TimerBoxModel) renderActiveTimer() string {
clientLine := fmt.Sprintf("Client: %s", m.timerInfo.ClientName)
content += clientLine + "\n"
}
-
+
// Start time (convert from UTC to local)
localStartTime := m.timerInfo.StartTime.Local()
startLine := fmt.Sprintf("Started: %s", localStartTime.Format("3:04 PM"))
content += startLine + "\n"
-
+
// Description if available
- if m.timerInfo.Description != "" {
+ if m.timerInfo.Description != nil {
content += "\n"
- descLine := fmt.Sprintf("Description: %s", m.timerInfo.Description)
+ descLine := fmt.Sprintf("Description: %s", *m.timerInfo.Description)
content += descLine + "\n"
}
-
+
// Billable rate if available
if m.timerInfo.BillableRate != nil {
rateLine := fmt.Sprintf("Rate: $%.2f/hr", *m.timerInfo.BillableRate)
content += rateLine + "\n"
}
-
+
return content
}
// renderInactiveTimer renders the inactive timer display
func (m TimerBoxModel) renderInactiveTimer() string {
- var content string
-
+ content := "⚪ Last Timer (Inactive)\n\n"
+
content += "No active timer\n\n"
content += "Ready to start tracking time.\n"
- content += "Use 'i' to punch in or select\n"
+ content += "Use 'p' to punch in, or select\n"
content += "a client/project from the left."
-
+
return content
}
-// UpdateTimerInfo updates the timer info
-func (m TimerBoxModel) UpdateTimerInfo(timerInfo TimerInfo) TimerBoxModel {
- m.timerInfo = timerInfo
- return m
-} \ No newline at end of file
+func (m TimerBoxModel) activeTime() time.Duration {
+ if !m.timerInfo.IsActive {
+ return 0
+ }
+ return m.currentTime.Sub(m.timerInfo.StartTime)
+}