From c02ad69bcaa8c443560f28b830d05a62e62de9d4 Mon Sep 17 00:00:00 2001 From: Dawid Zbinski Date: Wed, 25 Feb 2026 14:25:17 +0100 Subject: [PATCH] refactor: types --- internal/entry/entry.go | 1 + internal/entry/store.go | 51 +++++++++---------------------------- internal/entry/submit.go | 2 -- internal/schedule/format.go | 37 +++++++++++---------------- 4 files changed, 28 insertions(+), 63 deletions(-) diff --git a/internal/entry/entry.go b/internal/entry/entry.go index c7ac85d..3d62ada 100644 --- a/internal/entry/entry.go +++ b/internal/entry/entry.go @@ -5,6 +5,7 @@ import "time" const ( TypeLog = "log" TypeCheckout = "checkout" + TypeSubmit = "submit" ) // Entry represents a single time log entry (a "time commit"). diff --git a/internal/entry/store.go b/internal/entry/store.go index eea36fd..4d0e8ef 100644 --- a/internal/entry/store.go +++ b/internal/entry/store.go @@ -126,19 +126,19 @@ func ReadEntry(homeDir, slug, id string) (Entry, error) { return e, nil } -// ReadAllEntries reads all log entry files from a project's log directory. -func ReadAllEntries(homeDir, slug string) ([]Entry, error) { +// readAllOfType reads all entries of a given type from a project's log directory. +func readAllOfType[T any](homeDir, slug, entryType string) ([]T, error) { files, err := readAllFiles(homeDir, slug) if err != nil { return nil, err } - var entries []Entry + var entries []T for _, f := range files { - if !matchesType(f.data, TypeLog) { + if !matchesType(f.data, entryType) { continue } - var e Entry + var e T if err := json.Unmarshal(f.data, &e); err != nil { continue } @@ -147,6 +147,11 @@ func ReadAllEntries(homeDir, slug string) ([]Entry, error) { return entries, nil } +// ReadAllEntries reads all log entry files from a project's log directory. +func ReadAllEntries(homeDir, slug string) ([]Entry, error) { + return readAllOfType[Entry](homeDir, slug, TypeLog) +} + // IsCheckoutEntry checks if the file at the given path exists and is a checkout entry. func IsCheckoutEntry(homeDir, slug, id string) bool { path, err := EntryPath(homeDir, slug, id) @@ -208,42 +213,10 @@ func WriteSubmitEntry(homeDir, slug string, e SubmitEntry) error { // ReadAllSubmitEntries reads all submit marker entries from a project's log directory. func ReadAllSubmitEntries(homeDir, slug string) ([]SubmitEntry, error) { - files, err := readAllFiles(homeDir, slug) - if err != nil { - return nil, err - } - - var entries []SubmitEntry - for _, f := range files { - if !matchesType(f.data, TypeSubmit) { - continue - } - var e SubmitEntry - if err := json.Unmarshal(f.data, &e); err != nil { - continue - } - entries = append(entries, e) - } - return entries, nil + return readAllOfType[SubmitEntry](homeDir, slug, TypeSubmit) } // ReadAllCheckoutEntries reads all checkout entries from a project's log directory. func ReadAllCheckoutEntries(homeDir, slug string) ([]CheckoutEntry, error) { - files, err := readAllFiles(homeDir, slug) - if err != nil { - return nil, err - } - - var entries []CheckoutEntry - for _, f := range files { - if !matchesType(f.data, TypeCheckout) { - continue - } - var e CheckoutEntry - if err := json.Unmarshal(f.data, &e); err != nil { - continue - } - entries = append(entries, e) - } - return entries, nil + return readAllOfType[CheckoutEntry](homeDir, slug, TypeCheckout) } diff --git a/internal/entry/submit.go b/internal/entry/submit.go index 4522ec8..3e54327 100644 --- a/internal/entry/submit.go +++ b/internal/entry/submit.go @@ -2,8 +2,6 @@ package entry import "time" -const TypeSubmit = "submit" - // SubmitEntry marks a date range as submitted. type SubmitEntry struct { ID string `json:"id"` diff --git a/internal/schedule/format.go b/internal/schedule/format.go index 6d02c15..7f08191 100644 --- a/internal/schedule/format.go +++ b/internal/schedule/format.go @@ -181,16 +181,20 @@ func format12h(hhmm string) string { return fmt.Sprintf("%d:%s %s", display, m, suffix) } -func isWeekdays(days []string) bool { - if len(days) != 5 { +// matchExactSet returns true if actual contains exactly the expected strings (in any order). +func matchExactSet(actual []string, expected ...string) bool { + if len(actual) != len(expected) { return false } - set := map[string]bool{"MO": false, "TU": false, "WE": false, "TH": false, "FR": false} - for _, d := range days { - if _, ok := set[d]; !ok { + set := make(map[string]bool, len(expected)) + for _, e := range expected { + set[e] = false + } + for _, a := range actual { + if _, ok := set[a]; !ok { return false } - set[d] = true + set[a] = true } for _, v := range set { if !v { @@ -200,23 +204,12 @@ func isWeekdays(days []string) bool { return true } +func isWeekdays(days []string) bool { + return matchExactSet(days, "MO", "TU", "WE", "TH", "FR") +} + func isWeekends(days []string) bool { - if len(days) != 2 { - return false - } - set := map[string]bool{"SA": false, "SU": false} - for _, d := range days { - if _, ok := set[d]; !ok { - return false - } - set[d] = true - } - for _, v := range set { - if !v { - return false - } - } - return true + return matchExactSet(days, "SA", "SU") } var dayNames = map[string]string{