Added contact request logic and connected it to the backend

This commit is contained in:
Franklin 2023-04-14 18:00:19 -04:00
parent 49e7712407
commit 89fe0495cb
7 changed files with 101 additions and 13 deletions

2
Cargo.lock generated
View File

@ -721,6 +721,7 @@ dependencies = [
"wasm-bindgen",
"wasm-bindgen-futures",
"wasm-logger",
"web-sys",
"yew",
"yew-router",
"yew-utils",
@ -734,6 +735,7 @@ dependencies = [
"chrono",
"chrono-tz",
"format_num",
"rand",
"serde",
"serde_json",
"uuid",

View File

@ -20,6 +20,7 @@ wasm-bindgen = "0.2.84"
wasm-bindgen-futures = "0.4.34"
stdweb = "0.4.20"
js-sys = "0.3"
web-sys = "0.3.61"
# other libs
reqwest = { version = "0.11.11", features = ["rustls-tls", "json", "blocking"], default-features = false }

View File

@ -1,6 +1,6 @@
use std::collections::HashSet;
use jl_types::{dto::{filters::Filter, listing::Listing, project_card::ProjectCardDto}, domain::agent::Agent};
use jl_types::{dto::{filters::Filter, listing::Listing, project_card::ProjectCardDto, payloads::contact::ContactPayload}, domain::{agent::Agent, count::Count, contact::Contact}};
use reqwest::Method;
use uuid::Uuid;
@ -26,4 +26,17 @@ pub async fn get_project_listing(project_id: &Uuid) -> Result<Listing, err::Erro
pub async fn get_all_agents() -> Result<Vec<Agent>, err::Error> {
perform_request_without_client::<String, Vec<Agent>>(BASE_URL.into(), Method::GET, format!("read/agent"), None, 200, Vec::new(), None).await
}
pub async fn get_all_page_visits_count() -> Result<Count, err::Error> {
perform_request_without_client::<String, Count>(BASE_URL.into(), Method::GET, format!("admin/visits/count"), None, 200, Vec::new(), None).await
}
pub async fn get_all_contacts_count() -> Result<Count, err::Error> {
perform_request_without_client::<String, Count>(BASE_URL.into(), Method::GET, format!("admin/contacts/count"), None, 200, Vec::new(), None).await
}
pub async fn get_all_contacts() -> Result<Vec<Contact>, err::Error> {
perform_request_without_client::<String, Vec<Contact>>(BASE_URL.into(), Method::GET, format!("admin/contacts"), None, 200, Vec::new(), None).await
}
pub async fn create_new_contact_request(contact: ContactPayload) -> Result<(), err::Error> {
perform_request_without_client(BASE_URL.into(), Method::POST, format!("read/contact"), Some(contact), 200, Vec::new(), None).await
}

View File

@ -1,10 +1,62 @@
use jl_types::dto::payloads::contact::ContactPayload;
use yew::prelude::*;
use crate::components::{nav_bar::NavigationBar, footer::PageFooter};
use crate::{components::{nav_bar::NavigationBar, footer::PageFooter}, utils::input::{get_value_from_input_event, get_value_from_textarea_event}, api::backend::create_new_contact_request};
#[function_component(ContactPage)]
pub fn contact_page() -> Html {
let first_name = use_state(|| String::new());
let last_name = use_state(|| String::new());
let credential = use_state(|| String::new());
let messsage = use_state(|| String::new());
//TODO: Think about how this renders each time an input is typed onto. (Pretty sure it does, as use_state re-renders the whole component it's in when called)
let on_fn_input_changed = {
let first_name = first_name.clone();
Callback::from(move |e: InputEvent| {
first_name.set(get_value_from_input_event(e));
})
};
let on_ln_input_changed = {
let last_name = last_name.clone();
Callback::from(move |e: InputEvent| {
last_name.set(get_value_from_input_event(e));
})
};
let on_credential_input_changed = {
let credential = credential.clone();
Callback::from(move |e: InputEvent| {
credential.set(get_value_from_input_event(e));
})
};
let on_message_input_changed = {
let messsage = messsage.clone();
Callback::from(move |e: InputEvent| {
messsage.set(get_value_from_textarea_event(e));
})
};
let onclick_button = {
let first_name = first_name.clone();
let last_name = last_name.clone();
let credential = credential.clone();
let messsage = messsage.clone();
Callback::from(move |_| {
let contact = ContactPayload {
first_name: (*first_name).clone(),
last_name: (*last_name).clone(),
credential: (*credential).clone(),
message: (*messsage).clone()
};
wasm_bindgen_futures::spawn_local(async move {
match create_new_contact_request(contact).await {
Ok(_) => {},
Err(error) => log::error!("Error in sending a contact request to the backend: {error}")
};
});
})
};
html! {
<>
<NavigationBar/>
@ -23,25 +75,25 @@ pub fn contact_page() -> Html {
<div class={"contact-us-name-container"}>
<div class={"contact-us-textfield-container"}> // First name
<div class={"contact-us-textfield-label"}>{"Nombre"}</div>
<input class={"contact-us-textfield"}/>
<input class={"contact-us-textfield"} oninput={on_fn_input_changed}/>
</div>
<div class={"contact-us-textfield-container"}> // Last name
<div class={"contact-us-textfield-label"}>{"Apellido"}</div>
<input class={"contact-us-textfield"}/>
<input class={"contact-us-textfield"} oninput={on_ln_input_changed}/>
</div>
</div>
<div class={"contact-us-textfield-container"}> // Email or Phone number
<div class={"contact-us-textfield-label"}>{"Número de Teléfono o Correo"}</div>
<input class={"contact-us-textfield"}/>
<input class={"contact-us-textfield"} oninput={on_credential_input_changed}/>
</div>
<div class={"contact-us-textfield-container"}> // Message
<div class={"contact-us-textfield-label"}>{"Mensaje"}</div>
<textarea class={"contact-us-textarea"}/>
<textarea class={"contact-us-textarea"} oninput={on_message_input_changed}/>
</div>
<div class={"contact-us-button"}>
<div class={"contact-us-button"} onclick={onclick_button}>
{"Enviar"}
</div>
</div>

View File

@ -32,14 +32,14 @@ pub fn search_page() -> Html {
cities.insert(0, OptionWrapper::new(None));
cities_handle.set(cities);
},
Err(error) => info!("Error in loading cities: {error}")
Err(error) => log::error!("Error in loading cities: {error}")
};
match get_all_projects_with_filters_paged(&(*page_counter), filters).await {
Ok(projects) => {
search_results_handle.set(projects);
finished_loading.set(true);
},
Err(error) => info!("Error in loading projects: {error}"),
Err(error) => log::error!("Error in loading projects: {error}"),
};
});
});
@ -120,7 +120,7 @@ pub fn search_page() -> Html {
districts_vec.insert(0, OptionWrapper::new(None));
districts_handle.set(districts_vec);
},
Err(error) => info!("Error in dropdown callback: {}", error),
Err(error) => log::error!("Error in dropdown callback: {}", error),
};
});
}
@ -182,6 +182,10 @@ pub fn search_page() -> Html {
Some(project_district) => filters.push(Filter::InDistrict(project_district.clone())),
None => {},
};
match &(*unit_rooms_filter).option {
Some(rooms_filter) => filters.push(Filter::ByRoomCount(*rooms_filter as i32)),
None => {},
};
let search_results_handle = search_results_handle.clone();
let page_counter = page_counter.clone();
@ -190,9 +194,8 @@ pub fn search_page() -> Html {
Ok(projects) => {
search_results_handle.set(projects)
},
Err(error) => info!("Error in loading projects: {error}"),
Err(error) => log::error!("Error in loading projects: {error}"),
};
info!("done");
});
})};

16
src/utils/input.rs Normal file
View File

@ -0,0 +1,16 @@
use wasm_bindgen::{JsCast, UnwrapThrowExt};
use web_sys::{Event, HtmlInputElement, InputEvent, HtmlTextAreaElement};
pub fn get_value_from_input_event(e: InputEvent) -> String {
let event: Event = e.dyn_into().unwrap_throw();
let event_target = event.target().unwrap_throw();
let target: HtmlInputElement = event_target.dyn_into().unwrap_throw();
target.value()
}
pub fn get_value_from_textarea_event(e: InputEvent) -> String {
let event: Event = e.dyn_into().unwrap_throw();
let event_target = event.target().unwrap_throw();
let target: HtmlTextAreaElement = event_target.dyn_into().unwrap_throw();
target.value()
}

View File

@ -1 +1,2 @@
pub mod get_value;
pub mod get_value;
pub mod input;