diff --git a/src/tui/components/todo/explorer.rs b/src/tui/components/todo/explorer.rs index 8fcca82..365654b 100644 --- a/src/tui/components/todo/explorer.rs +++ b/src/tui/components/todo/explorer.rs @@ -1,5 +1,5 @@ use ratatui::{ - style::{Color, Modifier}, + style::{Color, Modifier, Stylize}, text::{Line, Span, Text}, widgets::{List, ListState}, }; @@ -39,7 +39,7 @@ impl Explorer<'_> { let id_list = tree .tree .traverse_pre_order_ids(scope) - .expect("This should nto panic as the node id should exist inside") + .expect("This should not panic as the node id should exist inside") .collect::>(); Self { @@ -61,7 +61,7 @@ impl From<&TodoNode> for ExplorerListItem<'_> { fn from(value: &TodoNode) -> Self { let spacer = Span::from(" ".repeat(value.depth)); let name = match value.kind { - TodoNodeKind::Group(ref g) => Span::from(g.name.clone()), + TodoNodeKind::Group(ref g) => Span::from(g.name.clone()).bg(g.tag.color), TodoNodeKind::Task(ref t) => Span::from(t.name.clone()), TodoNodeKind::Root => Span::from("THIS SHOULD NOT BE VISIBLE"), }; diff --git a/src/tui/components/todo/mod.rs b/src/tui/components/todo/mod.rs index 9096d8b..289966e 100644 --- a/src/tui/components/todo/mod.rs +++ b/src/tui/components/todo/mod.rs @@ -14,14 +14,16 @@ use crate::{ mod explorer; use explorer::Explorer; +mod tasklist; +use tasklist::TaskList; pub struct Todo<'text> { #[expect(dead_code)] signal_tx: Option>, kh: KastenHandle, - #[expect(dead_code)] layouts: Layouts, explorer: Explorer<'text>, + task_list: TaskList<'text>, } impl Todo<'_> { @@ -31,6 +33,7 @@ impl Todo<'_> { let mut l_state = ListState::default(); l_state.select_first(); let explorer = Explorer::new(&kt.todo_tree, &kt.todo_tree.root_id, l_state, 0); + let task_list = TaskList::new(&kt.todo_tree, &kt.todo_tree.root_id, l_state, 0); drop(kt); @@ -39,11 +42,11 @@ impl Todo<'_> { layouts: Layouts::default(), signal_tx: None, explorer, + task_list, }) } } -#[expect(dead_code)] struct Layouts { main: Layout, } @@ -60,13 +63,12 @@ impl Default for Layouts { impl Component for Todo<'_> { async fn init(&mut self, area: Size) -> color_eyre::Result<()> { let total_width = area.width; - - let mut l_state = ListState::default(); - l_state.select_first(); let tree = &self.kh.read().await.todo_tree; - let explorer = Explorer::new(tree, &tree.root_id, l_state, total_width); + let explorer = Explorer::new(tree, &tree.root_id, self.explorer.state, total_width / 2); + let task_list = TaskList::new(tree, &tree.root_id, self.task_list.state, total_width / 2); self.explorer = explorer; + self.task_list = task_list; Ok(()) } @@ -87,7 +89,22 @@ impl Component for Todo<'_> { } fn draw(&mut self, frame: &mut Frame, area: Rect) -> color_eyre::Result<()> { - frame.render_stateful_widget(&self.explorer.render_list, area, &mut self.explorer.state); + let (explorer_rect, task_list_rect) = { + let rects = self.layouts.main.split(area); + (rects[0], rects[1]) + }; + + frame.render_stateful_widget( + &self.explorer.render_list, + explorer_rect, + &mut self.explorer.state, + ); + + frame.render_stateful_widget( + &self.task_list.render_list, + task_list_rect, + &mut self.task_list.state, + ); Ok(()) } } diff --git a/src/tui/components/todo/tasklist.rs b/src/tui/components/todo/tasklist.rs new file mode 100644 index 0000000..c203b29 --- /dev/null +++ b/src/tui/components/todo/tasklist.rs @@ -0,0 +1,93 @@ +#![expect(dead_code)] +use ratatui::{ + style::{Color, Modifier}, + text::{Line, Span, Text}, + widgets::{List, ListState}, +}; +use tree::NodeId; + +use crate::types::{TodoNode, TodoNodeKind, TodoTree}; + +pub struct TaskList<'text> { + pub render_list: List<'text>, + pub id_list: Vec, + pub state: ListState, + pub width: u16, +} + +impl TaskList<'_> { + pub fn new(tree: &TodoTree, scope: &NodeId, state: ListState, width: u16) -> Self { + let mut id_list = vec![]; + + let render_list = List::new( + tree.tree + .traverse_pre_order(scope) + .expect("nthis should not panic as the node id should exist inside") + .zip( + tree.tree + .traverse_pre_order_ids(scope) + .expect("This should not panic as the nodeid should exist inside"), + ) + .filter_map(|(node, id)| { + let TodoNodeKind::Task(_) = node.data().kind else { + return None; + }; + + let mut tli: TaskListItem<'_> = node.data().into(); + + id_list.push(id); + + tli.width = width; + Some(Text::from(tli)) + }), + ) + .style(Color::White) + .highlight_style(Modifier::REVERSED) + .highlight_symbol("> "); + + Self { + render_list, + id_list, + state, + width, + } + } +} + +pub struct TaskListItem<'text> { + name: Span<'text>, + group: Span<'text>, + due_priority: Span<'text>, + width: u16, +} + +// its fine because if it fails, its my fault, not the users. +#[expect(clippy::fallible_impl_from)] +impl From<&TodoNode> for TaskListItem<'_> { + fn from(value: &TodoNode) -> Self { + let TodoNodeKind::Task(ref task) = value.kind else { + panic!("Should not be possible"); + }; + + let name = Span::from(task.name.clone()); + let group = Span::from(task.group.name.clone()); + let due_priority = task.due.map_or_else( + || Span::from(task.priority.to_string()), + |due_date| Span::from(due_date.to_string()), + ); + + Self { + name, + group, + due_priority, + width: 0, + } + } +} + +impl<'text> From> for Text<'text> { + fn from(value: TaskListItem<'text>) -> Self { + let line = Line::from(vec![value.name, value.group, value.due_priority]); + line.into() + } +} diff --git a/src/types/priority.rs b/src/types/priority.rs index 93d6f7e..10f0644 100644 --- a/src/types/priority.rs +++ b/src/types/priority.rs @@ -1,3 +1,5 @@ +use std::fmt::Display; + use dto::PriorityDTO; /// An Enum for the various `Priority` levels @@ -18,3 +20,9 @@ impl From for PriorityDTO { value.field1 } } + +impl Display for Priority { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "{}", self.field1) + } +}