Feature 3: relative due dates right-aligned in task list

- Replace absolute date with relative string (Overdue, Xh left, X days left)
- Overdue in Red, <24h in Yellow, >=24h in DarkGray
- Due string right-aligned via padding calculation
This commit is contained in:
Ruben Rosario
2026-06-21 16:24:54 +01:00
parent 5cb8d0cd4e
commit aa91fb7a9d
+34 -10
View File
@@ -49,6 +49,24 @@ pub fn render_tabs_bar(
frame.render_widget(tabs, area);
}
fn relative_due_str(due: chrono::NaiveDateTime) -> (String, Color) {
let now = chrono::Local::now().naive_local();
let diff = due - now;
if diff < chrono::Duration::zero() {
(" Overdue ".to_string(), Color::Red)
} else if diff < chrono::Duration::hours(24) {
let hours = diff.num_hours();
(format!(" {}h left ", hours), Color::Yellow)
} else {
let days = diff.num_days();
(
format!(" {} day{} left ", days, if days == 1 { "" } else { "s" }),
Color::DarkGray,
)
}
}
pub fn render_task_list(
frame: &mut Frame,
area: Rect,
@@ -61,6 +79,8 @@ pub fn render_task_list(
let done = tasks.iter().filter(|t| t.status == TaskStatus::Completed).count();
let todo = total - done;
let content_width = (area.width as usize).saturating_sub(5);
let items: Vec<ListItem> = tasks
.iter()
.map(|task| {
@@ -69,12 +89,12 @@ pub fn render_task_list(
TaskStatus::NeedsAction => "[ ]",
};
let due_str = task
let (due_text, due_color) = task
.due
.map(|d| d.format(" %d/%m/%Y %H:%M").to_string())
.unwrap_or_default();
.map(relative_due_str)
.unwrap_or((String::new(), Color::DarkGray));
let content = Line::from(vec![
let mut spans = vec![
Span::styled(
format!("{} ", checkbox),
Style::default().fg(if task.status == TaskStatus::Completed {
@@ -93,12 +113,16 @@ pub fn render_task_list(
},
),
),
Span::styled(
due_str,
Style::default().fg(Color::DarkGray),
),
]);
ListItem::new(content)
];
if !due_text.is_empty() {
let left_len: usize = spans.iter().map(|s| s.content.len()).sum();
let pad = content_width.saturating_sub(left_len + due_text.len());
spans.push(Span::raw(" ".repeat(pad)));
spans.push(Span::styled(due_text, Style::default().fg(due_color)));
}
ListItem::new(Line::from(spans))
})
.collect();