dialtone_yew 0.1.0

Dialtone Yew Webapp
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
}