//! 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));
}
}