login.rs
⎇
Raw
1use crate::i18n;
2use leptos::prelude::*;
3use wasm_bindgen_futures::spawn_local;
4
5use crate::api::{self, Me, input_value};
6use crate::app::AuthPhase;
7use crate::components::logo::Logo;
8
9#[component]
10pub fn LoginView(
11 set_me: WriteSignal<Option<Me>>,
12 set_phase: WriteSignal<AuthPhase>,
13) -> impl IntoView {
14 let (error, set_error) = signal(String::new());
15 let (busy, set_busy) = signal(false);
16
17 let on_submit = move |ev: web_sys::SubmitEvent| {
18 ev.prevent_default();
19 let name = input_value("login-name");
20 let pass = input_value("login-pass");
21 if name.trim().is_empty() || pass.is_empty() {
22 set_error.set(i18n::t(i18n::k::LOGIN_ERROR).into());
23 return;
24 }
25 set_error.set(String::new());
26 set_busy.set(true);
27 let name = name.trim().to_string();
28 spawn_local(async move {
29 match api::login(name, pass).await {
30 Ok(_) => match api::me().await {
31 Ok(m) => {
32 // Keep the current hash: deep links (e.g. #/users) survive
33 // the sign-in. A non-admin landing on an admin section is
34 // redirected to the files view by the shell instead.
35 set_me.set(Some(m));
36 set_phase.set(AuthPhase::Authed);
37 }
38 Err(e) => {
39 set_error.set(e.to_string());
40 set_busy.set(false);
41 }
42 },
43 Err(e) => {
44 set_error.set(e.to_string());
45 set_busy.set(false);
46 }
47 }
48 });
49 };
50
51 view! {
52 <div class="center-screen">
53 <div class="card auth-card">
54 <Logo class="auth-logo".to_string()/>
55 <h1>"filebrowser-ng"</h1>
56 <p class="muted">{i18n::tr(i18n::k::LOGIN_SUBTITLE)}</p>
57 <form on:submit=on_submit>
58 <label class="field">
59 <span>{i18n::tr(i18n::k::NAME)}</span>
60 <input
61 id="login-name"
62 type="text"
63 autofocus=true
64 autocomplete="username"
65 />
66 </label>
67 <label class="field">
68 <span>{i18n::tr(i18n::k::PASSWORD)}</span>
69 <input
70 id="login-pass"
71 type="password"
72 autocomplete="current-password"
73 />
74 </label>
75 <p class="error">{move || error.get()}</p>
76 <button class="btn-primary" type="submit" disabled=move || busy.get()>
77 {i18n::tr(i18n::k::SIGN_IN)}
78 </button>
79 </form>
80 </div>
81 </div>
82 }
83}
84