Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 7 additions & 7 deletions cmd/delete.go
Original file line number Diff line number Diff line change
Expand Up @@ -120,17 +120,17 @@ var deleteCmd = &cobra.Command{
fmt.Println()
ui.PrintWarning(ui.EmojiWarning, "You are about to delete this entry:")
fmt.Println()
ui.PrintInfo(4, "ID", fmt.Sprintf("%d", selectedEntry.ID))
ui.PrintInfo(4, "Project", selectedEntry.ProjectName)
ui.PrintInfo(4, "Start", selectedEntry.StartTime.Format("Jan 2, 2006 at 3:04 PM"))
ui.PrintInfo(4, ui.Bold("ID"), fmt.Sprintf("%d", selectedEntry.ID))
ui.PrintInfo(4, ui.Bold("Project"), selectedEntry.ProjectName)
ui.PrintInfo(4, ui.Bold("Start"), selectedEntry.StartTime.Format("Jan 2, 2006 at 3:04 PM"))
if selectedEntry.EndTime != nil {
ui.PrintInfo(4, "End", selectedEntry.EndTime.Format("Jan 2, 2006 at 3:04 PM"))
ui.PrintInfo(4, "Duration", ui.FormatDuration(selectedEntry.Duration()))
ui.PrintInfo(4, ui.Bold("End"), selectedEntry.EndTime.Format("Jan 2, 2006 at 3:04 PM"))
ui.PrintInfo(4, ui.Bold("Duration"), ui.FormatDuration(selectedEntry.Duration()))
} else {
ui.PrintInfo(4, "Status", ui.Warning("Running"))
ui.PrintInfo(4, ui.Bold("Status"), ui.Warning("Running"))
}
if selectedEntry.Description != "" {
ui.PrintInfo(4, "Description", selectedEntry.Description)
ui.PrintInfo(4, ui.Bold("Description"), selectedEntry.Description)
}
fmt.Println()

Expand Down
8 changes: 4 additions & 4 deletions cmd/edit.go
Original file line number Diff line number Diff line change
Expand Up @@ -251,7 +251,7 @@ var editCmd = &cobra.Command{

// Show confirmation with diff
fmt.Println()
ui.PrintInfo(0, "Changes to entry", fmt.Sprintf("#%d", selectedEntry.ID))
ui.PrintInfo(0, ui.Bold("Changes to entry"), fmt.Sprintf("#%d", selectedEntry.ID))
fmt.Println()

hasChanges := false
Expand All @@ -260,19 +260,19 @@ var editCmd = &cobra.Command{
hasChanges = true
oldStr := selectedEntry.StartTime.Format("01-02-2006 3:04 PM")
newStr := editedEntry.StartTime.Format("01-02-2006 3:04 PM")
fmt.Printf(" Start time: %s → %s\n", ui.Muted(oldStr), newStr)
fmt.Printf(" %s %s → %s\n", ui.Bold("Start time:"), ui.Muted(oldStr), newStr)
}

if !selectedEntry.EndTime.Equal(*editedEntry.EndTime) {
hasChanges = true
oldStr := selectedEntry.EndTime.Format("01-02-2006 3:04 PM")
newStr := editedEntry.EndTime.Format("01-02-2006 3:04 PM")
fmt.Printf(" End time: %s → %s\n", ui.Muted(oldStr), newStr)
fmt.Printf(" %s %s → %s\n", ui.Bold("End time:"), ui.Muted(oldStr), newStr)
}

if selectedEntry.Description != editedEntry.Description {
hasChanges = true
fmt.Printf(" Description: %s → %s\n", ui.Muted(fmt.Sprintf("%q", selectedEntry.Description)), fmt.Sprintf("%q", editedEntry.Description))
fmt.Printf(" %s %s → %s\n", ui.Bold("Description:"), ui.Muted(fmt.Sprintf("%q", selectedEntry.Description)), fmt.Sprintf("%q", editedEntry.Description))
}

if !hasChanges {
Expand Down
2 changes: 1 addition & 1 deletion cmd/export.go
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,7 @@ var exportCmd = &cobra.Command{
os.Exit(1)
}

ui.PrintSuccess(ui.EmojiExport, fmt.Sprintf("Exported %d entries to %s", len(entries), filename))
ui.PrintSuccess(ui.EmojiExport, fmt.Sprintf("Exported %s to %s", ui.Bold(fmt.Sprintf("%d entries", len(entries))), ui.Bold(filename)))

ui.NewlineBelow()
},
Expand Down
6 changes: 3 additions & 3 deletions cmd/init.go
Original file line number Diff line number Diff line change
Expand Up @@ -107,12 +107,12 @@ var initCmd = &cobra.Command{
}

fmt.Println()
ui.PrintSuccess(ui.EmojiSuccess, fmt.Sprintf("Created .tmporc for project '%s'", name))
ui.PrintSuccess(ui.EmojiSuccess, fmt.Sprintf("Created .tmporc for project %s", ui.Bold(name)))
if hourlyRate > 0 {
ui.PrintInfo(4, "Hourly Rate", fmt.Sprintf("$%.2f", hourlyRate))
ui.PrintInfo(4, ui.Bold("Hourly Rate"), fmt.Sprintf("$%.2f", hourlyRate))
}
if description != "" {
ui.PrintInfo(4, "Description", description)
ui.PrintInfo(4, ui.Bold("Description"), description)
}

fmt.Println()
Expand Down
6 changes: 3 additions & 3 deletions cmd/log.go
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ var logCmd = &cobra.Command{
fmt.Println()
}

fmt.Println(ui.Muted(fmt.Sprintf("─── %s ───", entryDate)))
fmt.Println(ui.Bold(ui.Muted(fmt.Sprintf("─── %s ───", entryDate))))
currentDate = entryDate
}

Expand All @@ -93,15 +93,15 @@ var logCmd = &cobra.Command{
timeRange += ui.Warning("(running)") + " "
}

fmt.Printf(" %s %-20s %s\n", timeRange, entry.ProjectName, ui.FormatDuration(duration))
fmt.Printf(" %s %s %s\n", timeRange, ui.Bold(fmt.Sprintf("%-20s", entry.ProjectName)), ui.FormatDuration(duration))
if entry.Description != "" {
fmt.Printf(" %s %s\n", ui.Muted("└─"), entry.Description)
}
}

fmt.Println()
ui.PrintSeparator()
fmt.Printf("%s %s\n", ui.Info("Total Time:"), ui.FormatDuration(totalDuration))
fmt.Printf("%s %s\n", ui.BoldInfo("Total Time:"), ui.Bold(ui.FormatDuration(totalDuration)))

ui.NewlineBelow()
},
Expand Down
14 changes: 7 additions & 7 deletions cmd/manual.go
Original file line number Diff line number Diff line change
Expand Up @@ -156,19 +156,19 @@ var manualCmd = &cobra.Command{

duration := entry.Duration()
fmt.Println()
ui.PrintSuccess(ui.EmojiSuccess, fmt.Sprintf("Created manual entry for '%s'", entry.ProjectName))
ui.PrintInfo(4, "Start", startTime.Format("Jan 2, 2006 at 3:04 PM"))
ui.PrintInfo(4, "End", endTime.Format("Jan 2, 2006 at 3:04 PM"))
ui.PrintInfo(4, "Duration", ui.FormatDuration(duration))
ui.PrintSuccess(ui.EmojiSuccess, fmt.Sprintf("Created manual entry for %s", ui.Bold(entry.ProjectName)))
ui.PrintInfo(4, ui.Bold("Start"), startTime.Format("Jan 2, 2006 at 3:04 PM"))
ui.PrintInfo(4, ui.Bold("End"), endTime.Format("Jan 2, 2006 at 3:04 PM"))
ui.PrintInfo(4, ui.Bold("Duration"), ui.FormatDuration(duration))

if entry.Description != "" {
ui.PrintInfo(4, "Description", entry.Description)
ui.PrintInfo(4, ui.Bold("Description"), entry.Description)
}

if entry.HourlyRate != nil {
earnings := duration.Hours() * *entry.HourlyRate
fmt.Printf(" %s %s\n", ui.Info("Hourly Rate:"), fmt.Sprintf("$%.2f", *entry.HourlyRate))
fmt.Printf(" %s %s\n", ui.Info("Earnings:"), fmt.Sprintf("$%.2f", earnings))
fmt.Printf(" %s %s\n", ui.BoldInfo("Hourly Rate:"), fmt.Sprintf("$%.2f", *entry.HourlyRate))
fmt.Printf(" %s %s\n", ui.BoldInfo("Earnings:"), fmt.Sprintf("$%.2f", earnings))
}

ui.NewlineBelow()
Expand Down
2 changes: 1 addition & 1 deletion cmd/start.go
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ var startCmd = &cobra.Command{
os.Exit(1)
}

ui.PrintSuccess(ui.EmojiStart, fmt.Sprintf("Started tracking time for '%s'", entry.ProjectName))
ui.PrintSuccess(ui.EmojiStart, fmt.Sprintf("Started tracking time for %s", ui.Bold(entry.ProjectName)))

if cfg, _, err := config.FindAndLoad(); err == nil && cfg != nil {
ui.PrintMuted(4, "└─ Config Source: .tmporc")
Expand Down
26 changes: 13 additions & 13 deletions cmd/stats.go
Original file line number Diff line number Diff line change
Expand Up @@ -110,20 +110,20 @@ func ShowPeriodStats(entries []*storage.TimeEntry, periodName string) {
}
}

ui.PrintSuccess(ui.EmojiStats, fmt.Sprintf("Stats for %s", periodName))
ui.PrintSuccess(ui.EmojiStats, fmt.Sprintf("Stats for %s", ui.Bold(periodName)))
fmt.Println()
ui.PrintInfo(4, "Total Time", fmt.Sprintf("%s (%.2f hours)", ui.FormatDuration(totalDuration), totalDuration.Hours()))
ui.PrintInfo(4, "Total Entries", fmt.Sprintf("%d", len(entries)))
ui.PrintInfo(4, ui.Bold("Total Time"), fmt.Sprintf("%s (%.2f hours)", ui.FormatDuration(totalDuration), totalDuration.Hours()))
ui.PrintInfo(4, ui.Bold("Total Entries"), fmt.Sprintf("%d", len(entries)))

if hasAnyEarnings {
ui.PrintInfo(4, "Earnings", fmt.Sprintf("$%.2f", totalEarnings))
ui.PrintInfo(4, ui.Bold("Earnings"), fmt.Sprintf("$%.2f", totalEarnings))
}

fmt.Println()
ui.PrintInfo(4, "By Project", "")
ui.PrintInfo(4, ui.Bold("By Project"), "")
for project, duration := range projectStats {
percentage := (duration.Seconds() / totalDuration.Seconds()) * 100
fmt.Printf(" %-20s %s (%.1f%%)\n", project, ui.FormatDuration(duration), percentage)
fmt.Printf(" %s %s (%.1f%%)\n", ui.Bold(fmt.Sprintf("%-20s", project)), ui.FormatDuration(duration), percentage)

if earnings, ok := projectEarnings[project]; ok && earnings > 0 {
fmt.Printf(" %s %s\n", ui.Muted("└─ Earnings:"), fmt.Sprintf("$%.2f", earnings))
Expand Down Expand Up @@ -176,20 +176,20 @@ func ShowAllTimeStats(entries []*storage.TimeEntry, db *storage.Database) {

projects, _ := db.GetAllProjects()

ui.PrintSuccess(ui.EmojiStats, "All-Time Statistics")
ui.PrintInfo(4, "Total Time", fmt.Sprintf("%s (%.2f hours)", ui.FormatDuration(totalDuration), totalDuration.Hours()))
ui.PrintInfo(4, "Total Entries", fmt.Sprintf("%d", len(entries)))
ui.PrintInfo(4, "Projects Tracked", fmt.Sprintf("%d", len(projects)))
ui.PrintSuccess(ui.EmojiStats, ui.Bold("All-Time Statistics"))
ui.PrintInfo(4, ui.Bold("Total Time"), fmt.Sprintf("%s (%.2f hours)", ui.FormatDuration(totalDuration), totalDuration.Hours()))
ui.PrintInfo(4, ui.Bold("Total Entries"), fmt.Sprintf("%d", len(entries)))
ui.PrintInfo(4, ui.Bold("Projects Tracked"), fmt.Sprintf("%d", len(projects)))

if hasAnyEarnings {
ui.PrintInfo(4, "Earnings", fmt.Sprintf("$%.2f", totalEarnings))
ui.PrintInfo(4, ui.Bold("Earnings"), fmt.Sprintf("$%.2f", totalEarnings))
}

fmt.Println()
ui.PrintInfo(4, "By Project", "")
ui.PrintInfo(4, ui.Bold("By Project"), "")
for project, duration := range projectStats {
percentage := (duration.Seconds() / totalDuration.Seconds()) * 100
fmt.Printf(" %-20s %s (%.1f%%)\n", project, ui.FormatDuration(duration), percentage)
fmt.Printf(" %s %s (%.1f%%)\n", ui.Bold(fmt.Sprintf("%-20s", project)), ui.FormatDuration(duration), percentage)

if earnings, ok := projectEarnings[project]; ok && earnings > 0 {
fmt.Printf(" %s %s\n", ui.Muted("└─ Earnings:"), fmt.Sprintf("$%.2f", earnings))
Expand Down
8 changes: 4 additions & 4 deletions cmd/status.go
Original file line number Diff line number Diff line change
Expand Up @@ -42,12 +42,12 @@ var statusCmd = &cobra.Command{

duration := time.Since(running.StartTime)

ui.PrintSuccess(ui.EmojiStatus, fmt.Sprintf("Currently tracking: %s", running.ProjectName))
ui.PrintInfo(4, "Started", running.StartTime.Format("3:04 PM"))
ui.PrintInfo(4, "Duration", ui.FormatDuration(duration))
ui.PrintSuccess(ui.EmojiStatus, fmt.Sprintf("Currently tracking: %s", ui.Bold(running.ProjectName)))
ui.PrintInfo(4, ui.Bold("Started"), running.StartTime.Format("3:04 PM"))
ui.PrintInfo(4, ui.Bold("Duration"), ui.FormatDuration(duration))

if running.Description != "" {
ui.PrintInfo(4, "Description", running.Description)
ui.PrintInfo(4, ui.Bold("Description"), running.Description)
}

ui.NewlineBelow()
Expand Down
4 changes: 2 additions & 2 deletions cmd/stop.go
Original file line number Diff line number Diff line change
Expand Up @@ -45,8 +45,8 @@ var stopCmd = &cobra.Command{

duration := time.Since(running.StartTime)

ui.PrintSuccess(ui.EmojiStop, fmt.Sprintf("Stopped tracking '%s'", running.ProjectName))
ui.PrintInfo(4, "Total Duration", ui.FormatDuration(duration))
ui.PrintSuccess(ui.EmojiStop, fmt.Sprintf("Stopped tracking %s", ui.Bold(running.ProjectName)))
ui.PrintInfo(4, ui.Bold("Total Duration"), ui.FormatDuration(duration))

ui.NewlineBelow()
},
Expand Down
13 changes: 9 additions & 4 deletions internal/ui/ui.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,11 @@ const (
FormatDim = "\033[2m"
FormatItalic = "\033[3m"
FormatUnderline = "\033[4m"

// Specific reset codes (don't reset colors)
ResetBoldDim = "\033[22m" // Reset bold and dim
ResetItalic = "\033[23m" // Reset italic
ResetUnderline = "\033[24m" // Reset underline
)

// Emoji Constants
Expand Down Expand Up @@ -68,22 +73,22 @@ func Muted(message string) string {

// Bold text formatting functions that return formatted string
func Bold(message string) string {
return FormatBold + message + ColorReset
return FormatBold + message + ResetBoldDim
}

// Dim text formatting functions that return formatted string
func Dim(message string) string {
return FormatDim + message + ColorReset
return FormatDim + message + ResetBoldDim
}

// Italic text formatting functions that return formatted string
func Italic(message string) string {
return FormatItalic + message + ColorReset
return FormatItalic + message + ResetItalic
}

// Underline text formatting functions that return formatted string
func Underline(message string) string {
return FormatUnderline + message + ColorReset
return FormatUnderline + message + ResetUnderline
}

// Bold success combined formatting functions for common use cases
Expand Down
11 changes: 7 additions & 4 deletions internal/ui/ui_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -49,28 +49,28 @@ func TestFormattingFunctions(t *testing.T) {
result := Bold("test")
assert.Contains(t, result, FormatBold)
assert.Contains(t, result, "test")
assert.Contains(t, result, ColorReset)
assert.Contains(t, result, ResetBoldDim)
})

t.Run("Dim adds dim formatting", func(t *testing.T) {
result := Dim("test")
assert.Contains(t, result, FormatDim)
assert.Contains(t, result, "test")
assert.Contains(t, result, ColorReset)
assert.Contains(t, result, ResetBoldDim)
})

t.Run("Italic adds italic formatting", func(t *testing.T) {
result := Italic("test")
assert.Contains(t, result, FormatItalic)
assert.Contains(t, result, "test")
assert.Contains(t, result, ColorReset)
assert.Contains(t, result, ResetItalic)
})

t.Run("Underline adds underline formatting", func(t *testing.T) {
result := Underline("test")
assert.Contains(t, result, FormatUnderline)
assert.Contains(t, result, "test")
assert.Contains(t, result, ColorReset)
assert.Contains(t, result, ResetUnderline)
})
}

Expand Down Expand Up @@ -180,6 +180,9 @@ func TestConstants(t *testing.T) {
assert.NotEmpty(t, FormatDim)
assert.NotEmpty(t, FormatItalic)
assert.NotEmpty(t, FormatUnderline)
assert.NotEmpty(t, ResetBoldDim)
assert.NotEmpty(t, ResetItalic)
assert.NotEmpty(t, ResetUnderline)
})

t.Run("Emoji constants are defined", func(t *testing.T) {
Expand Down