diff --git a/code/Cargo.lock b/code/Cargo.lock index 968349c..620610a 100644 --- a/code/Cargo.lock +++ b/code/Cargo.lock @@ -1200,6 +1200,7 @@ dependencies = [ "ahash 0.8.12", "egui", "enum-map", + "image", "jiff", "log", "mime_guess2", diff --git a/code/Cargo.toml b/code/Cargo.toml index 6ac7c6a..834a89a 100644 --- a/code/Cargo.toml +++ b/code/Cargo.toml @@ -11,7 +11,7 @@ dotenvy = "0.15.7" eframe = {version = "0.34.2", features = ["glow"]} egui = "0.34.2" egui_dock = "0.19.1" -egui_extras = {version = "0.34.2", features = ["datepicker"]} +egui_extras = {version = "0.34.2", features = ["datepicker", "image"]} hex = "0.4.3" rust_decimal = {version = "1.42.0", features = ["macros"]} sha2 = "0.11.0" diff --git a/code/src/app.rs b/code/src/app.rs index 75bc1d0..a3f8856 100644 --- a/code/src/app.rs +++ b/code/src/app.rs @@ -175,6 +175,7 @@ struct MainTabViewer { material_tree: egui_dock::DockState, rt: tokio::runtime::Runtime, equipment_modal_state: ModalWinState, + salary_modal_state: ModalWinState, is_dark_theme: bool, interface_scale_ratio: f32, is_admin: bool, @@ -231,6 +232,17 @@ impl Default for MainTabViewer { ]), status: ModalStatus::Add, }, + salary_modal_state: ModalWinState { + is_open: false, + can_finish: false, + data: HashMap::from([ + ("id".to_owned(), String::new()), + ("worker_id".to_owned(), String::new()), + ("salary_size".to_owned(), String::new()), + ("comment".to_owned(), String::new()), + ]), + status: ModalStatus::Add, + }, is_admin: false, } } @@ -350,7 +362,8 @@ impl MainTabViewer { }); if self.equipment_modal_state.is_open { egui::Modal::new(egui::Id::new("process_equipment_modal")).show(ui.ctx(), |ui| { - if ui.button("Закрыть").clicked() { + if ui.button("Закрыть").clicked() || ui.input(|i| i.key_pressed(egui::Key::Escape)) + { self.equipment_modal_state.is_open = false; } if self.equipment_modal_state.status != ModalStatus::Remove { @@ -467,9 +480,30 @@ impl MainTabViewer { * Чё надо: * 1. Список платежей. */ - let table = TableBuilder::new(ui) + + if self.is_admin && ui.button("Добавить").clicked() { + self.salary_modal_state + .data + .insert("id".to_owned(), String::new()); + self.salary_modal_state + .data + .insert("worker_id".to_owned(), String::new()); + self.salary_modal_state + .data + .insert("salary_size".to_owned(), String::new()); + self.salary_modal_state + .data + .insert("salary_date".to_owned(), String::new()); + self.salary_modal_state + .data + .insert("comment".to_owned(), String::new()); + self.salary_modal_state.is_open = true; + self.salary_modal_state.status = ModalStatus::Add; + } + TableBuilder::new(ui) .striped(true) - .columns(Column::auto(), 4) + .columns(Column::auto(), 5) + .sense(egui::Sense::click()) .header(30.0, |mut header| { header.col(|ui| { ui.heading("Имя сотрудника"); @@ -484,7 +518,94 @@ impl MainTabViewer { ui.heading("Описание"); }); }) - .body(|mut body| {}); + .body(|mut body| { + body.ui_mut().style_mut().interaction.selectable_labels = false; + for sal in (self.salaries.read().iter().clone()) { + body.row(20.0, |mut row| { + row.col(|ui| { + ui.label(&sal.worker.full_name); + }); + row.col(|ui| { + ui.label(&sal.salary_size.to_string()); + }); + row.col(|ui| { + ui.label(&sal.salary_date.date_naive().to_string()); + }); + row.col(|ui| { + ui.label(&sal.comment); + }); + row.col(|ui| { + if ui.button("Удалить").clicked() { + self.salary_modal_state + .data + .insert("id".to_owned(), sal.id.to_string()); + self.salary_modal_state + .data + .insert("worker_id".to_owned(), sal.worker.id.to_string()); + self.salary_modal_state + .data + .insert("salary_size".to_owned(), sal.salary_size.to_string()); + self.salary_modal_state + .data + .insert("salary_date".to_owned(), sal.salary_date.to_string()); + self.salary_modal_state + .data + .insert("comment".to_owned(), sal.comment.clone()); + self.salary_modal_state.is_open = true; + self.salary_modal_state.status = ModalStatus::Remove; + } + }); + if row.response().double_clicked() { + self.salary_modal_state + .data + .insert("id".to_owned(), sal.id.to_string()); + self.salary_modal_state + .data + .insert("worker_id".to_owned(), sal.worker.id.to_string()); + self.salary_modal_state + .data + .insert("salary_size".to_owned(), sal.salary_size.to_string()); + self.salary_modal_state + .data + .insert("salary_date".to_owned(), sal.salary_date.to_string()); + self.salary_modal_state + .data + .insert("comment".to_owned(), sal.comment.clone()); + self.salary_modal_state.is_open = true; + self.salary_modal_state.status = ModalStatus::Edit; + } + }); + } + }); + if self.salary_modal_state.is_open { + egui::Modal::new(egui::Id::new("salary_modal")).show(ui.ctx(), |ui| { + if ui.button("Закрыть").clicked() || ui.input(|i| i.key_pressed(egui::Key::Escape)) + { + self.salary_modal_state.is_open = false; + } + if self.salary_modal_state.status != ModalStatus::Remove { + egui::Grid::new("process_salary_grid").show(ui, |ui| { + let mut size = ui.available_size(); + size.x = 40.0; + ui.label("Сотрудник(-и):"); + egui::ComboBox::new("process_salary_grid_combobox", "").show_ui(ui, |ui| { + for wrkr in self.workers.read().clone().iter(){ + + } + }); + + ui.end_row(); + ui.label("Размер оплаты:"); + ui.add_sized( + size, + egui::TextEdit::singleline( + self.salary_modal_state.data.get_mut("salary_size").unwrap(), + ), + ); + }); + } + }); + } /* * 2. Возможность добавить платежи. * 3. Возможность назначить платежи сразу нескольким сотрудникам. @@ -529,7 +650,7 @@ impl egui_dock::TabViewer for MainTabViewer { &self.show_settings(ui); } _ => { - ui.label("This is not"); + ui.label("Welcome to Avalonia!"); } } } diff --git a/code/src/database.rs b/code/src/database.rs index 0e1927f..2e10586 100644 --- a/code/src/database.rs +++ b/code/src/database.rs @@ -355,7 +355,6 @@ impl DBOperator { worker: w.clone(), salary_date: sal.salary_date, salary_size: sal.salary_size, - cluster_id: sal.cluster_id, comment: sal.comment, }), None => {} @@ -364,46 +363,24 @@ impl DBOperator { Ok(rets) } - pub async fn get_salary_clusters(&self) -> Result, sqlx::Error> { - let clus = sqlx::query_as::<_, SalaryCluster>("SELECT * FROM `salary_cluster`") - .fetch_all(&self.pool) - .await?; - Ok(clus) - } pub async fn add_salary( &self, worker: Worker, salary_date: DateTime, salary_size: Option, - cluster: SalaryCluster, comment: Option, ) -> Result { - match sqlx::query("INSERT INTO Brewery.salary (id, worker_id, salary_size, salary_date, comment, cluster_id) VALUES(0, ?, ?, ?, ?, ?);") + match sqlx::query("INSERT INTO Brewery.salary (id, worker_id, salary_size, salary_date, comment) VALUES(0, ?, ?, ?, ?);") .bind(worker.id) .bind(salary_size.unwrap_or(worker.position.wage)) .bind(salary_date) .bind(comment.unwrap_or(String::new())) - .bind(cluster.id) .execute(&self.pool) .await{ Ok(_) => Ok(true), Err(_) => Ok(false) } } - pub async fn add_salary_cluster(&self, name: String) -> Result { - match sqlx::query("INSERT INTO `salary_cluster` (id, name) VALUES (0, ?)") - .bind(name) - .execute(&self.pool) - .await - { - Ok(_) => Ok(sqlx::query("SELECT LAST_INSERT_ID();") - .fetch_one(&self.pool) - .await - .unwrap() - .get(0)), - Err(_) => Ok(-1), - } - } } pub async fn estabilish_connection() -> Result<(), sqlx::Error> { diff --git a/code/src/lib.rs b/code/src/lib.rs new file mode 100644 index 0000000..2794306 --- /dev/null +++ b/code/src/lib.rs @@ -0,0 +1,6 @@ +#[cfg(test)] +mod tests{ + use super::*; + + +} \ No newline at end of file diff --git a/code/src/main.rs b/code/src/main.rs index 7c2d703..bff0232 100644 --- a/code/src/main.rs +++ b/code/src/main.rs @@ -6,8 +6,8 @@ mod models; mod payment_tab; mod recipe_tab; mod tab; -mod worker_tab; mod worker_database; +mod worker_tab; // mod schema; fn main() { dotenvy::dotenv().ok(); @@ -23,6 +23,9 @@ fn main() { eframe::run_native( "BCS", native_opts, - Box::new(|cc| Ok(Box::new(app::App::new(cc)))), + Box::new(|cc| { + egui_extras::install_image_loaders(&cc.egui_ctx); + Ok(Box::new(app::App::new(cc))) + }), ); } diff --git a/code/src/models.rs b/code/src/models.rs index 4342cac..d4533e5 100644 --- a/code/src/models.rs +++ b/code/src/models.rs @@ -1,4 +1,4 @@ -use std::{any::TypeId, ops::Deref}; +use std::{any::TypeId, collections::HashSet, ops::Deref}; use egui::TextBuffer; use sqlx::{ @@ -44,7 +44,6 @@ pub struct SalaryRow { pub salary_size: BigDecimal, pub salary_date: chrono::DateTime, pub comment: String, - pub cluster_id: i32, } pub struct Salary { @@ -53,12 +52,6 @@ pub struct Salary { pub salary_size: BigDecimal, pub salary_date: chrono::DateTime, pub comment: String, - pub cluster_id: i32, -} -#[derive(sqlx::Decode, sqlx::FromRow, sqlx::Encode)] -pub struct SalaryCluster { - pub id: i32, - pub name: String, } #[derive(Default, Clone, Hash)] @@ -147,6 +140,15 @@ pub struct ModalWinState { pub status: ModalStatus, } +#[derive(Default)] +pub struct SalaryModalState { + pub is_open: bool, + pub can_finish: bool, + pub data: std::collections::HashMap, + pub workers: HashSet, + pub status: ModalStatus, +} + #[derive(Default, PartialEq)] pub enum ModalStatus { #[default]