setup.rs
⎇
Raw
1use leptos::prelude::*;
2use wasm_bindgen_futures::spawn_local;
3
4use crate::api::{self, input_value, Me};
5use crate::app::AuthPhase;
6
7#[component]
8pub fn SetupView(
9 set_me: WriteSignal<Option<Me>>,
10 set_phase: WriteSignal<AuthPhase>,
11) -> impl IntoView {
12 let (error, set_error) = signal(String::new());
13 let (busy, set_busy) = signal(false);
14
15 let on_submit = move |ev: web_sys::SubmitEvent| {
16 ev.prevent_default();
17 let name = input_value("setup-name");
18 let pass = input_value("setup-pass");
19 let confirm = input_value("setup-confirm");
20 let name = name.trim();
21
22 if name.is_empty() || name.len() > 64 {
23 set_error.set("Please choose a name (1–64 characters).".into());
24 return;
25 }
26 if pass.len() < 8 {
27 set_error.set("Password must be at least 8 characters.".into());
28 return;
29 }
30 if pass != confirm {
31 set_error.set("Passwords don't match.".into());
32 return;
33 }
34
35 set_error.set(String::new());
36 set_busy.set(true);
37 let (name, pass) = (name.to_string(), pass);
38 spawn_local(async move {
39 match api::setup(name, pass).await {
40 Ok(_) => match api::me().await {
41 Ok(m) => {
42 set_me.set(Some(m));
43 set_phase.set(AuthPhase::Authed);
44 }
45 Err(e) => {
46 set_error.set(e.to_string());
47 set_busy.set(false);
48 }
49 },
50 Err(e) => {
51 set_error.set(e.to_string());
52 set_busy.set(false);
53 }
54 }
55 });
56 };
57
58 view! {
59 <div class="center-screen">
60 <div class="card auth-card">
61 <h1>"filebrowser-ng"</h1>
62 <p class="muted">
63 "First boot: create the admin account. This user can manage
64 other users and server settings."
65 </p>
66 <form on:submit=on_submit>
67 <label class="field">
68 <span>"Name"</span>
69 <input
70 id="setup-name"
71 type="text"
72 autofocus=true
73 autocomplete="username"
74 />
75 </label>
76 <label class="field">
77 <span>"Password"</span>
78 <input
79 id="setup-pass"
80 type="password"
81 autocomplete="new-password"
82 />
83 </label>
84 <label class="field">
85 <span>"Repeat password"</span>
86 <input
87 id="setup-confirm"
88 type="password"
89 autocomplete="new-password"
90 />
91 </label>
92 <p class="error">{move || error.get()}</p>
93 <button class="btn-primary" type="submit" disabled=move || busy.get()>
94 "Create admin account"
95 </button>
96 </form>
97 </div>
98 </div>
99 }
100}
101