//! Search input widget with match count and visual feedback. use ratatui::{ prelude::*, widgets::{Block, Borders, Paragraph}, }; use crate::daemon::tui::app::{App, InputMode, ViewMode}; /// Color for the search bar when there are no matches const NO_MATCH_COLOR: Color = Color::Red; /// Color for the search bar when actively searching const SEARCH_ACTIVE_COLOR: Color = Color::Yellow; pub fn render(f: &mut Frame, area: Rect, app: &App) { let view_label = match app.view_mode { ViewMode::Tasks => "Tasks", ViewMode::Contracts => "Contracts", ViewMode::Files => "Files", }; let (matched, total) = app.match_count(); let has_no_matches = app.has_no_matches(); let is_searching = matches!(app.input_mode, InputMode::Search); let has_query = !app.search_query.is_empty(); // Determine border style based on state let border_style = if has_no_matches { Style::default().fg(NO_MATCH_COLOR) } else if is_searching { Style::default().fg(SEARCH_ACTIVE_COLOR) } else { Style::default() }; // Build the search input content let search_text = if app.search_query.is_empty() { if is_searching { " Type to search...".to_string() } else { " Press / to search".to_string() } } else { format!(" {}", app.search_query) }; // Build the title with match count let title = if has_query { if has_no_matches { format!(" 🔍 Search [{}] - No matches ", view_label) } else { format!(" 🔍 Search [{}] - {}/{} matches ", view_label, matched, total) } } else { format!(" 🔍 Search [{}] ", view_label) }; // Create input text with appropriate style let text_style = if app.search_query.is_empty() && !is_searching { Style::default().fg(Color::DarkGray) } else if has_no_matches { Style::default().fg(NO_MATCH_COLOR) } else { Style::default() }; let input = Paragraph::new(Span::styled(search_text, text_style)).block( Block::default() .title(title) .borders(Borders::ALL) .border_style(border_style), ); f.render_widget(input, area); // Show cursor in search mode if is_searching { // Calculate cursor position based on actual search query length let cursor_x = area.x + app.search_query.len() as u16 + 2; f.set_cursor_position(Position::new(cursor_x, area.y + 1)); } }