use yew::prelude::*; use web_sys::HtmlInputElement; use gloo_storage::{LocalStorage, Storage}; #[derive(Properties, PartialEq)] pub struct LoginProps { pub on_login: Callback, // Callback with JWT token } #[function_component] pub fn Login(props: &LoginProps) -> Html { let server_url = use_state(String::new); let username = use_state(String::new); let password = use_state(String::new); let error_message = use_state(|| Option::::None); let is_loading = use_state(|| false); let server_url_ref = use_node_ref(); let username_ref = use_node_ref(); let password_ref = use_node_ref(); let on_server_url_change = { let server_url = server_url.clone(); Callback::from(move |e: Event| { let target = e.target_unchecked_into::(); server_url.set(target.value()); }) }; let on_username_change = { let username = username.clone(); Callback::from(move |e: Event| { let target = e.target_unchecked_into::(); username.set(target.value()); }) }; let on_password_change = { let password = password.clone(); Callback::from(move |e: Event| { let target = e.target_unchecked_into::(); password.set(target.value()); }) }; let on_submit = { let server_url = server_url.clone(); let username = username.clone(); let password = password.clone(); let error_message = error_message.clone(); let is_loading = is_loading.clone(); let on_login = props.on_login.clone(); Callback::from(move |e: SubmitEvent| { e.prevent_default(); let server_url = (*server_url).clone(); let username = (*username).clone(); let password = (*password).clone(); let error_message = error_message.clone(); let is_loading = is_loading.clone(); let on_login = on_login.clone(); // Basic client-side validation if server_url.trim().is_empty() || username.trim().is_empty() || password.is_empty() { error_message.set(Some("Please fill in all fields".to_string())); return; } is_loading.set(true); error_message.set(None); wasm_bindgen_futures::spawn_local(async move { web_sys::console::log_1(&"🚀 Starting login process...".into()); match perform_login(server_url.clone(), username.clone(), password.clone()).await { Ok((token, credentials)) => { web_sys::console::log_1(&"✅ Login successful!".into()); // Store token and credentials in local storage if let Err(_) = LocalStorage::set("auth_token", &token) { error_message.set(Some("Failed to store authentication token".to_string())); is_loading.set(false); return; } if let Err(_) = LocalStorage::set("caldav_credentials", &credentials) { error_message.set(Some("Failed to store credentials".to_string())); is_loading.set(false); return; } is_loading.set(false); on_login.emit(token); } Err(err) => { web_sys::console::log_1(&format!("❌ Login failed: {}", err).into()); error_message.set(Some(err)); is_loading.set(false); } } }); }) }; html! { } } /// Perform login using the CalDAV auth service async fn perform_login(server_url: String, username: String, password: String) -> Result<(String, String), String> { use crate::auth::{AuthService, CalDAVLoginRequest}; use serde_json; web_sys::console::log_1(&format!("📡 Creating auth service and request...").into()); let auth_service = AuthService::new(); let request = CalDAVLoginRequest { server_url: server_url.clone(), username: username.clone(), password: password.clone() }; web_sys::console::log_1(&format!("🚀 Sending login request to backend...").into()); match auth_service.login(request).await { Ok(response) => { web_sys::console::log_1(&format!("✅ Backend responded successfully").into()); // Create credentials object to store let credentials = serde_json::json!({ "server_url": server_url, "username": username, "password": password }); Ok((response.token, credentials.to_string())) }, Err(err) => { web_sys::console::log_1(&format!("❌ Backend error: {}", err).into()); Err(err) }, } }