Finished edit project. No uploads, just fetching and playing around in the editor

This commit is contained in:
Franklin 2023-04-22 11:39:00 -04:00
parent 39abe4caca
commit 6b20ac66f1
10 changed files with 105 additions and 15 deletions

View File

@ -6,7 +6,7 @@
gap: 50px; gap: 50px;
width: 100%; width: 100%;
height: 50vh; min-height: 50vh;
} }
.admin-start-welcome-message { .admin-start-welcome-message {
font-size: 18px; font-size: 18px;

View File

@ -14,6 +14,7 @@ body {
.admin-page-container { .admin-page-container {
padding-top: 40px; padding-top: 40px;
padding-left: 200px; padding-left: 200px;
padding-bottom: 20vh;
display: flex; display: flex;
flex-direction: column; flex-direction: column;
justify-content: center; justify-content: center;

View File

@ -0,0 +1,8 @@
.datepicker {
height: 50px;
background-color: white;
border: solid 0.5px #d8d8d8;
width: 100%;
text-indent: 10px;
}

View File

@ -31,3 +31,23 @@
width: 100%; width: 100%;
text-indent: 10px; text-indent: 10px;
} }
.admin-edit-submit-button {
width: 100%;
height: 60px;
margin-top: 20px;
border-radius: 5px;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
background-color: #02114A;
color: white;
font-family: Source Sans Pro;
font-size: 17px;
}
.admin-edit-submit-button:hover {
cursor: pointer;
}

View File

@ -29,6 +29,7 @@
<link data-trunk type="text/css" href="css/components/agent_card.css" rel="css" /> <link data-trunk type="text/css" href="css/components/agent_card.css" rel="css" />
<link data-trunk type="text/css" href="css/components/admin_nav_bar.css" rel="css" /> <link data-trunk type="text/css" href="css/components/admin_nav_bar.css" rel="css" />
<link data-trunk type="text/css" href="css/components/admin_project.css" rel="css" /> <link data-trunk type="text/css" href="css/components/admin_project.css" rel="css" />
<link data-trunk type="text/css" href="css/components/datepicker.css" rel="css" />
<link href="https://fonts.googleapis.com/css?family=Source+Sans+Pro" rel="stylesheet"> <link href="https://fonts.googleapis.com/css?family=Source+Sans+Pro" rel="stylesheet">

View File

@ -0,0 +1,54 @@
use std::str::FromStr;
use chrono::{NaiveDate};
use yew::prelude::*;
use crate::components::textfield::get_value_from_input_event;
/// The input type date field in html will always guarantee a valid date string.
#[function_component(DatePicker)]
pub fn datepicker(props: &DatePickerProps) -> Html {
let date_handle = props.value.clone();
let optional_cb = props.onchange.clone();
let cb = Callback::from(move |e: InputEvent| {
match parse_date(get_value_from_input_event(e)) {
Ok(date) => {
match optional_cb.clone() {
Some(callback) => callback.emit(Some(date.clone())),
None => {},
};
date_handle.set(Some(date));
},
Err(_) => {},
};
});
let date_handle = props.value.clone();
html! {
<div class={"textfield-container"}>
<div class={if props.required {"textfield-label-required"} else {"textfield-label"}}>{props.label.clone()}</div>
<input class={"datepicker"} type="date" oninput={cb} value={match (*date_handle).clone() {
Some(date) => date.to_string(),
None => NaiveDate::default().to_string()
}}/>
</div>
}
}
#[derive(PartialEq, Clone, Properties)]
pub struct DatePickerProps {
pub label: String,
pub value: UseStateHandle<Option<NaiveDate>>,
#[prop_or_default]
pub required: bool,
pub onchange: Option<Callback<Option<NaiveDate>>>
}
pub fn parse_date(date_str: String) -> Result<NaiveDate, ()> {
match NaiveDate::from_str(&date_str) {
Ok(date) => Ok(date),
Err(error) => {
log::error!("Falied to parse Date in DatePicker: {error}");
Err(())
},
}
}

View File

@ -9,3 +9,4 @@ pub mod admin_nav_bar;
pub mod admin_project; pub mod admin_project;
pub mod textfield; pub mod textfield;
pub mod dropdown; pub mod dropdown;
pub mod datepicker;

View File

@ -5,7 +5,7 @@ use uuid::Uuid;
use yew::prelude::*; use yew::prelude::*;
use yew_router::prelude::use_navigator; use yew_router::prelude::use_navigator;
use crate::{components::{admin_nav_bar::AdminNavigationBar, textfield::{TextField, TextFieldType}, dropdown::DropDown}, api::backend::{get_project_listing, get_all_agents}}; use crate::{components::{admin_nav_bar::AdminNavigationBar, textfield::{TextField, TextFieldType}, dropdown::DropDown, datepicker::DatePicker}, api::backend::{get_project_listing, get_all_agents}};
/// 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. /// 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)] #[function_component(AdminEditPage)]
@ -99,12 +99,12 @@ pub fn generate_fields_for_project(props: &ProjectFieldsProps) -> Html {
let project_state = use_state_eq(|| None); let project_state = use_state_eq(|| None);
let project_condition = use_state_eq(|| None); let project_condition = use_state_eq(|| None);
let project_type = use_state_eq(|| None); let project_type = use_state_eq(|| None);
let project_description = use_state_eq(|| "".to_string()); let project_description = use_state_eq(|| String::new());
let project_admin_tag: UseStateHandle<String> = use_state_eq(|| listing_opt.clone().unwrap_or_default().project.admin_tag.unwrap_or(String::new())); let project_admin_tag: UseStateHandle<String> = use_state_eq(|| String::new());
let project_finish_date = use_state_eq(|| listing_opt.clone().unwrap_or_default().project.finish_date); let project_finish_date = use_state_eq(|| None);
let project_floors = use_state_eq(|| listing_opt.clone().unwrap_or_default().project.floors.to_string()); let project_floors = use_state_eq(|| String::new());
let media: UseStateHandle<MediaList> = use_state_eq(|| listing_opt.clone().unwrap_or_default().project.media); let media: UseStateHandle<MediaList> = use_state_eq(|| MediaList { media_list: Vec::new() });
let units: UseStateHandle<Vec<Unit>> = use_state_eq(|| listing_opt.clone().unwrap_or_default().units); let units: UseStateHandle<Vec<Unit>> = use_state_eq(|| Vec::new());
let ontype_cb = { let ontype_cb = {
let user_typed = user_typed.clone(); let user_typed = user_typed.clone();
@ -137,7 +137,6 @@ pub fn generate_fields_for_project(props: &ProjectFieldsProps) -> Html {
}) })
}; };
let all_agents = use_state(|| Vec::new()); let all_agents = use_state(|| Vec::new());
use_state(|| { use_state(|| {
@ -184,6 +183,10 @@ pub fn generate_fields_for_project(props: &ProjectFieldsProps) -> Html {
}, },
None => String::new(), None => String::new(),
}); });
project_finish_date.set(match listing_opt.clone() {
Some(listing) => Some(listing.project.finish_date.date()),
None => None,
});
} }
html! { html! {
@ -228,9 +231,13 @@ pub fn generate_fields_for_project(props: &ProjectFieldsProps) -> Html {
} }
} }
<TextField label={"Pisos"} value={project_floors} required={true} /> <TextField label={"Pisos"} value={project_floors} required={true} />
<DatePicker label={"Fecha de entrega Est."} value={project_finish_date} required={true} />
<TextField label={"Descripción"} value={project_description} fieldtype={TextFieldType::TextArea} /> <TextField label={"Descripción"} value={project_description} fieldtype={TextFieldType::TextArea} />
<TextField label={"Comentario interno"} value={project_admin_tag} /> <TextField label={"Comentario interno"} value={project_admin_tag} />
<div class={"admin-edit-submit-button"}>
{"Actualizar"}
</div>
</> </>
} }
} }

View File

@ -17,8 +17,6 @@ pub fn search_page() -> Html {
let finished_loading = use_state(|| false); let finished_loading = use_state(|| false);
let project_state_filter_handle = use_state_eq(|| ProjectState::InConstruction); let project_state_filter_handle = use_state_eq(|| ProjectState::InConstruction);
let filters: Vec<Filter> = Vec::new();
// All code to execute on first render and never again // All code to execute on first render and never again
use_state(|| { use_state(|| {
let cities_handle = cities_handle.clone(); let cities_handle = cities_handle.clone();