// src/pages/login/ui.rs use crate::{ config::colors::themes::Theme, state::app::state::AppState, }; use ratatui::{ layout::{Alignment, Constraint, Direction, Layout, Rect, Margin}, style::{Style, Modifier, Color}, widgets::{Block, BorderType, Borders, Paragraph}, Frame, }; use canvas::{ FormEditor, render_canvas, render_suggestions_dropdown, DefaultCanvasTheme, }; use crate::pages::login::LoginFormState; use crate::dialog; pub fn render_login( f: &mut Frame, area: Rect, theme: &Theme, login_page: &LoginFormState, app_state: &AppState, ) { let login_state = &login_page.state; let editor = &login_page.editor; // Main container let block = Block::default() .borders(Borders::ALL) .border_type(BorderType::Plain) .border_style(Style::default().fg(theme.border)) .title(" Login ") .style(Style::default().bg(theme.bg)); f.render_widget(block, area); let inner_area = area.inner(Margin { horizontal: 1, vertical: 1, }); // Layout chunks let chunks = Layout::default() .direction(Direction::Vertical) .constraints([ Constraint::Length(4), // Form (2 fields + padding) Constraint::Length(1), // Error message Constraint::Length(3), // Buttons ]) .split(inner_area); let input_rect = render_canvas( f, chunks[0], editor, &DefaultCanvasTheme, ); // --- ERROR MESSAGE --- if let Some(err) = &login_state.error_message { f.render_widget( Paragraph::new(err.as_str()) .style(Style::default().fg(Color::Red)) .alignment(Alignment::Center), chunks[1], ); } // --- BUTTONS (unchanged) --- let button_chunks = Layout::default() .direction(Direction::Horizontal) .constraints([Constraint::Percentage(50), Constraint::Percentage(50)]) .split(chunks[2]); // Login Button let login_button_index = 0; let login_active = login_page.focus_outside_canvas && login_page.focused_button_index == login_button_index; let mut login_style = Style::default().fg(theme.fg); let mut login_border = Style::default().fg(theme.border); if login_active { login_style = login_style.fg(theme.highlight).add_modifier(Modifier::BOLD); login_border = login_border.fg(theme.accent); } f.render_widget( Paragraph::new("Login") .style(login_style) .alignment(Alignment::Center) .block( Block::default() .borders(Borders::ALL) .border_type(BorderType::Plain) .border_style(login_border), ), button_chunks[0], ); // Return Button let return_button_index = 1; let return_active = login_page.focus_outside_canvas && login_page.focused_button_index == return_button_index; let mut return_style = Style::default().fg(theme.fg); let mut return_border = Style::default().fg(theme.border); if return_active { return_style = return_style.fg(theme.highlight).add_modifier(Modifier::BOLD); return_border = return_border.fg(theme.accent); } f.render_widget( Paragraph::new("Return") .style(return_style) .alignment(Alignment::Center) .block( Block::default() .borders(Borders::ALL) .border_type(BorderType::Plain) .border_style(return_border), ), button_chunks[1], ); // --- SUGGESTIONS DROPDOWN (if active) --- if editor.mode() == canvas::AppMode::Edit { if let Some(input_rect) = input_rect { render_suggestions_dropdown( f, chunks[0], input_rect, &DefaultCanvasTheme, editor, ); } } // --- DIALOG --- if app_state.ui.dialog.dialog_show { dialog::render_dialog( f, f.area(), theme, &app_state.ui.dialog.dialog_title, &app_state.ui.dialog.dialog_message, &app_state.ui.dialog.dialog_buttons, app_state.ui.dialog.dialog_active_button_index, app_state.ui.dialog.is_loading, ); } }