Added backend api calls + network fetching hero section

This commit is contained in:
Franklin 2023-05-11 12:59:48 -04:00
parent 004564ec0b
commit 50917eecb9
15 changed files with 350 additions and 20 deletions

126
Cargo.lock generated
View File

@ -2,6 +2,15 @@
# It is not intended for manual editing.
version = 3
[[package]]
name = "aho-corasick"
version = "1.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "67fc08ce920c31afb70f013dcce1bfc3a3195de6a228474e45e1f145b36f8d04"
dependencies = [
"memchr",
]
[[package]]
name = "android_system_properties"
version = "0.1.5"
@ -78,11 +87,34 @@ dependencies = [
"js-sys",
"num-integer",
"num-traits",
"serde",
"time",
"wasm-bindgen",
"winapi",
]
[[package]]
name = "chrono-tz"
version = "0.8.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cf9cc2b23599e6d7479755f3594285efb3f74a1bdca7a7374948bc831e23a552"
dependencies = [
"chrono",
"chrono-tz-build",
"phf",
]
[[package]]
name = "chrono-tz-build"
version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d9998fb9f7e9b2111641485bf8beb32f92945f97f92a3d061f744cfef335f751"
dependencies = [
"parse-zoneinfo",
"phf",
"phf_codegen",
]
[[package]]
name = "codespan-reporting"
version = "0.11.1"
@ -200,6 +232,15 @@ dependencies = [
"percent-encoding",
]
[[package]]
name = "format_num"
version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "14ac05eb8d2eb4ed1eeff847911deae077b0b53332465de9d6a26b0ea9961bc8"
dependencies = [
"regex",
]
[[package]]
name = "futures"
version = "0.3.28"
@ -776,12 +817,59 @@ version = "1.17.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b7e5500299e16ebb147ae15a00a942af264cf3688f47923b8fc2cd5858f23ad3"
[[package]]
name = "parse-zoneinfo"
version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c705f256449c60da65e11ff6626e0c16a0a0b96aaa348de61376b249bc340f41"
dependencies = [
"regex",
]
[[package]]
name = "percent-encoding"
version = "2.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "478c572c3d73181ff3c2539045f6eb99e5491218eae919370993b890cdbdd98e"
[[package]]
name = "phf"
version = "0.11.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "928c6535de93548188ef63bb7c4036bd415cd8f36ad25af44b9789b2ee72a48c"
dependencies = [
"phf_shared",
]
[[package]]
name = "phf_codegen"
version = "0.11.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a56ac890c5e3ca598bbdeaa99964edb5b0258a583a9eb6ef4e89fc85d9224770"
dependencies = [
"phf_generator",
"phf_shared",
]
[[package]]
name = "phf_generator"
version = "0.11.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b1181c94580fa345f50f19d738aaa39c0ed30a600d95cb2d3e23f94266f14fbf"
dependencies = [
"phf_shared",
"rand",
]
[[package]]
name = "phf_shared"
version = "0.11.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e1fb5f6f826b772a8d4c0394209441e7d37cbbb967ae9c7e0e8134365c9ee676"
dependencies = [
"siphasher",
]
[[package]]
name = "pin-project"
version = "1.0.12"
@ -938,6 +1026,7 @@ dependencies = [
"err",
"js-sys",
"log",
"realtor-lp-types",
"reqwest",
"serde",
"serde_json",
@ -952,6 +1041,37 @@ dependencies = [
"yew-router",
]
[[package]]
name = "realtor-lp-types"
version = "0.1.0"
dependencies = [
"bincode",
"chrono",
"chrono-tz",
"format_num",
"rand",
"serde",
"serde_json",
"uuid",
]
[[package]]
name = "regex"
version = "1.8.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "af83e617f331cc6ae2da5443c602dfa5af81e517212d9d611a5b3ba1777b5370"
dependencies = [
"aho-corasick",
"memchr",
"regex-syntax",
]
[[package]]
name = "regex-syntax"
version = "0.7.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a5996294f19bd3aae0453a862ad728f60e6600695733dd5df01da90c54363a3c"
[[package]]
name = "reqwest"
version = "0.11.17"
@ -1116,6 +1236,12 @@ dependencies = [
"serde",
]
[[package]]
name = "siphasher"
version = "0.3.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7bd3e3206899af3f8b12af284fafc038cc1dc2b41d1b89dd17297221c5d225de"
[[package]]
name = "slab"
version = "0.4.8"

View File

@ -32,7 +32,7 @@ thousands = "0.2.0"
chrono = "0.4.23"
# Core
#realtor-lp-types = { path = "../realtor-lp-types", features = ["wasm"] }
realtor-lp-types = { path = "../realtor-lp-types", features = ["wasm"] }
[profile.release]

Binary file not shown.

After

Width:  |  Height:  |  Size: 130 KiB

BIN
assets/images/agent-pfp.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 318 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 48 KiB

View File

@ -18,7 +18,7 @@
}
.hero-banner-image {
width: 100%;
height: 150px;
height: 180px;
object-fit: cover;
background-color: rebeccapurple;
@ -33,13 +33,15 @@
border-radius: 100%;
border: 3px solid white;
background-color: white;
background-color: blue;
margin-top: -65px;
margin-top: -80px;
}
.hero-profile-picture {
object-fit: cover;
object-fit: fill;
width: 100%;
height: 100%;
border-radius: 100%;
}
.hero-name {
font-size: 20px;

View File

@ -0,0 +1,5 @@
.results-container {
display: grid;
gap: 20px;
}

View File

@ -16,6 +16,7 @@
<link data-trunk type="text/css" href="css/components/page/hero.css" rel="css" />
<link data-trunk type="text/css" href="css/components/page/agency.css" rel="css" />
<link data-trunk type="text/css" href="css/components/page/search.css" rel="css" />
<link data-trunk type="text/css" href="css/components/page/results.css" rel="css" />
<link data-trunk href="assets/text/robots.txt" rel="copy-file"/>

30
src/api/backend/mod.rs Normal file
View File

@ -0,0 +1,30 @@
use realtor_lp_types::domain::realtor::Realtor;
use reqwest::Method;
use uuid::Uuid;
use super::base::{perform_request_without_client};
const BASE_URL: &str = "http://0.0.0.0:8085/api/";
/*
pub fn get_auth_header() -> (String, String) {
let token = admin_panel::get_admin_token_from_storage();
match token {
Some(token) => (String::from("auth_token"), token),
None => (String::from("noauth"), String::new()),
}
}*/
pub async fn get_realtor_profile(realtor_id: Uuid) -> Result<Realtor, err::Error> {
perform_request_without_client::<String, Realtor>(
BASE_URL.into(),
Method::GET,
format!("public/realtor/{}", realtor_id),
None,
200,
Vec::new(),
None,
)
.await
}

119
src/api/base.rs Normal file
View File

@ -0,0 +1,119 @@
use err::{Error, MessageResource};
use reqwest::Client;
use serde::{de::DeserializeOwned, Serialize};
/// This function is mainly for when you don't have a client in your application and just want to get it over with.
/// This shouldn't be used as it takes more resource consumption than the above method.
pub async fn perform_request_without_client<B: Serialize, R: DeserializeOwned>(
base_url: String,
method: reqwest::Method,
path: String,
body: Option<B>,
expected_status_code: u16,
headers: Vec<(String, String)>,
params: Option<Vec<(String, String)>>,
) -> Result<R, Error> {
let client = Client::new();
let mut req_incomplete =
client.request(method, format!("{url}{path}", url = base_url, path = path));
for header in headers {
req_incomplete = req_incomplete.header(&header.0, &header.1);
}
if let Some(parameters) = params {
req_incomplete = req_incomplete.query(&parameters)
}
let req_complete = match body {
Some(b) => req_incomplete.json(&b),
None => req_incomplete.header("content-length", 0),
};
println!("{:?}", req_complete);
match req_complete.send().await {
// Error handling here
Ok(res) => {
// Request sent correctly
match res.status().as_u16() == expected_status_code {
true => {
match res.json::<R>().await {
Ok(resp_dto) => Ok(resp_dto), // Return correctly deserialized obj
Err(err) => Err(Error::Serde(MessageResource::from(err))),
}
}
false => {
//If status code is any other than expected
Err(Error::UnexpectedStatusCode(
expected_status_code,
res.status().as_u16(),
match res.json::<Vec<MessageResource>>().await {
Ok(messages) => messages,
Err(e) => vec![MessageResource::from(e)],
},
))
}
}
}
Err(e) => {
// Request couldn't be sent
Err(Error::Network(MessageResource::from(e)))
}
}
}
#[allow(unused)]
pub async fn perform_multipart_request_without_client<R: DeserializeOwned>(
base_url: String,
method: reqwest::Method,
path: String,
body: Vec<u8>,
expected_status_code: u16,
headers: Vec<(String, String)>,
params: Option<Vec<(String, String)>>,
) -> Result<R, Error> {
let client = Client::new();
let mut req_incomplete =
client.request(method, format!("{url}{path}", url = base_url, path = path));
for header in headers {
req_incomplete = req_incomplete.header(&header.0, &header.1);
}
if let Some(parameters) = params {
req_incomplete = req_incomplete.query(&parameters)
}
let part = reqwest::multipart::Part::bytes(body).file_name("image");
let form = reqwest::multipart::Form::new();
let form = form.part("image", part);
match req_incomplete.multipart(form).send().await {
// Error handling here
Ok(res) => {
// Request sent correctly
match res.status().as_u16() == expected_status_code {
true => {
match res.json::<R>().await {
Ok(resp_dto) => Ok(resp_dto), // Return correctly deserialized obj
Err(err) => Err(Error::Serde(MessageResource::from(err))),
}
}
false => {
//If status code is any other than expected
Err(Error::UnexpectedStatusCode(
expected_status_code,
res.status().as_u16(),
match res.json::<Vec<MessageResource>>().await {
Ok(messages) => messages,
Err(e) => vec![MessageResource::from(e)],
},
))
}
}
}
Err(e) => {
// Request couldn't be sent
Err(Error::Network(MessageResource::from(e)))
}
}
}

View File

@ -1 +1,2 @@
pub mod backend;
pub mod base;

View File

@ -5,10 +5,10 @@ pub fn agency_section() -> Html {
html! {
<div class={"agency-container"}>
<div class={"agency-head-1"}>
{"Meet Our"}
{"Conoce mas"}
</div>
<div class={"agency-head-2"}>
{"Partner"}
{"Sobre Nosotros"}
</div>
<img class={"agency-logo"} src={"images/remax-logo.png"} alt={"agency-logo"}/>
<div class="agency-body">

View File

@ -1,27 +1,38 @@
use realtor_lp_types::domain::realtor::Realtor;
use yew::prelude::*;
#[derive(PartialEq, Properties)]
pub struct HeroSectionProps {
pub realtor: Realtor
}
#[function_component(HeroSection)]
pub fn hero_section() -> Html {
pub fn hero_section(props: &HeroSectionProps) -> Html {
html! {
<div class={"hero-container"}>
<div class={"hero-profile-container"}>
<img class={"hero-banner-image"} src="" alt="realtor-banner-image"/>
<img class={"hero-banner-image"} src={
match props.realtor.banner_picture_url.clone() {
Some(url) => url,
None => "images/agent-banner.png".to_string()
}} alt="realtor-banner-image"/>
<div class={"hero-profile-picture-container"}>
<img class={"hero-profile-picture"} src="" alt="realtor-pfp"/>
<img class={"hero-profile-picture"} src={props.realtor.profile_picture_url.clone()} alt="realtor-pfp"/>
</div>
<div class={"hero-name"}>
{"Brooklyn Simmons"}
{props.realtor.name.clone()}
</div>
<div class={"hero-title"}>
{"Agent"}
{"Director Regional Remax Metropolitana RD"}
</div>
</div>
<div class={"hero-about-me-container"}>
<div class={"hero-about-me-title"}>
{"About me"}
{"Sobre mí"}
</div>
<div class={"hero-about-me-body"}>
{"Lorem ipsum dolor sit amet consectetur. Mauris sapien arcu ac quis eget sed nullam. Facilisi odio leo non lectus tincidunt orci dictum sed. Id vulputate maecenas scelerisque pellentesque rhoncus at ullamcorper."}
{props.realtor.bio.clone()}
</div>
</div>
</div>

View File

@ -2,5 +2,10 @@ use yew::prelude::*;
#[function_component(ResultsSection)]
pub fn results_section() -> Html {
html! {}
html! {
<div class={"results-container"}>
</div>
}
}

View File

@ -1,18 +1,48 @@
use std::str::FromStr;
use uuid::Uuid;
use yew::prelude::*;
use crate::components::{
use crate::{components::{
footer::Footer,
page::{
agency::AgencySection, contact::ContactSection, hero::HeroSection, results::ResultsSection,
search::SearchSection,
},
};
}, api::backend};
#[function_component(MainPage)]
pub fn main_page() -> Html {
let realtor_id = Uuid::from_str("544eac57-a80d-457e-9ee8-7ec14b2bebd0").unwrap();
let realtor_handle = use_state(|| None);
use_state(|| {
let realtor_handle = realtor_handle.clone();
wasm_bindgen_futures::spawn_local(async move {
realtor_handle.set(match backend::get_realtor_profile(realtor_id).await {
Ok(realtor) => Some(realtor),
Err(error) => {
log::error!("Error getting realtor_handle: {error}");
None
},
});
});
});
html! {
<div class={"main-page-container"}>
<HeroSection/>
{
if let Some(realtor) = (*realtor_handle).clone() {
html! {
<HeroSection realtor={realtor}/>
}
} else {
html! {
}
}
}
<AgencySection/>
<SearchSection/>
<ResultsSection/>