diff --git a/assets/styles/settings.css b/assets/styles/settings.css new file mode 100644 index 0000000..e6c84e8 --- /dev/null +++ b/assets/styles/settings.css @@ -0,0 +1,94 @@ +body { + background-color: var(--bg); + margin: 0; + color: var(--fg); +} + +.sidebar-container { + margin-top: 20px; + display: flex; + gap: 20px; + height: calc(100vh - 20px); +} + +.settings-container { + box-sizing: border-box; + display: flex; + flex-direction: column; + gap: 20px; + flex: 1; + width: 100%; + padding-right: 25px; + overflow-y: auto; + height: 100%; + padding-bottom: 20px; +} + +.settings-container { + background-color: var(--card-bg); + width: 100%; + height: 100%; + border-radius: 20px; + box-sizing: border-box; + padding: 25px; +} + +.dropdown-none { + display: none !important; +} + +.dropdown-button { + display: flex; + text-align: center; + align-items: center; + justify-content: center; + padding: 10px; + gap: 10px; + border-radius: 10px; + border: 0; + outline: 0; + text-transform: capitalize; + background-color: var(--bg); + color: var(--fg); +} + +.dropdown-chevron { + height: max-content; + width: max-content; + margin-top: auto; + margin-bottom: auto; +} + +.dropdown { + display: flex; + flex-direction: column; + width: max-content; + background-color: transparent; + margin-top: 10px; + margin-left: auto; + margin-right: auto; + background-color: var(--bg); + color: var(--fg); +} + +.dropdown button { + padding: 10px; + padding-left: 20px; + padding-right: 20px; + border: 0; + outline: 0; + background-color: transparent; + color: var(--fg); +} + +.dropdown button:hover { + background-color: var(--card-bg); +} + +.dropdown-button:hover { + background-color: var(--card-bg); +} + +.dropdown-wrapper { + width: max-content; +} \ No newline at end of file diff --git a/assets/styles/theme.css b/assets/styles/theme.css index e47926a..6cc2652 100644 --- a/assets/styles/theme.css +++ b/assets/styles/theme.css @@ -72,34 +72,36 @@ .black { /* States */ - --online: rgb(0, 255, 128); /* neon green */ - --offline: rgb(255, 77, 77); /* soft red */ - --warning: rgb(255, 193, 7); /* bright yellow */ - --maintenance: rgb(100, 181, 246); /* light blue */ + --online: rgb(0, 255, 128); /* neon green */ + --offline: rgb(255, 77, 77); /* soft red */ + --warning: rgb(255, 193, 7); /* bright yellow */ + --maintenance: rgb(100, 181, 246); /* light blue */ /* States bg (dark, translucent overlays) */ - --online-bg: rgba(0, 128, 64, 0.3); /* deep green */ - --offline-bg: rgba(139, 0, 0, 0.3); /* dark red */ - --warning-bg: rgba(153, 102, 0, 0.3); /* golden brown */ - --maintenance-bg: rgba(25, 118, 210, 0.3);/* muted blue */ + --online-bg: rgba(0, 128, 64, 0.3); /* deep green */ + --offline-bg: rgba(139, 0, 0, 0.3); /* dark red */ + --warning-bg: rgba(153, 102, 0, 0.3); /* golden brown */ + --maintenance-bg: rgba(25, 118, 210, 0.3); /* muted blue */ /* Overview data */ - --online-ov: #00ff80; /* neon green */ - --issue: rgb(255, 85, 0); /* warning orange */ - --cpu: rgb(66, 165, 245); /* light blue */ - --memory: rgb(200, 39, 228); /* purple */ - --storage: rgb(255, 111, 0); /* orange */ - --network: rgb(0, 200, 83); /* green */ + --online-ov: #00ff80; /* neon green */ + --issue: rgb(255, 85, 0); /* warning orange */ + --cpu: rgb(66, 165, 245); /* light blue */ + --memory: rgb(200, 39, 228); /* purple */ + --storage: rgb(255, 111, 0); /* orange */ + --network: rgb(0, 200, 83); /* green */ /* Usage levels */ - --low: rgb(11, 226, 86); /* neon green */ - --medium: rgb(231, 215, 72); /* bright yellow */ - --high: rgb(211, 56, 48); /* red */ + --low: rgb(11, 226, 86); /* neon green */ + --medium: rgb(231, 215, 72); /* bright yellow */ + --high: rgb(211, 56, 48); /* red */ /* Misc */ - --bg: #000000; /* pure black */ - --fg: #ffffff; /* pure white */ - --card-bg: #0e0e0e; /* almost black card */ - --progress-bg: #1a1a1a; /* very dark grey */ - --server-icon-bg: #111111; /* dark grey */ + --bg: #000000; /* pure black */ + --fg: #ffffff; /* pure white */ + --card-bg: #0e0e0e; /* almost black card */ + --progress-bg: #1a1a1a; /* very dark grey */ + --server-icon-bg: #111111; /* dark grey */ + --fg-selected: #f8fafc; + --bg-selected: #1a1a1a; } diff --git a/src/components/sidebar.rs b/src/components/sidebar.rs index ec029dd..70979a2 100644 --- a/src/components/sidebar.rs +++ b/src/components/sidebar.rs @@ -19,7 +19,7 @@ const SIDEBAR_ITEMS: &[SideBarItem] = &[ SideBarItem { name: "Settings", icon: || rsx!(lucide_dioxus::Settings { size: 35 }), - route: Route::Dashboard {}, + route: Route::Settings {}, }, ]; diff --git a/src/main.rs b/src/main.rs index 513397b..8cb7287 100644 --- a/src/main.rs +++ b/src/main.rs @@ -3,12 +3,14 @@ mod components; mod cookie; mod dashboard; mod login; +mod settings; use dioxus::prelude::*; use web_sys::window; use dashboard::Dashboard; use login::Login; +use settings::Settings; #[derive(Debug, Clone, Routable, PartialEq)] #[rustfmt::skip] @@ -17,6 +19,8 @@ enum Route { Login {}, #[route("/dashboard")] Dashboard {}, + #[route("/settings")] + Settings {}, } const FAVICON: Asset = asset!("/assets/favicon.ico"); @@ -29,7 +33,7 @@ fn main() { #[component] fn App() -> Element { - let mut theme = use_signal(|| String::from("light")); + let theme = use_signal(|| String::from("light")); use_effect({ let mut theme = theme.clone(); @@ -53,18 +57,6 @@ fn App() -> Element { document::Link { rel: "icon", href: FAVICON } document::Link { rel: "stylesheet", href: FONT_CSS } document::Link { rel: "stylesheet", href: THEME_CSS } - button { - onclick: move |_| { - let d = match theme.read().as_str() { - "dark" => String::from("black"), - "black" => String::from("light"), - _ => String::from("dark") - }; - cookie::set_cookie("theme", &d); - theme.set(d); - }, - "Click" - } Router:: { } } } diff --git a/src/settings.rs b/src/settings.rs new file mode 100644 index 0000000..e09318e --- /dev/null +++ b/src/settings.rs @@ -0,0 +1,68 @@ +use dioxus::prelude::*; + +use crate::{components::sidebar::SideBar, cookie}; + +pub enum Property { + Dropdown(&'static [&'static str]), +} + +const SETTINGS_CSS: Asset = asset!("/assets/styles/settings.css"); +const OPTIONS: &[(&str, Property, bool)] = &[( + "theme", + Property::Dropdown(&["light", "dark", "black"]), + true, +)]; + +#[component] +pub fn Settings() -> Element { + rsx! { + document::Link { rel: "stylesheet", href: SETTINGS_CSS } + + div { class: "sidebar-container", + SideBar { selected: 1 } + + div { class: "settings-container", + div { + for (name, prop, needs_refresh) in OPTIONS { + match prop { + Property::Dropdown(opts) => { + rsx!{ + div { class: "dropdown-wrapper", + button { class: "dropdown-button", onclick: |_| { + let Some(document) = web_sys::window().and_then(|w| w.document()) else { + return; + }; + let e = document.get_element_by_id(name).unwrap(); + if e.class_name() == "dropdown" { + e.set_class_name("dropdown dropdown-none"); + } else { + e.set_class_name("dropdown"); + } + }, + "{name}" + lucide_dioxus::ChevronDown { size: 16, class: "chevron", color: "currentColor" } + } + div { + id: "{name}", + class: "dropdown", + for o in opts { + button { onclick: move |_| { + cookie::set_cookie(name, &o); + if *needs_refresh { + if let Some(win) = web_sys::window() { + win.location().reload().unwrap(); + } + } + }, "{o}" } + } + } + } + } + } + } + } + } + } + } + } +}