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
117 changes: 117 additions & 0 deletions cmd/export.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
package cmd

import (
"fmt"
"os"
"path/filepath"
"time"

"github.com/DylanDevelops/tmpo/internal/export"
"github.com/DylanDevelops/tmpo/internal/storage"
"github.com/spf13/cobra"
)

var (
exportFormat string
exportOutput string
exportProject string
exportToday bool
exportWeek bool
)

var exportCmd = &cobra.Command{
Use: "export",
Short: "Export time entries",
Long: `Export time tracking data to different formats.`,
Run: func(cmd *cobra.Command, args []string) {
db, err := storage.Initialize()
if err != nil {
fmt.Fprintf(os.Stderr, "Error: %v\n", err)

os.Exit(1)
}

defer db.Close()

var entries []*storage.TimeEntry

if exportToday {
start := time.Now().Truncate(24 * time.Hour)
end := start.Add(24 * time.Hour)
entries, err = db.GetEntriesByDateRange(start, end)
} else if exportWeek {
now := time.Now()
weekday := int(now.Weekday())
if weekday == 0 {
weekday = 7 // sunday
}

start := now.AddDate(0, 0, -weekday+1).Truncate(24 * time.Hour)
end := start.AddDate(0, 0, 7)
entries, err = db.GetEntriesByDateRange(start, end)
} else if exportProject != "" {
entries, err = db.GetEntriesByProject(exportProject)
} else {
entries, err = db.GetEntries(0) // all
}

if err != nil {
fmt.Fprintf(os.Stderr, "Error: %v\n", err)

os.Exit(1)
}

if len(entries) == 0 {
fmt.Println("No entries to export.")

os.Exit(0)
}

filename := exportOutput
if filename == "" {
timestamp := time.Now().Format("2006-01-02")
ext := "csv"

if exportFormat == "json" {
ext = "json"
}

filename = fmt.Sprintf("tmpo-export-%s.%s", timestamp, ext)
}

if exportFormat == "csv" && filepath.Ext(filename) != ".csv" {
filename += ".csv"
} else if exportFormat == "json" && filepath.Ext(filename) != ".json" {
filename += ".json"
}

switch exportFormat {
case "csv":
err = export.ToCSV(entries, filename)
case "json":
err = export.ToJson(entries, filename)
default:
fmt.Fprintf(os.Stderr, "Error: Unknown format '%s'. Use 'csv' or 'json'\n", exportFormat)

os.Exit(1)
}

if err != nil {
fmt.Fprintf(os.Stderr, "Error: %v\n", err)

os.Exit(1)
}

fmt.Printf("[tmpo] Exported %d entries to %s\n", len(entries), filename)
},
}

func init() {
rootCmd.AddCommand(exportCmd)

exportCmd.Flags().StringVarP(&exportFormat, "format", "f", "csv", "Export format (csv or json)")
exportCmd.Flags().StringVarP(&exportOutput, "output", "o", "", "Output filename")
exportCmd.Flags().StringVarP(&exportProject, "project", "p", "", "Filter by project")
exportCmd.Flags().BoolVarP(&exportToday, "today", "t", false, "Export today's entries")
exportCmd.Flags().BoolVarP(&exportWeek, "week", "w", false, "Export this week's entries")
}
110 changes: 110 additions & 0 deletions cmd/log.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
package cmd

import (
"fmt"
"os"
"time"

"github.com/DylanDevelops/tmpo/internal/storage"
"github.com/spf13/cobra"
)

var (
logLimit int
logProject string
logToday bool
logWeek bool
)

var logCmd = &cobra.Command{
Use: "log",
Short: "View time tracking history",
Long: `Display past time tracking entries with optional filtering.`,
Run: func(cmd *cobra.Command, args []string) {
db, err := storage.Initialize()

if err != nil {
fmt.Fprintf(os.Stderr, "Error: %v\n", err)
os.Exit(1)
}

defer db.Close()

var entries []*storage.TimeEntry

if logToday {
start := time.Now().Truncate(24 * time.Hour)
end := start.Add(24 * time.Hour)
entries, err = db.GetEntriesByDateRange(start, end)
} else if logWeek {
now := time.Now()
weekday := int(now.Weekday())
if weekday == 0 {
weekday = 7 // sunday
}

start := now.AddDate(0, 0, -weekday+1).Truncate(24 * time.Hour)
end := start.AddDate(0, 0, 7)
entries, err = db.GetEntriesByDateRange(start, end)
} else if logProject != "" {
entries, err = db.GetEntriesByProject(logProject)
} else {
entries, err = db.GetEntries(logLimit)
}

if err != nil {
fmt.Fprintf(os.Stderr, "Error: %v\n", err)
os.Exit(1)
}

if len(entries) == 0 {
fmt.Println("No time entries found.")

return
}

fmt.Printf("\n[tmpo] Time Entries (%d total)\n\n", len(entries))

var totalDuration time.Duration
currentDate := ""

for _, entry := range entries {
entryDate := entry.StartTime.Format("Mon, Jan 2, 2006")
if entryDate != currentDate {
if currentDate != "" {
fmt.Println()
}

fmt.Printf("─── %s ───\n", entryDate)
currentDate = entryDate
}

duration := entry.Duration()
totalDuration += duration

timeRange := entry.StartTime.Format("3:04 PM")
if entry.EndTime != nil {
timeRange += " - " + entry.EndTime.Format("3:04 PM")
} else {
timeRange += " - (running)"
}

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

fmt.Printf("\n─────────────────────────────────────────\n")
fmt.Printf("Total Time: %s\n", formatDuration(totalDuration))
},
}

func init() {
rootCmd.AddCommand(logCmd)

logCmd.Flags().IntVarP(&logLimit, "limit", "l", 10, "Number of entries to show")
logCmd.Flags().StringVarP(&logProject, "project", "p", "", "Filter by project name")
logCmd.Flags().BoolVarP(&logToday, "today", "t", false, "Show today's entries")
logCmd.Flags().BoolVarP(&logWeek, "week", "w", false, "Show this week's entries")
}
Loading