use crate::app::App;
use crate::components::centered_rect;
use ratatui::{
layout::{Constraint, Direction, Layout},
style::{Color, Style},
text::{Line, Span},
widgets::{Block, Borders, Clear, Paragraph},
Frame,
};
pub fn render_manage_parents_popup(app: &App, frame: &mut Frame) {
render_relationship_popup(app, frame, "Set Parents");
}
pub fn render_manage_children_popup(app: &App, frame: &mut Frame) {
render_relationship_popup(app, frame, "Set Children");
}
fn render_relationship_popup(app: &App, frame: &mut Frame, title: &str) {
let area = centered_rect(60, 70, frame.area());
frame.render_widget(Clear, area);
let block = Block::default()
.title(title)
.borders(Borders::ALL)
.style(Style::default().bg(Color::Black));
let inner = block.inner(area);
frame.render_widget(block, area);
let chunks = Layout::default()
.direction(Direction::Vertical)
.margin(1)
.constraints([
Constraint::Length(3),
Constraint::Min(0),
Constraint::Length(1),
])
.split(inner);
render_relationship_search_box(app, frame, chunks[0]);
render_relationship_card_list(app, frame, chunks[1]);
render_relationship_instructions(app, frame, chunks[2]);
}
fn render_relationship_search_box(app: &App, frame: &mut Frame, area: ratatui::layout::Rect) {
let search_border_style = if app.relationship.search_active {
Style::default().fg(Color::Yellow)
} else {
Style::default().fg(Color::Gray)
};
let search_block = Block::default()
.title("Search")
.borders(Borders::ALL)
.border_style(search_border_style);
let search_text: Line = if app.relationship.search_active {
Line::from(vec![
Span::styled(&app.relationship.search, Style::default().fg(Color::White)),
Span::styled("_", Style::default().fg(Color::Yellow)),
])
} else if app.relationship.search.is_empty() {
Line::from(Span::styled(
"/ to search",
Style::default().fg(Color::DarkGray),
))
} else {
Line::from(Span::styled(
&app.relationship.search,
Style::default().fg(Color::White),
))
};
let search = Paragraph::new(search_text).block(search_block);
frame.render_widget(search, area);
}
fn render_relationship_card_list(app: &App, frame: &mut Frame, area: ratatui::layout::Rect) {
let filtered_cards: Vec<_> = if app.relationship.search.is_empty() {
app.relationship.card_ids.clone()
} else {
let search_lower = app.relationship.search.to_lowercase();
app.relationship
.card_ids
.iter()
.filter(|card_id| {
app.get_card_by_id(**card_id)
.map(|c| c.title.to_lowercase().contains(&search_lower))
.unwrap_or(false)
})
.copied()
.collect()
};
let mut lines = vec![];
for (idx, card_id) in filtered_cards.iter().enumerate() {
if let Some(card) = app.get_card_by_id(*card_id) {
let is_selected = app.relationship.selection.get() == Some(idx);
let is_checked = app.relationship.selected.contains(card_id);
let checkbox = if is_checked { "[✓]" } else { "[ ]" };
let style = if is_selected {
Style::default().fg(Color::White).bg(Color::Blue)
} else if is_checked {
Style::default().fg(Color::Green)
} else {
Style::default().fg(Color::White)
};
lines.push(Line::from(Span::styled(
format!("{} {}", checkbox, card.title),
style,
)));
}
}
if lines.is_empty() {
lines.push(Line::from(Span::styled(
"No eligible cards found",
Style::default().fg(Color::DarkGray),
)));
}
let list = Paragraph::new(lines);
frame.render_widget(list, area);
}
fn render_relationship_instructions(app: &App, frame: &mut Frame, area: ratatui::layout::Rect) {
let instructions_text = if app.relationship.search_active {
"Type to search | Enter/Esc: exit search"
} else {
"j/k: navigate | Space: toggle | /: search | Esc: close"
};
let instructions =
Paragraph::new(instructions_text).style(Style::default().fg(Color::DarkGray));
frame.render_widget(instructions, area);
}