From 39abe4cacaf07248f8840e96d3691d88afe7c50e Mon Sep 17 00:00:00 2001 From: Franklin Date: Thu, 20 Apr 2023 18:11:19 -0400 Subject: [PATCH] Edit project screen done --- css/admin-common.css | 18 +++- css/components/textfield.css | 44 +++++++++ css/edit.css | 13 ++- index.html | 1 + src/components/dropdown.rs | 51 ++++++++++ src/components/mod.rs | 4 +- src/components/textfield.rs | 80 +++++++++++++++ src/pages/admin/edit.rs | 184 +++++++++++++++++++++++++++++------ src/pages/search.rs | 6 +- 9 files changed, 363 insertions(+), 38 deletions(-) create mode 100644 css/components/textfield.css create mode 100644 src/components/dropdown.rs create mode 100644 src/components/textfield.rs diff --git a/css/admin-common.css b/css/admin-common.css index 172a110..2a90e14 100644 --- a/css/admin-common.css +++ b/css/admin-common.css @@ -4,4 +4,20 @@ font-family: Source Sans Pro; font-weight: 700; letter-spacing: 0.1rem; -} \ No newline at end of file +} +.admin-dropdown { + display: flex; + flex-direction: row; + justify-content: center; + align-items: center; + min-width: 150px; + width: 100%; + min-height: 50px; + + padding: 5px 10px; + border: 1px solid rgba(0, 0, 0, 0.0); + background-color: rgba(0, 0, 0, 0.04); + border-radius: 5px; + font-family: Source Sans Pro; + font-size: 16px; +} diff --git a/css/components/textfield.css b/css/components/textfield.css new file mode 100644 index 0000000..60ce415 --- /dev/null +++ b/css/components/textfield.css @@ -0,0 +1,44 @@ +.textfield-container { + display: flex; + flex-direction: column; + justify-content: center; + align-items: start; + gap: 4px; + + width: 100%; +} +.textfield-label { + font-family: Space Grotesk; + font-size: 16px; + font-weight: 900; + letter-spacing: 0.1rem; + text-transform: uppercase; +} +.textfield-label-required { + font-family: Space Grotesk; + font-size: 16px; + font-weight: 900; + letter-spacing: 0.1rem; + text-transform: uppercase; +} +.textfield-label-required:after { + color: #e32; + content: '*'; + display: inline; +} +.textfield { + height: 50px; + background-color: white; + border: solid 0.5px #d8d8d8; + + width: 100%; + text-indent: 10px; +} +.textarea { + height: 150px; + background-color: white; + border: solid 0.5px #d8d8d8; + + width: 100%; + padding: 10px; +} \ No newline at end of file diff --git a/css/edit.css b/css/edit.css index 5798af9..5cb5526 100644 --- a/css/edit.css +++ b/css/edit.css @@ -1,11 +1,12 @@ .admin-project-fields-container { display: flex; flex-direction: column; - justify-content: start; + justify-content: center; align-items: center; gap: 20px; - width: 90%; + width: 80%; + max-width: 750px; } .admin-project-field-container { @@ -21,4 +22,12 @@ font-family: Source Sans Pro; font-size: 16px; text-align: center; +} +.admin-project-textfield { + height: 50px; + background-color: white; + border: solid 0.5px #d8d8d8; + + width: 100%; + text-indent: 10px; } \ No newline at end of file diff --git a/index.html b/index.html index 641bffe..938bf21 100644 --- a/index.html +++ b/index.html @@ -25,6 +25,7 @@ + diff --git a/src/components/dropdown.rs b/src/components/dropdown.rs new file mode 100644 index 0000000..5f7a79f --- /dev/null +++ b/src/components/dropdown.rs @@ -0,0 +1,51 @@ +use std::fmt::Display; + +use jl_types::domain::{option_wrapper::OptionWrapper}; +use yew::prelude::*; +use yew_utils::vdom::comp_with; + +/// Give this component a list of options +#[function_component(DropDown)] +pub fn dropdown(props: &DropDownProps) -> Html { + let selection_changed_cb = { + let onchange_cb = props.onchange.clone(); + let selected = props.selected.clone(); + Callback::from(move |option: OptionWrapper| { + selected.set(option.option.clone()); + match onchange_cb.clone() { + Some(additional_cb) => additional_cb.emit(option), + None => {}, + }; + + }) + }; + let drop_down = comp_with::>>(yew_utils::components::drop_down::DropDownProps { + initial: { + OptionWrapper::new((*props.selected).clone())}, + options: { + let mut options: Vec> = props.options.clone().into_iter().map(|option| OptionWrapper::new(Some(option))).collect(); + if props.has_none { options.insert(0, OptionWrapper::new(None)); } + options + }, + selection_changed: selection_changed_cb.clone(), + class_css: Some("admin-dropdown".into()) + }); + //if (*props.selected).is_none() {selection_changed_cb.emit( OptionWrapper::new((*props.selected).clone()));} + html! { + {drop_down} + } +} + +#[derive(PartialEq, Properties, Clone)] +pub struct DropDownProps { + #[prop_or_default] + pub options: Vec, + /// in case that there is no selected option, this will reflect a None variant + pub selected: UseStateHandle>, + #[prop_or_default] + pub unpicked_text: String, + #[prop_or_default] + pub onchange: Option>>, + #[prop_or_default] + pub has_none: bool +} \ No newline at end of file diff --git a/src/components/mod.rs b/src/components/mod.rs index e960300..aef93dc 100644 --- a/src/components/mod.rs +++ b/src/components/mod.rs @@ -6,4 +6,6 @@ pub mod feature; pub mod footer; pub mod agent_card; pub mod admin_nav_bar; -pub mod admin_project; \ No newline at end of file +pub mod admin_project; +pub mod textfield; +pub mod dropdown; \ No newline at end of file diff --git a/src/components/textfield.rs b/src/components/textfield.rs new file mode 100644 index 0000000..8dad1ba --- /dev/null +++ b/src/components/textfield.rs @@ -0,0 +1,80 @@ +// COMPONENTFORLIB +use wasm_bindgen::{JsCast, UnwrapThrowExt}; +use web_sys::{HtmlInputElement, HtmlTextAreaElement}; +use yew::prelude::*; + + +/// This component is a text +#[function_component(TextField)] +pub fn textfield(props: &TextFieldProps) -> Html { + let on_input_changed = { + let handle = props.value.clone(); + let fieldtype = props.fieldtype.clone(); + let onchange = props.onchange.clone(); + Callback::from(move |e: InputEvent| { + match fieldtype { + TextFieldType::Input => { + let value = get_value_from_input_event(e); + match onchange.clone() { + Some(onchange) => { onchange.emit(value.clone()); }, + None => {} + }; + handle.set(value); + }, + TextFieldType::TextArea => { + let value = get_value_from_input_event(e); + match onchange.clone() { + Some(onchange) => { onchange.emit(value.clone()); }, + None => {} + }; + handle.set(value); + }, + } + }) + }; + html! { +
+
{props.label.clone()}
+ { + if props.fieldtype == TextFieldType::Input { + html! { } + } else { + html! {