// src/components/handlers/sidebar.rs use ratatui::{ widgets::{Block, List, ListItem}, layout::{Rect, Direction, Layout, Constraint}, style::Style, Frame, }; use crate::config::colors::themes::Theme; use common::proto::multieko2::table_definition::{ProfileTreeResponse}; use ratatui::text::{Span, Line}; const SIDEBAR_WIDTH: u16 = 16; pub fn calculate_sidebar_layout(show_sidebar: bool, main_content_area: Rect) -> (Option, Rect) { if show_sidebar { let chunks = Layout::default() .direction(Direction::Horizontal) .constraints([ Constraint::Length(SIDEBAR_WIDTH), Constraint::Min(0), ]) .split(main_content_area); (Some(chunks[0]), chunks[1]) } else { (None, main_content_area) } } pub fn render_sidebar( f: &mut Frame, area: Rect, theme: &Theme, profile_tree: &ProfileTreeResponse, selected_profile: &Option, ) { let sidebar_block = Block::default().style(Style::default().bg(theme.bg)); let mut items = Vec::new(); if let Some(profile_name) = selected_profile { if let Some(profile) = profile_tree.profiles.iter() .find(|p| &p.name == profile_name) { // Profile header items.push(ListItem::new(Line::from(vec![ Span::styled("📁 ", Style::default().fg(theme.accent)), Span::styled(&profile.name, Style::default().fg(theme.highlight)), ]))); // Tables for (table_idx, table) in profile.tables.iter().enumerate() { let is_last = table_idx == profile.tables.len() - 1; let prefix = if is_last { "└─ " } else { "├─ " }; let mut line = vec![ Span::styled(format!(" {}", prefix), Style::default().fg(theme.fg)), Span::styled(&table.name, Style::default().fg(theme.fg)), ]; if !table.depends_on.is_empty() { line.push(Span::styled( format!(" → {}", table.depends_on.join(", ")), Style::default().fg(theme.secondary) )); } items.push(ListItem::new(Line::from(line))); } } } else { items.push(ListItem::new(Span::styled( "No profile selected", Style::default().fg(theme.secondary) ))); } let list = List::new(items) .block(sidebar_block) .highlight_style(Style::default().fg(theme.highlight)) .highlight_symbol(">>"); f.render_widget(list, area); }