use common::{CommonAdmin, CommonDriver}; use std::{ error::Error, fmt::{self, Debug, Display, Formatter}, }; use wasm_bindgen::{JsCast, JsValue}; use wasm_bindgen_futures::JsFuture; use web_sys::{Request, RequestInit, RequestMode, Response}; use yew::props; use yew::{html, Component, Context, Html, Properties}; //Trait to handle Future yew HTMLS pub trait UseAble { //Return HTML if didn't fail return error if not fn use_it(self) -> Result; } impl UseAble for CommonDriver { fn use_it(self) -> Result { let name = self.name; let address = self.address; let id = self.id; let html = html! {

{ "Driver:" }

{ format!("Name: {}", name) }

{ format!("Address: {}", address) }

{ format!("ID: {}", id) }

}; Ok(html) } } impl UseAble for CommonAdmin { fn use_it(self) -> Result { let name = self.name; let address = self.address; let id = self.id; let html = html! {

{ "Admin:" }

{ format!("Name: {}", name) }

{ format!("Address: {}", address) }

{ format!("ID: {}", id) }

}; Ok(html) } } //Wwasm bingdengen code const DRIVER_URL: &str = "http://db.sewelam.tech/api/driver/50"; const ADMIN_URL: &str = "http://db.sewelam.tech/api/admin/"; const TICKET_URL: &str = "http://db.sewelam.tech/api/ticket/"; const FUNNY_TXT_URL: &str = "https://whatthecommit.com/index.txt"; const INCORRECT_URL: &str = "http://libkyy.cf"; //Generic Msg for our states pub enum Msg { SetDataFetchState(FetchState), GetData, GetError, } pub struct RandomCommit { commit: FetchState, } //This trait is for all yew components impl Component for RandomCommit { type Message = Msg; type Properties = (); fn create(_ctx: &Context) -> Self { Self { commit: FetchState::NotFetching, //Default state is not fetching anything } } fn update(&mut self, ctx: &Context, msg: Self::Message) -> bool { match msg { Msg::SetDataFetchState(fetch_state) => { self.commit = fetch_state; true } Msg::GetData => { ctx.link().send_future(async { match fetch_url_text(FUNNY_TXT_URL).await { Ok(commit) => Msg::SetDataFetchState(FetchState::Success(commit)), Err(err) => Msg::SetDataFetchState(FetchState::Failed(err)), } }); ctx.link() .send_message(Msg::SetDataFetchState(FetchState::Fetching)); false } Msg::GetError => { ctx.link().send_future(async { match fetch_url_text(INCORRECT_URL).await { Ok(commit) => Msg::SetDataFetchState(FetchState::Success(commit)), Err(err) => Msg::SetDataFetchState(FetchState::Failed(err)), } }); ctx.link() .send_message(Msg::SetDataFetchState(FetchState::Fetching)); false } } } fn view(&self, ctx: &Context) -> Html { match &self.commit { FetchState::NotFetching => html! { <> }, FetchState::Fetching => html! { "Fetching" }, FetchState::Success(data) => { html! { <> {data} } } FetchState::Failed(err) => html! { err }, } } } //Generate Struct and implement component for driver using CommonDriver pub struct DriverComponent { driver: FetchState, } #[derive(Default, Properties, PartialEq)] pub struct ApiParams { pub entered_id: i32, } impl ApiParams { pub fn new_api_thingy_with_id(id: i32) -> Self { props! { ApiParams { entered_id: id }} } } //implement the component for Driver using a string impl Component for DriverComponent { type Message = Msg; type Properties = ApiParams; fn create(_ctx: &Context) -> Self { Self { driver: FetchState::NotFetching, } } fn update(&mut self, ctx: &Context, msg: Self::Message) -> bool { match msg { Msg::SetDataFetchState(fetch_state) => { self.driver = fetch_state; true } Msg::GetData => { ctx.link().send_future(async { match fetch_url_text(DRIVER_URL).await { Ok(driver) => Msg::SetDataFetchState(FetchState::Success(driver)), Err(err) => Msg::SetDataFetchState(FetchState::Failed(err)), } }); ctx.link() .send_message(Msg::SetDataFetchState(FetchState::Fetching)); false } Msg::GetError => { ctx.link().send_future(async { match fetch_url_text(INCORRECT_URL).await { Ok(driver) => Msg::SetDataFetchState(FetchState::Success(driver)), Err(err) => Msg::SetDataFetchState(FetchState::Failed(err)), } }); ctx.link() .send_message(Msg::SetDataFetchState(FetchState::Fetching)); false } } } fn view(&self, ctx: &Context) -> Html { match &self.driver { FetchState::NotFetching => html! { <>
}, FetchState::Fetching => html! { "Fetching" }, FetchState::Success(data) => html! { <> {data}
}, FetchState::Failed(err) => html! { err }, } } } #[derive(Debug, Clone, PartialEq)] pub struct FetchError { err: JsValue, } impl Display for FetchError { fn fmt(&self, f: &mut Formatter) -> fmt::Result { Debug::fmt(&self.err, f) } } impl Error for FetchError {} impl From for FetchError { fn from(value: JsValue) -> Self { Self { err: value } } } //Enum for Fetchstates that takes a generic type --> String/Driver etc. pub enum FetchState { NotFetching, Fetching, Success(T), Failed(FetchError), } async fn fetch_url_text(url: &'static str) -> Result { let mut opts = RequestInit::new(); opts.method("GET"); opts.mode(RequestMode::Cors); //Cors is required for fetch to work //initialise request let request = Request::new_with_str_and_init(url, &opts)?; let window = gloo::utils::window(); let resp_value = JsFuture::from(window.fetch_with_request(&request)).await?; let resp: Response = resp_value.dyn_into().unwrap(); let text = JsFuture::from(resp.text()?).await?; Ok(text.as_string().unwrap()) } //Admin component