🎨 Isolate infra and ui components
The src/base.rs is still to be reworked.
This commit is contained in:
117
src/ui/components/modal.rs
Normal file
117
src/ui/components/modal.rs
Normal file
@@ -0,0 +1,117 @@
|
||||
use std::collections::HashMap;
|
||||
use std::sync::OnceLock;
|
||||
|
||||
use dioxus::prelude::*;
|
||||
|
||||
use super::button::{ErrorButton, SuccessButton, WarningButton};
|
||||
|
||||
use crate::infrastructure::services::random_svg_generators::{
|
||||
generate_random_svg_avatar, AvatarConfig, AvatarFeeling,
|
||||
};
|
||||
|
||||
include!(concat!(env!("OUT_DIR"), "/style_vars.rs"));
|
||||
|
||||
use style::{COLOR_CRITICAL_100, COLOR_SUCCESS_100, COLOR_WARNING_100};
|
||||
|
||||
turf::style_sheet!("src/ui/components/modal.scss");
|
||||
|
||||
#[derive(Clone, Copy, Eq, PartialEq, Hash)]
|
||||
pub enum Severity {
|
||||
Ok,
|
||||
Warning,
|
||||
Critical,
|
||||
}
|
||||
|
||||
fn avatar_configs() -> &'static HashMap<Severity, AvatarConfig<'static>> {
|
||||
static HASHMAP: OnceLock<HashMap<Severity, AvatarConfig>> = OnceLock::new();
|
||||
HASHMAP.get_or_init(|| {
|
||||
let mut configs = HashMap::new();
|
||||
configs.insert(
|
||||
Severity::Critical,
|
||||
AvatarConfig::new(AvatarFeeling::Alerting, COLOR_CRITICAL_100),
|
||||
);
|
||||
configs.insert(
|
||||
Severity::Warning,
|
||||
AvatarConfig::new(AvatarFeeling::Warning, COLOR_WARNING_100),
|
||||
);
|
||||
configs.insert(
|
||||
Severity::Ok,
|
||||
AvatarConfig::new(AvatarFeeling::Ok, COLOR_SUCCESS_100),
|
||||
);
|
||||
configs
|
||||
})
|
||||
}
|
||||
|
||||
#[derive(Props, Clone, PartialEq)]
|
||||
pub struct ModalProps {
|
||||
pub severity: Severity,
|
||||
#[props(optional)]
|
||||
pub title: Option<String>,
|
||||
pub children: Element,
|
||||
#[props(optional)]
|
||||
pub on_confirm: Option<EventHandler<MouseEvent>>,
|
||||
}
|
||||
|
||||
#[component]
|
||||
pub fn Modal(props: ModalProps) -> Element {
|
||||
let avatar_config = avatar_configs().get(&props.severity);
|
||||
|
||||
let random_figure_future =
|
||||
use_resource(move || async move { generate_random_svg_avatar(avatar_config).await });
|
||||
|
||||
let icon = match &*random_figure_future.read_unchecked() {
|
||||
Some(svg) => Some(rsx! {
|
||||
div {
|
||||
class: ClassName::MODAL_CONTENT_ICON_PLACEHOLDER,
|
||||
dangerous_inner_html: svg.as_str(),
|
||||
}
|
||||
}),
|
||||
None => None,
|
||||
};
|
||||
|
||||
let button_class = match &props.severity {
|
||||
Severity::Ok => SuccessButton,
|
||||
Severity::Warning => WarningButton,
|
||||
Severity::Critical => ErrorButton,
|
||||
};
|
||||
|
||||
icon.as_ref()?;
|
||||
|
||||
rsx! {
|
||||
style { {STYLE_SHEET} },
|
||||
|
||||
div {
|
||||
class: ClassName::MODAL,
|
||||
|
||||
div {
|
||||
class: ClassName::MODAL_CONTENT,
|
||||
|
||||
div {
|
||||
class: ClassName::MODAL_CONTENT_ICON,
|
||||
{icon}
|
||||
},
|
||||
|
||||
div {
|
||||
class: ClassName::MODAL_CONTENT_TITLE,
|
||||
{props.title},
|
||||
},
|
||||
|
||||
div {
|
||||
class: ClassName::MODAL_CONTENT_MSG,
|
||||
{props.children},
|
||||
},
|
||||
|
||||
div {
|
||||
class: ClassName::MODAL_CONTENT_BUTTONS,
|
||||
button_class {
|
||||
onclick: move |evt| {
|
||||
if let Some(cb) = &props.on_confirm {
|
||||
cb.call(evt);
|
||||
}
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user