From c693287063454e2ab80ee475d5ab263f1076152f Mon Sep 17 00:00:00 2001 From: Franklin Date: Sat, 15 Apr 2023 20:37:35 -0400 Subject: [PATCH] a --- css/admin-agents.css | 0 css/admin-contacts.css | 0 css/admin-projects.css | 9 ++ css/components/admin_project.css | 60 +++++++++++ css/edit.css | 24 +++++ index.html | 5 + src/components/admin_project.rs | 62 +++++++++++ src/components/mod.rs | 3 +- src/pages/admin/agents.rs | 21 +++- src/pages/admin/contacts.rs | 20 +++- src/pages/admin/edit.rs | 174 +++++++++++++++++++++++++++++++ src/pages/admin/mod.rs | 3 +- src/pages/admin/projects.rs | 32 +++++- src/routes/main_router.rs | 7 +- 14 files changed, 406 insertions(+), 14 deletions(-) create mode 100644 css/admin-agents.css create mode 100644 css/admin-contacts.css create mode 100644 css/admin-projects.css create mode 100644 css/components/admin_project.css create mode 100644 css/edit.css create mode 100644 src/components/admin_project.rs create mode 100644 src/pages/admin/edit.rs diff --git a/css/admin-agents.css b/css/admin-agents.css new file mode 100644 index 0000000..e69de29 diff --git a/css/admin-contacts.css b/css/admin-contacts.css new file mode 100644 index 0000000..e69de29 diff --git a/css/admin-projects.css b/css/admin-projects.css new file mode 100644 index 0000000..b5e4501 --- /dev/null +++ b/css/admin-projects.css @@ -0,0 +1,9 @@ +.admin-projects-table { + display: flex; + flex-direction: column; + justify-content: center; + align-items: space-evenly; + gap: 5px; + + width: 90%; +} \ No newline at end of file diff --git a/css/components/admin_project.css b/css/components/admin_project.css new file mode 100644 index 0000000..9cdc363 --- /dev/null +++ b/css/components/admin_project.css @@ -0,0 +1,60 @@ +.admin-project-container { + display: flex; + flex-direction: row; + justify-content: space-evenly; + align-items: center; + gap: 5px; + + height: 40px; + width: 100%; +} +.admin-project-container:hover { + cursor: pointer; + background-color: #02104a51; + border-radius: 3px; + transition-duration: 0.3s; +} +.admin-project-trash-bin { + display: flex; + justify-content: center; + align-items: center; + font-size: 13px; + width: 25px; + height: 25px; +} +.admin-project-trash-bin-selected { + display: flex; + justify-content: center; + align-items: center; + + border-radius: 3px; + font-size: 13px; + background-color: #e32; + color: white; + width: 25px; + height: 25px; +} +.admin-project-trash-bin:hover { + cursor: pointer; +} +.admin-project-location { + font-size: 13px; + font-family: Source Sans Pro; + font-weight: 100; + text-align: start; + width: 150px; +} +.admin-project-column { + font-size: 13px; + font-family: Source Sans Pro; + font-weight: 100; + text-align: start; + width: 100px; +} +.admin-project-index { + font-size: 13px; + font-family: Source Sans Pro; + font-weight: 100; + text-align: start; + width: 15px; +} diff --git a/css/edit.css b/css/edit.css new file mode 100644 index 0000000..5798af9 --- /dev/null +++ b/css/edit.css @@ -0,0 +1,24 @@ +.admin-project-fields-container { + display: flex; + flex-direction: column; + justify-content: start; + align-items: center; + gap: 20px; + + width: 90%; +} + +.admin-project-field-container { + display: flex; + flex-direction: row; + justify-content: space-between; + align-items: center; + + width: 100%; +} + +.admin-project-field-label { + font-family: Source Sans Pro; + font-size: 16px; + text-align: center; +} \ No newline at end of file diff --git a/index.html b/index.html index a26d2c5..641bffe 100644 --- a/index.html +++ b/index.html @@ -15,6 +15,10 @@ + + + + @@ -23,6 +27,7 @@ + diff --git a/src/components/admin_project.rs b/src/components/admin_project.rs new file mode 100644 index 0000000..3cc0195 --- /dev/null +++ b/src/components/admin_project.rs @@ -0,0 +1,62 @@ +use jl_types::{dto::project_card::ProjectCardDto, domain::project_state::ProjectState}; +use yew::prelude::*; +use yew_router::{prelude::use_navigator}; + +use crate::{routes::main_router::Route, pages::admin::edit::{EditType, EditItem}}; + +#[function_component(AdminProject)] +pub fn admin_project(props: &AdminProjectProps) -> Html { + let navigator = use_navigator().unwrap(); + let location_formatted = format!("{}, {}", props.project.city, props.project.district); + let is_attempting_delete = use_state(|| false); + let delete_project = { + let is_attempting_delete = is_attempting_delete.clone(); + Callback::from(move |event: MouseEvent| { + if *is_attempting_delete { + // Call delete + is_attempting_delete.set(false); + } else { + is_attempting_delete.set(true); + } + event.stop_propagation(); + }) + }; + let onclick_item = { + let props = props.clone(); + Callback::from(move |_| { + navigator.push(&Route::AdminEdit { edit_type: EditType::Existing(props.project.id), edit_item: EditItem::Project }); + }) + }; + html! { +
+
+ {props.index + 1} +
+
+ {location_formatted} +
+
+ {props.project.project_type} +
+
+ {props.project.project_condition.clone()} +
+
+ {match props.project.project_state { + ProjectState::InConstruction => "En Construcción", + ProjectState::Finished => "Terminado", + }} +
+
+ +
+
+ + } +} + +#[derive(PartialEq, Properties, Clone)] +pub struct AdminProjectProps { + pub project: ProjectCardDto, + pub index: usize, +} \ No newline at end of file diff --git a/src/components/mod.rs b/src/components/mod.rs index 29ee16e..e960300 100644 --- a/src/components/mod.rs +++ b/src/components/mod.rs @@ -5,4 +5,5 @@ pub mod floating_widget; pub mod feature; pub mod footer; pub mod agent_card; -pub mod admin_nav_bar; \ No newline at end of file +pub mod admin_nav_bar; +pub mod admin_project; \ No newline at end of file diff --git a/src/pages/admin/agents.rs b/src/pages/admin/agents.rs index 1e42bd0..02a7ef7 100644 --- a/src/pages/admin/agents.rs +++ b/src/pages/admin/agents.rs @@ -1,15 +1,30 @@ use yew::prelude::*; -use crate::components::admin_nav_bar::AdminNavigationBar; +use crate::{components::admin_nav_bar::AdminNavigationBar, api::backend::get_all_agents}; #[function_component(AdminAgents)] pub fn admin_agents() -> Html { + + let agents = use_state(|| Vec::new()); + + use_state(|| { + let agents_handle = agents.clone(); + wasm_bindgen_futures::spawn_local(async move { + match get_all_agents().await { + Ok(agents) => { + agents_handle.set(agents); + }, + Err(error) => log::error!("Error retrieving agents from backend. Error: {}", error), + }; + }); + }); + html! { <> -
+
- {""} +
{"Agentes"}
diff --git a/src/pages/admin/contacts.rs b/src/pages/admin/contacts.rs index 6246591..5dbff44 100644 --- a/src/pages/admin/contacts.rs +++ b/src/pages/admin/contacts.rs @@ -1,15 +1,29 @@ use yew::prelude::*; -use crate::components::admin_nav_bar::AdminNavigationBar; +use crate::{components::admin_nav_bar::AdminNavigationBar, api::backend::get_all_contacts}; #[function_component(AdminContacts)] pub fn admin_contacts() -> Html { + let contacts = use_state(|| Vec::new()); + + use_state(|| { + let contacts_handle = contacts.clone(); + wasm_bindgen_futures::spawn_local(async move { + match get_all_contacts().await { + Ok(contacts) => { + contacts_handle.set(contacts); + }, + Err(error) => log::error!("Error retrieving contacts from backend. Error: {}", error), + }; + }); + }); html! { <> -
+
- {""} +
{"Solicitudes de Contacto"}
+
diff --git a/src/pages/admin/edit.rs b/src/pages/admin/edit.rs new file mode 100644 index 0000000..df81dd3 --- /dev/null +++ b/src/pages/admin/edit.rs @@ -0,0 +1,174 @@ +use std::{fmt::Display, str::FromStr}; + +use chrono::Utc; +use jl_types::{ domain::{agent::Agent, project_state::ProjectState, project_condition::ProjectCondition, project_type::ProjectType, media::{Media, MediaList}, unit::Unit}, dto::listing::Listing}; +use uuid::Uuid; +use yew::prelude::*; +use yew_router::prelude::use_navigator; + +use crate::{components::admin_nav_bar::AdminNavigationBar, api::backend::get_project_listing}; + +/// All of the editing actions of the admin panel will lead to here. This should take an id of anything. A unit, a project, an agent. And its corresponding ID. +#[function_component(AdminEditPage)] +pub fn edit_page(props: &AdminEditPageProps) -> Html { + let navigator = use_navigator().unwrap(); + let listing = use_state(|| None); + + use_state(|| { + let listing = listing.clone(); + match props.edit_item { + EditItem::Agent => { + + }, + EditItem::Project => { + match props.edit_type { + EditType::New => {}, + EditType::Existing(uid) => { + wasm_bindgen_futures::spawn_local(async move { + let listing_result = get_project_listing(&uid).await; + match listing_result { + Ok(listing_persisted) => { + listing.set(Some(listing_persisted)); + }, + Err(error) => log::error!("Error loading listing: {error}") + } + }); + }, + }; + }, + EditItem::Unit(_) => {}, + }}); + + html! { + <> + +
+
+
{format!("Editar {}", match props.edit_item { + EditItem::Agent => "Agente", + EditItem::Project => "Proyecto", + EditItem::Unit(_) => "Unidad", + })}
+ { + match props.edit_item { + EditItem::Agent => {html! {}}, + EditItem::Project => {html! { }}, + EditItem::Unit(_) => {html! {}}, + } + } +
+
+ + + } + +} + +#[derive(PartialEq, Clone)] +pub enum EditItem { + Agent, + Project, + /// Project Uid + Unit(Uuid), +} +#[derive(PartialEq, Clone)] +pub enum EditType { + New, Existing(Uuid) +} + +#[derive(Properties, PartialEq)] +pub struct AdminEditPageProps { + pub edit_item: EditItem, + pub edit_type: EditType, +} + +#[derive(Properties, PartialEq, Clone)] +pub struct ProjectFieldsProps { + pub listing: Option+} + +#[allow(unused)] +#[function_component(ProjectFields)] +pub fn generate_fields_for_project(props: &ProjectFieldsProps) -> Html { + let listing_opt = props.listing.clone(); + let location_city = use_state(|| listing_opt.clone().unwrap_or_default().location.city); + let location_district = use_state(|| listing_opt.clone().unwrap_or_default().location.district); + let agent: UseStateHandle> = use_state(|| { + match listing_opt.clone() { + Some(listing) => Some(listing.agent), + None => None, + } + }); + let project_state = use_state(|| listing_opt.clone().unwrap_or_default().project.project_state); + let project_condition = use_state(|| listing_opt.clone().unwrap_or_default().project.project_condition); + let project_type = use_state(|| listing_opt.clone().unwrap_or_default().project.project_type); + let project_description = use_state(|| listing_opt.clone().unwrap_or_default().project.description); + let project_admin_tag: UseStateHandle> = use_state(|| listing_opt.clone().unwrap_or_default().project.admin_tag); + let project_finish_date = use_state(|| listing_opt.clone().unwrap_or_default().project.finish_date); + let project_floors = use_state(|| listing_opt.clone().unwrap_or_default().project.floors); + let media: UseStateHandle = use_state(|| listing_opt.clone().unwrap_or_default().project.media); + let units: UseStateHandle> = use_state(|| listing_opt.clone().unwrap_or_default().units); + + + html! { + + } +} + +impl Display for EditItem { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + match self { + EditItem::Agent => write!(f, "agent"), + EditItem::Project => write!(f, "project"), + EditItem::Unit(id) => write!(f, "unit{id}"), + } + } +} +impl Display for EditType { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + match self { + EditType::New => write!(f, "new"), + EditType::Existing(id) => { + let fmt_id = id.to_string().replace("-", ""); + write!(f, "existing{fmt_id}") + }, + } + } +} +impl FromStr for EditItem { + type Err = (); + + fn from_str(s: &str) -> Result { + if s.starts_with("unit") { + let (_, p_id) = s.split_at(4); + let uid: Result = p_id.try_into(); + if let Ok(id) = uid { + return Ok(Self::Unit(id)); + } + } + match s { + "agent" => Ok(Self::Agent), + "project" => Ok(Self::Project), + _ => Err(()) + } + } +} +impl FromStr for EditType { + type Err = (); + + fn from_str(s: &str) -> Result { + if s.starts_with("existing") { + let existing = s.replace("-", ""); + let (_, p_id) = existing.split_at(8); + let uid = p_id.to_string(); + let uid: Result = uid.as_str().try_into(); + if let Ok(id) = uid { + return Ok(Self::Existing(id)); + } + } + match s { + "new" => Ok(Self::New), + _ => Err(()) + } + } +} \ No newline at end of file diff --git a/src/pages/admin/mod.rs b/src/pages/admin/mod.rs index 0b5c509..05b5913 100644 --- a/src/pages/admin/mod.rs +++ b/src/pages/admin/mod.rs @@ -2,4 +2,5 @@ pub mod login; pub mod start; pub mod projects; pub mod contacts; -pub mod agents; \ No newline at end of file +pub mod agents; +pub mod edit; \ No newline at end of file diff --git a/src/pages/admin/projects.rs b/src/pages/admin/projects.rs index ead6174..9e2ac7e 100644 --- a/src/pages/admin/projects.rs +++ b/src/pages/admin/projects.rs @@ -1,15 +1,41 @@ use yew::prelude::*; -use crate::components::admin_nav_bar::AdminNavigationBar; +use crate::{components::{admin_nav_bar::AdminNavigationBar, admin_project::AdminProject}, api::backend::get_all_projects_with_filters_paged}; #[function_component(AdminProjects)] pub fn admin_projects() -> Html { + + let projects = use_state(|| Vec::new()); + + use_state(|| { + let projects_handle = projects.clone(); + wasm_bindgen_futures::spawn_local(async move { + match get_all_projects_with_filters_paged(&1, Vec::new()).await { + Ok(projects) => { + projects_handle.set(projects); + }, + Err(error) => log::error!("Error retrieving projects from backend. Error: {}", error), + }; + }); + }); + + + html! { <> -
+
- {""} +
{"Proyectos"}
+
+
+ {(*projects).clone().into_iter().enumerate().map(|(key, project)| html! { + <> + +
+ + }).collect::()} +
diff --git a/src/routes/main_router.rs b/src/routes/main_router.rs index e7c005e..e682f3c 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, admin::{login::AdminLoginPage, start::AdminStart, projects::AdminProjects, agents::AdminAgents, contacts::AdminContacts}, agents::AgentsPage}}; +use crate::{pages::{landing::LandingPage, search::{SearchPage}, details::DetailsPage, not_found::NotFoundPage, contact::ContactPage, admin::{login::AdminLoginPage, start::AdminStart, projects::AdminProjects, agents::AdminAgents, contacts::AdminContacts, edit::{EditType, EditItem, AdminEditPage}}, agents::AgentsPage}}; #[derive(Clone, Routable, PartialEq)] pub enum Route { @@ -28,6 +28,8 @@ pub enum Route { AdminAgents, #[at("/admin/contacts")] AdminContacts, + #[at("/admin/edit/:edit_type/:edit_item")] + AdminEdit { edit_type: EditType, edit_item: EditItem }, #[not_found] #[at("/404")] @@ -48,7 +50,6 @@ pub fn switch(routes: Route) -> Html { Route::AdminProjects => html! { }, Route::AdminAgents => html! { }, Route::AdminContacts => html! { }, - - + Route::AdminEdit { edit_type, edit_item } => html! { }, } } \ No newline at end of file