// src/client/ui.rs use crossterm::{ event::{self, Event, KeyCode, KeyModifiers}, execute, terminal::{disable_raw_mode, enable_raw_mode, EnterAlternateScreen, LeaveAlternateScreen}, }; use ratatui::{ backend::CrosstermBackend, layout::{Constraint, Direction, Layout}, Terminal, }; use std::io; use crate::proto::multieko2::{AdresarRequest, adresar_client::AdresarClient}; use crate::client::colors::Theme; use crate::client::components::{form::render_form, preview_card::render_preview_card, command_line::render_command_line}; pub async fn run_client() -> Result<(), Box> { // Setup terminal enable_raw_mode()?; let mut stdout = io::stdout(); execute!(stdout, EnterAlternateScreen)?; let backend = CrosstermBackend::new(stdout); let mut terminal = Terminal::new(backend)?; let mut client = AdresarClient::connect("http://[::1]:50051").await?; // Initialize 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", ]; let mut command_mode = false; let mut command_input = String::new(); let theme = Theme::dark(); loop { terminal.draw(|f| { let root = Layout::default() .direction(Direction::Vertical) .constraints([Constraint::Min(10), Constraint::Length(1)]) .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, ); // Command line render_command_line(f, root[1], &command_input, command_mode, &theme); })?; if let Event::Key(key) = event::read()? { if command_mode { match key.code { KeyCode::Enter => { if command_input == "w" { break; } 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(); } _ => {} } continue; } if command_mode { match key.code { KeyCode::Enter => { match command_input.as_str() { "w" => break, // Save and exit "q" => { // Quit without saving disable_raw_mode()?; execute!(terminal.backend_mut(), LeaveAlternateScreen)?; 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(); } _ => {} } continue; } 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::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, }; } KeyCode::Enter => { if current_field == fields.len() - 1 { break; } else { current_field += 1; } } _ => {} } } } // Cleanup terminal disable_raw_mode()?; execute!(terminal.backend_mut(), LeaveAlternateScreen)?; // Create and send request let request = tonic::Request::new(AdresarRequest { firma, kz, drc, ulica, psc, mesto, stat, banka, ucet, skladm, ico, kontakt, telefon, skladu, fax, }); let response = client.create_adresar(request).await?; println!("Adresar created: {:?}", response.into_inner()); Ok(()) }