diff --git a/client/src/components/auth/login.rs b/client/src/components/auth/login.rs index eae711a..148810f 100644 --- a/client/src/components/auth/login.rs +++ b/client/src/components/auth/login.rs @@ -1,111 +1,62 @@ -// src/components/login/login.rs +// src/components/auth/login.rs use ratatui::{ - widgets::{Block, BorderType, Borders, List, ListItem, ListState, Paragraph}, - style::Style, - text::{Line, Span, Text}, layout::{Alignment, Constraint, Direction, Layout, Rect}, + style::Style, + text::{Line, Span}, + widgets::{Block, BorderType, Borders, Paragraph}, Frame, }; use crate::config::colors::themes::Theme; +#[derive(Default)] pub struct LoginState { - pub fields: Vec, - pub values: Vec, - pub selected_field: usize, + pub return_selected: bool, } impl LoginState { - pub fn new() -> Self { - Self { - fields: vec!["Username".to_string(), "Password".to_string()], - values: vec![String::new(), String::new()], - selected_field: 0, - } - } - - pub fn next_field(&mut self) { - self.selected_field = (self.selected_field + 1) % self.fields.len(); - } - - pub fn previous_field(&mut self) { - self.selected_field = if self.selected_field == 0 { - self.fields.len() - 1 - } else { - self.selected_field - 1 - }; - } - - pub fn render(&mut self, f: &mut Frame, area: Rect, theme: &Theme) { + pub fn render(&self, f: &mut Frame, area: Rect, theme: &Theme) { let block = Block::default() .borders(Borders::ALL) .border_type(BorderType::Rounded) .border_style(Style::default().fg(theme.accent)) - .style(Style::default().bg(theme.bg)); + .style(Style::default().bg(theme.bg)) + .title(" Login "); let inner_area = block.inner(area); f.render_widget(block, area); + // Simple layout with return button let chunks = Layout::default() .direction(Direction::Vertical) .constraints([ + Constraint::Percentage(40), Constraint::Length(3), - Constraint::Length(5), - Constraint::Min(1), + Constraint::Percentage(40), ]) .split(inner_area); - // Title - let title = Line::from(Span::styled("Login", Style::default().fg(theme.highlight))); - let title_widget = Paragraph::new(title).alignment(Alignment::Center); - f.render_widget(title_widget, chunks[0]); + let button_style = if self.return_selected { + Style::default() + .fg(theme.highlight) + .add_modifier(ratatui::style::Modifier::BOLD) + } else { + Style::default().fg(theme.fg) + }; - // Login form - let form_chunks = Layout::default() - .direction(Direction::Vertical) - .constraints([ - Constraint::Length(3), - Constraint::Length(3), - Constraint::Length(3), - ]) - .split(chunks[1]); + let button = Paragraph::new("Return to Intro") + .style(button_style) + .alignment(Alignment::Center) + .block( + Block::default() + .borders(Borders::ALL) + .border_type(BorderType::Plain) + .border_style(if self.return_selected { + Style::default().fg(theme.accent) + } else { + Style::default().fg(theme.border) + }), + ); - // Username field - let username_block = Block::default() - .title("Username") - .borders(Borders::ALL) - .border_style(if self.selected_field == 0 { - Style::default().fg(theme.highlight) - } else { - Style::default().fg(theme.border) - }); - let username = Paragraph::new(self.values[0].as_str()) - .block(username_block); - f.render_widget(username, form_chunks[0]); - - // Password field - let password_block = Block::default() - .title("Password") - .borders(Borders::ALL) - .border_style(if self.selected_field == 1 { - Style::default().fg(theme.highlight) - } else { - Style::default().fg(theme.border) - }); - let password = Paragraph::new("*".repeat(self.values[1].len())) - .block(password_block); - f.render_widget(password, form_chunks[1]); - - // Submit button - let submit_block = Block::default() - .borders(Borders::ALL) - .border_style(if self.selected_field == 2 { - Style::default().fg(theme.highlight) - } else { - Style::default().fg(theme.border) - }); - let submit = Paragraph::new("Submit") - .block(submit_block) - .alignment(Alignment::Center); - f.render_widget(submit, form_chunks[2]); + f.render_widget(button, chunks[1]); } } diff --git a/client/src/state/pages.rs b/client/src/state/pages.rs index 9f5f7c7..b888164 100644 --- a/client/src/state/pages.rs +++ b/client/src/state/pages.rs @@ -1,3 +1,4 @@ // src/state/pages.rs pub mod form; +pub mod auth; diff --git a/client/src/state/pages/auth.rs b/client/src/state/pages/auth.rs new file mode 100644 index 0000000..07ad666 --- /dev/null +++ b/client/src/state/pages/auth.rs @@ -0,0 +1,64 @@ +// src/state/pages/auth.rs +use ratatui::{ + layout::{Alignment, Constraint, Direction, Layout, Rect}, + style::Style, + text::{Line, Span}, + widgets::{Block, BorderType, Borders, Paragraph}, + prelude::Widget, + Frame, +}; +use crate::config::colors::themes::Theme; + +#[derive(Default)] +pub struct AuthState { + pub return_selected: bool, +} + +impl AuthState { + pub fn render(&mut self, f: &mut Frame, area: Rect, theme: &Theme) { + let block = Block::default() + .borders(Borders::ALL) + .border_type(BorderType::Rounded) + .border_style(Style::default().fg(theme.accent)) + .style(Style::default().bg(theme.bg)) + .title(" Authentication "); + + let inner_area = block.inner(area); + f.render_widget(block, area); + + let chunks = Layout::default() + .direction(Direction::Vertical) + .constraints([ + Constraint::Percentage(40), + Constraint::Length(3), + Constraint::Percentage(40), + ]) + .split(inner_area); + + // Return button + let button_style = if self.return_selected { + Style::default() + .fg(theme.highlight) + .add_modifier(ratatui::style::Modifier::BOLD) + } else { + Style::default().fg(theme.fg) + }; + + f.render_widget( + Paragraph::new("Return to Intro") + .style(button_style) + .alignment(Alignment::Center) + .block( + Block::default() + .borders(Borders::ALL) + .border_type(BorderType::Plain) + .border_style(if self.return_selected { + Style::default().fg(theme.accent) + } else { + Style::default().fg(theme.border) + }), + ), + chunks[1] + ); + } +} diff --git a/client/src/ui/handlers/render.rs b/client/src/ui/handlers/render.rs index b8a4c4e..0745182 100644 --- a/client/src/ui/handlers/render.rs +++ b/client/src/ui/handlers/render.rs @@ -13,11 +13,13 @@ use crate::config::colors::themes::Theme; use ratatui::layout::{Constraint, Direction, Layout}; use ratatui::Frame; use crate::state::pages::form::FormState; +use crate::state::pages::auth::AuthState; use crate::state::state::AppState; pub fn render_ui( f: &mut Frame, form_state: &mut FormState, + auth_state: &mut AuthState, theme: &Theme, is_edit_mode: bool, total_count: u64, @@ -44,6 +46,8 @@ pub fn render_ui( if app_state.ui.show_intro { // Use app_state's intro_state directly app_state.ui.intro_state.render(f, main_content_area, theme); + }else if app_state.ui.show_login { + auth_state.render(f, main_content_area, theme); } else if app_state.ui.show_admin { // Create temporary AdminPanelState for rendering let mut admin_state = AdminPanelState::new( diff --git a/client/src/ui/handlers/ui.rs b/client/src/ui/handlers/ui.rs index 8e25617..c75767f 100644 --- a/client/src/ui/handlers/ui.rs +++ b/client/src/ui/handlers/ui.rs @@ -8,6 +8,7 @@ use crate::config::colors::themes::Theme; use crate::config::binds::config::Config; use crate::ui::handlers::render::render_ui; use crate::state::pages::form::FormState; +use crate::state::pages::auth::AuthState; use crate::modes::handlers::event::EventHandler; use crate::state::state::AppState; use crate::components::admin::{admin_panel::AdminPanelState}; @@ -20,6 +21,7 @@ pub async fn run_ui() -> Result<(), Box> { let mut command_handler = CommandHandler::new(); let theme = Theme::from_str(&config.colors.theme); let mut intro_state = IntroState::new(); + let mut auth_state = AuthState::default(); // Initialize app_state first let mut app_state = AppState::new()?; @@ -66,6 +68,7 @@ pub async fn run_ui() -> Result<(), Box> { render_ui( f, &mut form_state, + &mut auth_state, &theme, event_handler.is_edit_mode, app_state.total_count,