Skip to main content

saga_time/cli/
mod.rs

1pub mod commands;
2
3use clap::{Parser, Subcommand};
4
5#[derive(Parser, Debug)]
6#[command(name = "saga", version, about = "Time tracking from the terminal")]
7pub struct Cli {
8    #[command(subcommand)]
9    pub command: Option<Commands>,
10}
11
12#[derive(Subcommand, Debug)]
13pub enum Commands {
14    /// Launch interactive TUI
15    Tui,
16
17    /// Start a timer
18    Start {
19        /// Project name
20        project: String,
21        /// Description
22        #[arg(short, long)]
23        description: Option<String>,
24        /// Tags
25        #[arg(short, long)]
26        tag: Vec<String>,
27        /// Mark as non-billable
28        #[arg(long)]
29        no_billable: bool,
30    },
31
32    /// Stop the active timer
33    Stop {
34        /// Update description
35        #[arg(short, long)]
36        description: Option<String>,
37    },
38
39    /// Show current timer status
40    Status,
41
42    /// Cancel the active timer (discard)
43    Cancel,
44
45    /// Resume the last stopped timer
46    Resume,
47
48    /// Add a completed time entry
49    Add {
50        /// Project name
51        #[arg(short, long)]
52        project: String,
53        /// Start time (HH:MM or YYYY-MM-DD HH:MM)
54        #[arg(short, long)]
55        start: String,
56        /// End time (HH:MM or YYYY-MM-DD HH:MM)
57        #[arg(short, long)]
58        end: String,
59        /// Description
60        #[arg(short, long)]
61        description: Option<String>,
62        /// Tags
63        #[arg(short, long)]
64        tag: Vec<String>,
65    },
66
67    /// List recent time entries
68    Log {
69        /// Show today's entries
70        #[arg(long)]
71        today: bool,
72        /// Show this week's entries
73        #[arg(long)]
74        week: bool,
75        /// Show this month's entries
76        #[arg(long)]
77        month: bool,
78        /// Filter by project
79        #[arg(long)]
80        project: Option<String>,
81        /// Filter by client
82        #[arg(long)]
83        client: Option<String>,
84    },
85
86    /// Generate reports
87    Report {
88        /// Period: daily, weekly, monthly
89        #[arg(long, default_value = "weekly")]
90        period: String,
91        /// Format: table, csv, pdf
92        #[arg(long, default_value = "table")]
93        format: String,
94        /// Output file
95        #[arg(short, long)]
96        output: Option<String>,
97    },
98
99    /// Manage projects
100    Projects {
101        #[command(subcommand)]
102        action: ProjectAction,
103    },
104
105    /// Manage clients
106    Clients {
107        #[command(subcommand)]
108        action: ClientAction,
109    },
110
111    /// Manage tags
112    Tags {
113        #[command(subcommand)]
114        action: TagAction,
115    },
116
117    /// Manage billing rates
118    Rates {
119        #[command(subcommand)]
120        action: RateAction,
121    },
122
123    /// Generate or list invoices
124    Invoice {
125        #[command(subcommand)]
126        action: InvoiceAction,
127    },
128
129    /// Manage configuration
130    Config {
131        #[command(subcommand)]
132        action: ConfigAction,
133    },
134}
135
136#[derive(Subcommand, Debug)]
137pub enum ProjectAction {
138    /// List projects
139    List {
140        /// Include archived projects
141        #[arg(long)]
142        all: bool,
143    },
144    /// Add a new project
145    Add {
146        /// Project name
147        name: String,
148        /// Client name
149        #[arg(short, long)]
150        client: Option<String>,
151        /// Color (hex)
152        #[arg(long)]
153        color: Option<String>,
154        /// Budget hours
155        #[arg(short, long)]
156        budget: Option<f64>,
157    },
158    /// Edit a project
159    Edit {
160        /// Project name
161        name: String,
162        /// New name
163        #[arg(long)]
164        new_name: Option<String>,
165        /// New color
166        #[arg(long)]
167        color: Option<String>,
168        /// New budget
169        #[arg(long)]
170        budget: Option<f64>,
171    },
172    /// Archive a project
173    Archive {
174        /// Project name
175        name: String,
176    },
177    /// Activate an archived project
178    Activate {
179        /// Project name
180        name: String,
181    },
182}
183
184#[derive(Subcommand, Debug)]
185pub enum ClientAction {
186    /// List clients
187    List,
188    /// Add a new client
189    Add {
190        /// Client name
191        name: String,
192        /// Contact info
193        #[arg(long)]
194        contact: Option<String>,
195        /// Email
196        #[arg(long)]
197        email: Option<String>,
198    },
199    /// Edit a client
200    Edit {
201        /// Client name
202        name: String,
203        /// New name
204        #[arg(long)]
205        new_name: Option<String>,
206        /// New contact
207        #[arg(long)]
208        contact: Option<String>,
209        /// New email
210        #[arg(long)]
211        email: Option<String>,
212    },
213    /// Delete a client
214    Delete {
215        /// Client name
216        name: String,
217    },
218}
219
220#[derive(Subcommand, Debug)]
221pub enum TagAction {
222    /// List tags
223    List,
224    /// Add a tag
225    Add {
226        /// Tag name
227        name: String,
228        /// Color (hex)
229        #[arg(long)]
230        color: Option<String>,
231    },
232    /// Delete a tag
233    Delete {
234        /// Tag name
235        name: String,
236    },
237}
238
239#[derive(Subcommand, Debug)]
240pub enum RateAction {
241    /// Set a rate
242    Set {
243        /// Hourly rate
244        rate: f64,
245        /// For project
246        #[arg(long)]
247        project: Option<String>,
248        /// For client
249        #[arg(long)]
250        client: Option<String>,
251        /// Currency
252        #[arg(long, default_value = "USD")]
253        currency: String,
254    },
255    /// List rates
256    List,
257}
258
259#[derive(Subcommand, Debug)]
260pub enum InvoiceAction {
261    /// Generate an invoice
262    Generate {
263        /// Client name
264        #[arg(short, long)]
265        client: String,
266        /// Period start (YYYY-MM-DD)
267        #[arg(short, long)]
268        from: String,
269        /// Period end (YYYY-MM-DD)
270        #[arg(short, long)]
271        to: String,
272        /// Output file
273        #[arg(short, long)]
274        output: Option<String>,
275    },
276    /// List invoices
277    List,
278}
279
280#[derive(Subcommand, Debug)]
281pub enum ConfigAction {
282    /// Show current config
283    Show,
284    /// Set a config value
285    Set {
286        /// Key
287        key: String,
288        /// Value
289        value: String,
290    },
291    /// Show config file path
292    Path,
293}