diff options
author | T <t@tjp.lol> | 2025-08-05 12:36:30 -0600 |
---|---|---|
committer | T <t@tjp.lol> | 2025-08-06 12:13:11 -0600 |
commit | 65e2ed65775d64afbc6065a3b4ac1069020093ca (patch) | |
tree | f94fabfed5be2d2622429ebc7c8af1bf51085824 /internal/tui/timer_box.go | |
parent | 665bd389a0a1c8adadcaa1122e846cc81f5ead31 (diff) |
most features in TUI working, remaining unimplemented keybinds need a modal view
Diffstat (limited to 'internal/tui/timer_box.go')
-rw-r--r-- | internal/tui/timer_box.go | 107 |
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) +} |