Add task count to task list panel header
Show 'X todo / Y done' in the Tasks panel title bar. Also includes prior uncommitted work: - Pagination in fetch_tasks (maxResults=100 + pageToken loop) - fetch_tasks_since for incremental pull sync - SyncStats struct with version/last_sync/last_pull/changed counts - Periodic push (30s) and pull (5min) sync engine - event::poll(100ms) for non-blocking UI refresh - Ctrl+R full sync (push + pull) - refresh_if_needed() to reload data after background sync - Retry mechanism (MAX_SYNC_RETRIES=3) for sync queue items - HTTP status code checks in fetch_lists/fetch_tasks/fetch_tasks_since - Fix move_task URL to use reqwest query() - Remove CASCADE via replace_all_lists (use insert_list instead) - has_pending_sync() to prevent pull during pending push
This commit is contained in:
+30
-3
@@ -5,6 +5,7 @@ use ratatui::layout::{Alignment, Rect};
|
||||
use ratatui::Frame;
|
||||
|
||||
use crate::domain::models::*;
|
||||
use crate::app::SyncStats;
|
||||
use super::NetworkStatus;
|
||||
|
||||
const TAB_COLOR: Color = Color::Cyan;
|
||||
@@ -56,6 +57,10 @@ pub fn render_task_list(
|
||||
focused: bool,
|
||||
_scroll: u16,
|
||||
) {
|
||||
let total = tasks.len();
|
||||
let done = tasks.iter().filter(|t| t.status == TaskStatus::Completed).count();
|
||||
let todo = total - done;
|
||||
|
||||
let items: Vec<ListItem> = tasks
|
||||
.iter()
|
||||
.map(|task| {
|
||||
@@ -100,7 +105,7 @@ pub fn render_task_list(
|
||||
let block = Block::default()
|
||||
.borders(Borders::ALL)
|
||||
.border_style(Style::default().fg(if focused { FOCUS_COLOR } else { Color::DarkGray }))
|
||||
.title(" Tasks ")
|
||||
.title(format!(" Tasks ({} todo / {} done) ", todo, done))
|
||||
.title_alignment(Alignment::Left);
|
||||
|
||||
let list = List::new(items)
|
||||
@@ -185,18 +190,40 @@ pub fn render_status_bar(
|
||||
frame: &mut Frame,
|
||||
area: Rect,
|
||||
status: &NetworkStatus,
|
||||
sync_stats: &SyncStats,
|
||||
) {
|
||||
let (text, color) = match status {
|
||||
let (status_text, color) = match status {
|
||||
NetworkStatus::Online => (" ONLINE ", STATUS_ONLINE),
|
||||
NetworkStatus::Offline => (" OFFLINE ", STATUS_OFFLINE),
|
||||
NetworkStatus::Syncing => (" SYNCING... ", STATUS_SYNC),
|
||||
};
|
||||
|
||||
let right_text = match sync_stats.last_sync_time {
|
||||
Some(time) => {
|
||||
let time_str = time.format("%H:%M:%S").to_string();
|
||||
let mut parts: Vec<String> = Vec::new();
|
||||
if sync_stats.lists_changed > 0 {
|
||||
parts.push(format!("{} lists", sync_stats.lists_changed));
|
||||
}
|
||||
if sync_stats.tasks_changed > 0 {
|
||||
parts.push(format!("{} tasks", sync_stats.tasks_changed));
|
||||
}
|
||||
if parts.is_empty() {
|
||||
format!(" {} last sync ", time_str)
|
||||
} else {
|
||||
format!(" {} last sync: {} ", time_str, parts.join(", "))
|
||||
}
|
||||
}
|
||||
None => String::new(),
|
||||
};
|
||||
|
||||
let full_text = format!("{}{}", status_text, right_text);
|
||||
|
||||
let block = Block::default()
|
||||
.style(Style::default().bg(color).fg(Color::Black));
|
||||
|
||||
let paragraph = Paragraph::new(Line::from(Span::styled(
|
||||
text,
|
||||
full_text,
|
||||
Style::default().fg(Color::Black).add_modifier(Modifier::BOLD),
|
||||
)))
|
||||
.block(block)
|
||||
|
||||
Reference in New Issue
Block a user