diff options
Diffstat (limited to 'src/address.rs')
-rw-r--r-- | src/address.rs | 239 |
1 files changed, 239 insertions, 0 deletions
diff --git a/src/address.rs b/src/address.rs new file mode 100644 index 0000000..d048dc0 --- /dev/null +++ b/src/address.rs @@ -0,0 +1,239 @@ +use yew::prelude::*; +use vcard::properties; +use vcard::parameters; +use vcard::values::{self, text}; +use std::collections::HashSet; + +#[derive(Clone)] +pub struct Address { + pub post_office_box: String, + pub extension: String, + pub street: String, + pub locality: String, + pub region: String, + pub code: String, + pub country: String, + address_type: AddressType, +} + +impl Address { + pub fn new_with_type(address_type: AddressType) -> Self { + Self { + post_office_box: String::new(), + extension: String::new(), + street: String::new(), + locality: String::new(), + region: String::new(), + code: String::new(), + country: String::new(), + address_type + } + } + pub fn to_vcard_address(&self) -> properties::Address { + let address_value = values::address_value::AddressValue::from_components( + match self.post_office_box.is_empty() { + true => None, + false => Some(text::Component::from_str(&self.post_office_box).unwrap()), + }, + match self.extension.is_empty() { + true => None, + false => Some(text::Component::from_str(&self.extension).unwrap()), + }, + match self.street.is_empty() { + true => None, + false => Some(text::Component::from_str(&self.street).unwrap()), + }, + match self.locality.is_empty() { + true => None, + false => Some(text::Component::from_str(&self.locality).unwrap()), + }, + match self.region.is_empty() { + true => None, + false => Some(text::Component::from_str(&self.region).unwrap()), + }, + match self.code.is_empty() { + true => None, + false => Some(text::Component::from_str(&self.code).unwrap()), + }, + match self.country.is_empty() { + true => None, + false => Some(text::Component::from_str(&self.country).unwrap()), + }, + ); + + let mut address = properties::Address::from_address_value(address_value); + + let type_values = { + let mut type_values = HashSet::new(); + + type_values.insert( + match self.address_type { + AddressType::Home => values::type_value::TypeValue::Home, + AddressType::Work => values::type_value::TypeValue::Work, + } + ); + + vcard::Set::from_hash_set(type_values).unwrap() + }; + + address.typ = Some(parameters::typ::Type::from_type_values(type_values)); + + address + } +} + +#[derive(Clone, Copy, PartialEq)] +pub enum AddressType { + Home, + Work, +} + +impl AddressType { + pub fn to_str(&self) -> &str { + match self { + AddressType::Home => "Home", + AddressType::Work => "Work", + } + } +} + +pub struct AddressView { + link: ComponentLink<Self>, + value: Address, + oninput: Callback<Address>, +} + +pub enum Msg { + UpdatePostOfficeBox(String), + UpdateExtension(String), + UpdateStreet(String), + UpdateLocality(String), + UpdateRegion(String), + UpdateCode(String), + UpdateCountry(String), +} + +#[derive(Clone, PartialEq, Properties)] +pub struct Props { + pub oninput: Callback<Address>, + pub address_type: AddressType, + //pub errors: Vec<String>, +} + +impl Component for AddressView { + type Message = Msg; + type Properties = Props; + fn create(props: <Self as yew::Component>::Properties, link: yew::html::Scope<Self>) -> Self { + Self { + link, + value: Address::new_with_type(props.address_type), + oninput: props.oninput, + } + } + fn update(&mut self, msg: <Self as yew::Component>::Message) -> bool { + match msg { + Msg::UpdatePostOfficeBox(b) => self.value.post_office_box = b, + Msg::UpdateExtension(e) => self.value.extension = e, + Msg::UpdateStreet(s) => self.value.street = s, + Msg::UpdateLocality(l) => self.value.locality = l, + Msg::UpdateRegion(r) => self.value.region = r, + Msg::UpdateCode(p) => self.value.code = p, + Msg::UpdateCountry(c) => self.value.country = c, + }; + self.oninput.emit(self.value.clone()); + true + } + fn change(&mut self, props: <Self as yew::Component>::Properties) -> bool { + self.oninput = props.oninput; + self.value.address_type = props.address_type; + true + } + fn view(&self) -> yew::virtual_dom::VNode { + html!{ + <div class="box"> + <h3 class="subtitle">{ format!("{} Address", self.value.address_type.to_str()) }</h3> + + <div class="columns is-mobile is-multiline"> + + <div class="field column is-one-fifth-widescreen is-one-quarter-desktop is-one-third-tablet is-half-mobile"> + <label class="label">{ "Post Office Box" }</label> + <div class="control"> + <input id="post_office_box" + type="text" + placeholder="" + oninput=self.link.callback(|e: InputData| Msg::UpdatePostOfficeBox(e.value)) + /> + </div> + </div> + + <div class="field column is-one-fifth-widescreen is-one-quarter-desktop is-one-third-tablet is-half-mobile"> + <label class="label">{ "Extension" }</label> + <div class="control"> + <input id="extension" + type="text" + placeholder="" + oninput=self.link.callback(|e: InputData| Msg::UpdateExtension(e.value)) + /> + </div> + </div> + + <div class="field column is-one-fifth-widescreen is-one-quarter-desktop is-one-third-tablet is-half-mobile"> + <label class="label">{ "Street" }</label> + <div class="control"> + <input id="street" + type="text" + placeholder="" + oninput=self.link.callback(|e: InputData| Msg::UpdateStreet(e.value)) + /> + </div> + </div> + + <div class="field column is-one-fifth-widescreen is-one-quarter-desktop is-one-third-tablet is-half-mobile"> + <label class="label">{ "Locality" }</label> + <div class="control"> + <input id="locality" + type="text" + placeholder="" + oninput=self.link.callback(|e: InputData| Msg::UpdateLocality(e.value)) + /> + </div> + </div> + + <div class="field column is-one-fifth-widescreen is-one-quarter-desktop is-one-third-tablet is-half-mobile"> + <label class="label">{ "Region" }</label> + <div class="control"> + <input id="region" + type="text" + placeholder="" + oninput=self.link.callback(|e: InputData| Msg::UpdateRegion(e.value)) + /> + </div> + </div> + + <div class="field column is-one-fifth-widescreen is-one-quarter-desktop is-one-third-tablet is-half-mobile"> + <label class="label">{ "Postal Code" }</label> + <div class="control"> + <input id="code" + type="text" + placeholder="" + oninput=self.link.callback(|e: InputData| Msg::UpdateCode(e.value)) + /> + </div> + </div> + + <div class="field column is-one-fifth-widescreen is-one-quarter-desktop is-one-third-tablet is-half-mobile"> + <label class="label">{ "Country" }</label> + <div class="control"> + <input id="country" + type="text" + placeholder="" + oninput=self.link.callback(|e: InputData| Msg::UpdateCountry(e.value)) + /> + </div> + </div> + + </div> + </div> + } + } +}
\ No newline at end of file |