Initial commit: TUI Watson time tracker implementation
This commit is contained in:
commit
2f0cc79631
7 changed files with 1389 additions and 0 deletions
102
src/ui.rs
Normal file
102
src/ui.rs
Normal file
|
|
@ -0,0 +1,102 @@
|
|||
use ratatui::{
|
||||
layout::{Constraint, Direction, Layout, Rect},
|
||||
style::{Color, Modifier, Style},
|
||||
text::{Line, Span},
|
||||
widgets::{Block, Borders, List, ListItem, Paragraph},
|
||||
Frame,
|
||||
};
|
||||
|
||||
use crate::state::{AppState, TimeItem};
|
||||
|
||||
const ACTIVE_COLOR: Color = Color::Green;
|
||||
const INACTIVE_COLOR: Color = Color::Yellow;
|
||||
|
||||
pub fn render(frame: &mut Frame, state: &AppState) {
|
||||
let chunks = Layout::default()
|
||||
.direction(Direction::Vertical)
|
||||
.constraints([
|
||||
Constraint::Ratio(1, 3),
|
||||
Constraint::Ratio(1, 3),
|
||||
Constraint::Ratio(1, 3),
|
||||
])
|
||||
.split(frame.size());
|
||||
|
||||
render_section(
|
||||
frame,
|
||||
chunks[0],
|
||||
"Permanent Items",
|
||||
&state.permanent_items,
|
||||
state.current_pane == 0,
|
||||
state.selected_indices[0],
|
||||
state,
|
||||
);
|
||||
|
||||
render_section(
|
||||
frame,
|
||||
chunks[1],
|
||||
"Recurring Items",
|
||||
&state.recurring_items,
|
||||
state.current_pane == 1,
|
||||
state.selected_indices[1],
|
||||
state,
|
||||
);
|
||||
|
||||
render_section(
|
||||
frame,
|
||||
chunks[2],
|
||||
"Recent Items",
|
||||
&state.recent_items,
|
||||
state.current_pane == 2,
|
||||
state.selected_indices[2],
|
||||
state,
|
||||
);
|
||||
}
|
||||
|
||||
fn render_section(
|
||||
frame: &mut Frame,
|
||||
area: Rect,
|
||||
title: &str,
|
||||
items: &[TimeItem],
|
||||
is_active: bool,
|
||||
selected: usize,
|
||||
state: &AppState,
|
||||
) {
|
||||
let border_color = if is_active { ACTIVE_COLOR } else { INACTIVE_COLOR };
|
||||
|
||||
let block = Block::default()
|
||||
.borders(Borders::ALL)
|
||||
.title(title)
|
||||
.style(Style::default().fg(border_color));
|
||||
|
||||
let items: Vec<ListItem> = items
|
||||
.iter()
|
||||
.enumerate()
|
||||
.map(|(i, item)| {
|
||||
let is_running = state
|
||||
.active_timer
|
||||
.as_ref()
|
||||
.map(|(active, _)| active.name == item.name)
|
||||
.unwrap_or(false);
|
||||
|
||||
let style = if is_running {
|
||||
Style::default().fg(ACTIVE_COLOR).add_modifier(Modifier::BOLD)
|
||||
} else if i == selected && is_active {
|
||||
Style::default().fg(border_color).add_modifier(Modifier::REVERSED)
|
||||
} else {
|
||||
Style::default()
|
||||
};
|
||||
|
||||
let mut line = item.name.clone();
|
||||
if !item.tags.is_empty() {
|
||||
line.push_str(" [");
|
||||
line.push_str(&item.tags.join(", "));
|
||||
line.push(']');
|
||||
}
|
||||
|
||||
ListItem::new(Line::from(vec![Span::styled(line, style)]))
|
||||
})
|
||||
.collect();
|
||||
|
||||
let list = List::new(items).block(block);
|
||||
frame.render_widget(list, area);
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue