Don't load local card info by default, add user page, theme loading

This commit is contained in:
2024-09-05 00:59:51 -04:00
parent 20d7f62f33
commit 0a8091e843
11 changed files with 104 additions and 18 deletions

View File

@@ -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..."
}
} },

View File

@@ -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, },
})
}
}

View File

@@ -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(),
},
},
}

View File

@@ -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

View File

@@ -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
View 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
View 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,
}

View File

@@ -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 => "",
}
)

View File

@@ -1,5 +1,6 @@
pub mod index;
pub mod inventory;
pub mod user;
#[cfg(client)]
use perseus::utils::get_path_prefix_client;

View 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()
}

View File

@@ -0,0 +1 @@
pub mod index;