diff --git a/application/Cargo.toml b/application/Cargo.toml index 4b12627..2148ed8 100644 --- a/application/Cargo.toml +++ b/application/Cargo.toml @@ -16,6 +16,7 @@ console_error_panic_hook = "0.1" leptos-use = "0.10.2" serde = "1.0.196" serde_json = "1.0.113" +rand = "0.8.5" # utils # strum = { version = "0.25", features = ["derive", "strum_macros"] } diff --git a/application/public/styles.scss b/application/public/styles.scss index 6dfbded..0a0ef13 100644 --- a/application/public/styles.scss +++ b/application/public/styles.scss @@ -110,3 +110,40 @@ form { width: 400px; } +.toastcontainer { + display: flex; + flex-direction: column-reverse; + gap: 10px; + position: fixed; + top: 0; + left: 0; + z-index: 999; + padding: 10px; +} + +.toastcontainer span { + padding: 10px 20px; + border-radius: 10px; + width: 300px; + font-weight: bold; +} + +.toastcontainer span:hover { + cursor: pointer; +} + +.warning { + background-color: #f29826; +} + +.error { + background-color: #d9534f; +} + +.info { + background-color: #2181d4; +} + +.success { + background-color: #4bb24b; +} diff --git a/application/src/components/mod.rs b/application/src/components/mod.rs index 302260f..1679cad 100644 --- a/application/src/components/mod.rs +++ b/application/src/components/mod.rs @@ -1 +1,2 @@ pub mod navbar; +pub mod toast; diff --git a/application/src/components/toast.rs b/application/src/components/toast.rs new file mode 100644 index 0000000..4245d3d --- /dev/null +++ b/application/src/components/toast.rs @@ -0,0 +1,18 @@ +use crate::util; +use leptos::*; + +/// Navigation bar +#[component] +pub fn Toasts() -> impl IntoView { + let notifications = expect_context::(); + + view! { +
+ {move || notifications.notifications.get().into_iter() + .map(|n| view! { + {n.text} + } + ).collect_view()} +
+ } +} diff --git a/application/src/lib.rs b/application/src/lib.rs index 8f74d53..d229040 100644 --- a/application/src/lib.rs +++ b/application/src/lib.rs @@ -20,6 +20,7 @@ pub fn App() -> impl IntoView { // Provides context that manages stylesheets, titles, meta tags, etc. provide_meta_context(); util::surrealdb::init_surrealdb(); + util::toast::init_toast(); let websocket = expect_context::(); let _participants = use_context::() @@ -58,6 +59,7 @@ pub fn App() -> impl IntoView { } > +
diff --git a/application/src/util/mod.rs b/application/src/util/mod.rs index 9538350..659d17f 100644 --- a/application/src/util/mod.rs +++ b/application/src/util/mod.rs @@ -1 +1,2 @@ pub mod surrealdb; +pub mod toast; diff --git a/application/src/util/toast.rs b/application/src/util/toast.rs new file mode 100644 index 0000000..860e430 --- /dev/null +++ b/application/src/util/toast.rs @@ -0,0 +1,41 @@ +use leptos::*; +use rand::distributions::{Alphanumeric, DistString}; + +#[derive(Clone)] +pub struct NotificationsContext { + pub notifications: ReadSignal>, + pub set_notifications: WriteSignal>, +} + +#[derive(Clone)] +pub struct ToastNotification { + pub text: String, + pub option: String, // error, warning, info, success + pub id: String, +} + +pub fn init_toast() { + let (notifications, set_notifications) = create_signal::>(vec![]); + provide_context(NotificationsContext { + notifications, + set_notifications, + }); +} + +pub fn add_toast(text: String, option: String) { + let context = expect_context::(); + + let id = Alphanumeric.sample_string(&mut rand::thread_rng(), 4); + + let mut vec = context.notifications.get(); + vec.push(ToastNotification { text, option, id }); + context.set_notifications.set(vec); +} + +pub fn remove_toast(id: String) { + let context = expect_context::(); + + let mut vec = context.notifications.get(); + vec.retain(|x| x.id != id); + context.set_notifications.set(vec); +}