diff --git a/Cargo.lock b/Cargo.lock index 78e41a3..0ea1c2d 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1309,8 +1309,19 @@ version = "0.0.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f41f2deec9249d16ef6b1a8442fbe16013f67053797052aa0b7d2f5ebd0f0098" dependencies = [ + "icondata_ai", "icondata_bs", "icondata_core", + "icondata_io", +] + +[[package]] +name = "icondata_ai" +version = "0.0.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c8fe5fa2eed7715d5388e046d97f09d3baddd155b487454eb9cda3168c79d4b" +dependencies = [ + "icondata_core", ] [[package]] @@ -1328,6 +1339,15 @@ version = "0.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1640a4c1d5ddd08ab1d9854ffa7a2fa3dc52339492676b6d3031e77ca579f434" +[[package]] +name = "icondata_io" +version = "0.0.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "134d9fb91cdd0e7ac971199e2c8c8eb917a975faeeee54b227a0068c4f70c886" +dependencies = [ + "icondata_core", +] + [[package]] name = "ident_case" version = "1.0.1" diff --git a/Cargo.toml b/Cargo.toml index 6b8531e..659bfc4 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -22,7 +22,10 @@ leptos_icons = { version = "0.1.0", default_features = false, features = [ "BsPlayFill", "BsPauseFill", "BsSkipStartFill", - "BsSkipEndFill" + "BsSkipEndFill", + "IoReturnUpBackSharp", + "AiEyeFilled", + "AiEyeInvisibleFilled" ] } dotenv = { version = "0.15.0", optional = true } diesel = { version = "2.1.4", features = ["postgres", "r2d2", "time"], optional = true } diff --git a/src/app.rs b/src/app.rs index ae1aa39..5955bb5 100644 --- a/src/app.rs +++ b/src/app.rs @@ -1,6 +1,8 @@ use leptos::*; use leptos_meta::*; use leptos_router::*; +use crate::pages::login::*; +use crate::pages::signup::*; #[component] pub fn App() -> impl IntoView { @@ -21,6 +23,8 @@ pub fn App() -> impl IntoView { + + diff --git a/src/lib.rs b/src/lib.rs index 1897b87..f73732d 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -5,6 +5,7 @@ pub mod playstatus; pub mod playbar; pub mod database; pub mod models; +pub mod pages; pub mod users; pub mod search; use cfg_if::cfg_if; diff --git a/src/pages.rs b/src/pages.rs new file mode 100644 index 0000000..40f63fd --- /dev/null +++ b/src/pages.rs @@ -0,0 +1,2 @@ +pub mod login; +pub mod signup; \ No newline at end of file diff --git a/src/pages/login.rs b/src/pages/login.rs new file mode 100644 index 0000000..0d55a26 --- /dev/null +++ b/src/pages/login.rs @@ -0,0 +1,91 @@ +use crate::auth::login; +use leptos::leptos_dom::*; +use leptos::*; +use leptos_icons::AiIcon::*; +use leptos_icons::IoIcon::*; +use leptos_icons::*; + +#[component] +pub fn Login() -> impl IntoView { + let (username_or_email, set_username_or_email) = create_signal("".to_string()); + let (password, set_password) = create_signal("".to_string()); + + let (show_password, set_show_password) = create_signal(false); + + let toggle_password = move |_| { + set_show_password.update(|show_password| *show_password = !*show_password); + log!("showing password"); + }; + + let on_submit = move |ev: leptos::ev::SubmitEvent| { + ev.prevent_default(); + + let username_or_email1 = username_or_email.get(); + let password1 = password.get(); + + spawn_local(async move { + let login_result = login(username_or_email1, password1).await; + if let Err(err) = login_result { + // Handle the error here, e.g., log it or display to the user + log!("Error logging in: {:?}", err); + } else if let Ok(true) = login_result { + // Redirect to the login page + log!("Logged in Successfully!"); + leptos_router::use_navigate()("/", Default::default()); + log!("Navigated to home page after login"); + } else if let Ok(false) = login_result { + log!("Invalid username or password"); + } + }); + }; + + view! { +
+
+ +
+

LibreTunes

+
+ +
+
+ } +} diff --git a/src/pages/signup.rs b/src/pages/signup.rs new file mode 100644 index 0000000..c2de8f8 --- /dev/null +++ b/src/pages/signup.rs @@ -0,0 +1,104 @@ +use crate::auth::signup; +use crate::models::User; +use leptos::ev::input; +use leptos::leptos_dom::*; +use leptos::*; +use leptos_icons::AiIcon::*; +use leptos_icons::IoIcon::*; +use leptos_icons::*; + +#[component] +pub fn Signup() -> impl IntoView { + let (username, set_username) = create_signal("".to_string()); + let (email, set_email) = create_signal("".to_string()); + let (password, set_password) = create_signal("".to_string()); + + let (show_password, set_show_password) = create_signal(false); + + let navigate = leptos_router::use_navigate(); + + let toggle_password = move |_| { + set_show_password.update(|show_password| *show_password = !*show_password); + log!("showing password"); + }; + + let on_submit = move |ev: leptos::ev::SubmitEvent| { + ev.prevent_default(); + let new_user = User { + id: None, + username: username.get(), + email: email.get(), + password: Some(password.get()), + created_at: None, + }; + log!("new user: {:?}", new_user); + + spawn_local(async move { + if let Err(err) = signup(new_user).await { + // Handle the error here, e.g., log it or display to the user + log!("Error signing up: {:?}", err); + } else { + // Redirect to the login page + log!("Signed up successfully!"); + leptos_router::use_navigate()("/", Default::default()); + log!("Navigated to home page after signup") + } + }); + }; + + view! { +
+
+ +
+

LibreTunes

+
+ +
+
+ } +} diff --git a/style/login.scss b/style/login.scss new file mode 100644 index 0000000..e694d3a --- /dev/null +++ b/style/login.scss @@ -0,0 +1,151 @@ +@import "theme.scss"; + +.login-container { + display: flex; + flex-direction: column; + align-items: center; + position: fixed; + top: 50%; + left: 50%; + width: 27rem; + height: 30rem; + transform: translate(-50%, -50%); + background: $auth-containers; + z-index: 1; + border-radius: 8px; + overflow: hidden; +} + +.login-container .header h1 { + margin-top: 3rem; + font-size: 2.5rem; + color: $accent-color; +} +.login-container .login-form { + width: 75%; +} +.login-form .input-box:first-child { + margin-top: 1rem; +} +.login-form .input-box { + position: relative; + margin-top: 3rem; +} +.login-form .input-box input { + position: relative; + width: 100%; + max-width: 34vw; + padding: 17px 0px 10px; + background: transparent; + outline: none; + border: none; + box-shadow: none; + color: #23242a; + font-size: 1.1em; + font-family: "Roboto", sans-serif; + font-weight: 400; + letter-spacing: 0px; + text-indent: 10px; + vertical-align: middle; + z-index: 10; + color: #fff; +} +.login-form .input-box span { + position: absolute; + left: 0; + padding: 15px 0px 10px; + pointer-events: none; + color: black; + font-size: 1.19em; + letter-spacing: 0.5px; + transition: 0.5s; +} +.login-form .input-box input:valid ~ span, +.login-form .input-box input:focus ~ span { + color: rgb(94, 93, 93); + font-size: 0.9rem; + transform: translateY(-30px); + font-weight: 400; +} +.login-form .input-box i { + position: absolute; + left: 0; + bottom: 0; + width: 100%; + height: 2px; + background: $auth-inputs; + border-radius: 4px; + overflow: hidden; + transition: 0.5s; + pointer-events: none; +} + +.login-form .input-box input:valid ~ i, +.login-form .input-box input:focus ~ i { + height: 2.6rem; +} +.login-form .forgot-pw { + display: inline-flex; + margin-top: 3px; + font-size: 0.9rem; + cursor: pointer; + color: #8f8f8f; + text-decoration: underline; +} +.login-form .forgot-pw:hover { + color: #fff; + transition: all 0.2s; +} +.login-form input[type="submit"] { + margin-top: 3rem; + width: 100%; + height: 3rem; + border: none; + border-radius: 8px; + color: rgb(210, 207, 207); + cursor: pointer; + font-size: 1.1rem; + font-weight: 600; + background-color: $accent-color; +} +.login-form .go-to-signup { + color: #8f8f8f; + font-size: 0.9rem; +} +.login-form .go-to-signup a { + cursor: pointer; + color: #8f8f8f; + text-decoration: underline; +} +.login-form .go-to-signup a:hover { + color: black; + transition: all 0.2s; +} +.login-container .return { + position: absolute; + left: 10px; + top: 10px; + font-size: 1.8rem; + color: white; + cursor: pointer; + transition: all 0.3s; + border-radius: 8px; + display: flex; + align-items: center; + justify-content: center; + padding: 0.3rem; +} +.login-container .return:hover { + background-color: rgba(0, 0, 0, 0.4); +} +.login-password-visibility { + position: absolute; + font-size: 1.7rem; + top: 28%; + right: 5px; + z-index: 5; + cursor: pointer; + border: none; + background-color: transparent; + color: white; +} diff --git a/style/main.scss b/style/main.scss index e49fe50..60b68fd 100644 --- a/style/main.scss +++ b/style/main.scss @@ -1,5 +1,7 @@ @import 'playbar.scss'; @import 'theme.scss'; +@import 'login.scss'; +@import 'signup.scss'; body { font-family: sans-serif; diff --git a/style/signup.scss b/style/signup.scss new file mode 100644 index 0000000..30f87dc --- /dev/null +++ b/style/signup.scss @@ -0,0 +1,151 @@ +@import "theme.scss"; + +.auth-page-container { + display: flex; + justify-content: center; + align-items: center; + width: 100%; + height: 100vh; + background-color: black; +} + +.signup-container { + display: flex; + flex-direction: column; + align-items: center; + position: fixed; + top: 50%; + left: 50%; + width: 27rem; + height: 35rem; + transform: translate(-50%, -50%); + background: $auth-containers; + z-index: 1; + border-radius: 8px; + overflow: hidden; +} +.signup-container .header h1 { + margin-top: 3rem; + font-size: 2.5rem; + color: $accent-color; +} +.signup-container .signup-form { + width: 80%; +} +.signup-form .input-box { + position: relative; + margin-top: 3rem; +} +.signup-form .input-box:first-child { + margin-top: 0.7rem; +} +.signup-form .input-box input { + position: relative; + width: 100%; + max-width: 34vw; + padding: 17px 0px 10px; + background: transparent; + outline: none; + border: none; + box-shadow: none; + color: #23242a; + font-size: 1.1em; + font-family: "Roboto", sans-serif; + font-weight: 400; + letter-spacing: 0px; + text-indent: 10px; + vertical-align: middle; + z-index: 10; + color: #fff; +} +.signup-form .input-box span { + position: absolute; + left: 0; + padding: 15px 0px 10px; + pointer-events: none; + color: black; + font-size: 1.19em; + letter-spacing: 0.5px; + transition: 0.5s; +} +.signup-form .input-box input:valid ~ span, +.signup-form .input-box input:focus ~ span { + color: rgb(94, 93, 93); + font-size: 0.9rem; + transform: translateY(-30px); + font-weight: 400; +} +.signup-form .input-box i { + position: absolute; + left: 0; + bottom: 0; + width: 100%; + height: 2px; + background: $auth-inputs; + border-radius: 4px; + overflow: hidden; + transition: 0.5s; + pointer-events: none; +} + +.signup-form .input-box input:valid ~ i, +.signup-form .input-box input:focus ~ i { + height: 2.6rem; +} + +.signup-form input[type="submit"] { + margin-top: 3.5rem; + width: 100%; + height: 45px; + border: none; + border-radius: 8px; + color: white; + cursor: pointer; + font-size: 1.1rem; + font-weight: 600; + background-color: $accent-color; +} +.signup-form .go-to-login { + color: #8f8f8f; + font-size: 0.9rem; +} +.signup-form .go-to-login a { + cursor: pointer; + color: #8f8f8f; + text-decoration: underline; +} +.signup-form .go-to-login a:hover { + color: black; + transition: all 0.2s; +} +.signup-container .return { + position: absolute; + left: 10px; + top: 10px; + font-size: 1.8rem; + color: white; + cursor: pointer; + transition: all 0.3s; + border-radius: 8px; + display: flex; + align-items: center; + justify-content: center; + padding: 0.3rem; +} +.signup-container .return:hover { + background-color: rgba(0, 0, 0, 0.4); +} +.password-visibility { + position: absolute; + font-size: 1.7rem; + top: 28%; + right: 5px; + z-index: 5; + cursor: pointer; + border: none; + background-color: transparent; + color: white; +} +.pw-requirements { + font-size: 0.7rem; +} diff --git a/style/theme.scss b/style/theme.scss index 9ac5872..3e5d81c 100644 --- a/style/theme.scss +++ b/style/theme.scss @@ -6,3 +6,6 @@ $controls-click-color: #909090; $play-bar-background-color: #212121; $play-grad-start: #0a0533; $play-grad-end: $accent-color; + +$auth-inputs: #796dd4; +$auth-containers: white;