use crate::AppScreen;
use crossterm::event::KeyCode;
use ratatui::{
prelude::*,
widgets::{Block, Borders, List, ListItem, Paragraph, Wrap, Padding},
};
const TITLE_ART: &str = r###"
██▓ ▒█████ ▒█████ ██ ▄█▀ ██▓ ███▄ █ ██████ ██▓▓█████▄ ▓█████
▓██▒ ▒██▒ ██▒▒██▒ ██▒ ██▄█▒ ▓██▒ ██ ▀█ █ ▒██ ▒ ▓██▒▒██▀ ██▌▓█ ▀
▒██░ ▒██░ ██▒▒██░ ██▒▓███▄░ ▒██▒▓██ ▀█ ██▒░ ▓██▄ ▒██▒░██ █▌▒███
▒██░ ▒██ ██░▒██ ██░▓██ █▄ ░██░▓██▒ ▐▌██▒ ▒ ██▒░██░░▓█▄ ▌▒▓█ ▄
░██████▒░ ████▓▒░░ ████▓▒░▒██▒ █▄ ░██░▒██░ ▓██░▒██████▒▒░██░░▒████▓ ░▒████▒
░ ▒░▓ ░░ ▒░▒░▒░ ░ ▒░▒░▒░ ▒ ▒▒ ▓▒ ░▓ ░ ▒░ ▒ ▒ ▒ ▒▓▒ ▒ ░░▓ ▒▒▓ ▒ ░░ ▒░ ░
░ ░ ▒ ░ ░ ▒ ▒░ ░ ▒ ▒░ ░ ░▒ ▒░ ▒ ░░ ░░ ░ ▒░░ ░▒ ░ ░ ▒ ░ ░ ▒ ▒ ░ ░ ░
░ ░ ░ ░ ░ ▒ ░ ░ ░ ▒ ░ ░░ ░ ▒ ░ ░ ░ ░ ░ ░ ░ ▒ ░ ░ ░ ░ ░
░ ░ ░ ░ ░ ░ ░ ░ ░ ░ ░ ░ ░ ░ ░
░
"###;
pub struct StartMenu {
pub options: Vec<String>,
pub selected_index: usize,
}
impl StartMenu {
pub fn new() -> Self {
Self {
options: vec![
"⤓ Load Data".to_string(),
"Σ Statistics".to_string(),
"⌕ Filter".to_string(),
"⏻ Exit".to_string(),
],
selected_index: 0,
}
}
pub fn next(&mut self) {
self.selected_index = (self.selected_index + 1) % self.options.len();
}
pub fn previous(&mut self) {
if self.selected_index > 0 {
self.selected_index -= 1;
} else {
self.selected_index = self.options.len() - 1;
}
}
}
use crate::ui::components::help_bar::HelpBar;
use crate::AppState;
use crate::ui::theme;
pub fn render_start_menu(f: &mut Frame, menu: &StartMenu, app_state: &AppState) {
let screen_chunks = Layout::default()
.direction(Direction::Vertical)
.constraints([
Constraint::Percentage(30),
Constraint::Percentage(10),
Constraint::Min(0),
Constraint::Length(1),
])
.split(f.area());
let title_area = screen_chunks[0];
let description_area = screen_chunks[1];
let options_area_with_h_padding = screen_chunks[2];
let help_bar_area_with_h_padding = screen_chunks[3];
let title = Paragraph::new(TITLE_ART)
.alignment(Alignment::Center)
.style(theme::BORDER_STYLE); f.render_widget(title, title_area);
let description_text = "A terminal-based data analysis tool. Select an option to continue.";
let description = Paragraph::new(description_text)
.wrap(Wrap { trim: true })
.alignment(Alignment::Center)
.block(Block::default());
f.render_widget(description, description_area);
let options_padded_chunks = Layout::default()
.direction(Direction::Horizontal)
.constraints([
Constraint::Percentage(10),
Constraint::Min(0),
Constraint::Percentage(10),
])
.split(options_area_with_h_padding);
let options_content_area = options_padded_chunks[1];
let items: Vec<ListItem> = menu
.options
.iter()
.enumerate()
.map(|(i, option)| {
let style = if i == menu.selected_index {
theme::HIGHLIGHT_STYLE } else {
Style::new().fg(Color::White) };
ListItem::new(option.clone()).style(style)
})
.collect();
let list = List::new(items)
.block(Block::default().borders(Borders::ALL).padding(Padding::horizontal(10)).border_style(theme::BORDER_STYLE)) .highlight_style(theme::HIGHLIGHT_STYLE) .highlight_symbol(">> ");
f.render_widget(list, options_content_area);
let help_bar_padded_chunks = Layout::default()
.direction(Direction::Horizontal)
.constraints([
Constraint::Percentage(5),
Constraint::Min(0),
Constraint::Percentage(5),
])
.split(help_bar_area_with_h_padding);
let help_bar_content_area = help_bar_padded_chunks[1];
HelpBar::new().render_widget(help_bar_content_area, f.buffer_mut(), &app_state.current_screen, &app_state.input_mode);
}
pub fn handle_input(key: KeyCode, app_state: &mut AppState) -> Option<AppScreen> { let menu = &mut app_state.start_menu; match key {
KeyCode::Up => {
menu.previous();
app_state.needs_redraw = true;
None
}
KeyCode::Down => {
menu.next();
app_state.needs_redraw = true;
None
}
KeyCode::Enter => {
let selected_option = menu.options[menu.selected_index].as_str();
app_state.needs_redraw = true;
match selected_option {
"⤓ Load Data" => Some(AppScreen::LoadData),
"Σ Statistics" => Some(AppScreen::StatisticsView),
"⌕ Filter" => Some(AppScreen::FilterView),
"⏻ Exit" => Some(AppScreen::Exit),
_ => None,
}
}
_ => None,
}
}