diff --git a/app/src/infra/common_component.rs b/app/src/infra/common_component.rs new file mode 100644 index 0000000..36f82ba --- /dev/null +++ b/app/src/infra/common_component.rs @@ -0,0 +1,68 @@ +use anyhow::{Error, Result}; +use yew::{ + prelude::*, + services::{fetch::FetchTask, ConsoleService}, +}; + +pub trait CommonComponent>: Component { + fn handle_msg(&mut self, msg: ::Message) -> Result; + fn mut_common(&mut self) -> &mut CommonComponentParts; +} + +pub struct CommonComponentParts> { + pub link: ComponentLink, + pub props: ::Properties, + pub error: Option, + pub task: Option, +} + +impl> CommonComponentParts { + pub fn create(props: ::Properties, link: ComponentLink) -> Self { + Self { + link, + props, + error: None, + task: None, + } + } + + pub fn update(com: &mut C, msg: ::Message) -> ShouldRender { + com.mut_common().error = None; + match com.handle_msg(msg) { + Err(e) => { + ConsoleService::error(&e.to_string()); + com.mut_common().error = Some(e); + true + } + Ok(b) => b, + } + } + + pub fn call_backend( + &mut self, + method: M, + req: Req, + callback: Cb, + ) -> Result<()> + where + M: Fn(Req, Callback) -> Result, + Cb: Fn(Resp) -> ::Message + 'static, + { + self.task = Some(method(req, self.link.callback(callback))?); + Ok(()) + } +} + +impl> std::ops::Deref for CommonComponentParts { + type Target = ::Properties; + + fn deref(&self) -> &::Target { + &self.props + } +} + +impl> std::ops::DerefMut for CommonComponentParts { + fn deref_mut(&mut self) -> &mut ::Target { + &mut self.props + } +} diff --git a/app/src/infra/mod.rs b/app/src/infra/mod.rs index 3615653..2e58c62 100644 --- a/app/src/infra/mod.rs +++ b/app/src/infra/mod.rs @@ -1,4 +1,5 @@ pub mod api; +pub mod common_component; pub mod cookies; pub mod graphql; pub mod modal;