Files
yugioh-inventory/src/components/layout.rs

170 lines
5.6 KiB
Rust

use crate::{
capsules::{
forgot_password_form::{ForgotPasswordFormProps, FORGOT_PASSWORD_FORM},
login_form::{LoginFormProps, LOGIN_FORM},
register_form::{RegisterFormProps, REGISTER_FORM},
},
components::header::Header,
global_state::AppStateRx,
state_enums::{ContentState, OpenState},
};
use perseus::prelude::*;
use sycamore::prelude::*;
cfg_if::cfg_if! {
if #[cfg(client)] {
use crate::endpoints::CARD_INFO;
use crate::templates::get_api_path;
use crate::models::card::CardTable;
}
}
#[derive(Prop)]
pub struct LayoutProps<'a, G: Html> {
pub content_state: ContentState,
pub children: Children<'a, G>,
}
// Using elements from here: https://flowbite.com/docs/components/buttons/
#[component]
pub fn Layout<'a, G: Html>(
cx: Scope<'a>,
LayoutProps {
content_state,
children,
}: LayoutProps<'a, G>,
) -> View<G> {
let global_state = Reactor::<G>::from_cx(cx).get_global_state::<AppStateRx>(cx);
// Set the theme
// TODO use theme for pages
global_state.style.theme.current.set(match content_state {
ContentState::None => (*global_state.style.theme.default.get()).clone(),
_ => (*global_state.style.theme.default.get()).clone(),
});
#[cfg(client)]
let _ = web_sys::window()
.unwrap()
.document()
.unwrap()
.document_element()
.unwrap()
.set_attribute("data-theme", &global_state.style.theme.current.get());
let children = children.call(cx);
// Check if the client is authenticated or not
#[cfg(client)]
global_state.auth.detect_state();
let content_state_header = content_state.clone();
#[cfg(client)]
{
// TODO -> try to use suspense
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 local_card_user_pref && !card_table_loaded {
let client = reqwest::Client::new();
let response = client
.get(get_api_path(CARD_INFO).as_str())
.send()
.await
.unwrap();
// TODO add error handling
let response = response.json::<CardTable>().await.unwrap();
global_state.constants.card_table.set(Some(response));
global_state.constants.is_loaded.set(true);
}
});
}
view! { cx,
// Main page header, including login functionality
Header(content_state = content_state_header)
// 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.modals_open.login.get() {
OpenState::Open => {
view! { cx,
(LOGIN_FORM.widget(cx, "",
LoginFormProps{
remember_me: true,
}
))
}
}
OpenState::Closed => {
view!{ cx, }
}
})
(match *global_state.modals_open.register.get() {
OpenState::Open => {
view! { cx,
(REGISTER_FORM.widget(cx, "",
RegisterFormProps{
registration_code: true,
nickname: true,
email: true,
}
))
}
}
OpenState::Closed => {
view!{ cx, }
}
})
(match *global_state.modals_open.forgot_password.get() {
OpenState::Open => {
view! { cx,
(FORGOT_PASSWORD_FORM.widget(cx, "",
ForgotPasswordFormProps{}
))
}
}
OpenState::Closed => {
view!{ cx, }
}
})
}
main(style = "my-8") {
(match content_state {
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") {
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"
) { "Inventory" }
}
}
}
// Content body
div(class = "container mx-auto px-6") {
div(class = "md:flex mt-8 md:-mx-4") {
div(class = "rounded-md overflow-hidden bg-cover bg-center") {
(children)
}
}
}
},
_ => view!{ cx, },
})
}
}
}