summaryrefslogtreecommitdiff
path: root/internal/tui/timer_box.go
diff options
context:
space:
mode:
authorT <t@tjp.lol>2025-08-05 11:37:02 -0600
committerT <t@tjp.lol>2025-08-05 11:37:08 -0600
commit665bd389a0a1c8adadcaa1122e846cc81f5ead31 (patch)
treef34f9ec77891308c600c680683f60951599429c3 /internal/tui/timer_box.go
parentdc895cec9d8a84af89ce2501db234dff33c757e2 (diff)
WIP TUI
Diffstat (limited to 'internal/tui/timer_box.go')
-rw-r--r--internal/tui/timer_box.go101
1 files changed, 101 insertions, 0 deletions
diff --git a/internal/tui/timer_box.go b/internal/tui/timer_box.go
new file mode 100644
index 0000000..17781ee
--- /dev/null
+++ b/internal/tui/timer_box.go
@@ -0,0 +1,101 @@
+package tui
+
+import (
+ "fmt"
+
+ tea "github.com/charmbracelet/bubbletea"
+)
+
+// 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()
+ }
+
+ // 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),
+ )
+}
+
+// renderActiveTimer renders the active timer display
+func (m TimerBoxModel) renderActiveTimer() string {
+ var content string
+
+ // Timer duration
+ timerLine := fmt.Sprintf("Duration: %s", FormatDuration(m.timerInfo.Duration))
+ 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)
+ content += projectLine + "\n"
+ } else {
+ 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 != "" {
+ content += "\n"
+ 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 += "No active timer\n\n"
+ content += "Ready to start tracking time.\n"
+ content += "Use 'i' 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