// src/client/ui.rs use crossterm::event::{Event, KeyCode, KeyModifiers}; use crate::client::terminal::AppTerminal; use crate::client::components::{render_command_line, render_form, render_preview_card, render_status_line}; use crate::client::colors::Theme; use ratatui::layout::{Constraint, Direction, Layout, Rect}; use std::env; pub fn run_ui() -> Result<(), Box> { let mut app_terminal = AppTerminal::new()?; let mut command_mode = false; let mut command_input = String::new(); let theme = Theme::dark(); // Initialize form fields let mut firma = String::new(); let mut kz = String::new(); let mut drc = String::new(); let mut ulica = String::new(); let mut psc = String::new(); let mut mesto = String::new(); let mut stat = String::new(); let mut banka = String::new(); let mut ucet = String::new(); let mut skladm = String::new(); let mut ico = String::new(); let mut kontakt = String::new(); let mut telefon = String::new(); let mut skladu = String::new(); let mut fax = String::new(); let mut current_field: usize = 0; let fields = vec![ "Firma", "KZ", "DRC", "Ulica", "PSC", "Mesto", "Stat", "Banka", "Ucet", "Skladm", "ICO", "Kontakt", "Telefon", "Skladu", "Fax", ]; // Get the current directory let current_dir = env::current_dir()? .to_string_lossy() .to_string(); // Track whether the state has been saved let mut is_saved = false; loop { app_terminal.draw(|f| { let root = Layout::default() .direction(Direction::Vertical) .constraints([ Constraint::Min(10), // Main content area Constraint::Length(1), // Status line Constraint::Length(1), // Command line ]) .split(f.area()); // Main content area let main_chunks = Layout::default() .direction(Direction::Horizontal) .constraints([Constraint::Percentage(60), Constraint::Percentage(40)]) .split(root[0]); // Left panel - Form render_form( f, main_chunks[0], &fields, &mut current_field, &[ &firma, &kz, &drc, &ulica, &psc, &mesto, &stat, &banka, &ucet, &skladm, &ico, &kontakt, &telefon, &skladu, &fax, ], &theme, ); // Right panel - Preview Card render_preview_card( f, main_chunks[1], &[ &firma, &ulica, &mesto, &psc, &ico, &kontakt, &telefon, ], &theme, ); // Status line render_status_line(f, root[1], ¤t_dir, &theme); // Command line render_command_line(f, root[2], &command_input, command_mode, &theme); })?; // Event handling if let Event::Key(key) = app_terminal.read_event()? { if command_mode { match key.code { KeyCode::Enter => { // Handle the command let should_exit = app_terminal.handle_command(&command_input, &mut is_saved)?; if should_exit { return Ok(()); } command_mode = false; command_input.clear(); } KeyCode::Char(c) => command_input.push(c), KeyCode::Backspace => { command_input.pop(); } KeyCode::Esc => { command_mode = false; command_input.clear(); } _ => {} } } else { match key.code { KeyCode::Char(':') => { command_mode = true; command_input.clear(); } KeyCode::Tab => { if key.modifiers.contains(KeyModifiers::SHIFT) { current_field = current_field.saturating_sub(1); } else { current_field = (current_field + 1) % fields.len(); } } KeyCode::BackTab => current_field = current_field.saturating_sub(1), KeyCode::Down => current_field = (current_field + 1) % fields.len(), KeyCode::Up => current_field = current_field.saturating_sub(1), KeyCode::Enter => { // Move to the next field, wrapping around to the first field if necessary current_field = (current_field + 1) % fields.len(); } KeyCode::Char(c) => { match current_field { 0 => firma.push(c), 1 => kz.push(c), 2 => drc.push(c), 3 => ulica.push(c), 4 => psc.push(c), 5 => mesto.push(c), 6 => stat.push(c), 7 => banka.push(c), 8 => ucet.push(c), 9 => skladm.push(c), 10 => ico.push(c), 11 => kontakt.push(c), 12 => telefon.push(c), 13 => skladu.push(c), 14 => fax.push(c), _ => (), } } KeyCode::Backspace => { match current_field { 0 => firma.pop(), 1 => kz.pop(), 2 => drc.pop(), 3 => ulica.pop(), 4 => psc.pop(), 5 => mesto.pop(), 6 => stat.pop(), 7 => banka.pop(), 8 => ucet.pop(), 9 => skladm.pop(), 10 => ico.pop(), 11 => kontakt.pop(), 12 => telefon.pop(), 13 => skladu.pop(), 14 => fax.pop(), _ => None, }; } _ => {} } } } } }