Added agent shortcode validation on details page.

This commit is contained in:
Franklin 2023-04-15 08:41:18 -04:00
parent b12b7bb34d
commit e624aa7799
7 changed files with 117 additions and 11 deletions

View File

@ -22,7 +22,7 @@
- [x] Space between Unit selection menu and unit media on empty unit features - [x] Space between Unit selection menu and unit media on empty unit features
- [x] Make the navbar logo bigger - [x] Make the navbar logo bigger
- [x] Finish agents screen - [x] Finish agents screen
- [ ] Finish Contact us screen - [x] Finish Contact us screen
- [x] Link agent info with details screen, remove hardcoded pic and details - [x] Link agent info with details screen, remove hardcoded pic and details
- [x] Whatsapp button should direct to agent's phone number wa.me link - [x] Whatsapp button should direct to agent's phone number wa.me link
@ -31,5 +31,5 @@ New todo's
- [ ] Static image folder for start page - [ ] Static image folder for start page
- [ ] Admin panel with page loads & contact us clicks - [ ] Admin panel with page loads & contact us clicks
- [ ] Put JL on top of the Agents section - [ ] Put JL on top of the Agents section
- [ ] If someone enters the page from an agent, make anything that appears on the website reference them. - [x] If someone enters the page from an agent, make anything that appears on the website reference them.
- [x] Contact us Functionality - [x] Contact us Functionality

View File

@ -28,6 +28,10 @@ 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 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_agent_with_shortcode(shortcode: &String) -> Result<Agent, err::Error> {
perform_request_without_client::<String, Agent>(BASE_URL.into(), Method::GET, format!("read/agent/{shortcode}"), None, 200, Vec::new(), None).await
}
pub async fn get_all_page_visits_count() -> Result<Count, err::Error> { 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 perform_request_without_client::<String, Count>(BASE_URL.into(), Method::GET, format!("admin/visits/count"), None, 200, Vec::new(), None).await
} }

View File

@ -1,15 +1,52 @@
use jl_types::{dto::listing::Listing, domain::{unit_type::UnitType, unit::Unit}}; use jl_types::{dto::listing::Listing, domain::{unit_type::UnitType, unit::Unit, agent::Agent}};
use log::{error}; use log::{error};
use thousands::Separable; use thousands::Separable;
use uuid::Uuid; use uuid::Uuid;
use yew::prelude::*; use yew::prelude::*;
use yew_router::{prelude::{use_location}};
use crate::{components::{nav_bar::NavigationBar, media_slideshow::MediaSlideshow, floating_widget::FloatingWidget, feature::FeatureItem, footer::PageFooter}, api::backend::get_project_listing}; use crate::{components::{nav_bar::NavigationBar, media_slideshow::MediaSlideshow, floating_widget::FloatingWidget, feature::FeatureItem, footer::PageFooter}, api::backend::{get_project_listing, get_agent_with_shortcode}, utils::storage::{self, StorageKey}};
const ALPHABET_LETTERS: &str = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"; const ALPHABET_LETTERS: &str = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
#[function_component(DetailsPage)] #[function_component(DetailsPage)]
pub fn details_page(props: &DetailsPageProps) -> Html { pub fn details_page(props: &DetailsPageProps) -> Html {
// Agent shortcode part
let location = use_location().unwrap();
let query_params: Vec<(String, String)> = location.query().unwrap();
let override_agent_handle: UseStateHandle<Option<Agent>> = use_state(|| None);
for query_param in query_params {
if query_param.0 == String::from("shortcode") {
// Store shortcode in localstorage
match storage::store_in_local_storage(StorageKey::AgentShortcode, &query_param.1) {
Ok(_) => {},
Err(error) => log::error!("Error storing agent shortcode in localstorage\n: {}", error),
};
}
}
let persisted_shortcode_res = storage::get_from_local_storage(StorageKey::AgentShortcode);
match persisted_shortcode_res {
Ok(persisted_shortcode_opt) => {
match persisted_shortcode_opt {
Some(persisted_shortcode) => {
// Get agent from server
let override_agent_handle = override_agent_handle.clone();
wasm_bindgen_futures::spawn_local(async move {
match get_agent_with_shortcode(&persisted_shortcode).await {
Ok(agent) => { override_agent_handle.set(Some(agent)) },
Err(error) => error!("Error fetching agent with shortcode. Error: {:?}", error),
};
})
},
None => {}
}
},
Err(error) => log::error!("Error reading agent shortcode from localstorage\n: {}", error),
};
// Project loading part
let finished_loading = use_state(|| false); let finished_loading = use_state(|| false);
let listing_handle: UseStateHandle<Listing> = use_state(|| Listing::default()); let listing_handle: UseStateHandle<Listing> = use_state(|| Listing::default());
let selected_unit_handle = use_state(|| 0); let selected_unit_handle = use_state(|| 0);
@ -54,7 +91,10 @@ pub fn details_page(props: &DetailsPageProps) -> Html {
html!{ html!{
<> <>
<NavigationBar/> <NavigationBar/>
<FloatingWidget phone_number={listing.agent.credential.clone()} project_id={listing.project.id}/> <FloatingWidget phone_number={
if let Some(overriden_agent) = (*override_agent_handle).clone()
{ overriden_agent.credential.clone() } else { listing.agent.credential.clone() }
} project_id={listing.project.id}/>
<div class={"page-container"}> <div class={"page-container"}>
{ {
if *finished_loading { if *finished_loading {
@ -67,12 +107,21 @@ pub fn details_page(props: &DetailsPageProps) -> Html {
// Agent // Agent
<div class={"details-head-agent-container"}> <div class={"details-head-agent-container"}>
// Profile pic // Profile pic
<img class={"details-head-agent-profile-picture"} src={listing.agent.profile_picture_url} alt={"agent_pfp"}/> <img class={"details-head-agent-profile-picture"} src={
if let Some(overriden_agent) = (*override_agent_handle).clone()
{ overriden_agent.profile_picture_url.clone() } else { listing.agent.profile_picture_url.clone() }
} alt={"agent_pfp"}/>
<div class={"details-head-agent-text-container"}> <div class={"details-head-agent-text-container"}>
<div class={"details-head-agent-heading"}>{listing.agent.full_name}</div> <div class={"details-head-agent-heading"}>{
if let Some(overriden_agent) = (*override_agent_handle).clone()
{ overriden_agent.full_name.clone() } else { listing.agent.full_name.clone() }
}</div>
<div class={"details-head-agent-subheading"}>{ <div class={"details-head-agent-subheading"}>{
format_phone_number(&listing.agent.credential) format_phone_number(&{
if let Some(overriden_agent) = (*override_agent_handle).clone()
{ overriden_agent.credential.clone() } else { listing.agent.credential.clone() }
})
}</div> }</div>
</div> </div>
</div> </div>

View File

@ -4,5 +4,4 @@ pub mod details;
pub mod not_found; pub mod not_found;
pub mod contact; pub mod contact;
pub mod admin; pub mod admin;
pub mod agents; pub mod agents;
pub mod thanks;

View File

View File

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

53
src/utils/storage.rs Normal file
View File

@ -0,0 +1,53 @@
use std::fmt::Display;
use err::{MessageResource, Error};
use web_sys::window;
pub enum StorageKey {
AgentShortcode,
}
impl Display for StorageKey {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
StorageKey::AgentShortcode => write!(f, "agentshortcode"),
}
}
}
/// Store a simple string in local storage. Result is just for error handling,
/// no value is returned in case of success.
pub fn store_in_local_storage(key: StorageKey, val: &str) -> Result<(), Error> {
match window() {
Some(window) => match window.local_storage() {
Ok(local_storage_opt) => match local_storage_opt {
Some(local_storage) => match local_storage.set_item(key.to_string().as_str(), val) {
Ok(_) => Ok(()),
Err(js_err) => Err(Error::IO(MessageResource::new_from_string(format!("JsValue: {:#?}", js_err.as_string())))),
},
None => Err(Error::IO(MessageResource::new_from_str("Error accessing local storage instance from window object. Result was fine, option came back as none."))),
},
Err(e) => Err(Error::IO(MessageResource::new_from_string(format!("Error accessing local storage instance from window object. Resulting error: {:#?}", e.as_string())))),
},
None => Err(Error::IO(MessageResource::new_from_string(format!("Error accessing Window object.")))),
}
}
/// Call all the javascript API's to get an item from LocalStorage
/// This fn returns a Result<Option<String>> Since there can be an error
/// accessing the objects/instances needed to access the item and there
/// can also be an absence of the item itself.
pub fn get_from_local_storage(key: StorageKey) -> Result<Option<String>, Error> {
match window() {
Some(window) => match window.local_storage() {
Ok(local_storage_opt) => match local_storage_opt {
Some(local_storage) => match local_storage.get_item(key.to_string().as_str()) {
Ok(value) => Ok(value),
Err(js_err) => Err(Error::IO(MessageResource::new_from_string(format!("JsValue: {:#?}", js_err.as_string())))),
},
None => Err(Error::IO(MessageResource::new_from_str("Error accessing local storage instance from window object. Result was fine, option came back as none."))),
},
Err(e) => Err(Error::IO(MessageResource::new_from_string(format!("Error accessing local storage instance from window object. Resulting error: {:#?}", e.as_string())))),
},
None => Err(Error::IO(MessageResource::new_from_string(format!("Error accessing Window object.")))),
}
}