From 090d285ff9ef017edaea7c8b860f4bd96955401a Mon Sep 17 00:00:00 2001 From: Franklin Date: Thu, 13 Apr 2023 09:19:17 -0400 Subject: [PATCH] Fixed spacing issues, added most client corrections and remax logo to footer, along with socials --- Readme.md | 15 ++- css/admin-login.css | 0 css/components/footer.css | 42 +++++++- css/components/media_slideshow.css | 15 ++- css/details.css | 51 ++++++---- css/navbar.css | 4 + css/search.css | 3 +- index.html | 3 + src/components/footer.rs | 20 +++- src/components/nav_bar.rs | 12 ++- src/components/project_card.rs | 2 +- src/constants/mod.rs | 1 + src/pages/admin/login.rs | 19 ++++ src/pages/admin/mod.rs | 1 + src/pages/agents.rs | 17 ++++ src/pages/details.rs | 153 +++++++++++++++++------------ src/pages/mod.rs | 4 +- src/pages/search.rs | 31 +++++- src/routes/main_router.rs | 11 ++- 19 files changed, 303 insertions(+), 101 deletions(-) create mode 100644 css/admin-login.css create mode 100644 src/pages/admin/login.rs create mode 100644 src/pages/admin/mod.rs create mode 100644 src/pages/agents.rs diff --git a/Readme.md b/Readme.md index 7e8dffa..6a6011f 100644 --- a/Readme.md +++ b/Readme.md @@ -6,4 +6,17 @@ - [ ] Show page to client and start work on admin panel - [ ] Whatsapp button link - [ ] Contact widget should be whatsapp OR email depending on agent contact info -- [ ] Footer should have call to action? \ No newline at end of file +- [ ] Footer should have call to action? + +- [x] If no properties are found footer jumps up, shouldn't happen. +- [x] Agentes / Quienes Somos (Similar al de remax) (recordar poner a jorge ledesma de primero y despues a los demas agentes) +- [x] Que se pueda buscar por cant. de habitaciones +- [x] Cambiar unidad 1 unid 2 etc... -> Tipo A Tipo B Tipo C Etc... +- [x] Cambiar orden de el menu de unidades (poner area comun de ultimo) y quitar que se pueda varias areas comunes +- [x] Spacing de menu de unidades +- [x] Poner Features arriba de la desc y las imagenes de la unidad +- [ ] Poner el logo de remax en el footer +- [ ] Poner logos de facebook, instagram, youtube, en el footer (Sin enlaces) +- [ ] Poner boton de solicita tu prestamo, que rediriga a remax (Se te dará el enlace), abajo de el disclaimer en la página de detalles de proyecto +- [ ] Contenido statico folder de imagenes para la imagen de portada de inicio, que se roten aleatoriamente cada día +- [x] Space between Unit selection menu and unit media on empty unit features \ No newline at end of file diff --git a/css/admin-login.css b/css/admin-login.css new file mode 100644 index 0000000..e69de29 diff --git a/css/components/footer.css b/css/components/footer.css index 8a95967..e6e280c 100644 --- a/css/components/footer.css +++ b/css/components/footer.css @@ -2,11 +2,11 @@ .footer { display: flex; flex-direction: row; - justify-content: center; + justify-content: space-evenly; align-items: center; width: 100%; - height: 170px; + height: 210px; background-color: #02114A; } @@ -19,11 +19,28 @@ height: 100%; margin-left: 20px; } +.footer-remax-container { + display: flex; + flex-direction: row; + justify-content: center; + align-items: center; + gap: 20px; + + height: 100%; +} .footer-logo { object-fit: cover; width: 100px; height: 100px; } +.footer-remax-logo { + position: absolute; + margin-left: 140px; + margin-top: -15px; + object-fit: cover; + width: 40px; + height: 40px; +} .footer-copyright-text { font-size: 9px; font-family: Inter; @@ -36,6 +53,7 @@ justify-content: center; align-items: center; gap: 3px; + margin-bottom: 10px; } .footer-credit { font-size: 13px; @@ -54,6 +72,26 @@ cursor: pointer; transition-duration: 0.4s; } +.footer-brand-socials { + display: flex; + flex-direction: row; + justify-content: center; + align-items: center; + gap: 20px; + + width: 100%; +} +.footer-brand-social-container { + display: flex; + justify-content: center; + align-items: center; + + width: 30px; + height: 30px; + border-radius: 30px; + background-color: white; +} + /* .footer-call-to-action-container { display: flex; diff --git a/css/components/media_slideshow.css b/css/components/media_slideshow.css index 2c8c98b..480b2cc 100644 --- a/css/components/media_slideshow.css +++ b/css/components/media_slideshow.css @@ -80,4 +80,17 @@ @keyframes fade { from {opacity: .4} to {opacity: 1} - } \ No newline at end of file + } + +/* Desktop view */ +@media only screen and (min-width: 750px) { + .media-slideshow-frame { + height: 55vw; + max-height: 550px; + } +} + +/* Desktop view */ +@media only screen and (min-width: 1200px) { + +} \ No newline at end of file diff --git a/css/details.css b/css/details.css index 4589726..203ce48 100644 --- a/css/details.css +++ b/css/details.css @@ -7,7 +7,7 @@ Divide the Details page into 3 main sections: display: flex; flex-direction: column; justify-content: stretch; - align-items: start; + align-items: center; padding: 0px 15px; margin-top: 30px; } @@ -18,6 +18,7 @@ Divide the Details page into 3 main sections: justify-content: stretch; align-items: center; width: 100%; + max-width: 1000px; gap: 20px; margin-bottom: 15px; } @@ -70,9 +71,10 @@ Divide the Details page into 3 main sections: .details-body { display: flex; flex-direction: column; - justify-content: stretch; + justify-content: center; align-items: center; width: 100%; + max-width: 1000px; gap: 15px; margin-top: -10px; margin-bottom: 30px; @@ -95,14 +97,15 @@ Divide the Details page into 3 main sections: .details-body-features { display: flex; - flex-direction: column; - justify-content: stretch; - align-items: start; - gap: 25px; + flex-flow: row wrap; + flex-direction: row; + justify-content: center; + align-items: center; + gap: 3%; width: 100%; height: 200px; - margin-bottom: 60px; + margin: 20px 0px; } .details-body-feature-item { @@ -114,6 +117,7 @@ Divide the Details page into 3 main sections: font-family: Inter; font-size: 24px; + width: clamp(200px, calc(100% * (0.40) - 10px), 1000px); } .details-body-feature-item-icon-container { @@ -162,10 +166,9 @@ Divide the Details page into 3 main sections: .details-body-units-selection-container { display: flex; flex-direction: row; - justify-content: center; + justify-content: space-evenly; align-items: center; flex-wrap: wrap; - gap: 30px; width: 100%; } @@ -214,20 +217,26 @@ Divide the Details page into 3 main sections: color: rgba(34, 34, 34, 0.873); } -.details-body-unit-features { - display: flex; - flex-direction: column; - justify-content: stretch; - align-items: start; - gap: 25px; - - width: 100%; - height: 200px; - margin-bottom: 60px; -} - .details-body-disclaimer { width: 100%; font-size: 13px; font-family: Inter; +} + +/* Desktop view */ +@media only screen and (min-width: 750px) { + .details-body-units-media-slideshow-frame { + height: 55vw; + max-height: 550px; + } + .details-body-features { + flex-direction: row; + flex-flow: row wrap; + justify-content: center; + align-items: center; + } +} +/* Desktop view */ +@media only screen and (min-width: 1200px) { + } \ No newline at end of file diff --git a/css/navbar.css b/css/navbar.css index bf5f1fa..e59b73a 100644 --- a/css/navbar.css +++ b/css/navbar.css @@ -117,6 +117,9 @@ padding-bottom: 10px; font-family: Space Grotesk; } +.navbar-item-selected:hover { + cursor: default; +} .navbar-item:hover { background-color: #ffffff14; font-size: 13pt; @@ -207,6 +210,7 @@ padding-bottom: 10px; font-family: Source Sans Pro; font-weight: bold; + } .navbar-item:hover { diff --git a/css/search.css b/css/search.css index de81730..0fc2a63 100644 --- a/css/search.css +++ b/css/search.css @@ -92,7 +92,7 @@ .project-search-button { margin-top: 20px; height: 50px; - background-color: #5D6A73; + background-color: #02114A; color: white; border: 0px; border-radius: 5px; @@ -105,7 +105,6 @@ cursor: pointer; font-size: 24px; transition-duration: 0.3s; - background-color: #252631; } /* Results */ diff --git a/index.html b/index.html index 9a021c8..f5b9c17 100644 --- a/index.html +++ b/index.html @@ -10,10 +10,13 @@ + + + diff --git a/src/components/footer.rs b/src/components/footer.rs index fdb3b5f..0764025 100644 --- a/src/components/footer.rs +++ b/src/components/footer.rs @@ -5,7 +5,21 @@ pub fn page_footer() -> Html { html! {
- +
+ + +
+
+
+ +
+
+ +
+
+ +
+
{"Powered by"}
@@ -13,6 +27,10 @@ pub fn page_footer() -> Html {
+ + + + /*
diff --git a/src/components/nav_bar.rs b/src/components/nav_bar.rs index 632d14c..3f2a74e 100644 --- a/src/components/nav_bar.rs +++ b/src/components/nav_bar.rs @@ -2,7 +2,7 @@ use stdweb::web::{IEventTarget, event::ResizeEvent}; use yew::prelude::*; use yew_router::prelude::{use_navigator, use_route}; -use crate::{routes::main_router::{Route}, constants::{NAVBAR_COL_LANDING, NAVBAR_COL_CONTACTO, NAVBAR_COL_PROYECTOS}}; +use crate::{routes::main_router::{Route}, constants::{NAVBAR_COL_LANDING, NAVBAR_COL_CONTACTO, NAVBAR_COL_PROYECTOS, NAVBAR_COL_AGENTES}}; //use yew_router::prelude::use_navigator; @@ -16,6 +16,7 @@ pub fn navigation_bar() -> Html { let cloned_navigator_3 = navigator.clone(); let cloned_navigator_4 = navigator.clone(); let cloned_navigator_5 = navigator.clone(); + let cloned_navigator_6 = navigator.clone(); let navbar_toggle = use_state(|| true); let on_click_hamburger = { @@ -54,10 +55,17 @@ pub fn navigation_bar() -> Html {
{NAVBAR_COL_PROYECTOS}
+ +
+ {NAVBAR_COL_AGENTES} +
+ { if (*window_device_handle) == WindowDevice::Mobile { html! { diff --git a/src/components/project_card.rs b/src/components/project_card.rs index 7e51f76..64fc414 100644 --- a/src/components/project_card.rs +++ b/src/components/project_card.rs @@ -27,7 +27,7 @@ pub fn project_card(props: &ProjectCardProps) -> Html { let project_title = format!("{} en {}, {}", props.project.project_type, props.project.district, props.project.city); - let project_price = format!("Desde ${} USD", match props.project.starts_from { + let project_price = format!("Desde US${}", match props.project.starts_from { Some(price) => { let price_separated = price.separate_with_commas(); if price_separated.contains(".") { diff --git a/src/constants/mod.rs b/src/constants/mod.rs index e0eceba..3acbbfc 100644 --- a/src/constants/mod.rs +++ b/src/constants/mod.rs @@ -1,6 +1,7 @@ pub const NAVBAR_COL_LANDING: &str = "Inicio"; pub const NAVBAR_COL_PROYECTOS: &str = "Proyectos"; pub const NAVBAR_COL_CONTACTO: &str = "Contacto"; +pub const NAVBAR_COL_AGENTES: &str = "Agentes"; pub const PRIMARY_COLOR: &str = "#41BDD9"; pub const SECONDARY_COLOR: &str = "#5D6A73"; \ No newline at end of file diff --git a/src/pages/admin/login.rs b/src/pages/admin/login.rs new file mode 100644 index 0000000..bb78d08 --- /dev/null +++ b/src/pages/admin/login.rs @@ -0,0 +1,19 @@ +use yew::prelude::*; +use yew_router::prelude::use_navigator; + +#[function_component(AdminLoginPage)] +pub fn login_page() -> Html { + let _navigator = use_navigator().unwrap(); + html! { + + } +} \ No newline at end of file diff --git a/src/pages/admin/mod.rs b/src/pages/admin/mod.rs new file mode 100644 index 0000000..b3044f6 --- /dev/null +++ b/src/pages/admin/mod.rs @@ -0,0 +1 @@ +pub mod login; \ No newline at end of file diff --git a/src/pages/agents.rs b/src/pages/agents.rs new file mode 100644 index 0000000..6ce2a3f --- /dev/null +++ b/src/pages/agents.rs @@ -0,0 +1,17 @@ +use yew::prelude::*; + +use crate::components::{nav_bar::NavigationBar, footer::PageFooter}; + + +#[function_component(AgentsPage)] +pub fn agents_page() -> Html { + html!{ + <> + +
//TODO: remove this margin when landing page done + {"Agents Page"} +
+ + + } +} \ No newline at end of file diff --git a/src/pages/details.rs b/src/pages/details.rs index e58e63a..4e38a6b 100644 --- a/src/pages/details.rs +++ b/src/pages/details.rs @@ -1,4 +1,4 @@ -use jl_types::{dto::listing::Listing, domain::unit_type::UnitType}; +use jl_types::{dto::listing::Listing, domain::{unit_type::UnitType, unit::Unit}}; use log::{error, info}; use thousands::Separable; use uuid::Uuid; @@ -6,6 +6,8 @@ use yew::prelude::*; use crate::{components::{nav_bar::NavigationBar, media_slideshow::MediaSlideshow, floating_widget::FloatingWidget, feature::FeatureItem, footer::PageFooter}, api::backend::get_project_listing}; +const ALPHABET_LETTERS: &str = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"; + #[function_component(DetailsPage)] pub fn details_page(props: &DetailsPageProps) -> Html { let finished_loading = use_state(|| false); @@ -30,6 +32,12 @@ pub fn details_page(props: &DetailsPageProps) -> Html { }); let listing = (*listing_handle).clone(); + let mut forsale_units: Vec<&Unit> = listing.units.iter().filter(|unit| unit.unit_type == UnitType::ForSale).collect(); + let mut not_forsale_units: Vec<&Unit> = listing.units.iter().filter(|unit| unit.unit_type == UnitType::NotForSale).collect(); + + let mut organized_units = Vec::new(); + organized_units.append(&mut forsale_units); + organized_units.append(&mut not_forsale_units); let project_title = format!("{} en {}, {}", &listing.project.project_type, &listing.location.district, &listing.location.city); //let project_description = &listing.project.description; @@ -43,7 +51,7 @@ pub fn details_page(props: &DetailsPageProps) -> Html { let cloned_selected_unit_handle = selected_unit_handle.clone(); - let selected_unit_opt = listing.units.get(*cloned_selected_unit_handle); + let selected_unit_opt = organized_units.get(*cloned_selected_unit_handle); html!{ <> @@ -68,10 +76,10 @@ pub fn details_page(props: &DetailsPageProps) -> Html {
- +
-
+
@@ -109,43 +117,39 @@ pub fn details_page(props: &DetailsPageProps) -> Html { html! {
{"Unidades"}
-
- { // Maps all the units to generate the unit selection menu - listing.units.iter().enumerate().map(|(index, unit)| { - let cloned_selected_unit_handle = cloned_selected_unit_handle.clone(); - let select_unit_onclick_cb = { - let cloned_selected_unit_handle = cloned_selected_unit_handle.clone(); - Callback::from(move |_| cloned_selected_unit_handle.set(index)) - }; - html! { -
- { - match unit.unit_type { - UnitType::ForSale => html! { - <> - -
{format!("Unidad {}", index + 1)}
- - }, - UnitType::NotForSale => html! { - <> - -
{"Área común"}
- - } - } + + {create_unit_selection_menu(&organized_units, selected_unit_handle)} + + { + if unit.unit_type == UnitType::ForSale { + let price_separated = unit.price_usd.separate_with_commas(); + html! { +
+ { + html! { + <> + + + + + } - -
- } - }).collect::() + } +
+ } + } else { + html! {} } -
+ } + + +
{ if unit.media.media_list.len() >= 1 { @@ -172,32 +176,7 @@ pub fn details_page(props: &DetailsPageProps) -> Html {
-
- - { // Features only to be shown on a ForSale unit - if unit.unit_type == UnitType::ForSale { - let price_separated = unit.price_usd.separate_with_commas(); - html! { - <> - - - - - } - } else {html! {}} - } - - // Features that always are shown - -
- -
+
{"*Unidades sujetas a disponibilidad"} @@ -244,3 +223,47 @@ pub struct DetailsPageProps { } +pub fn create_unit_selection_menu(units: &Vec<&Unit>, selected_unit_handle: UseStateHandle) -> Html { + + html! { +
+ { // Maps all the units to generate the unit selection menu + units.iter().enumerate().map(|(index, unit)| { + let cloned_selected_unit_handle = selected_unit_handle.clone(); + let select_unit_onclick_cb = { + let cloned_selected_unit_handle = cloned_selected_unit_handle.clone(); + Callback::from(move |_| cloned_selected_unit_handle.set(index)) + }; + html! { +
+ { + match unit.unit_type { + UnitType::ForSale => html! { + <> + +
{format!("Unidad {}", ALPHABET_LETTERS.chars().nth(index).unwrap_or_else(|| index.to_string().chars().nth(1).unwrap()))}
+ + }, + UnitType::NotForSale => html! { + <> + +
{"Área común"}
+ + } + } + } + +
+ } + }).collect::() + + + } +
+ } +} \ No newline at end of file diff --git a/src/pages/mod.rs b/src/pages/mod.rs index de4016d..7796b72 100644 --- a/src/pages/mod.rs +++ b/src/pages/mod.rs @@ -2,4 +2,6 @@ pub mod landing; pub mod search; pub mod details; pub mod not_found; -pub mod contact; \ No newline at end of file +pub mod contact; +pub mod admin; +pub mod agents; \ No newline at end of file diff --git a/src/pages/search.rs b/src/pages/search.rs index 0813b2f..df17c34 100644 --- a/src/pages/search.rs +++ b/src/pages/search.rs @@ -54,6 +54,7 @@ pub fn search_page() -> Html { let project_city_filter: UseStateHandle> = use_state(|| OptionWrapper::new(None)); // Dropdown let project_district_filter: UseStateHandle> = use_state(|| OptionWrapper::new(None)); + let unit_rooms_filter: UseStateHandle> = use_state(|| OptionWrapper::new(None)); //TODO: Think about price filtering /*// TextField let _project_min_price_filter: UseStateHandle> = use_state(|| OptionWrapper::new(None)); @@ -111,7 +112,6 @@ pub fn search_page() -> Html { Callback::from(move |project_city: OptionWrapper| { let districts_handle = districts_handle.clone(); - info!("{}", project_city.to_string()); cloned_project_city_filter.set(project_city.clone()); wasm_bindgen_futures::spawn_local(async move { match get_all_districts_in_city(&project_city.to_string()).await { @@ -134,13 +134,24 @@ pub fn search_page() -> Html { selection_changed: { let cloned_project_district_filter = project_district_filter.clone(); Callback::from(move |project_district: OptionWrapper| { - info!("{}", project_district.to_string()); cloned_project_district_filter.set(project_district) } )}, class_css: Some("project-search-filter-item".into()) }); + let unit_room_amount_drop_down = comp_with::>>(DropDownProps { + initial: OptionWrapper::new(None), + options: vec![OptionWrapper::new(None), OptionWrapper::new(Some(1)), OptionWrapper::new(Some(2)), OptionWrapper::new(Some(3)), OptionWrapper::new(Some(4)), OptionWrapper::new(Some(5)), OptionWrapper::new(Some(6)), OptionWrapper::new(Some(7)), OptionWrapper::new(Some(8)), OptionWrapper::new(Some(9)), OptionWrapper::new(Some(10))], + selection_changed: { + let unit_rooms_filter = unit_rooms_filter.clone(); + Callback::from(move |unit_room_amount: OptionWrapper| { + unit_rooms_filter.set(unit_room_amount) + }) + }, + class_css: Some("project-search-filter-item".into()) + }); + let search_onclick = { let search_results_handle = search_results_handle.clone(); let page_counter = page_counter.clone(); @@ -262,6 +273,13 @@ pub fn search_page() -> Html { {project_district_drop_down}
+
+
+ {"Habitaciones"} +
+ {unit_room_amount_drop_down} +
+ @@ -273,6 +291,15 @@ pub fn search_page() -> Html { if *finished_loading { html!{
// Search Results Content + {if (*search_results_handle).len() == 0 { + html!{ +
+ {"No se han encontrado proyectos con los filtros de busqueda especificados."} +
+ } + } else { + html! {} + }} {(*search_results_handle).clone().into_iter().map(|project| html!{}).collect::()}
} diff --git a/src/routes/main_router.rs b/src/routes/main_router.rs index 0dcff53..88fe5d2 100644 --- a/src/routes/main_router.rs +++ b/src/routes/main_router.rs @@ -3,7 +3,7 @@ use yew::prelude::*; use uuid::Uuid; -use crate::{pages::{landing::LandingPage, search::{SearchPage}, details::DetailsPage, not_found::NotFoundPage, contact::ContactPage}}; +use crate::{pages::{landing::LandingPage, search::{SearchPage}, details::DetailsPage, not_found::NotFoundPage, contact::ContactPage, admin::login::AdminLoginPage, agents::AgentsPage}}; #[derive(Clone, Routable, PartialEq)] pub enum Route { @@ -15,6 +15,11 @@ pub enum Route { Details { project_id: Uuid }, #[at("/contact")] Contact, + #[at("/agentes")] + Agentes, + + #[at("/admin")] + Admin, #[not_found] #[at("/404")] @@ -27,6 +32,8 @@ pub fn switch(routes: Route) -> Html { Route::Search => html! { }, Route::Details { project_id } => html! { }, Route::NotFound => html! { }, - Route::Contact => html! { } + Route::Contact => html! { }, + Route::Admin => html! { }, + Route::Agentes => html! { }, } } \ No newline at end of file