Added agent shortcode validation on details page.
This commit is contained in:
parent
b12b7bb34d
commit
e624aa7799
@ -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
|
@ -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
|
||||||
}
|
}
|
||||||
|
@ -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>
|
||||||
|
@ -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;
|
|
@ -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
53
src/utils/storage.rs
Normal 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.")))),
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user