Skip to content

Commit

Permalink
frontend: add a client redirect component (#664)
Browse files Browse the repository at this point in the history
* use relative link

* use redirect component

* use client redirect
  • Loading branch information
vnghia authored Jan 15, 2025
1 parent d7a47f1 commit 2b11df3
Show file tree
Hide file tree
Showing 11 changed files with 333 additions and 303 deletions.
24 changes: 12 additions & 12 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

14 changes: 0 additions & 14 deletions nghe-frontend/src/client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,6 @@ use codee::string::{FromToStringCodec, OptionCodec};
use concat_string::concat_string;
use gloo_net::http;
use leptos::prelude::*;
use leptos_router::NavigateOptions;
use leptos_router::hooks::use_navigate;
use leptos_use::storage::use_local_storage;
use nghe_api::common::{JsonEndpoint, JsonURL};
use uuid::Uuid;
Expand All @@ -18,8 +16,6 @@ pub struct Client {
impl Client {
const API_KEY_STORAGE_KEY: &'static str = "api-key";

pub const EXPECT_MSG: &'static str = "use_client_redirect should prevent this";

pub fn new(api_key: Uuid) -> Self {
Self { authorization: concat_string!("Bearer ", api_key.to_string()) }
}
Expand All @@ -36,16 +32,6 @@ impl Client {
Signal::derive(move || read_api_key.with(|api_key| api_key.map(Client::new)))
}

pub fn use_client_redirect() -> (Signal<Option<Client>>, RenderEffect<()>) {
let client = Self::use_client();
let effect = RenderEffect::new(move |_| {
if client.with(Option::is_none) {
use_navigate()("/login", NavigateOptions::default());
}
});
(client, effect)
}

async fn json_impl<R: JsonEndpoint>(
request: &R,
authorization: Option<&str>,
Expand Down
203 changes: 103 additions & 100 deletions nghe-frontend/src/components/authentication/login.rs
Original file line number Diff line number Diff line change
@@ -1,119 +1,122 @@
use leptos::either::Either;
use leptos::html;
use leptos::prelude::*;
use leptos_router::NavigateOptions;
use leptos_router::components::Redirect;
use nghe_api::key::create::Request;

use crate::client::Client;
use crate::components::form;

pub fn Login() -> impl IntoView {
let navigate = leptos_router::hooks::use_navigate();

let (read_api_key, set_api_key) = Client::use_api_key();
Effect::new(move || {
View::new(move || {
if read_api_key.with(Option::is_some) {
navigate("/", NavigateOptions::default());
}
});

let username = RwSignal::new(String::default());
let password = RwSignal::new(String::default());
let client = RwSignal::new(nghe_api::constant::SERVER_NAME.into());
Redirect(component_props_builder(&Redirect).path("/").build());
Either::Left(())
} else {
let username = RwSignal::new(String::default());
let password = RwSignal::new(String::default());
let client = RwSignal::new(nghe_api::constant::SERVER_NAME.into());

let (username_error, set_username_error) = signal(Option::default());
let (password_error, set_password_error) = signal(Option::default());
let (client_error, set_client_error) = signal(Option::default());
let (username_error, set_username_error) = signal(Option::default());
let (password_error, set_password_error) = signal(Option::default());
let (client_error, set_client_error) = signal(Option::default());

let login_action = Action::<_, _, SyncStorage>::new_unsync(move |request: &Request| {
let request = request.clone();
async move {
let api_key = Client::json_no_auth(&request).await?.api_key.api_key;
set_api_key(Some(api_key));
Ok(())
}
});
let login_action = Action::<_, _, SyncStorage>::new_unsync(move |request: &Request| {
let request = request.clone();
async move {
let api_key = Client::json_no_auth(&request).await?.api_key.api_key;
set_api_key(Some(api_key));
Ok(())
}
});

html::section().class("bg-gray-50 dark:bg-gray-900 w-full").child(
html::div()
.class(
"flex flex-col items-center justify-center px-6 py-8 mx-auto md:h-screen lg:py-0",
)
.child((
html::div()
.class(
"flex items-center mb-6 text-2xl font-semibold text-gray-900 \
dark:text-white",
)
.child("Nghe"),
form::Form(
"Login",
move || {
(
form::input::Text(
"username",
"Username",
"username",
None,
None,
username,
username_error,
),
form::input::Text(
"password",
"Password",
"password",
None,
None,
password,
password_error,
),
form::input::Text(
"client",
"Client",
"text",
None,
None,
client,
client_error,
),
Either::Right(
html::section().class("bg-gray-50 dark:bg-gray-900 w-full").child(
html::div()
.class(
"flex flex-col items-center justify-center px-6 py-8 mx-auto \
md:h-screen lg:py-0",
)
},
"Login",
move |_| {
let username = username();
let username_error = if username.is_empty() {
Some("Username could not be empty")
} else {
None
};
set_username_error(username_error);
.child((
html::div()
.class(
"flex items-center mb-6 text-2xl font-semibold text-gray-900 \
dark:text-white",
)
.child("Nghe"),
form::Form(
"Login",
move || {
(
form::input::Text(
"username",
"Username",
"username",
None,
None,
username,
username_error,
),
form::input::Text(
"password",
"Password",
"password",
None,
None,
password,
password_error,
),
form::input::Text(
"client",
"Client",
"text",
None,
None,
client,
client_error,
),
)
},
"Login",
move |_| {
let username = username();
let username_error = if username.is_empty() {
Some("Username could not be empty")
} else {
None
};
set_username_error(username_error);

let password = password();
let password_error = if password.len() < 8 {
Some("Password must have at least 8 characters")
} else {
None
};
set_password_error(password_error);
let password = password();
let password_error = if password.len() < 8 {
Some("Password must have at least 8 characters")
} else {
None
};
set_password_error(password_error);

let client = client();
let client_error = if client.is_empty() {
Some("Client could not be empty")
} else {
None
};
set_client_error(client_error);
let client = client();
let client_error = if client.is_empty() {
Some("Client could not be empty")
} else {
None
};
set_client_error(client_error);

if username_error.is_some()
|| password_error.is_some()
|| client_error.is_some()
{
return;
}
login_action.dispatch(Request { username, password, client });
},
login_action,
if username_error.is_some()
|| password_error.is_some()
|| client_error.is_some()
{
return;
}
login_action.dispatch(Request { username, password, client });
},
login_action,
),
)),
),
)),
)
)
}
})
}
Loading

0 comments on commit 2b11df3

Please sign in to comment.