1// SPDX-FileCopyrightText: Amolith <amolith@secluded.site>
2//
3// SPDX-License-Identifier: AGPL-3.0-or-later
4
5package habit
6
7import (
8 "errors"
9 "fmt"
10
11 "git.secluded.site/go-lunatask"
12 "git.secluded.site/lune/internal/client"
13 "git.secluded.site/lune/internal/completion"
14 "git.secluded.site/lune/internal/config"
15 "git.secluded.site/lune/internal/dateutil"
16 "git.secluded.site/lune/internal/ui"
17 "github.com/spf13/cobra"
18)
19
20// ErrUnknownHabit indicates the specified habit key was not found in config.
21var ErrUnknownHabit = errors.New("unknown habit key")
22
23// TrackCmd tracks a habit activity. Exported for potential use by shortcuts.
24var TrackCmd = &cobra.Command{
25 Use: "track KEY",
26 Short: "Track a habit",
27 Long: `Record that a habit was performed.
28
29KEY is the habit key from your config (not the raw Lunatask ID).
30Tracks for today by default. Use --date to specify another date
31using natural language (e.g., "yesterday", "2 days ago", "March 5").`,
32 Args: cobra.ExactArgs(1),
33 ValidArgsFunction: completion.Habits,
34 RunE: runTrack,
35}
36
37func init() {
38 TrackCmd.Flags().StringP("date", "d", "", "Date performed (default: today)")
39}
40
41func runTrack(cmd *cobra.Command, args []string) error {
42 habitKey := args[0]
43
44 cfg, err := config.Load()
45 if err != nil {
46 return err
47 }
48
49 habit := cfg.HabitByKey(habitKey)
50 if habit == nil {
51 return fmt.Errorf("%w: %s", ErrUnknownHabit, habitKey)
52 }
53
54 date, err := resolveDate(cmd)
55 if err != nil {
56 return err
57 }
58
59 apiClient, err := client.New()
60 if err != nil {
61 return err
62 }
63
64 req := &lunatask.TrackHabitActivityRequest{PerformedOn: date}
65
66 if err := ui.SpinVoid("Tracking habit…", func() error {
67 _, err := apiClient.TrackHabitActivity(cmd.Context(), habit.ID, req)
68
69 return err
70 }); err != nil {
71 return err
72 }
73
74 fmt.Fprintf(cmd.OutOrStdout(), "%s\n",
75 ui.Success.Render("Tracked "+habit.Name+" for "+date.String()))
76
77 return nil
78}
79
80func resolveDate(cmd *cobra.Command) (lunatask.Date, error) {
81 dateStr, _ := cmd.Flags().GetString("date")
82
83 return dateutil.Parse(dateStr)
84}