envelope_cli/tui/dialogs/
help.rs

1//! Help dialog
2//!
3//! Shows contextual keyboard shortcuts
4
5use ratatui::{
6    style::{Color, Modifier, Style},
7    text::{Line, Span},
8    widgets::{Block, Borders, Clear, Paragraph, Wrap},
9    Frame,
10};
11
12use crate::tui::app::{ActiveView, App};
13use crate::tui::layout::centered_rect;
14
15/// Render the help dialog
16pub fn render(frame: &mut Frame, app: &mut App) {
17    let area = centered_rect(60, 70, frame.area());
18
19    // Clear the background
20    frame.render_widget(Clear, area);
21
22    let block = Block::default()
23        .title(" Help ")
24        .title_style(
25            Style::default()
26                .fg(Color::Cyan)
27                .add_modifier(Modifier::BOLD),
28        )
29        .borders(Borders::ALL)
30        .border_style(Style::default().fg(Color::Cyan));
31
32    // Build help text based on current view
33    let help_lines = get_help_lines(app);
34
35    let paragraph = Paragraph::new(help_lines)
36        .block(block)
37        .wrap(Wrap { trim: false });
38
39    frame.render_widget(paragraph, area);
40}
41
42/// Get help lines for the current context
43fn get_help_lines(app: &App) -> Vec<Line<'static>> {
44    let mut lines = vec![
45        Line::from(vec![Span::styled(
46            "Global Keys",
47            Style::default()
48                .add_modifier(Modifier::BOLD)
49                .fg(Color::Yellow),
50        )]),
51        Line::from(""),
52        key_line("q", "Quit application"),
53        key_line("?", "Show/hide help"),
54        key_line(":", "Open command palette"),
55        key_line("Tab", "Switch panel focus"),
56        key_line("h/l", "Move focus left/right"),
57        key_line("j/k", "Move selection up/down"),
58        Line::from(""),
59    ];
60
61    // View-specific help
62    match app.active_view {
63        ActiveView::Accounts => {
64            lines.push(Line::from(vec![Span::styled(
65                "Account View",
66                Style::default()
67                    .add_modifier(Modifier::BOLD)
68                    .fg(Color::Yellow),
69            )]));
70            lines.push(Line::from(""));
71            lines.push(key_line("Enter", "View transactions for account"));
72            lines.push(key_line("1", "Switch to Accounts view"));
73            lines.push(key_line("2", "Switch to Budget view"));
74            lines.push(key_line("3", "Switch to Reports view"));
75            lines.push(key_line("A", "Toggle archived accounts"));
76        }
77        ActiveView::Register => {
78            lines.push(Line::from(vec![Span::styled(
79                "Transaction Register",
80                Style::default()
81                    .add_modifier(Modifier::BOLD)
82                    .fg(Color::Yellow),
83            )]));
84            lines.push(Line::from(""));
85            lines.push(key_line("a/n", "Add new transaction"));
86            lines.push(key_line("e/Enter", "Edit transaction"));
87            lines.push(key_line("c", "Toggle cleared status"));
88            lines.push(key_line("Ctrl+d", "Delete transaction"));
89            lines.push(key_line("g", "Go to top"));
90            lines.push(key_line("G", "Go to bottom"));
91            lines.push(Line::from(""));
92            lines.push(Line::from(vec![Span::styled(
93                "Multi-Select Mode",
94                Style::default()
95                    .add_modifier(Modifier::BOLD)
96                    .fg(Color::Yellow),
97            )]));
98            lines.push(Line::from(""));
99            lines.push(key_line("v", "Toggle multi-select mode"));
100            lines.push(key_line("Space", "Toggle selection (in multi-select)"));
101            lines.push(key_line("C", "Bulk categorize selected"));
102        }
103        ActiveView::Budget => {
104            lines.push(Line::from(vec![Span::styled(
105                "Budget View",
106                Style::default()
107                    .add_modifier(Modifier::BOLD)
108                    .fg(Color::Yellow),
109            )]));
110            lines.push(Line::from(""));
111            lines.push(key_line("[/H", "Previous period"));
112            lines.push(key_line("]/L", "Next period"));
113            lines.push(key_line("m", "Move funds between categories"));
114            lines.push(key_line("Enter", "Edit budget amount"));
115        }
116        ActiveView::Reports => {
117            lines.push(Line::from(vec![Span::styled(
118                "Reports View",
119                Style::default()
120                    .add_modifier(Modifier::BOLD)
121                    .fg(Color::Yellow),
122            )]));
123            lines.push(Line::from(""));
124            lines.push(Line::from("Reports view coming soon!"));
125        }
126        ActiveView::Reconcile => {
127            lines.push(Line::from(vec![Span::styled(
128                "Reconciliation",
129                Style::default()
130                    .add_modifier(Modifier::BOLD)
131                    .fg(Color::Yellow),
132            )]));
133            lines.push(Line::from(""));
134            lines.push(key_line("Tab", "Switch between header and transactions"));
135            lines.push(key_line("Space", "Toggle cleared status"));
136            lines.push(key_line("Enter", "Start reconciliation / Complete"));
137            lines.push(key_line("j/k", "Navigate transactions"));
138            lines.push(key_line("Esc", "Cancel reconciliation"));
139        }
140    }
141
142    lines.push(Line::from(""));
143    lines.push(Line::from(vec![Span::styled(
144        "Press any key to close",
145        Style::default().fg(Color::White),
146    )]));
147
148    lines
149}
150
151/// Create a formatted key line
152fn key_line(key: &str, description: &str) -> Line<'static> {
153    Line::from(vec![
154        Span::styled(format!("{:>12}", key), Style::default().fg(Color::Cyan)),
155        Span::raw("  "),
156        Span::styled(description.to_string(), Style::default().fg(Color::White)),
157    ])
158}