pinakes/crates/pinakes-ui/src/components/login.rs
NotAShelf 3ccddce7fd
treewide: fix various UI bugs; optimize crypto dependencies & format
Signed-off-by: NotAShelf <raf@notashelf.dev>
Change-Id: If8fe8b38c1d9c4fecd40ff71f88d2ae06a6a6964
2026-03-06 18:29:33 +03:00

79 lines
2.5 KiB
Rust

use dioxus::prelude::*;
#[component]
pub fn Login(
on_login: EventHandler<(String, String)>,
#[props(default)] error: Option<String>,
#[props(default = false)] loading: bool,
) -> Element {
let mut username = use_signal(String::new);
let mut password = use_signal(String::new);
let on_submit = {
move |_| {
let u = username.read().clone();
let p = password.read().clone();
if !u.is_empty() && !p.is_empty() {
on_login.call((u, p));
}
}
};
let on_key = move |e: KeyboardEvent| {
if e.key() == Key::Enter {
let u = username.read().clone();
let p = password.read().clone();
if !u.is_empty() && !p.is_empty() {
on_login.call((u, p));
}
}
};
rsx! {
div { class: "login-container",
div { class: "login-card",
h2 { class: "login-title", "Pinakes" }
p { class: "login-subtitle", "Sign in to continue" }
if let Some(ref err) = error {
div { class: "login-error", "{err}" }
}
div { class: "login-form",
div { class: "form-group",
label { class: "form-label", "Username" }
input {
r#type: "text",
placeholder: "Enter username",
value: "{username}",
disabled: loading,
oninput: move |e: Event<FormData>| username.set(e.value()),
onkeypress: on_key,
}
}
div { class: "form-group",
label { class: "form-label", "Password" }
input {
r#type: "password",
placeholder: "Enter password",
value: "{password}",
disabled: loading,
oninput: move |e: Event<FormData>| password.set(e.value()),
onkeypress: on_key,
}
}
button {
class: "btn btn-primary login-btn",
disabled: loading,
onclick: on_submit,
if loading {
"Signing in..."
} else {
"Sign In"
}
}
}
}
}
}
}