Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion leptos/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,11 @@ edition = "2024"
[dependencies]
codee = { version = "0.3.0", features = ["json_serde"] }
console_error_panic_hook = "0.1.7"
leptos = { version = "0.7.7", features = ["csr", "nightly"] }
leptos = { version = "0.7.7", features = ["csr", "nightly", "tracing"] }
leptos-use = { version = "0.15.7", features = ["storage", "docs" ] }
leptos_meta = "0.7.7"
leptos_router = { version = "0.7.7", features = ["tracing"] }
reactive_stores = "0.1.8"
serde = { workspace = true, features = ["derive"] }
stylance = "0.5.5"
thaw = { version = "0.4.4", features = ["csr", "nightly"] }
Expand Down
6 changes: 6 additions & 0 deletions leptos/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -5,5 +5,11 @@ fmt:
# cargo +nightly fmt
leptosfmt src

check:
cargo clippy --no-deps -- -Dwarnings

fix: fmt
cargo clippy --fix --allow-dirty

css:
stylance . --output-file app.css
11 changes: 8 additions & 3 deletions leptos/app.css
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
// This file is generated from ./src/app.module.scss
.header-bb66a2d {
.header-372e0a1 {
}

body {
Expand All @@ -12,11 +12,16 @@ main {
margin: 1ex;
}

.nav-bb66a2d {
.nav-372e0a1 {
display: flex;
flex-direction: row;
}

.nav-bb66a2d a {
.nav-372e0a1 a {
margin: 1ex;
}

.login-372e0a1 {
max-width: 30em;
margin: auto;
}
2 changes: 0 additions & 2 deletions leptos/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,12 @@
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<link data-trunk rel="css" href="app.css" />
<!--
<link
href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/css/bootstrap.min.css"
rel="stylesheet"
integrity="sha384-QWTKZyjpPEjISv5WaRU9OFeRpok6YctnYmDr5pNlyT2bRjXh0JMhjY6hW+ALEwIH"
crossorigin="anonymous"
/>
-->
</head>
<body></body>
</html>
5 changes: 5 additions & 0 deletions leptos/src/app.module.scss → leptos/src/_app.module.scss
Original file line number Diff line number Diff line change
Expand Up @@ -20,3 +20,8 @@ main {
.nav a {
margin: 1ex;
}

.login {
max-width: 30em;
margin: auto;
}
28 changes: 12 additions & 16 deletions leptos/src/app.rs
Original file line number Diff line number Diff line change
@@ -1,35 +1,31 @@
use leptos::prelude::*;
use leptos_router::components::{Route, Router, Routes};
use leptos_router::path;
use leptos_use::storage::use_local_storage;
use codee::string::JsonSerdeCodec;
use reactive_stores::Store;
use thaw::*;

use crate::components::home;
use crate::storage::AppState;

stylance::import_crate_style!( #[allow(dead_code)] app_style, "src/app.module.scss");
use crate::components::{home, login};
use crate::storage::GlobalState;

#[component]
pub fn App() -> impl IntoView {

let (storage_email, _set_storage_email) = signal("email".to_string());
let (_state, _set_state, _reset) = use_local_storage::<AppState, JsonSerdeCodec>(storage_email);

let theme = RwSignal::new(Theme::light());

provide_context(Store::new(GlobalState::default()));

view! {
<Router>
<h1>"Leptos App"</h1>
<nav class=app_style::nav>
<a href="/">"Home"</a>
<a href="/ehr/form">"EHR Form"</a>
</nav>
<h3>"Rusty App"</h3>
<ConfigProvider theme>
<nav class=crate::css::styles::nav>
<a href="/">"Home"</a>
<a href="/form">"Form"</a>
<a href="/login">"Login"</a>
</nav>
<main>
<Routes fallback=|| "not found.">
<Route path=path!("/") view=home::Home />
<Route path=path!("/ehr/form") view=home::Home />
<Route path=path!("/login") view=login::Login />
</Routes>
</main>
</ConfigProvider>
Expand Down
24 changes: 10 additions & 14 deletions leptos/src/components/home.rs
Original file line number Diff line number Diff line change
@@ -1,23 +1,19 @@
use leptos::prelude::*;
use leptos::logging::log;
use thaw::*;
use reactive_stores::Store;

use crate::components::login::{AlreadyLoggedIn, Login};
use crate::storage::{GlobalState, GlobalStateStoreFields};

#[component]
pub fn Home() -> impl IntoView {
let state = expect_context::<Store<GlobalState>>();

let email = RwSignal::new(String::from(""));
let password = RwSignal::new(String::from(""));

let login_clicked = move |_| {
log!("Login button is clicked");
log!("Email={} and password={}", email.get(), password.get());
};
let logged_in = state.is_logged_in();
tracing::info!("Already logged in? {}", logged_in.get_untracked());

view! {
<Flex vertical=true>
<Input value=email placeholder="Email" />
<Input value=password input_type=InputType::Password placeholder="OTP/API Key" />
<Button on_click=login_clicked>"Login"</Button>
</Flex>
<Show when=move || !logged_in.get() fallback=|| view! { <AlreadyLoggedIn /> }>
<Login />
</Show>
}
}
51 changes: 51 additions & 0 deletions leptos/src/components/login.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
// use codee::string::JsonSerdeCodec;
use leptos::prelude::*;
// use leptos_use::storage::use_local_storage;
use reactive_stores::Store;
use thaw::*;

use crate::css::styles;
use crate::storage::{GlobalState, GlobalStateStoreFields};

#[component]
pub fn Login() -> impl IntoView {
let state = expect_context::<Store<GlobalState>>();
let logged_in = state.is_logged_in();
let email = state.email();
let password = state.api_key();

let login_clicked = move |_| {
tracing::debug!("Login button is clicked. Email={}", email.get_untracked());
tracing::info!("TODO: implement the login flow here");

*logged_in.write() = true;
};

view! {
<Flex vertical=true class=styles::login>
<Input value=email placeholder="Email" />
<Input value=password input_type=InputType::Password placeholder="OTP/API Key" />
<Button on_click=login_clicked>"Login"</Button>
</Flex>
}
}

#[component]
pub fn AlreadyLoggedIn() -> impl IntoView {
let state = expect_context::<Store<GlobalState>>();
let logged_in = state.is_logged_in();
let email = state.email();
let password = state.api_key();

let logout = move |_| {
tracing::info!("Starting logout...");
*email.write() = String::default();
*password.write() = String::default();
*logged_in.write() = false;
};

view! {
<div>"Already logged in"</div>
<Button on_click=logout>"Logout"</Button>
}
}
1 change: 1 addition & 0 deletions leptos/src/components/mod.rs
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
pub(crate) mod home;
pub(crate) mod login;
3 changes: 3 additions & 0 deletions leptos/src/css.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
//! css module.

stylance::import_crate_style!( #[allow(dead_code)] pub styles, "src/_app.module.scss");
4 changes: 3 additions & 1 deletion leptos/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,13 @@ use tracing_subscriber::fmt;
use tracing_subscriber_wasm::MakeConsoleWriter;

mod app;
mod storage;
mod components;
mod css;
mod storage;

fn main() {
fmt()
.with_ansi(false)
.with_writer(MakeConsoleWriter::default().map_trace_level_to(tracing::Level::DEBUG))
// For some reason, if we don't do this in the browser, we get a runtime error.
.without_time()
Expand Down
24 changes: 22 additions & 2 deletions leptos/src/storage.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,26 @@
//! Storage
//! Various storage

#![allow(dead_code)]

use reactive_stores::Store;

#[derive(serde::Serialize, serde::Deserialize, Clone, PartialEq, Default)]
pub struct AppState {
pub(crate) struct LocalStorage {
pub trainer: String,
}

impl LocalStorage {
/// Key to use in local storage
pub const KEY: &'static str = "login-state";
}

/// Global state to be shared across components.
#[derive(Clone, Debug, Default, Store)]
pub struct GlobalState {
/// Current user email.
pub email: String,
/// API Key
pub api_key: String,
/// Is user logged in
pub is_logged_in: bool,
}
12 changes: 12 additions & 0 deletions rustfmt.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
newline_style = "unix"
use_field_init_shorthand = true
use_try_shorthand = true

indent_style = "Block"
group_imports = "StdExternalCrate"
# report_todo = "Always"
# report_fixme = "Always"
unstable_features = true
format_strings = true
imports_granularity = "Module"
wrap_comments = true
Loading