From 5a03734b6767fed04c0913384584d8f59dc597ea Mon Sep 17 00:00:00 2001 From: jelemux Date: Tue, 24 Nov 2020 21:58:51 +0100 Subject: add traits for viewmodel and view --- src/view/main.rs | 335 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 335 insertions(+) create mode 100644 src/view/main.rs (limited to 'src/view/main.rs') diff --git a/src/view/main.rs b/src/view/main.rs new file mode 100644 index 0000000..e1753b4 --- /dev/null +++ b/src/view/main.rs @@ -0,0 +1,335 @@ +use crate::view::telephone::TelephoneView; +use std::collections::HashSet; +use super::name::{NameView}; +use super::address::AddressView; +use genpdf::Element as _; +use genpdf::{elements, style, fonts}; +use qrcodegen::QrCode; +use qrcodegen::QrCodeEcc; +use yew::prelude::*; +use vcard::{VCard, VCardError}; +use super::input_objects::utility::*; +use super::input_objects::name::Name; +use super::input_objects::address::Address; +use super::input_objects::telephone::Telephone; +use super::input_objects::VCardPropertyInputObject; + + +pub struct MainView { + link: ComponentLink, + error: Vec, + name: Name, + address: Address, + telephone: Telephone, + download: Option, + selected_option: DownloadOption, +} + +pub enum Msg { + UpdateName(Name), + UpdateAddress(Address), + UpdateTelephone(Telephone), + Generate(DownloadOption), + Nope, +} + +impl Component for MainView { + type Message = Msg; + type Properties = (); + + fn create(_props: Self::Properties, link: ComponentLink) -> Self { + MainView { + link, + error: vec![], + name: Name::new(), + address: Address::new(), + telephone: Telephone::new(), + download: None, + selected_option: DownloadOption::VCard + } + } + + fn update(&mut self, msg: Self::Message) -> ShouldRender { + self.error.clear(); + match msg { + Msg::UpdateName(value) => { + self.name = value; + self.link.send_message(Msg::Generate(self.selected_option)); + }, + Msg::UpdateAddress(value) => { + self.address = value; + self.link.send_message(Msg::Generate(self.selected_option)); + }, + Msg::UpdateTelephone(value) => { + self.telephone = value; + self.link.send_message(Msg::Generate(self.selected_option)); + }, + Msg::Generate(option) => { + self.selected_option = option; + + let vcard_content = match self.generate_vcard() { + Ok(vcard) => Some(vcard.to_string()), + Err(VCardError::FormatError(err)) => { + self.error.push(err.to_string()); + None + } + Err(VCardError::EmptyFormatName) => { + self.error.push(String::from("At least one of the name fields should be filled out.")); + None + } + }; + + match option { + DownloadOption::VCard => { + if vcard_content.is_some() { + self.download = Some( + Download { + file_name: format!("{}.vcs", self.name.formatted_name()), + content: vcard_content.unwrap().to_string(), + mime_type: MimeType::VCard, + } + ) + } + } + DownloadOption::QrCode => { + if vcard_content.is_some() { + match QrCode::encode_text(vcard_content.as_ref().unwrap(), QrCodeEcc::Low) { + Ok(qr) => self.download = Some( + Download { + file_name: format!("QR-Code VCard {}.svg", self.name.formatted_name()), + content: qr.to_svg_string(4), + mime_type: MimeType::SVG, + } + ), + Err(_) => self.error.push(String::from("Sorry, VCard is too long!")), + }; + } + } + DownloadOption::PDF => { + match self.generate_pdf() { + Ok(pdf) => self.download = Some( + Download { + file_name: format!("Visitenkarten {}.pdf", self.name.formatted_name()), + content: pdf, + mime_type: MimeType::PDF, + } + ), + Err(_) => self.error.push(String::from("Unexpected error while generating the PDF. Please contact me about it.")), + } + } + } + } + Msg::Nope => return false, + }; + if self.error.len() > 0 { + self.download = None; + } + true + } + + fn change(&mut self, _props: Self::Properties) -> ShouldRender { + false + } + + fn view(&self) -> Html { + + let download_options = self.link.callback(|e: ChangeData| + match e { + ChangeData::Select(v) => match v.value().as_str() { + "vcard" => Msg::Generate(DownloadOption::VCard), + "pdf" => Msg::Generate(DownloadOption::PDF), + "qrcode" => Msg::Generate(DownloadOption::QrCode), + _ => Msg::Nope, + }, + _ => Msg::Nope, + } + ); + + html!{ + <> +
+
+
+
+

{ "A Generator for vCards" }

+

{ "Supports generating vCards (.vcf), print-ready PDF business cards and QR Codes" }

+
+
+
+ +
+
+ + { self.render_errors() } + + + + + + + +
+
+ +
+ + { self.render_download() } +
+ +
+ { self.render_preview() } +
+ +
+
+
+ + + + } + } +} + +impl MainView { + fn render_errors(&self) -> Html { + html!{ + <> + { + for self.error.iter().map(|err| + html!{ +
+ { err } +
+ } + ) + } + + } + } + fn render_download(&self) -> Html { + if self.download.is_some() { + let download = self.download.as_ref().unwrap(); + + html!{ + + { "Download" } + + } + } else { + html!{} + } + } + fn render_preview(&self) -> Html { + if self.download.is_some() { + let download = self.download.as_ref().unwrap(); + + match download.mime_type { + MimeType::PDF => html!{ +