use crate::app::App;
use crate::models::Project;
use ratatui::{
layout::{Constraint, Direction, Layout, Rect},
style::{Color, Modifier, Style},
text::{Line, Span},
widgets::{Block, Borders, List, ListItem},
Frame,
};
pub fn render(f: &mut Frame, area: Rect, project: &Project, is_focused: bool, app: &App) {
let border_style = if is_focused {
Style::default().fg(Color::White)
} else {
Style::default().fg(Color::DarkGray)
};
let todo_count = project.tasks.iter().filter(|t| t.status == "todo").count();
let doing_count = project.tasks.iter().filter(|t| t.status == "doing").count();
let done_count = project.tasks.iter().filter(|t| t.status == "done").count();
let total_count = project.tasks.len();
let title = format!(" {} ({}/{}) ", project.name, done_count, total_count);
let block = Block::default()
.title(title)
.title_alignment(ratatui::layout::Alignment::Center)
.borders(Borders::ALL)
.border_style(border_style)
.border_type(ratatui::widgets::BorderType::Rounded);
let inner = block.inner(area);
f.render_widget(block, area);
let columns = Layout::default()
.direction(Direction::Horizontal)
.constraints([
Constraint::Percentage(33),
Constraint::Percentage(33),
Constraint::Percentage(34),
])
.split(inner);
let todo_tasks: Vec<_> = project.tasks.iter().filter(|t| t.status == "todo").collect();
let doing_tasks: Vec<_> = project.tasks.iter().filter(|t| t.status == "doing").collect();
let done_tasks: Vec<_> = project.tasks.iter().filter(|t| t.status == "done").collect();
render_column(f, columns[0], "待办", &todo_tasks, 0, app, is_focused);
render_column(f, columns[1], "进行中", &doing_tasks, 1, app, is_focused);
render_column(f, columns[2], "已完成", &done_tasks, 2, app, is_focused);
}
fn render_column(
f: &mut Frame,
area: Rect,
title: &str,
tasks: &[&crate::models::Task],
column_idx: usize,
app: &App,
is_pane_focused: bool,
) {
let current_column = app.selected_column.get(&app.focused_pane).copied().unwrap_or(0);
let is_column_focused = is_pane_focused && current_column == column_idx;
let (border_color, title_style) = if is_column_focused {
(Color::White, Style::default().fg(Color::White).add_modifier(Modifier::BOLD))
} else {
(Color::DarkGray, Style::default().fg(Color::Gray))
};
let items: Vec<ListItem> = tasks
.iter()
.enumerate()
.map(|(i, task)| {
let selected_idx = app.selected_task_index.get(&app.focused_pane).copied().unwrap_or(0);
let is_selected = is_column_focused && i == selected_idx;
let style = if is_selected {
Style::default()
.bg(Color::Rgb(41, 98, 218))
.fg(Color::White)
.add_modifier(Modifier::BOLD)
} else {
Style::default()
};
let priority_indicator = match task.priority.as_deref() {
Some("high") => Span::styled("● ", Style::default().fg(Color::Red)),
Some("medium") => Span::styled("● ", Style::default().fg(Color::Yellow)),
Some("low") => Span::styled("● ", Style::default().fg(Color::Blue)),
_ => Span::raw(" "),
};
let selection_indicator = if is_selected {
Span::styled("▶ ", Style::default().fg(Color::White))
} else {
Span::raw(" ")
};
ListItem::new(Line::from(vec![
Span::raw(" "),
selection_indicator,
priority_indicator,
Span::raw(&task.title),
Span::raw(" "),
]))
.style(style)
})
.collect();
let title_with_count = format!(" {} ({}) ", title, tasks.len());
let list = List::new(items).block(
Block::default()
.title(title_with_count)
.title_alignment(ratatui::layout::Alignment::Center)
.title_style(title_style)
.borders(Borders::ALL)
.border_style(Style::default().fg(border_color))
.border_type(ratatui::widgets::BorderType::Rounded),
);
f.render_widget(list, area);
}