From 6dfa21a0059859bd4063309c9a9784a9e93fe188 Mon Sep 17 00:00:00 2001 From: schn33fuchs Date: Wed, 29 Apr 2026 20:41:31 +0200 Subject: [PATCH] Login and Showing of all Users implemented At /login and /users --- frontend/src/lib.rs | 8 +- frontend/src/pages/ticket.rs | 4 +- frontend/src/pages/user.rs | 141 +++++++++++++++++++++++++++++++++++ 3 files changed, 150 insertions(+), 3 deletions(-) diff --git a/frontend/src/lib.rs b/frontend/src/lib.rs index 330ad82..8b604c6 100644 --- a/frontend/src/lib.rs +++ b/frontend/src/lib.rs @@ -15,6 +15,10 @@ enum Route { AllTickets, #[at("/register")] Register, + #[at("/login")] + Login, + #[at("/users")] + AllUsers, #[not_found] #[at("/404")] NotFound, @@ -25,9 +29,11 @@ fn switch(route: Route) -> Html { Route::Home => html! { }, Route::NotFound => html! { }, Route::Ticket => html! { }, - Route::TicketById { id } => html! { }, + Route::TicketById { id } => html! { }, Route::AllTickets => html! { }, Route::Register => html! { }, + Route::Login => html! { }, + Route::AllUsers => html! {}, } } diff --git a/frontend/src/pages/ticket.rs b/frontend/src/pages/ticket.rs index fac1faa..4708c8e 100644 --- a/frontend/src/pages/ticket.rs +++ b/frontend/src/pages/ticket.rs @@ -156,8 +156,8 @@ pub fn submit_ticket_component() -> Html { } } -#[component(ShowTicketByID)] -pub fn show_ticket_by_id_component(props: &TicketProps) -> Html { +#[component(TicketByID)] +pub fn ticket_by_id_component(props: &TicketProps) -> Html { let ticket = use_state(|| None::); let error = use_state(|| None::); let loading = use_state(|| false); diff --git a/frontend/src/pages/user.rs b/frontend/src/pages/user.rs index 3e3743d..5d1ca48 100644 --- a/frontend/src/pages/user.rs +++ b/frontend/src/pages/user.rs @@ -1,6 +1,7 @@ use gloo_net::http::Request; use serde::{Deserialize, Serialize}; use wasm_bindgen_futures::spawn_local; +use web_sys::js_sys::Atomics::load; use yew::prelude::*; #[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] @@ -37,6 +38,11 @@ pub struct FilteredUser { pub is_admin: bool, } +#[derive(Properties, PartialEq)] +pub struct UserProps { + id: i16, +} + #[component(Register)] pub fn register_component() -> Html { let first_name = use_state(|| "".to_string()); @@ -146,3 +152,138 @@ pub fn register_component() -> Html { } } + +#[component(Login)] +pub fn login_component() -> Html { + let username = use_state(|| "".to_string()); + let pwd = use_state(|| "".to_string()); + let loading = use_state(|| false); + let error = use_state(|| String::new()); + let success = use_state(|| false); + + let onsubmit = { + let username = username.clone(); + let pwd = pwd.clone(); + let loading = loading.clone(); + let error = error.clone(); + let success = success.clone(); + + Callback::from(move |e: SubmitEvent| { + e.prevent_default(); + let username = (*username).clone(); + let pwd = (*pwd).clone(); + let loading = loading.clone(); + let error = error.clone(); + let success = success.clone(); + + loading.set(true); + error.set(String::new()); + success.set(false); + + spawn_local(async move { + let payload = LoginScheme { username, pwd }; + + let response = Request::post("/api/login") + .header("Content-Type", "application/json") + .credentials(web_sys::RequestCredentials::Include) + .json(&payload) + .unwrap() + .send() + .await; + + loading.set(false); + + match response { + Ok(r) if r.status() == 200 => success.set(true), + Ok(r) => { + let text = r.text().await.unwrap_or_else(|_| "unknown".into()); + error.set(format!("HTTP {}: {}", r.status(), text)); + } + Err(err) => error.set(format!("Network error: {}", err)), + } + }); + }) + }; + + html! { +
+ + + + if *success {

{"Logged in — cookie set by server"}

} + if !error.is_empty() {

{(*error).clone()}

} +
+ } +} + +#[component(AllUsers)] +pub fn all_users_component() -> Html { + let users = use_state(|| Vec::::new()); + let error = use_state(|| None::); + let loading = use_state(|| false); + + { + let users = users.clone(); + let error = error.clone(); + let loading = loading.clone(); + + use_effect_with((), move |_| { + loading.set(true); + spawn_local(async move { + let url = format!("/api/users"); + match Request::get(&url).send().await { + Ok(response) if response.status() == 200 => { + match response.json::>().await { + Ok(u) => users.set(u), + Err(err) => error.set(Some(format!("Parse error: {}", err))), + } + } + Ok(response) => { + if let Ok(text) = response.text().await { + error.set(Some(text)); + } else { + error.set(Some(format!("status {}", response.status()))); + } + } + Err(err) => error.set(Some(format!("Network error: {}", err))), + } + loading.set(false); + }); + || () + }); + } + + if *loading { + html! {

{ "Loading" }

} + } else if let Some(e) = &*error { + html! {

{ format!("Error: {}", e) }

} + } else { + html! { +
    + { for users.iter().map(|t| html! { +
  • +

    { format!("{} {}- #{}", t.first_name, t.last_name, t.id) }

    +
  • + })} +
+ } + } +} + +//#[component(UserByID)] +//pub fn user_by_id_component()