Finished edit project. No uploads, just fetching and playing around in the editor
This commit is contained in:
parent
39abe4caca
commit
6b20ac66f1
@ -6,7 +6,7 @@
|
||||
gap: 50px;
|
||||
|
||||
width: 100%;
|
||||
height: 50vh;
|
||||
min-height: 50vh;
|
||||
}
|
||||
.admin-start-welcome-message {
|
||||
font-size: 18px;
|
||||
|
@ -14,6 +14,7 @@ body {
|
||||
.admin-page-container {
|
||||
padding-top: 40px;
|
||||
padding-left: 200px;
|
||||
padding-bottom: 20vh;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
|
8
css/components/datepicker.css
Normal file
8
css/components/datepicker.css
Normal file
@ -0,0 +1,8 @@
|
||||
.datepicker {
|
||||
height: 50px;
|
||||
background-color: white;
|
||||
border: solid 0.5px #d8d8d8;
|
||||
|
||||
width: 100%;
|
||||
text-indent: 10px;
|
||||
}
|
20
css/edit.css
20
css/edit.css
@ -31,3 +31,23 @@
|
||||
width: 100%;
|
||||
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;
|
||||
}
|
@ -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/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/datepicker.css" rel="css" />
|
||||
|
||||
|
||||
<link href="https://fonts.googleapis.com/css?family=Source+Sans+Pro" rel="stylesheet">
|
||||
|
54
src/components/datepicker.rs
Normal file
54
src/components/datepicker.rs
Normal 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(())
|
||||
},
|
||||
}
|
||||
}
|
@ -9,3 +9,4 @@ pub mod admin_nav_bar;
|
||||
pub mod admin_project;
|
||||
pub mod textfield;
|
||||
pub mod dropdown;
|
||||
pub mod datepicker;
|
@ -5,7 +5,7 @@ use uuid::Uuid;
|
||||
use yew::prelude::*;
|
||||
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.
|
||||
#[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_condition = use_state_eq(|| None);
|
||||
let project_type = use_state_eq(|| None);
|
||||
let project_description = use_state_eq(|| "".to_string());
|
||||
let project_admin_tag: UseStateHandle<String> = use_state_eq(|| listing_opt.clone().unwrap_or_default().project.admin_tag.unwrap_or(String::new()));
|
||||
let project_finish_date = use_state_eq(|| listing_opt.clone().unwrap_or_default().project.finish_date);
|
||||
let project_floors = use_state_eq(|| listing_opt.clone().unwrap_or_default().project.floors.to_string());
|
||||
let media: UseStateHandle<MediaList> = use_state_eq(|| listing_opt.clone().unwrap_or_default().project.media);
|
||||
let units: UseStateHandle<Vec<Unit>> = use_state_eq(|| listing_opt.clone().unwrap_or_default().units);
|
||||
let project_description = use_state_eq(|| String::new());
|
||||
let project_admin_tag: UseStateHandle<String> = use_state_eq(|| String::new());
|
||||
let project_finish_date = use_state_eq(|| None);
|
||||
let project_floors = use_state_eq(|| String::new());
|
||||
let media: UseStateHandle<MediaList> = use_state_eq(|| MediaList { media_list: Vec::new() });
|
||||
let units: UseStateHandle<Vec<Unit>> = use_state_eq(|| Vec::new());
|
||||
|
||||
let ontype_cb = {
|
||||
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());
|
||||
|
||||
use_state(|| {
|
||||
@ -184,6 +183,10 @@ pub fn generate_fields_for_project(props: &ProjectFieldsProps) -> Html {
|
||||
},
|
||||
None => String::new(),
|
||||
});
|
||||
project_finish_date.set(match listing_opt.clone() {
|
||||
Some(listing) => Some(listing.project.finish_date.date()),
|
||||
None => None,
|
||||
});
|
||||
}
|
||||
|
||||
html! {
|
||||
@ -228,9 +231,13 @@ pub fn generate_fields_for_project(props: &ProjectFieldsProps) -> Html {
|
||||
}
|
||||
}
|
||||
<TextField label={"Pisos"} value={project_floors} required={true} />
|
||||
<TextField label={"Descripción"} value={project_description} fieldtype={TextFieldType::TextArea}/>
|
||||
<DatePicker label={"Fecha de entrega Est."} value={project_finish_date} required={true} />
|
||||
<TextField label={"Descripción"} value={project_description} fieldtype={TextFieldType::TextArea} />
|
||||
<TextField label={"Comentario interno"} value={project_admin_tag} />
|
||||
|
||||
<div class={"admin-edit-submit-button"}>
|
||||
{"Actualizar"}
|
||||
</div>
|
||||
</>
|
||||
}
|
||||
}
|
||||
|
@ -17,8 +17,6 @@ pub fn search_page() -> Html {
|
||||
let finished_loading = use_state(|| false);
|
||||
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
|
||||
use_state(|| {
|
||||
let cities_handle = cities_handle.clone();
|
||||
|
Loading…
Reference in New Issue
Block a user