Files
komp_ac/client/src/state/pages/auth.rs
2025-04-12 16:22:07 +02:00

284 lines
8.0 KiB
Rust

// src/state/pages/auth.rs
use crate::state::canvas_state::CanvasState;
use lazy_static::lazy_static;
lazy_static! {
pub static ref AVAILABLE_ROLES: Vec<String> = vec![
"admin".to_string(),
"moderator".to_string(),
"accountant".to_string(),
"viewer".to_string(),
];
}
#[derive(Default)]
pub struct AuthState {
pub return_selected: bool,
pub username: String,
pub password: String,
pub error_message: Option<String>,
pub current_field: usize,
pub current_cursor_pos: usize,
pub auth_token: Option<String>,
pub user_id: Option<String>,
pub role: Option<String>,
pub has_unsaved_changes: bool,
}
#[derive(Default, Clone)] // Add Clone derive
pub struct RegisterState {
pub username: String,
pub email: String,
pub password: String,
pub password_confirmation: String,
pub role: String,
pub error_message: Option<String>,
pub current_field: usize,
pub current_cursor_pos: usize,
pub has_unsaved_changes: bool,
pub show_role_suggestions: bool,
pub role_suggestions: Vec<String>,
pub selected_suggestion_index: Option<usize>,
pub in_suggestion_mode: bool,
}
impl AuthState {
pub fn new() -> Self {
Self {
return_selected: false,
username: String::new(),
password: String::new(),
error_message: None,
current_field: 0,
current_cursor_pos: 0,
auth_token: None,
user_id: None,
role: None,
has_unsaved_changes: false,
}
}
}
impl RegisterState {
pub fn new() -> Self {
Self {
username: String::new(),
email: String::new(),
password: String::new(),
password_confirmation: String::new(),
role: String::new(),
error_message: None,
current_field: 0,
current_cursor_pos: 0,
has_unsaved_changes: false,
show_role_suggestions: false,
role_suggestions: Vec::new(),
selected_suggestion_index: None,
in_suggestion_mode: false,
}
}
/// Updates role suggestions based on current input.
pub fn update_role_suggestions(&mut self) {
let current_input = self.role.to_lowercase();
self.role_suggestions = AVAILABLE_ROLES
.iter()
.filter(|role| role.to_lowercase().contains(&current_input))
.cloned()
.collect();
self.show_role_suggestions = !self.role_suggestions.is_empty();
}
}
impl CanvasState for AuthState {
fn current_field(&self) -> usize {
self.current_field
}
fn current_cursor_pos(&self) -> usize {
let len = match self.current_field {
0 => self.username.len(),
1 => self.password.len(),
_ => 0,
};
self.current_cursor_pos.min(len)
}
fn has_unsaved_changes(&self) -> bool {
self.has_unsaved_changes
}
fn inputs(&self) -> Vec<&String> {
vec![&self.username, &self.password]
}
fn get_current_input(&self) -> &str {
match self.current_field {
0 => &self.username,
1 => &self.password,
_ => "",
}
}
fn get_current_input_mut(&mut self) -> &mut String {
match self.current_field {
0 => &mut self.username,
1 => &mut self.password,
_ => panic!("Invalid current_field index in AuthState"),
}
}
fn fields(&self) -> Vec<&str> {
vec!["Username/Email", "Password"]
}
fn set_current_field(&mut self, index: usize) {
if index < 2 { // AuthState only has 2 fields
self.current_field = index;
// IMPORTANT: Clamp cursor position to the length of the NEW field
let len = match self.current_field {
0 => self.username.len(),
1 => self.password.len(),
_ => 0,
};
self.current_cursor_pos = self.current_cursor_pos.min(len);
}
}
fn set_current_cursor_pos(&mut self, pos: usize) {
let len = match self.current_field {
0 => self.username.len(),
1 => self.password.len(),
_ => 0,
};
// Ensure stored position is always valid
self.current_cursor_pos = pos.min(len);
}
fn set_has_unsaved_changes(&mut self, changed: bool) {
// Allow the generic handler to signal changes
self.has_unsaved_changes = changed;
}
// --- Autocomplete Support (Not Used for AuthState) ---
fn get_suggestions(&self) -> Option<&[String]> {
None // AuthState doesn't provide suggestions
}
fn get_selected_suggestion_index(&self) -> Option<usize> {
None // AuthState doesn't have selected suggestions
}
}
impl CanvasState for RegisterState {
fn current_field(&self) -> usize {
self.current_field
}
fn current_cursor_pos(&self) -> usize {
let len = match self.current_field {
0 => self.username.len(),
1 => self.email.len(),
2 => self.password.len(),
3 => self.password_confirmation.len(),
4 => self.role.len(),
_ => 0,
};
self.current_cursor_pos.min(len)
}
fn has_unsaved_changes(&self) -> bool {
self.has_unsaved_changes
}
fn inputs(&self) -> Vec<&String> {
vec![
&self.username,
&self.email,
&self.password,
&self.password_confirmation,
&self.role,
]
}
fn get_current_input(&self) -> &str {
match self.current_field {
0 => &self.username,
1 => &self.email,
2 => &self.password,
3 => &self.password_confirmation,
4 => &self.role,
_ => "",
}
}
fn get_current_input_mut(&mut self) -> &mut String {
match self.current_field {
0 => &mut self.username,
1 => &mut self.email,
2 => &mut self.password,
3 => &mut self.password_confirmation,
4 => &mut self.role,
_ => panic!("Invalid current_field index in RegisterState"),
}
}
fn fields(&self) -> Vec<&str> {
vec![
"Username",
"Email (Optional)",
"Password (Optional)",
"Confirm Password",
"Role (Oprional)"
]
}
fn set_current_field(&mut self, index: usize) {
if index < 5 { // RegisterState has 5 fields
self.current_field = index;
let len = match self.current_field {
0 => self.username.len(),
1 => self.email.len(),
2 => self.password.len(),
3 => self.password_confirmation.len(),
4 => self.role.len(),
_ => 0,
};
self.current_cursor_pos = self.current_cursor_pos.min(len);
}
}
fn set_current_cursor_pos(&mut self, pos: usize) {
let len = match self.current_field {
0 => self.username.len(),
1 => self.email.len(),
2 => self.password.len(),
3 => self.password_confirmation.len(),
4 => self.role.len(),
_ => 0,
};
self.current_cursor_pos = pos.min(len);
}
fn set_has_unsaved_changes(&mut self, changed: bool) {
self.has_unsaved_changes = changed;
}
fn get_suggestions(&self) -> Option<&[String]> {
// Only show suggestions for the role field (index 4) when requested
if self.current_field == 4 && self.in_suggestion_mode && self.show_role_suggestions {
Some(&self.role_suggestions)
} else {
None
}
}
fn get_selected_suggestion_index(&self) -> Option<usize> {
if self.current_field == 4 && self.in_suggestion_mode && self.show_role_suggestions {
self.selected_suggestion_index
} else {
None
}
}
}