use super::account::AccountRoute;
use super::register::RegisterRoute;
use crate::components::common::dt_button::*;
use crate::components::common::dt_input_password::*;
use crate::components::common::dt_input_text::*;
use crate::components::common::dt_status_text::*;
use crate::components::common::main_layout::*;
use crate::components::common::titled_panel::*;
use crate::utils::set_focus::set_focus;
use crate::AppSiteConnection;
use bounce::use_atom;
use bounce::UseAtomHandle;
use dialtone_common::utils::make_acct::make_acct;
use dialtone_reqwest::api_v1::users::authenticate::authenticate;
use std::rc::Rc;
use yew::prelude::*;
use yew_router::prelude::*;
struct LoginFormState {
pub history: AnyHistory,
pub disabled_login_button: UseStateHandle<bool>,
pub in_progress: UseStateHandle<bool>,
pub username: UseStateHandle<String>,
pub password: UseStateHandle<String>,
pub status_hidden: UseStateHandle<bool>,
pub sc_atom: UseAtomHandle<AppSiteConnection>,
}
#[function_component(Login)]
pub fn login() -> Html {
let form_state = Rc::new(LoginFormState {
history: use_history().unwrap(),
disabled_login_button: use_state(|| true),
in_progress: use_state(|| false),
username: use_state(|| "".to_string()),
password: use_state(|| "".to_string()),
status_hidden: use_state(|| true),
sc_atom: use_atom::<AppSiteConnection>(),
});
let on_button_click = {
let form_state = Rc::clone(&form_state);
Callback::from(move |_| {
let form_state = Rc::clone(&form_state);
form_state.in_progress.set(true);
form_state.status_hidden.set(true);
wasm_bindgen_futures::spawn_local(async move {
let sc = &form_state.sc_atom.0;
let authorized = authenticate(sc, &form_state.username, &form_state.password).await;
match authorized {
Ok(new_sc) => {
let acct =
make_acct(new_sc.user_name.as_ref().unwrap(), new_sc.host_name());
let app_site_connection = AppSiteConnection(new_sc);
let _ = &app_site_connection.save();
form_state.sc_atom.set(app_site_connection);
form_state.history.push(AccountRoute::Index { acct: acct });
}
Err(_) => {
form_state.status_hidden.set(false);
form_state.in_progress.set(false);
set_focus("login_username");
}
}
});
})
};
let on_username = {
let form_state = Rc::clone(&form_state);
Callback::from(move |s| {
form_state.username.set(s);
if !form_state.username.is_empty() && !form_state.password.is_empty() {
form_state.disabled_login_button.set(false);
}
})
};
let on_password = {
let form_state = Rc::clone(&form_state);
Callback::from(move |s| {
form_state.password.set(s);
if !form_state.username.is_empty() && !form_state.password.is_empty() {
form_state.disabled_login_button.set(false);
}
})
};
use_effect_with_deps(
move |_| {
set_focus("login_username");
|| ()
},
(),
);
let h = html! {
<MainLayout>
<div class="centered_form_page">
<TitledPanel title="Login">
<form class="basic_form"
onsubmit={Callback::from(|e: FocusEvent| e.prevent_default())}
autocomplete="off">
<label for="login_username">{"Username:"}</label>
<DtInputText
id="login_username"
disabled=false
name="login_username"
on_update_value={on_username}/>
<label for="login_password">{"Password:"}</label>
<DtInputPassword
id="login_password"
disabled=false name="login_password"
on_update_value={on_password}/>
<DtStatusText
hidden={*form_state.status_hidden}
status_type={StatusType::ERROR}>
{"LOGIN FAILED"}
</DtStatusText>
<DtButton
text="Login"
disabled={*form_state.disabled_login_button}
on_click={on_button_click.clone()}
id="login_button"
in_progress={*form_state.in_progress}/>
<span>
<Link<RegisterRoute>
classes={classes!("in_page_action")}
to={RegisterRoute::Index}>{"Register New Account"}
</Link<RegisterRoute>></span>
</form>
</TitledPanel>
</div>
</MainLayout>
};
h
}