From 4f8f2f4a4093d7854a2d1ed02c25f39f3523ab75 Mon Sep 17 00:00:00 2001 From: filipriec Date: Fri, 28 Mar 2025 20:48:06 +0100 Subject: [PATCH] step4 --- client/src/components/auth/login.rs | 73 +++++++++-------------------- client/src/components/form/form.rs | 51 ++++++++++++++++++-- 2 files changed, 69 insertions(+), 55 deletions(-) diff --git a/client/src/components/auth/login.rs b/client/src/components/auth/login.rs index cc73317..dec6f73 100644 --- a/client/src/components/auth/login.rs +++ b/client/src/components/auth/login.rs @@ -1,23 +1,24 @@ // src/components/auth/login.rs use crate::{ - components::handlers::canvas::render_canvas, // Import render_canvas + components::form::form::render_generic_form, config::colors::themes::Theme, - state::{pages::auth::AuthState, pages::form::FormState}, // Import FormState + state::pages::auth::AuthState, }; use ratatui::{ - layout::{Alignment, Constraint, Direction, Layout, Margin, Rect}, + layout::{Alignment, Constraint, Direction, Layout, Rect}, style::{Color, Style}, widgets::{Block, BorderType, Borders, Paragraph}, Frame, }; +use ratatui::prelude::Margin; pub fn render_login( f: &mut Frame, area: Rect, theme: &Theme, - state: &AuthState, // Changed to immutable borrow for rendering + state: &AuthState, ) { - // Main login block (remains the same) + // Main login block with rounded borders let block = Block::default() .borders(Borders::ALL) .border_type(BorderType::Rounded) @@ -33,61 +34,33 @@ pub fn render_login( }); // Define field names - let fields: &[&str] = &["Username/Email", "Password"]; + let fields = &["Username/Email", "Password"]; - // Prepare inputs for render_canvas (mask password) - // Note: We need an owned String for the masked password to get a reference. - let password_display_owned = "*".repeat(state.password.len()); - let inputs: &[&String] = &[&state.username, &password_display_owned]; - - // Determine if we are in "edit mode" (fields focused vs buttons focused) - let is_edit_mode = !state.return_selected; - - // --- Temporary FormState for render_canvas --- - // HACK: Create a temporary FormState to satisfy the render_canvas signature. - // This avoids modifying render_canvas for now, but ideally, render_canvas - // would be refactored to take cursor_pos and has_unsaved_changes directly. - let field_names_owned: Vec = - fields.iter().map(|&s| s.to_string()).collect(); - let mut temp_form_state = FormState::new(field_names_owned); - temp_form_state.current_cursor_pos = state.current_cursor_pos; - // We don't use the 'unsaved changes' warning border for login - temp_form_state.has_unsaved_changes = false; - // -------------------------------------------- - - // Adjusted layout: Canvas area, Error area, Buttons area + // Split layout for form and buttons let chunks = Layout::default() .direction(Direction::Vertical) .constraints([ - // Height for canvas: fields.len() + 2 for borders - Constraint::Length(fields.len() as u16 + 2), - Constraint::Min(1), // Spacer/error message area - Constraint::Length(3), // Buttons area height + Constraint::Min(3), // Form area (will be managed by render_generic_form) + Constraint::Length(3), // Buttons area ]) .split(inner_area); - let canvas_area = chunks[0]; - let error_area = chunks[1]; - let button_area = chunks[2]; // Use the last chunk for buttons - - // --- Render Input Fields using render_canvas --- - render_canvas( + // Render form using generic component + render_generic_form( f, - canvas_area, - &temp_form_state, // Pass the temporary state + chunks[0], + "Login", + state, fields, - &state.current_field, // Pass the current field index from AuthState - inputs, // Pass the prepared username and masked password theme, - is_edit_mode, // Controls border color (accent when true) + !state.return_selected, // is_edit_mode ); - // --- End render_canvas --- - // Render buttons (logic remains mostly the same, uses button_area) + // Render buttons let button_chunks = Layout::default() .direction(Direction::Horizontal) .constraints([Constraint::Percentage(50), Constraint::Percentage(50)]) - .split(button_area); // Use the dedicated button_area + .split(chunks[1]); // Login button let login_style = if !state.return_selected { @@ -143,15 +116,11 @@ pub fn render_login( button_chunks[1], ); - // Render error message if present (uses error_area) + // Render error message if present if let Some(err) = &state.error_message { let err_block = Paragraph::new(err.as_str()) - .style(Style::default().fg(Color::Red)) // Keep explicit error color + .style(Style::default().fg(Color::Red)) .alignment(Alignment::Center); - f.render_widget(err_block, error_area); // Render in the middle area + f.render_widget(err_block, chunks[0]); // Render over form area } - - // Cursor position is now handled internally by render_canvas - // No need for manual f.set_cursor_position here } - diff --git a/client/src/components/form/form.rs b/client/src/components/form/form.rs index 72c1c51..47d349f 100644 --- a/client/src/components/form/form.rs +++ b/client/src/components/form/form.rs @@ -1,4 +1,4 @@ -// src/components/handlers/form.rs +// src/components/form/form.rs use ratatui::{ widgets::{Paragraph, Block, Borders}, layout::{Layout, Constraint, Direction, Rect, Margin, Alignment}, @@ -6,13 +6,14 @@ use ratatui::{ Frame, }; use crate::config::colors::themes::Theme; -use crate::state::pages::form::FormState; +use crate::state::canvas_state::CanvasState; use crate::components::handlers::canvas::render_canvas; +// Original form renderer (keep for backward compatibility) pub fn render_form( f: &mut Frame, area: Rect, - form_state: &FormState, + form_state: &impl CanvasState, fields: &[&str], current_field: &usize, inputs: &[&String], @@ -64,3 +65,47 @@ pub fn render_form( is_edit_mode, ); } + +// New generic form renderer +pub fn render_generic_form( + f: &mut Frame, + area: Rect, + title: &str, + state: &impl CanvasState, + fields: &[&str], + theme: &Theme, + is_edit_mode: bool, +) { + // Create form card + let form_card = Block::default() + .borders(Borders::ALL) + .border_style(Style::default().fg(theme.border)) + .title(format!(" {} ", title)) + .style(Style::default().bg(theme.bg).fg(theme.fg)); + + f.render_widget(form_card, area); + + // Define inner area + let inner_area = area.inner(Margin { + horizontal: 1, + vertical: 1, + }); + + // Create main layout + let main_layout = Layout::default() + .direction(Direction::Vertical) + .constraints([Constraint::Min(1)]) + .split(inner_area); + + // Delegate to render_canvas + render_canvas( + f, + main_layout[0], + state, + fields, + &state.current_field(), + &state.inputs(), + theme, + is_edit_mode, + ); +}