diff --git a/code/src/app.rs b/code/src/app.rs index fc1f2c1..afcba48 100644 --- a/code/src/app.rs +++ b/code/src/app.rs @@ -4,9 +4,10 @@ use crate::{ database::DBOperator, material_tab::MaterialTabViewer, models::{ - Equipment, LoginModalState, Material, MaterialCategory, MaterialRow, ModalStatus, - ModalWinState, Position, Worker, + Equipment, LoginModalState, LoginStatus, Material, MaterialCategory, MaterialRow, + ModalStatus, ModalWinState, Position, Worker, }, + payment_tab::PaymentTabViewer, tab::*, worker_tab::{self, *}, }; @@ -82,6 +83,19 @@ impl App<'_> { impl eframe::App for App<'_> { fn ui(&mut self, ui: &mut egui::Ui, _frame: &mut eframe::Frame) { + if self.login_modal_state.status == LoginStatus::Finished { + ui.horizontal(|ui| { + ui.label(self.login_modal_state.data.get("login").unwrap()); + if ui.button("Выйти").clicked() { + self.login_modal_state.is_open = true; + self.login_modal_state.status = LoginStatus::Login; + self.login_modal_state.data.insert("login", String::new()); + self.login_modal_state + .data + .insert("password", String::new()); + } + }); + } if self.login_modal_state.is_open { egui::Modal::new(egui::Id::new("login_modal")).show(ui.ctx(), |ui| { ui.label("Пройдите авторизацию:"); @@ -159,6 +173,7 @@ struct MainTabViewer { worker_tree: egui_dock::DockState, material_tabs: MaterialTabViewer, material_tree: egui_dock::DockState, + payment_tabs: PaymentTabViewer, rt: tokio::runtime::Runtime, equipment_modal_state: ModalWinState, is_dark_theme: bool, @@ -202,6 +217,7 @@ impl Default for MainTabViewer { tab_type: TabTypes::MaterialTypeList, }, ]), + payment_tabs: PaymentTabViewer::default(), rt, is_dark_theme: true, interface_scale_ratio: 1.2, @@ -227,6 +243,7 @@ impl MainTabViewer { is_admin, worker_tabs: WorkerTabViewer::new(is_admin), material_tabs: MaterialTabViewer::new(is_admin), + payment_tabs: PaymentTabViewer::new(is_admin), ..Default::default() } } diff --git a/code/src/database.rs b/code/src/database.rs index 60a41d6..de8728a 100644 --- a/code/src/database.rs +++ b/code/src/database.rs @@ -206,9 +206,9 @@ impl DBOperator { } } - pub async fn update_worker(&self, worker: Worker) -> Result { + pub async fn update_worker(&self, worker: WorkerRow) -> Result { match sqlx::query("UPDATE Brewery.worker SET position_id=?, hire_date=?, is_fired=?, full_name=? WHERE id=?;") - .bind(worker.position.id) + .bind(worker.position_id) .bind(worker.hire_date) .bind(worker.is_fired) .bind(worker.full_name) diff --git a/code/src/main.rs b/code/src/main.rs index 67b6ec6..f71cc22 100644 --- a/code/src/main.rs +++ b/code/src/main.rs @@ -3,6 +3,7 @@ mod app; mod database; mod material_tab; mod models; +mod payment_tab; mod recipe_tab; mod tab; mod worker_tab; diff --git a/code/src/models.rs b/code/src/models.rs index 3e05621..6190428 100644 --- a/code/src/models.rs +++ b/code/src/models.rs @@ -112,7 +112,7 @@ pub struct Product<'a> { price_per_unit: rust_decimal::Decimal, } #[derive(Default)] -pub struct User{ +pub struct User { login: String, is_admin: bool, worker: Worker, @@ -142,7 +142,7 @@ pub struct LoginModalState<'a> { pub fail_message: String, } -#[derive(Default)] +#[derive(Default, PartialEq)] pub enum LoginStatus { #[default] Login, diff --git a/code/src/payment_tab.rs b/code/src/payment_tab.rs new file mode 100644 index 0000000..f4ff7f0 --- /dev/null +++ b/code/src/payment_tab.rs @@ -0,0 +1,51 @@ +use crate::{ + database::DBOperator, + tab::{TABS_CAN_BE_WINDOWS, Tab, TabTypes}, +}; + +pub struct PaymentTabViewer { + db_oper: DBOperator, + is_admin: bool, + rt: tokio::runtime::Runtime, +} +impl PaymentTabViewer { + pub fn new(is_admin: bool) -> Self { + Self { + is_admin, + ..Default::default() + } + } +} +impl egui_dock::TabViewer for PaymentTabViewer { + type Tab = Tab; + fn title(&mut self, tab: &mut Self::Tab) -> egui::WidgetText { + (&*tab.title).into() + } + fn ui(&mut self, ui: &mut egui::Ui, tab: &mut Self::Tab) { + match &tab.tab_type { + _ => { + ui.label("Nope"); + } + } + } + fn id(&mut self, tab: &mut Self::Tab) -> egui::Id { + egui::Id::new(&tab.title) + } + fn allowed_in_windows(&self, _tab: &mut Self::Tab) -> bool { + TABS_CAN_BE_WINDOWS + } + fn is_closeable(&self, _tab: &Self::Tab) -> bool { + !self.is_admin + } +} +impl Default for PaymentTabViewer { + fn default() -> Self { + let rt = tokio::runtime::Runtime::new().unwrap(); + let db_oper = rt.block_on(async { DBOperator::new().await }); + Self { + db_oper, + rt, + is_admin: false, + } + } +} diff --git a/code/src/worker_tab.rs b/code/src/worker_tab.rs index 63fa5c1..241a73a 100644 --- a/code/src/worker_tab.rs +++ b/code/src/worker_tab.rs @@ -14,27 +14,9 @@ pub struct WorkerTabViewer { db_oper: DBOperator, workers: Arc>>, positions: Arc>>, - show_worker_add_modal: bool, - show_worker_edit_modal: bool, - show_position_add_modal: bool, - fire_worker_id: String, - add_worker_name: String, - add_worker_hire_date: String, - add_worker_position: Position, - can_add_worker: bool, - can_edit_worker: bool, - add_position_name: String, - add_position_wage: String, - - edit_worker_id: i32, - edit_worker_name: String, - edit_worker_hire_date: String, - edit_worker_is_fired: bool, - edit_worker_position: Position, rt: tokio::runtime::Runtime, - show_position_delete_modal: bool, - delete_position: Position, + process_worker_state: ModalWinState, process_position_state: ModalWinState, is_admin: bool, @@ -85,189 +67,10 @@ impl WorkerTabViewer { self.update_workers(); } }); - if self.show_worker_add_modal { - egui::Modal::new("add_worker".into()).show(ui.ctx(), |ui| { - if ui.button("Закрыть").clicked() { - self.show_worker_add_modal = false; - } - ui.horizontal(|ui| { - ui.vertical(|ui| { - ui.label("Имя сотрудника:"); - ui.label("Дата найма:"); - ui.label("Должность:"); - }); - ui.vertical(|ui| { - ui.add( - egui::TextEdit::singleline(&mut self.add_worker_name) - .hint_text("Напр: Иванов Иван"), - ); - ui.add( - egui::TextEdit::singleline(&mut self.add_worker_hire_date) - .hint_text("Напр: 12-02-2010"), - ); - egui::ComboBox::from_label("Выбрать!") - .selected_text(format!("{}", self.add_worker_position.name)) - .show_ui(ui, |ui| { - self.rt.block_on(async { - for pos in self.positions.read().clone().iter() { - ui.selectable_value( - &mut self.add_worker_position, - pos.clone(), - &pos.name, - ); - } - }); - }); - }); - }); - - if chrono::NaiveDate::parse_from_str(&self.add_worker_hire_date, "%d-%m-%Y") - .is_err() - { - ui.label(egui::RichText::new("ДАТА УКАЗАНА НЕВЕРНО").color(egui::Color32::RED)); - self.can_add_worker = false; - } else { - self.can_add_worker = true; - } - ui.vertical_centered(|ui| { - let resp = ui.add_enabled(self.can_add_worker, egui::Button::new("Добавить")); - if resp.clicked() { - self.rt.block_on(async { - let ndate = chrono::NaiveDate::parse_from_str( - &self.add_worker_hire_date, - "%d-%m-%Y", - ) - .unwrap(); - self.db_oper - .add_worker(Worker { - id: 0, - full_name: self.add_worker_name.clone(), - hire_date: ndate - .and_hms_opt(0, 0, 0) - .unwrap() - .and_local_timezone(chrono::Local) - .unwrap(), - position: self.add_worker_position.clone(), - is_fired: false, - }) - .await - .ok(); - - self.show_worker_add_modal = false; - }); - self.update_workers(); - } - }); - }); - } - if self.show_worker_edit_modal { - egui::Modal::new("edit_worker".into()).show(ui.ctx(), |ui| { - if ui.button("Закрыть").clicked() { - self.show_worker_edit_modal = false; - } - let mut size = ui.spacing().interact_size; - size.x = 200.0; - - egui::Grid::new("edit_worker_grid").show(ui, |ui| { - ui.label("ID"); - let old = self.edit_worker_id.clone(); - egui::ComboBox::from_id_salt("edit_worker_id") - .selected_text(format!("#{:08}", &self.edit_worker_id)) - .show_ui(ui, |ui| { - self.rt.block_on(async { - for worker in self.workers.read().clone().iter() { - ui.selectable_value( - &mut self.edit_worker_id, - worker.id, - format!("#{:08} | {}", worker.id, worker.full_name), - ); - } - }); - }); - if self.edit_worker_id != old { - self.rt.block_on(async { - let wrkr = - match self.db_oper.get_worker_by_id(self.edit_worker_id).await { - Ok(worker) => worker, - Err(_) => Worker::default(), - }; - self.edit_worker_name = wrkr.full_name; - self.edit_worker_hire_date = - wrkr.hire_date.format("%Y-%m-%d").to_string(); - self.edit_worker_position = wrkr.position; - self.edit_worker_is_fired = wrkr.is_fired; - }); - } - ui.end_row(); - - ui.label("Имя"); - ui.add_sized(size, |ui: &mut egui::Ui| { - ui.text_edit_singleline(&mut self.edit_worker_name) - }); - ui.end_row(); - - ui.label("Должность"); - egui::ComboBox::from_id_salt("edit_worker_pos") - .selected_text(&self.edit_worker_position.name) - .show_ui(ui, |ui| { - self.rt.block_on(async { - for pos in self.positions.read().clone().iter() { - ui.selectable_value( - &mut self.edit_worker_position, - pos.clone(), - &pos.name, - ); - } - }); - }); - ui.end_row(); - - ui.label("Дата найма"); - ui.text_edit_singleline(&mut self.edit_worker_hire_date); - ui.end_row(); - - ui.checkbox(&mut self.edit_worker_is_fired, "Уволен"); - ui.end_row(); - }); - if chrono::NaiveDate::parse_from_str(&self.edit_worker_hire_date, "%Y-%m-%d") - .is_ok() - && self.edit_worker_name.len() > 0 - { - self.can_edit_worker = true; - } else { - self.can_edit_worker = false; - } - let resp = ui.add_enabled(self.can_edit_worker, egui::Button::new("Добавить")); - if resp.clicked() { - self.rt.block_on(async { - let ndate = chrono::NaiveDate::parse_from_str( - &self.edit_worker_hire_date, - "%Y-%m-%d", - ) - .unwrap(); - self.db_oper - .update_worker(Worker { - id: self.edit_worker_id, - full_name: self.edit_worker_name.clone(), - hire_date: ndate - .and_hms_opt(0, 0, 0) - .unwrap() - .and_local_timezone(chrono::Local) - .unwrap(), - position: self.edit_worker_position.clone(), - is_fired: self.edit_worker_is_fired, - }) - .await - .unwrap(); - }); - self.update_workers(); - self.show_worker_edit_modal = false; - } - }); - } if self.process_worker_state.is_open { egui::Modal::new(egui::Id::new("process_worker_modal")).show(ui.ctx(), |ui| { - if ui.button("Закрыть").clicked() { + if ui.button("Закрыть").clicked() || ui.input(|i| i.key_pressed(egui::Key::Escape)) + { self.process_worker_state.is_open = false; } if self.process_worker_state.status != ModalStatus::Remove { @@ -318,6 +121,18 @@ impl WorkerTabViewer { ) .hint_text("1970-01-23"), ); + ui.end_row(); + if self.process_worker_state.status == ModalStatus::Edit { + ui.label("Уволен:"); + let data = self.process_worker_state.data.get("is_fired").unwrap(); + let mut checked = data.parse::().unwrap(); + ui.checkbox(&mut checked, ""); + if checked.to_string() != data.clone() { + self.process_worker_state + .data + .insert("is_fired".to_string(), checked.to_string()); + } + } }); self.process_worker_state.can_finish = self.check_date( @@ -331,7 +146,7 @@ impl WorkerTabViewer { let btext = match self.process_worker_state.status { ModalStatus::Add => "Добавить", ModalStatus::Edit => "Сохранить", - ModalStatus::Remove => "Уволить", + _ => "Подтвердить", }; if !self.process_worker_state.can_finish { ui.label("Проверьте правильность всех полей"); @@ -344,47 +159,105 @@ impl WorkerTabViewer { match self.process_worker_state.status { ModalStatus::Add => { self.rt.block_on(async { - self.db_oper.add_worker(WorkerRow { - id: self - .process_worker_state - .data - .get("id") + self.db_oper + .add_worker(WorkerRow { + id: self + .process_worker_state + .data + .get("id") + .unwrap() + .parse::() + .unwrap(), + full_name: self + .process_worker_state + .data + .get("full_name") + .unwrap() + .clone(), + position_id: self + .process_worker_state + .data + .get("position_id") + .unwrap() + .parse::() + .unwrap(), + hire_date: chrono::NaiveDate::parse_from_str( + &self + .process_worker_state + .data + .get("hire_date") + .unwrap(), + "%Y-%m-%d", + ) .unwrap() - .parse::() - .unwrap(), - full_name: *self - .process_worker_state - .data - .get("full_name") - .unwrap(), - position_id: self - .process_worker_state - .data - .get("position_id") + .and_hms_opt(0, 0, 0) .unwrap() - .parse::() + .and_local_timezone(chrono::Local) .unwrap(), - hire_date: chrono::NaiveDate::parse_from_str( - &self.edit_worker_hire_date, - "%Y-%m-%d", - ) - .unwrap() - .and_hms_opt(0, 0, 0) - .unwrap() - .and_local_timezone(chrono::Local) - .unwrap(), - is_fired: false, - }) + is_fired: false, + }) + .await + .ok() }); } - ModalStatus::Edit => {} - ModalStatus::Remove => {} + ModalStatus::Edit => { + self.rt.block_on(async { + self.db_oper + .update_worker(WorkerRow { + id: self + .process_worker_state + .data + .get("id") + .unwrap() + .parse::() + .unwrap(), + full_name: self + .process_worker_state + .data + .get("full_name") + .unwrap() + .clone(), + position_id: self + .process_worker_state + .data + .get("position_id") + .unwrap() + .parse::() + .unwrap(), + is_fired: self + .process_worker_state + .data + .get("is_fired") + .unwrap() + .parse::() + .unwrap(), + hire_date: chrono::NaiveDate::parse_from_str( + &self + .process_worker_state + .data + .get("hire_date") + .unwrap(), + "%Y-%m-%d", + ) + .unwrap() + .and_hms_opt(0, 0, 0) + .unwrap() + .and_local_timezone(chrono::Local) + .unwrap(), + }) + .await + .ok(); + }); + } + _ => {} } + self.update_workers(); + self.process_worker_state.is_open = false; } }); } TableBuilder::new(ui) - .column(Column::auto()) + .vscroll(false) .column(Column::auto()) .column(Column::auto()) .column(Column::auto()) @@ -421,11 +294,26 @@ impl WorkerTabViewer { row.col(|ui| { ui.label(if wk.is_fired { "Да" } else { "Нет" }); }); - row.col(|ui| { - if ui.button("Уволить").clicked() { - todo!(); - } - }); + if row.response().clicked() { + self.process_worker_state.is_open = true; + self.process_worker_state.status = ModalStatus::Edit; + self.process_worker_state + .data + .insert("id".to_string(), wk.id.to_string()); + self.process_worker_state + .data + .insert("full_name".to_string(), wk.full_name.clone()); + self.process_worker_state.data.insert( + "hire_date".to_string(), + wk.hire_date.date_naive().to_string(), + ); + self.process_worker_state + .data + .insert("is_fired".to_string(), wk.is_fired.to_string()); + self.process_worker_state + .data + .insert("position_id".to_string(), wk.position.id.to_string()); + } }); } }); @@ -509,7 +397,8 @@ impl WorkerTabViewer { if self.process_position_state.is_open { egui::Modal::new(egui::Id::new("process_worker_pos_modal")).show(ui.ctx(), |ui| { - if ui.button("Закрыть").clicked() { + if ui.button("Закрыть").clicked() || ui.input(|i| i.key_pressed(egui::Key::Escape)) + { self.process_position_state.is_open = false; } @@ -539,6 +428,9 @@ impl WorkerTabViewer { ModalStatus::Add => { btext = String::from("Добавить"); self.process_position_state.can_finish = true; + self.process_position_state + .data + .insert("id".to_string(), String::new()); } ModalStatus::Edit => { btext = String::from("Сохранить"); @@ -550,7 +442,10 @@ impl WorkerTabViewer { .read() .clone() .iter() - .find(|wrkr| wrkr.position.id == self.delete_position.id) + .find(|wrkr| { + wrkr.position.id.to_string() + == self.process_position_state.data.get("id").unwrap().clone() + }) .iter() .len() == 0; @@ -568,7 +463,7 @@ impl WorkerTabViewer { self.rt.block_on(async { self.db_oper .add_position(Position { - id: pos["id"].parse::().unwrap(), + id: 0, name: pos["name"].clone(), wage: bigdecimal::BigDecimal::from_str( pos["wage"].as_str(), @@ -690,25 +585,6 @@ impl Default for WorkerTabViewer { }, workers, positions: positions, - show_worker_add_modal: false, - show_worker_edit_modal: false, - show_position_add_modal: false, - show_position_delete_modal: false, - fire_worker_id: String::new(), - add_worker_name: String::new(), - add_worker_position: Position::default(), - add_worker_hire_date: String::new(), - can_add_worker: false, - can_edit_worker: false, - add_position_name: String::new(), - add_position_wage: String::new(), - delete_position: Position::default(), - - edit_worker_id: 1, - edit_worker_name: String::new(), - edit_worker_hire_date: String::new(), - edit_worker_position: Position::default(), - edit_worker_is_fired: false, db_oper, rt,