cli_tutor/ui/
command_list.rs1use crate::app::App;
2use ratatui::{
3 layout::Rect,
4 style::{Color, Modifier, Style},
5 text::{Line, Span},
6 widgets::{Block, Borders, List, ListItem, ListState},
7 Frame,
8};
9
10pub fn render(app: &App, frame: &mut Frame, area: Rect) {
12 let items: Vec<ListItem> = app
13 .modules
14 .iter()
15 .enumerate()
16 .map(|(i, m)| {
17 let ex_count = m.exercises.len();
18 let completed = app
19 .progress
20 .modules
21 .get(&m.module.name)
22 .map(|p| p.completed.len())
23 .unwrap_or(0);
24
25 let badge = if completed == ex_count && ex_count > 0 {
26 " ✓"
27 } else {
28 ""
29 };
30
31 let line = Line::from(vec![
32 Span::styled(
33 format!("{:<10}", m.module.name),
34 if i == app.selected_module {
35 Style::default().add_modifier(Modifier::BOLD)
36 } else {
37 Style::default()
38 },
39 ),
40 Span::styled(
41 format!("[{:>2}]", ex_count),
42 Style::default().fg(Color::DarkGray),
43 ),
44 Span::styled(badge, Style::default().fg(Color::Green)),
45 ]);
46 ListItem::new(line)
47 })
48 .collect();
49
50 let mut state = ListState::default();
51 state.select(Some(app.selected_module));
52
53 let list = List::new(items)
54 .block(Block::default().borders(Borders::RIGHT).title("Modules"))
55 .highlight_style(Style::default().bg(Color::White).fg(Color::Black));
57
58 frame.render_stateful_widget(list, area, &mut state);
59}