Add basic library code to manage projects, activities and times.

This commit is contained in:
Olli 2025-08-29 11:56:45 +02:00
commit fb576f3d51
7 changed files with 663 additions and 0 deletions

117
lib/timer.go Normal file
View file

@ -0,0 +1,117 @@
package lib
import (
"os"
"path/filepath"
"time"
)
type NoTimerActiveError struct{}
func (e *NoTimerActiveError) Error() string {
return "No timer is currently active."
}
// StartTimer starts a new timer.
func StartTimer() (*Time, error) {
// Stop active timer
activeTimer, _ := GetTimer()
if activeTimer != nil {
timer, stopErr := StopTimer()
if stopErr != nil {
return timer, stopErr
}
}
// Start new timer
newTimer := Time{
Start: time.Now(),
}
setErr := setTimer(&newTimer)
if setErr != nil {
return nil, setErr
}
return &newTimer, nil
}
// UpdateTimer sets the project and activity on the current timer.
func UpdateTimer(project *Project, activity *Activity) (*Time, error) {
timer, timerErr := GetTimer()
if timerErr != nil {
return timer, timerErr
}
if timer == nil {
return nil, &NoTimerActiveError{}
}
timer.ProjectID = project.ID
timer.ActivityID = activity.ID
setError := setTimer(timer)
if setError != nil {
return timer, setError
}
return timer, nil
}
// StopTimer stops the current timer and records the resulting time entry.
func StopTimer() (*Time, error) {
timer, timerErr := GetTimer()
if timerErr != nil {
return timer, timerErr
}
if timer == nil {
return nil, &NoTimerActiveError{}
}
timer.End = time.Now()
recordErr := SetTime(timer)
if recordErr != nil {
return timer, recordErr
}
file, fileErr := getTimerFile()
if fileErr != nil {
return timer, fileErr
}
removeErr := os.Remove(file)
if removeErr != nil {
return timer, removeErr
}
return nil, nil
}
// GetTimer returns the active timer.
func GetTimer() (*Time, error) {
file, fileErr := getTimerFile()
if fileErr != nil {
return nil, fileErr
}
return readTime(file)
}
// setTimer persists a time entry as current timer. If there is already a current timer, it will be overwritten.
func setTimer(entry *Time) error {
file, fileErr := getTimerFile()
if fileErr != nil {
return fileErr
}
return writeTime(entry, file)
}
// getTimerFile returns the file name for the timer.
func getTimerFile() (string, error) {
folder, err := getDataDir("time")
if err != nil {
return "", err
}
return filepath.Join(folder, "timer.json"), nil
}