budget_tracker_tui 1.4.0

A feature rich TUI budget tracker app
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
use crate::app::state::AppMode;

#[derive(Debug, Clone, PartialEq, Eq)]
pub struct KeyBindingInfo {
    pub key: &'static str,
    pub description: &'static str,
    pub group: &'static str,
    pub extended_description: Option<&'static str>,
}

impl KeyBindingInfo {
    pub const fn new(
        key: &'static str,
        description: &'static str,
        group: &'static str,
        extended_description: Option<&'static str>,
    ) -> Self {
        Self {
            key,
            description,
            group,
            extended_description,
        }
    }
}

pub fn get_help_for_mode(mode: AppMode) -> Vec<KeyBindingInfo> {
    match mode {
        AppMode::Normal => vec![
            KeyBindingInfo::new("↑/↓", "Navigate transactions", "Navigation", None),
            KeyBindingInfo::new("PgUp/PgDn", "Scroll page up/down", "Navigation", None),
            KeyBindingInfo::new("Ctrl+Up/Down", "Jump to First/Last", "Navigation", None),
            KeyBindingInfo::new(
                "a",
                "Add new transaction",
                "Actions",
                Some(
                    "Opens the 'Add Transaction' form where you can input details like date, amount, category, etc.",
                ),
            ),
            KeyBindingInfo::new(
                "e",
                "Edit selected transaction",
                "Actions",
                Some("Opens the edit mode for the currently selected transaction."),
            ),
            KeyBindingInfo::new(
                "d",
                "Delete selected transaction",
                "Actions",
                Some("Prompts for confirmation to delete the selected transaction."),
            ),
            KeyBindingInfo::new(
                "Ctrl+C",
                "Copy selected transaction",
                "Actions",
                Some(
                    "Creates a duplicate of the selected transaction with today's date, keeping the same description, category, subcategory, amount, and type.",
                ),
            ),
            KeyBindingInfo::new(
                "r",
                "Manage recurring transactions",
                "Actions",
                Some("Opens the recurring transactions manager."),
            ),
            KeyBindingInfo::new(
                "f",
                "Filter transactions",
                "Actions",
                Some("Enables simple filtering mode. Type to filter by any field."),
            ),
            KeyBindingInfo::new(
                "s",
                "Monthly Summary",
                "Actions",
                Some("View a monthly breakdown of income vs expenses."),
            ),
            KeyBindingInfo::new(
                "c",
                "Category Summary",
                "Actions",
                Some("View expenses broken down by category and subcategory."),
            ),
            KeyBindingInfo::new(
                "b",
                "Budget View",
                "Actions",
                Some(
                    "View monthly budget progress and budgeted category spending for the selected month.",
                ),
            ),
            KeyBindingInfo::new(
                "o",
                "Settings",
                "Actions",
                Some(
                    "Open application settings: database location, category management, CSV import/export, budget and display preferences.",
                ),
            ),
            KeyBindingInfo::new("1/F1", "Sort by Date", "Sorting", None),
            KeyBindingInfo::new("2/F2", "Sort by Description", "Sorting", None),
            KeyBindingInfo::new("3/F3", "Sort by Category", "Sorting", None),
            KeyBindingInfo::new("4/F4", "Sort by Subcategory", "Sorting", None),
            KeyBindingInfo::new("5/F5", "Sort by Type", "Sorting", None),
            KeyBindingInfo::new("6/F6", "Sort by Amount", "Sorting", None),
            KeyBindingInfo::new(
                "q/Esc",
                "Quit / Clear Filters",
                "System",
                Some("If filters are active, clears them. Otherwise, quits the application."),
            ),
            KeyBindingInfo::new(
                "Ctrl+H",
                "Show Keybindings Help",
                "System",
                Some("Shows this help menu."),
            ),
        ],
        AppMode::Adding | AppMode::Editing => vec![
            KeyBindingInfo::new("Tab/↑/↓", "Navigate fields", "Navigation", None),
            KeyBindingInfo::new(
                "Date Field",
                "Transaction Date (YYYY-MM-DD)",
                "Fields",
                Some(
                    "Enter the date of the transaction (YYYY-MM-DD). Use Arrow keys to adjust day by day. Hold Shift + Arrow keys to jump by month. Accurate dating helps with monthly filtering.",
                ),
            ),
            KeyBindingInfo::new(
                "Amount Field",
                "Transaction Amount",
                "Fields",
                Some(
                    "Numerical value of the transaction. Positive numbers are standard. The 'Type' field determines if it's income or expense. For expenses, enter the positive cost.",
                ),
            ),
            KeyBindingInfo::new(
                "Category",
                "Main Category",
                "Fields",
                Some(
                    "Primary classification (e.g., 'Food', 'Housing'). Press Enter to open a selection list of categories from the current catalog.",
                ),
            ),
            KeyBindingInfo::new(
                "Subcategory",
                "Sub Category",
                "Fields",
                Some(
                    "More specific classification (e.g., 'Groceries', 'Rent'). Useful for detailed breakdown in the Category Summary view.",
                ),
            ),
            KeyBindingInfo::new(
                "Type",
                "Expense / Income",
                "Fields",
                Some(
                    "Classifies the transaction as 'Expense' or 'Income'. This affects how totals are calculated in summaries. Use Left/Right arrows to toggle.",
                ),
            ),
            KeyBindingInfo::new(
                "Description",
                "Notes / Details",
                "Fields",
                Some(
                    "Optional details about the transaction. Add context that doesn't fit in categories.",
                ),
            ),
            KeyBindingInfo::new(
                "←/→",
                "Toggle type / Adjust date / Move cursor",
                "Input",
                Some(
                    "On the Type field toggles Income/Expense; on the Date field moves the date by one day; on text fields moves the cursor.",
                ),
            ),
            KeyBindingInfo::new(
                "Shift+←/→",
                "Jump month (Date field)",
                "Input",
                Some("In date fields, moves date by one month instead of one day."),
            ),
            KeyBindingInfo::new(
                "+/-",
                "Adjust date",
                "Input",
                Some(
                    "On the Date field, '+' or '=' moves the date forward a day and '-' moves it back.",
                ),
            ),
            KeyBindingInfo::new(
                "Enter",
                "Save / Toggle type / Open selection",
                "Actions",
                Some(
                    "On the Type field toggles Income/Expense; on Category/Subcategory opens a selection list; on any other field saves the transaction.",
                ),
            ),
            KeyBindingInfo::new("Esc", "Cancel", "Actions", None),
            KeyBindingInfo::new("Ctrl+H", "Show Keybindings Help", "System", None),
        ],
        AppMode::ConfirmDelete => vec![
            KeyBindingInfo::new("y", "Confirm deletion", "Actions", None),
            KeyBindingInfo::new("n/Esc", "Cancel deletion", "Actions", None),
            KeyBindingInfo::new("Ctrl+H", "Show Keybindings Help", "System", None),
        ],
        AppMode::Filtering => vec![
            KeyBindingInfo::new("Any Char", "Type filter text", "Input", None),
            KeyBindingInfo::new("Bksp/Del", "Delete character", "Input", None),
            KeyBindingInfo::new("←/→", "Move cursor", "Navigation", None),
            KeyBindingInfo::new(
                "Ctrl+F",
                "Switch to Advanced Filter",
                "Actions",
                Some("Switch to advanced filtering mode for more specific criteria."),
            ),
            KeyBindingInfo::new("Ctrl+R", "Clear filter", "Actions", None),
            KeyBindingInfo::new("Enter", "Apply filter", "Actions", None),
            KeyBindingInfo::new("Esc", "Clear filter", "Actions", None),
            KeyBindingInfo::new("Ctrl+H", "Show Keybindings Help", "System", None),
        ],
        AppMode::AdvancedFiltering => vec![
            KeyBindingInfo::new("Tab/↑/↓", "Navigate fields", "Navigation", None),
            KeyBindingInfo::new(
                "Start Date",
                "Filter From Date",
                "Fields",
                Some("Include transactions on or after this date."),
            ),
            KeyBindingInfo::new(
                "End Date",
                "Filter To Date",
                "Fields",
                Some("Include transactions on or before this date."),
            ),
            KeyBindingInfo::new(
                "Min Amount",
                "Minimum Amount",
                "Fields",
                Some("Filter transactions with amount greater than or equal to this."),
            ),
            KeyBindingInfo::new(
                "Max Amount",
                "Maximum Amount",
                "Fields",
                Some("Filter transactions with amount less than or equal to this."),
            ),
            KeyBindingInfo::new(
                "Category",
                "Filter Category",
                "Fields",
                Some("Filter by specific category."),
            ),
            KeyBindingInfo::new(
                "Subcategory",
                "Filter Subcategory",
                "Fields",
                Some("Filter by specific subcategory."),
            ),
            KeyBindingInfo::new(
                "Type",
                "Filter Type",
                "Fields",
                Some("Filter by Expense or Income."),
            ),
            KeyBindingInfo::new(
                "Desc",
                "Filter Description",
                "Fields",
                Some("Filter by text in description."),
            ),
            KeyBindingInfo::new(
                "←/→",
                "Adjust date / Toggle type / Move cursor",
                "Input",
                Some(
                    "On the Start/End Date fields adjusts by a day; on the Type field toggles Expense/Income; on text fields moves the cursor.",
                ),
            ),
            KeyBindingInfo::new("Shift+←/→", "Jump month (date fields)", "Input", None),
            KeyBindingInfo::new("Ctrl+R", "Clear all filters", "Actions", None),
            KeyBindingInfo::new(
                "Enter",
                "Save & Apply / Open selection",
                "Actions",
                Some(
                    "On the Category/Subcategory fields opens a selection list; on any other field saves and applies the filters.",
                ),
            ),
            KeyBindingInfo::new("Esc", "Cancel / Back to Normal Mode", "Actions", None),
            KeyBindingInfo::new("Ctrl+H", "Show Keybindings Help", "System", None),
        ],
        AppMode::Summary => vec![
            KeyBindingInfo::new("↑/↓", "Change Month", "Navigation", None),
            KeyBindingInfo::new("←/→ / [/] / PgUp/PgDn", "Change Year", "Navigation", None),
            KeyBindingInfo::new(
                "m",
                "Toggle Multi-Month View",
                "View",
                Some("Switch between single month view and multi-month view."),
            ),
            KeyBindingInfo::new(
                "c",
                "Toggle Cumulative View",
                "View",
                Some("Toggle cumulative (running total) view."),
            ),
            KeyBindingInfo::new("q/Esc", "Back to Transactions", "Actions", None),
            KeyBindingInfo::new("Ctrl+H", "Show Keybindings Help", "System", None),
        ],
        AppMode::CategorySummary => vec![
            KeyBindingInfo::new("↑/↓", "Select Category/Subcategory", "Navigation", None),
            KeyBindingInfo::new("←/→ / [/]", "Change Year", "Navigation", None),
            KeyBindingInfo::new("PgUp/PgDn", "Jump Selected Month", "Navigation", None),
            KeyBindingInfo::new("Enter", "Expand/Collapse Category", "Actions", None),
            KeyBindingInfo::new("q/Esc", "Back to Transactions", "Actions", None),
            KeyBindingInfo::new("Ctrl+H", "Show Keybindings Help", "System", None),
        ],
        AppMode::Budget => vec![
            KeyBindingInfo::new("↑/↓", "Select Budget Row", "Navigation", None),
            KeyBindingInfo::new("←/→", "Change Month", "Navigation", None),
            KeyBindingInfo::new("Shift+←/→", "Change Year", "Navigation", None),
            KeyBindingInfo::new("q/Esc", "Back to Transactions", "Actions", None),
            KeyBindingInfo::new("Ctrl+H", "Show Keybindings Help", "System", None),
        ],
        AppMode::Settings => vec![
            KeyBindingInfo::new("Tab/↑/↓", "Navigate settings", "Navigation", None),
            KeyBindingInfo::new(
                "Database Path",
                "SQLite Database Location",
                "Fields",
                Some(
                    "Path to the SQLite database that stores your transactions and category catalog. Point this at a new file to create a fresh database, or an existing file to load different data. Tip: place it in iCloud Drive, Google Drive, or Dropbox to sync across devices.",
                ),
            ),
            KeyBindingInfo::new(
                "Manage Categories",
                "Open Category Catalog",
                "Fields",
                Some("Select this action and press Enter to open the category catalog manager."),
            ),
            KeyBindingInfo::new(
                "Import Transactions",
                "Import from CSV",
                "Fields",
                Some(
                    "Press Enter to open a path prompt and import a CSV. New rows are added and exact duplicates are skipped; recurring occurrences are regenerated automatically.",
                ),
            ),
            KeyBindingInfo::new(
                "Export Transactions",
                "Export to CSV",
                "Fields",
                Some(
                    "Press Enter to open a path prompt and export all transactions to a CSV file you can back up or share.",
                ),
            ),
            KeyBindingInfo::new(
                "Target Budget",
                "Monthly Budget Goal",
                "Fields",
                Some("Set a target monthly budget amount for reference in summaries."),
            ),
            KeyBindingInfo::new(
                "Hourly Rate",
                "Hourly Earning Rate",
                "Fields",
                Some(
                    "Optional. Enter your hourly rate to enable viewing transaction amounts as equivalent hours worked.",
                ),
            ),
            KeyBindingInfo::new(
                "Show Hours",
                "Toggle Hours View",
                "Fields",
                Some(
                    "Enable to display transaction amounts in equivalent hours based on your hourly rate.",
                ),
            ),
            KeyBindingInfo::new(
                "Fuzzy Search",
                "Toggle Fuzzy Search",
                "Fields",
                Some(
                    "Toggle to enable fuzzy searching for categories/subcategories. When enabled, selecting 'Category' opens a search bar to filter both category and subcategory at once.",
                ),
            ),
            KeyBindingInfo::new(
                "Hide Help Bar",
                "Toggle Help Bar",
                "Fields",
                Some(
                    "Toggle to hide the bottom help bar for a cleaner interface. Ctrl+H will still work. NOT RECOMMENDED unless you know the keybindings well.",
                ),
            ),
            KeyBindingInfo::new(
                "←/→",
                "Toggle Options / Move cursor",
                "Navigation",
                Some(
                    "On toggle settings changes the value (e.g. Yes/No); on path/number fields moves the text cursor.",
                ),
            ),
            KeyBindingInfo::new(
                "Ctrl+D",
                "Reset Database Path",
                "Actions",
                Some(
                    "On the Database Path field, resets it to the default location for the current data directory.",
                ),
            ),
            KeyBindingInfo::new("Ctrl+U", "Clear Field", "Actions", None),
            KeyBindingInfo::new(
                "Enter",
                "Save Settings / Activate Action",
                "Actions",
                Some(
                    "On editable fields saves your settings; on action rows (Manage Categories, Import, Export) opens that action.",
                ),
            ),
            KeyBindingInfo::new("Esc", "Cancel / Back", "Actions", None),
            KeyBindingInfo::new("Ctrl+H", "Show Keybindings Help", "System", None),
        ],
        AppMode::CategoryCatalog => vec![
            KeyBindingInfo::new("↑/↓", "Navigate categories", "Navigation", None),
            KeyBindingInfo::new("a", "Add category", "Actions", None),
            KeyBindingInfo::new("e/Enter", "Edit selected category", "Actions", None),
            KeyBindingInfo::new("d", "Delete selected category", "Actions", None),
            KeyBindingInfo::new("q/Esc", "Back to Settings", "Actions", None),
            KeyBindingInfo::new("Ctrl+H", "Show Keybindings Help", "System", None),
        ],
        AppMode::CategoryEditor => vec![
            KeyBindingInfo::new("Tab/↑/↓", "Navigate fields", "Navigation", None),
            KeyBindingInfo::new("←/→", "Toggle type / move cursor", "Navigation", None),
            KeyBindingInfo::new("Enter", "Toggle type or save", "Actions", None),
            KeyBindingInfo::new("Esc", "Cancel editor", "Actions", None),
            KeyBindingInfo::new(
                "Target Budget",
                "Expense-only category budget goal",
                "Fields",
                Some(
                    "Optional for expense categories only. Income categories do not use per-category target budgets in the budget view.",
                ),
            ),
            KeyBindingInfo::new(
                "Tag",
                "Optional label",
                "Fields",
                Some("Optional. Store an extra short label for the category row."),
            ),
            KeyBindingInfo::new("Ctrl+H", "Show Keybindings Help", "System", None),
        ],
        AppMode::ConfirmCategoryDelete => vec![
            KeyBindingInfo::new("y", "Confirm delete", "Actions", None),
            KeyBindingInfo::new("n/Esc", "Cancel delete", "Actions", None),
            KeyBindingInfo::new("Ctrl+H", "Show Keybindings Help", "System", None),
        ],
        AppMode::RecurringSettings => vec![
            KeyBindingInfo::new("Tab/↑/↓", "Navigate fields", "Navigation", None),
            KeyBindingInfo::new(
                "Active",
                "Enable/Disable",
                "Fields",
                Some("Toggle if this transaction will be recurring."),
            ),
            KeyBindingInfo::new(
                "Frequency",
                "Recurrence Interval",
                "Fields",
                Some(
                    "Determines the interval for the transaction. Options include 'Daily', 'Weekly', 'Bi-Weekly', 'Semi-Monthly' (15th and last day), 'Semi-Monthly (Weekday Adjusted)' (15th and last day, moved earlier to the nearest weekday when either falls on a weekend), 'Monthly', 'Quarterly', and 'Yearly'. The app will automatically generate these transactions up to the current date when you open it.",
                ),
            ),
            KeyBindingInfo::new(
                "End Date",
                "Stop Date",
                "Fields",
                Some(
                    "Optional. If set, the recurring transaction will stop being generated after this date. Leave empty for indefinite recurrence.",
                ),
            ),
            KeyBindingInfo::new(
                "←/→",
                "Toggle active / Adjust end date",
                "Input",
                Some(
                    "On the Active field toggles recurrence on/off; on the End Date field moves the date by one day.",
                ),
            ),
            KeyBindingInfo::new("Shift+←/→", "Jump month (End Date)", "Input", None),
            KeyBindingInfo::new(
                "Enter",
                "Select frequency / Save",
                "Actions",
                Some(
                    "On the Frequency field opens the frequency picker; on any other field saves the recurring settings.",
                ),
            ),
            KeyBindingInfo::new("Esc", "Cancel", "Actions", None),
            KeyBindingInfo::new(
                "Tip!",
                "Your recurring transaction changes",
                "Info",
                Some(
                    "The recurring transactions generate from the initial transaction up to the current date. If a recurring transaction needs to be changed, set an end date and then create a new transaction with the updated details. That can then be set as recurring again to continue.",
                ),
            ),
            KeyBindingInfo::new("Ctrl+H", "Show Keybindings Help", "System", None),
        ],
        AppMode::SelectingCategory
        | AppMode::SelectingSubcategory
        | AppMode::SelectingFilterCategory
        | AppMode::SelectingFilterSubcategory
        | AppMode::SelectingRecurrenceFrequency => vec![
            KeyBindingInfo::new("↑/↓", "Navigate options", "Navigation", None),
            KeyBindingInfo::new("Enter", "Confirm Selection", "Actions", None),
            KeyBindingInfo::new("Esc", "Cancel Selection", "Actions", None),
            KeyBindingInfo::new("Ctrl+H", "Show Keybindings Help", "System", None),
        ],
        AppMode::FuzzyFinding => vec![
            KeyBindingInfo::new(
                "Any Char",
                "Type to search",
                "Input",
                Some("Type to filter the list of categories and subcategories."),
            ),
            KeyBindingInfo::new("↑/↓", "Navigate results", "Navigation", None),
            KeyBindingInfo::new(
                "Enter",
                "Select Category",
                "Actions",
                Some("Confirm selection. Auto-fills both Category and Subcategory fields."),
            ),
            KeyBindingInfo::new("Esc", "Cancel", "Actions", None),
            KeyBindingInfo::new("Ctrl+H", "Show Keybindings Help", "System", None),
        ],
        AppMode::ImportTransactions | AppMode::ExportTransactions => vec![
            KeyBindingInfo::new(
                "Any Char",
                "Type the file path",
                "Input",
                Some("Type or paste an absolute path to the CSV file."),
            ),
            KeyBindingInfo::new("←/→", "Move cursor", "Navigation", None),
            KeyBindingInfo::new("Ctrl+U", "Clear path", "Actions", None),
            KeyBindingInfo::new("Ctrl+D", "Reset to default location", "Actions", None),
            KeyBindingInfo::new("Enter", "Confirm import/export", "Actions", None),
            KeyBindingInfo::new("Esc", "Cancel / back to Settings", "Actions", None),
            KeyBindingInfo::new("Ctrl+H", "Show Keybindings Help", "System", None),
        ],
        _ => vec![
            KeyBindingInfo::new("Ctrl+H", "Close Help", "System", None),
            KeyBindingInfo::new("Esc", "Close Help", "System", None),
        ],
    }
}