93 lines
3.5 KiB
Rust
93 lines
3.5 KiB
Rust
use web_sys::HtmlInputElement;
|
|
use yew::prelude::*;
|
|
|
|
use crate::api;
|
|
|
|
#[derive(Properties, PartialEq)]
|
|
pub struct Props {
|
|
pub on_setup: Callback<()>,
|
|
}
|
|
|
|
#[function_component(SetupPage)]
|
|
pub fn setup_page(props: &Props) -> Html {
|
|
let username = use_state(String::new);
|
|
let password = use_state(String::new);
|
|
let confirm = use_state(String::new);
|
|
let error = use_state(|| None::<String>);
|
|
|
|
let on_submit = {
|
|
let username = username.clone();
|
|
let password = password.clone();
|
|
let confirm = confirm.clone();
|
|
let error = error.clone();
|
|
let on_setup = props.on_setup.clone();
|
|
Callback::from(move |e: SubmitEvent| {
|
|
e.prevent_default();
|
|
let u = (*username).clone();
|
|
let p = (*password).clone();
|
|
let c = (*confirm).clone();
|
|
let error = error.clone();
|
|
let on_setup = on_setup.clone();
|
|
|
|
if p != c {
|
|
error.set(Some("Passwords do not match".into()));
|
|
return;
|
|
}
|
|
if p.len() < 4 {
|
|
error.set(Some("Password must be at least 4 characters".into()));
|
|
return;
|
|
}
|
|
|
|
wasm_bindgen_futures::spawn_local(async move {
|
|
match api::setup(&u, &p).await {
|
|
Ok(_) => on_setup.emit(()),
|
|
Err(e) => error.set(Some(e.0)),
|
|
}
|
|
});
|
|
})
|
|
};
|
|
|
|
html! {
|
|
<div class="auth-page">
|
|
<div class="auth-card">
|
|
<h1>{ "Shanty" }</h1>
|
|
<p class="text-muted">{ "Create your admin account to get started" }</p>
|
|
|
|
if let Some(ref err) = *error {
|
|
<div class="error">{ err }</div>
|
|
}
|
|
|
|
<form onsubmit={on_submit}>
|
|
<div class="form-group">
|
|
<label>{ "Username" }</label>
|
|
<input type="text" autocomplete="username" value={(*username).clone()}
|
|
oninput={let u = username.clone(); Callback::from(move |e: InputEvent| {
|
|
let input: HtmlInputElement = e.target_unchecked_into();
|
|
u.set(input.value());
|
|
})} />
|
|
</div>
|
|
<div class="form-group">
|
|
<label>{ "Password" }</label>
|
|
<input type="password" autocomplete="new-password" value={(*password).clone()}
|
|
oninput={let p = password.clone(); Callback::from(move |e: InputEvent| {
|
|
let input: HtmlInputElement = e.target_unchecked_into();
|
|
p.set(input.value());
|
|
})} />
|
|
</div>
|
|
<div class="form-group">
|
|
<label>{ "Confirm Password" }</label>
|
|
<input type="password" autocomplete="new-password" value={(*confirm).clone()}
|
|
oninput={let c = confirm.clone(); Callback::from(move |e: InputEvent| {
|
|
let input: HtmlInputElement = e.target_unchecked_into();
|
|
c.set(input.value());
|
|
})} />
|
|
</div>
|
|
<button type="submit" class="btn btn-primary" style="width: 100%; margin-top: 1rem;">
|
|
{ "Create Admin Account" }
|
|
</button>
|
|
</form>
|
|
</div>
|
|
</div>
|
|
}
|
|
}
|