Don't load local card info by default, add user page, theme loading
This commit is contained in:
@@ -102,13 +102,18 @@ pub fn Header<G: Html>(cx: Scope, props: HeaderProps) -> View<G> {
|
||||
}
|
||||
// Title
|
||||
div (class="navbar-center lg:flex") {
|
||||
(props.content_state.to_string())
|
||||
// (props.content_state.to_string())
|
||||
}
|
||||
// User buttons
|
||||
div (class="navbar-end") {
|
||||
(match *global_state.auth.state.get() {
|
||||
LoginState::Authenticated => { view! { cx,
|
||||
button(on:click = handle_log_out, class = "btn btn-primary mr-2") {
|
||||
a (href = "user") {
|
||||
button (class = "btn mr-2") {
|
||||
"Preferences"
|
||||
}
|
||||
}
|
||||
button(on:click = handle_log_out, class = "btn btn-secondary mr-2") {
|
||||
"Log out"
|
||||
}
|
||||
} },
|
||||
@@ -121,7 +126,7 @@ pub fn Header<G: Html>(cx: Scope, props: HeaderProps) -> View<G> {
|
||||
}
|
||||
} },
|
||||
LoginState::Unknown => { view! { cx,
|
||||
div (class = "px-5 py-2.5 me-2 mb-2") {
|
||||
p {
|
||||
"Loading..."
|
||||
}
|
||||
} },
|
||||
|
||||
@@ -65,8 +65,9 @@ pub fn Layout<'a, G: Html>(
|
||||
spawn_local_scoped(cx, async move {
|
||||
let global_state = Reactor::<G>::from_cx(cx).get_global_state::<AppStateRx>(cx);
|
||||
|
||||
let local_card_user_pref = (*global_state.user_pref.local_card_data.get()).clone();
|
||||
let card_table_loaded = (*global_state.constants.is_loaded.get()).clone();
|
||||
if !card_table_loaded {
|
||||
if local_card_user_pref && !card_table_loaded {
|
||||
let client = reqwest::Client::new();
|
||||
let response = client
|
||||
.get(get_api_path(CARD_INFO).as_str())
|
||||
@@ -88,12 +89,12 @@ pub fn Layout<'a, G: Html>(
|
||||
|
||||
// Modals
|
||||
section(class = "flex-2") {
|
||||
(match (*global_state.constants.card_table.get()).clone() {
|
||||
Some(card_table) => { view!{ cx,
|
||||
p { "DONE" }
|
||||
} },
|
||||
None => { view!{ cx, p { "Loading cards" } } },
|
||||
})
|
||||
// (match (*global_state.constants.card_table.get()).clone() {
|
||||
// Some(card_table) => { view!{ cx,
|
||||
// p { "DONE" }
|
||||
// } },
|
||||
// None => { view!{ cx, p { "Loading cards" } } },
|
||||
// })
|
||||
|
||||
(match *global_state.modals_open.login.get() {
|
||||
OpenState::Open => {
|
||||
@@ -141,12 +142,10 @@ pub fn Layout<'a, G: Html>(
|
||||
|
||||
main(style = "my-8") {
|
||||
(match content_state {
|
||||
ContentState::None => view!{ cx, },
|
||||
ContentState::Tournaments => view!{ cx, },
|
||||
ContentState::Inventory => view!{ cx,
|
||||
// Body header
|
||||
div (class = "container mx-auto px-6 py-3") {
|
||||
nav (class = "sm:flex sm:justify-center sm:items-center mt-4 hidden") {
|
||||
nav (class = "sm:flex sm:justify-center sm:items-center mt-4") {
|
||||
div (class = "flex flex-col sm:flex-row"){
|
||||
a(href = "inventory",
|
||||
class = "mt-3 text-gray-600 hover:underline sm:mx-3 sm:mt-0"
|
||||
@@ -163,6 +162,7 @@ pub fn Layout<'a, G: Html>(
|
||||
}
|
||||
}
|
||||
},
|
||||
_ => view!{ cx, },
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,12 +6,14 @@ use serde::{Deserialize, Serialize};
|
||||
use crate::{
|
||||
models::{auth::WebAuthInfo, card::CardTable},
|
||||
state_enums::{LoginState, OpenState},
|
||||
DEFAULT_THEME,
|
||||
};
|
||||
|
||||
|
||||
#[derive(Serialize, Deserialize, ReactiveState, Clone)]
|
||||
#[rx(alias = "AppStateRx")]
|
||||
pub struct AppState {
|
||||
#[rx(nested)]
|
||||
pub user_pref: UserPreferences,
|
||||
#[rx(nested)]
|
||||
pub constants: ConstData,
|
||||
#[rx(nested)]
|
||||
@@ -22,6 +24,12 @@ pub struct AppState {
|
||||
pub style: StyleData,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, ReactiveState, Clone)]
|
||||
#[rx(alias = "UserPreferencesRx")]
|
||||
pub struct UserPreferences {
|
||||
pub local_card_data: bool,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, ReactiveState, Clone)]
|
||||
#[rx(alias = "ConstDataRx")]
|
||||
pub struct ConstData {
|
||||
@@ -68,9 +76,12 @@ pub fn get_global_state_creator() -> GlobalStateCreator {
|
||||
#[engine_only_fn]
|
||||
pub async fn get_build_state() -> AppState {
|
||||
AppState {
|
||||
user_pref: UserPreferences {
|
||||
local_card_data: false,
|
||||
},
|
||||
constants: ConstData {
|
||||
is_loaded: false,
|
||||
card_table: None
|
||||
card_table: None,
|
||||
},
|
||||
auth: AuthData {
|
||||
state: LoginState::Unknown,
|
||||
@@ -86,8 +97,8 @@ pub async fn get_build_state() -> AppState {
|
||||
},
|
||||
style: StyleData {
|
||||
theme: ThemeData {
|
||||
current: "luxury".to_owned(),
|
||||
default: "luxury".to_owned(),
|
||||
current: DEFAULT_THEME.to_owned(),
|
||||
default: DEFAULT_THEME.to_owned(),
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
23
src/main.rs
23
src/main.rs
@@ -14,6 +14,9 @@ mod templates;
|
||||
use perseus::prelude::*;
|
||||
use sycamore::prelude::view;
|
||||
|
||||
// TODO -> save theme in where changed
|
||||
const DEFAULT_THEME: &str = "light";
|
||||
|
||||
cfg_if::cfg_if! {
|
||||
if #[cfg(engine)] {
|
||||
use std::net::SocketAddr;
|
||||
@@ -72,18 +75,36 @@ pub fn main<G: Html>() -> PerseusApp<G> {
|
||||
.global_state_creator(crate::global_state::get_global_state_creator())
|
||||
.template(crate::templates::index::get_template())
|
||||
.template(crate::templates::inventory::index::get_template())
|
||||
.template(crate::templates::user::index::get_template())
|
||||
.capsule_ref(&*crate::capsules::login_form::LOGIN_FORM)
|
||||
.capsule_ref(&*crate::capsules::forgot_password_form::FORGOT_PASSWORD_FORM)
|
||||
.capsule_ref(&*crate::capsules::register_form::REGISTER_FORM)
|
||||
.error_views(crate::error_views::get_error_views())
|
||||
.index_view(|cx| {
|
||||
view! { cx,
|
||||
html (class = "flex w-full h-full", data-theme = "luxury"){
|
||||
html (class = "flex w-full h-full", data-theme = DEFAULT_THEME){
|
||||
head {
|
||||
meta(charset = "UTF-8")
|
||||
meta(name = "viewport", content = "width=device-width, initial-scale=1.0")
|
||||
// Perseus automatically resolves `/.perseus/static/` URLs to the contents of the `static/` directory at the project root
|
||||
link(rel = "stylesheet", href = ".perseus/static/style.css")
|
||||
|
||||
script {
|
||||
(format!(
|
||||
"
|
||||
function setTheme() {{
|
||||
const theme = localStorage.getItem(\"theme\");
|
||||
const element = document.documentElement;
|
||||
if (theme === null) {{
|
||||
element.setAttribute(\"data-theme\", \"{}\");
|
||||
}} else {{
|
||||
element.setAttribute(\"data-theme\", theme);
|
||||
}}
|
||||
}}
|
||||
setTheme();
|
||||
"
|
||||
, DEFAULT_THEME))
|
||||
}
|
||||
}
|
||||
body (class = "w-full"){
|
||||
// Quirk: this creates a wrapper `<div>` around the root `<div>` by necessity
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
pub mod auth;
|
||||
pub mod card;
|
||||
pub mod generic;
|
||||
pub mod theme;
|
||||
pub mod user;
|
||||
|
||||
7
src/models/theme.rs
Normal file
7
src/models/theme.rs
Normal file
@@ -0,0 +1,7 @@
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
#[derive(Serialize, Deserialize, Clone, Debug)]
|
||||
pub enum Theme {
|
||||
Plain,
|
||||
Purrely,
|
||||
}
|
||||
9
src/models/user.rs
Normal file
9
src/models/user.rs
Normal file
@@ -0,0 +1,9 @@
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use super::theme::Theme;
|
||||
|
||||
#[derive(Serialize, Deserialize, Clone, Debug)]
|
||||
pub struct UserPreferences {
|
||||
pub use_local_card_db: bool,
|
||||
pub theme: Theme,
|
||||
}
|
||||
@@ -14,6 +14,7 @@ pub enum ContentState {
|
||||
None,
|
||||
Inventory,
|
||||
Tournaments,
|
||||
User,
|
||||
}
|
||||
|
||||
impl Display for ContentState {
|
||||
@@ -24,6 +25,7 @@ impl Display for ContentState {
|
||||
match self {
|
||||
ContentState::Inventory => "Inventory",
|
||||
ContentState::Tournaments => "Tournament",
|
||||
ContentState::User => "User",
|
||||
ContentState::None => "",
|
||||
}
|
||||
)
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
pub mod index;
|
||||
pub mod inventory;
|
||||
pub mod user;
|
||||
|
||||
#[cfg(client)]
|
||||
use perseus::utils::get_path_prefix_client;
|
||||
|
||||
27
src/templates/user/index.rs
Normal file
27
src/templates/user/index.rs
Normal file
@@ -0,0 +1,27 @@
|
||||
use crate::{components::layout::Layout, state_enums::ContentState};
|
||||
use perseus::prelude::*;
|
||||
use sycamore::prelude::*;
|
||||
|
||||
fn user_index_page<G: Html>(cx: Scope) -> View<G> {
|
||||
view! { cx,
|
||||
Layout(content_state = ContentState::User) {
|
||||
// Anything we put in here will be rendered inside the `<main>` block of the layout
|
||||
p { "Hello World!" }
|
||||
br {}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[engine_only_fn]
|
||||
fn head(cx: Scope) -> View<SsrNode> {
|
||||
view! { cx,
|
||||
title { "User Page" }
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_template<G: Html>() -> Template<G> {
|
||||
Template::build("user")
|
||||
.view(user_index_page)
|
||||
.head(head)
|
||||
.build()
|
||||
}
|
||||
1
src/templates/user/mod.rs
Normal file
1
src/templates/user/mod.rs
Normal file
@@ -0,0 +1 @@
|
||||
pub mod index;
|
||||
Reference in New Issue
Block a user