Разнёс вкладки по разным файлам, дабы не бояться app.rs на 100500 строк
parent
07a8d64167
commit
ec2cae91c0
1162
code/src/app.rs
1162
code/src/app.rs
File diff suppressed because it is too large
Load Diff
|
|
@ -1,8 +1,11 @@
|
|||
#![cfg_attr(not(debug_assertions), windows_subsystem = "windows")]
|
||||
|
||||
mod app;
|
||||
mod database;
|
||||
mod material_tab;
|
||||
mod models;
|
||||
mod recipe_tab;
|
||||
mod tab;
|
||||
mod worker_tab;
|
||||
// mod schema;
|
||||
fn main() {
|
||||
dotenvy::dotenv().ok();
|
||||
|
|
|
|||
|
|
@ -0,0 +1,581 @@
|
|||
use std::{collections::HashMap, sync::Arc};
|
||||
|
||||
use egui::mutex::RwLock;
|
||||
use egui_extras::{Column, TableBuilder};
|
||||
|
||||
use crate::{database::DBOperator, models::{Material, MaterialCategory, MaterialRow, ModalStatus, ModalWinState}, tab::{TABS_CAN_BE_WINDOWS, Tab, TabTypes}};
|
||||
|
||||
pub struct MaterialTabViewer {
|
||||
db_oper: DBOperator,
|
||||
rt: tokio::runtime::Runtime,
|
||||
process_mcat_state: ModalWinState,
|
||||
|
||||
process_material_state: ModalWinState,
|
||||
|
||||
mat_cats: Arc<RwLock<Vec<MaterialCategory>>>,
|
||||
mats: Arc<RwLock<Vec<Material>>>,
|
||||
}
|
||||
impl MaterialTabViewer {
|
||||
fn update_material_category(&mut self) {
|
||||
self.mat_cats = Arc::new(RwLock::new(
|
||||
self.rt
|
||||
.block_on(async { self.db_oper.get_mcat().await.unwrap() }),
|
||||
));
|
||||
}
|
||||
fn update_materials(&mut self) {
|
||||
self.mats = Arc::new(RwLock::new(
|
||||
self.rt
|
||||
.block_on(async { self.db_oper.get_materials().await.unwrap() }),
|
||||
));
|
||||
}
|
||||
fn show_material(&mut self, ui: &mut egui::Ui) {
|
||||
ui.horizontal(|ui| {
|
||||
if ui.button("Добавить").clicked() {
|
||||
self.process_material_state.is_open = true;
|
||||
self.process_material_state.status = ModalStatus::Add;
|
||||
}
|
||||
if ui.button("Удалить").clicked() {
|
||||
self.process_material_state.is_open = true;
|
||||
self.process_material_state.status = ModalStatus::Remove;
|
||||
}
|
||||
if ui.button("Обновить").clicked() {
|
||||
self.update_materials();
|
||||
}
|
||||
});
|
||||
|
||||
TableBuilder::new(ui)
|
||||
.striped(true)
|
||||
.cell_layout(egui::Layout::centered_and_justified(
|
||||
egui::Direction::LeftToRight,
|
||||
))
|
||||
.vscroll(true)
|
||||
.column(Column::auto())
|
||||
.column(Column::auto())
|
||||
.column(Column::auto())
|
||||
.sense(egui::Sense::click())
|
||||
.header(20.0, |mut header| {
|
||||
header.col(|ui| {
|
||||
ui.heading("Название");
|
||||
});
|
||||
header.col(|ui| {
|
||||
ui.heading("Тип");
|
||||
});
|
||||
header.col(|ui| {
|
||||
ui.heading("Количество");
|
||||
});
|
||||
})
|
||||
.body(|mut body| {
|
||||
body.ui_mut().style_mut().interaction.selectable_labels = false;
|
||||
self.rt.block_on(async {
|
||||
for mat in self.mats.read().clone().iter() {
|
||||
body.row(30.0, |mut row| {
|
||||
row.col(|ui| {
|
||||
ui.label(&mat.name);
|
||||
});
|
||||
row.col(|ui| {
|
||||
ui.label(&mat.category.name);
|
||||
});
|
||||
row.col(|ui| {
|
||||
ui.label(mat.quantity.to_string());
|
||||
});
|
||||
if row.response().double_clicked() {
|
||||
self.process_material_state.is_open = true;
|
||||
self.process_material_state.status = ModalStatus::Edit;
|
||||
self.process_material_state
|
||||
.data
|
||||
.insert("id".into(), mat.id.to_string());
|
||||
self.process_material_state
|
||||
.data
|
||||
.insert("name".into(), mat.name.to_string());
|
||||
self.process_material_state
|
||||
.data
|
||||
.insert("category_id".into(), mat.category.id.to_string());
|
||||
self.process_material_state
|
||||
.data
|
||||
.insert("quantity".into(), mat.quantity.to_string());
|
||||
}
|
||||
});
|
||||
}
|
||||
})
|
||||
});
|
||||
if self.process_material_state.is_open {
|
||||
egui::Modal::new("process_material".into()).show(ui.ctx(), |ui| {
|
||||
if ui.button("Закрыть").clicked() {
|
||||
self.process_material_state.is_open = false;
|
||||
}
|
||||
egui::Grid::new("process_material_grid").show(ui, |ui| {
|
||||
let old = self.process_material_state.data.get("id").unwrap().clone();
|
||||
if self.process_material_state.status != ModalStatus::Add {
|
||||
ui.label("Материал");
|
||||
|
||||
let mats = self.mats.read().clone();
|
||||
|
||||
let sel_id = self
|
||||
.process_material_state
|
||||
.data
|
||||
.get("id")
|
||||
.map(|d| d.as_str())
|
||||
.unwrap_or("");
|
||||
let cur_name = mats
|
||||
.iter()
|
||||
.find(|m| m.id.to_string() == sel_id)
|
||||
.map(|m| m.name.clone())
|
||||
.unwrap_or_default();
|
||||
egui::ComboBox::from_id_salt("process_material_combobox_mat")
|
||||
.selected_text(cur_name)
|
||||
.show_ui(ui, |ui| {
|
||||
for mat in self.mats.read().iter().clone() {
|
||||
ui.selectable_value(
|
||||
self.process_material_state.data.get_mut("id").unwrap(),
|
||||
mat.id.to_string(),
|
||||
&mat.name,
|
||||
);
|
||||
}
|
||||
let id = self
|
||||
.process_material_state
|
||||
.data
|
||||
.get_mut("id")
|
||||
.unwrap()
|
||||
.clone();
|
||||
if id != old {
|
||||
self.process_material_state.data.insert(
|
||||
"name".to_owned(),
|
||||
mats.iter()
|
||||
.find(|m| m.id.to_string() == id)
|
||||
.unwrap()
|
||||
.name
|
||||
.clone(),
|
||||
);
|
||||
self.process_material_state.data.insert(
|
||||
"quantity".to_owned(),
|
||||
mats.iter()
|
||||
.find(|m| m.id.to_string() == id)
|
||||
.unwrap()
|
||||
.quantity
|
||||
.to_string(),
|
||||
);
|
||||
self.process_material_state.data.insert(
|
||||
"category_id".to_owned(),
|
||||
mats.iter()
|
||||
.find(|m| m.id.to_string() == id)
|
||||
.unwrap()
|
||||
.category
|
||||
.id
|
||||
.to_string(),
|
||||
);
|
||||
}
|
||||
});
|
||||
ui.end_row();
|
||||
}
|
||||
let old = self
|
||||
.process_material_state
|
||||
.data
|
||||
.get("category_id")
|
||||
.unwrap()
|
||||
.clone();
|
||||
if self.process_material_state.status != ModalStatus::Remove {
|
||||
ui.label("Название");
|
||||
ui.text_edit_singleline(
|
||||
self.process_material_state.data.get_mut("name").unwrap(),
|
||||
);
|
||||
|
||||
ui.end_row();
|
||||
ui.label("Количество");
|
||||
ui.text_edit_singleline(
|
||||
self.process_material_state
|
||||
.data
|
||||
.get_mut("quantity")
|
||||
.unwrap(),
|
||||
);
|
||||
|
||||
ui.end_row();
|
||||
ui.label("Тип");
|
||||
|
||||
let mats = self.mat_cats.read().clone();
|
||||
|
||||
let sel_id = self
|
||||
.process_material_state
|
||||
.data
|
||||
.get("category_id")
|
||||
.map(|d| d.as_str())
|
||||
.unwrap_or_default();
|
||||
let cur_name = mats
|
||||
.iter()
|
||||
.find(|m| m.id.to_string() == sel_id)
|
||||
.map(|m| m.name.clone())
|
||||
.unwrap_or_default();
|
||||
egui::ComboBox::from_id_salt("process_material_combobox_cat")
|
||||
.selected_text(cur_name)
|
||||
.show_ui(ui, |ui| {
|
||||
for mat in self.mat_cats.read().iter() {
|
||||
ui.selectable_value(
|
||||
self.process_material_state
|
||||
.data
|
||||
.get_mut("category_id")
|
||||
.unwrap(),
|
||||
mat.id.to_string(),
|
||||
&mat.name.clone(),
|
||||
);
|
||||
}
|
||||
});
|
||||
ui.end_row();
|
||||
}
|
||||
});
|
||||
match self.process_material_state.status {
|
||||
ModalStatus::Add => {
|
||||
let resp = ui.add_enabled(
|
||||
self.process_material_state.data.get("name").unwrap().len() > 0
|
||||
&& self
|
||||
.process_material_state
|
||||
.data
|
||||
.get("quantity")
|
||||
.unwrap()
|
||||
.len()
|
||||
> 0,
|
||||
egui::Button::new("Добавить"),
|
||||
);
|
||||
if resp.clicked() {
|
||||
self.rt.block_on(async {
|
||||
self.db_oper
|
||||
.add_material(MaterialRow {
|
||||
id: self
|
||||
.process_material_state
|
||||
.data
|
||||
.get("id")
|
||||
.unwrap()
|
||||
.parse::<i32>()
|
||||
.unwrap(),
|
||||
name: self
|
||||
.process_material_state
|
||||
.data
|
||||
.get("name")
|
||||
.unwrap()
|
||||
.to_string(),
|
||||
quantity: self
|
||||
.process_material_state
|
||||
.data
|
||||
.get("quantity")
|
||||
.unwrap()
|
||||
.parse::<i32>()
|
||||
.unwrap(),
|
||||
category_id: self
|
||||
.process_material_state
|
||||
.data
|
||||
.get("category_id")
|
||||
.unwrap()
|
||||
.parse::<i32>()
|
||||
.unwrap(),
|
||||
})
|
||||
.await
|
||||
.unwrap();
|
||||
});
|
||||
self.update_materials();
|
||||
self.process_material_state.is_open = false;
|
||||
}
|
||||
}
|
||||
ModalStatus::Edit => {
|
||||
if ui.button("Сохранить").clicked() {
|
||||
self.rt.block_on(async {
|
||||
self.db_oper
|
||||
.update_material(MaterialRow {
|
||||
id: self
|
||||
.process_material_state
|
||||
.data
|
||||
.get("id")
|
||||
.unwrap()
|
||||
.parse::<i32>()
|
||||
.unwrap(),
|
||||
name: self
|
||||
.process_material_state
|
||||
.data
|
||||
.get("name")
|
||||
.unwrap()
|
||||
.to_string(),
|
||||
quantity: self
|
||||
.process_material_state
|
||||
.data
|
||||
.get("quantity")
|
||||
.unwrap()
|
||||
.parse::<i32>()
|
||||
.unwrap(),
|
||||
category_id: self
|
||||
.process_material_state
|
||||
.data
|
||||
.get("category_id")
|
||||
.unwrap()
|
||||
.parse::<i32>()
|
||||
.unwrap(),
|
||||
})
|
||||
.await
|
||||
.unwrap();
|
||||
});
|
||||
self.update_materials();
|
||||
self.process_material_state.is_open = false;
|
||||
}
|
||||
}
|
||||
ModalStatus::Remove => {
|
||||
if ui.button("Удалить").clicked() {
|
||||
self.rt.block_on(async {
|
||||
self.db_oper
|
||||
.delete_material(MaterialRow {
|
||||
id: self
|
||||
.process_material_state
|
||||
.data
|
||||
.get("id")
|
||||
.unwrap()
|
||||
.parse::<i32>()
|
||||
.unwrap(),
|
||||
name: "".to_owned(),
|
||||
quantity: 0,
|
||||
category_id: 0,
|
||||
})
|
||||
.await
|
||||
.unwrap();
|
||||
});
|
||||
self.update_materials();
|
||||
self.process_material_state.is_open = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
fn show_material_type(&mut self, ui: &mut egui::Ui) {
|
||||
ui.horizontal(|ui| {
|
||||
if ui.button("Добавить").clicked() {
|
||||
self.process_mcat_state.is_open = true;
|
||||
self.process_mcat_state.status = ModalStatus::Add;
|
||||
}
|
||||
if ui.button("Удалить").clicked() {
|
||||
self.process_mcat_state.is_open = true;
|
||||
self.process_mcat_state.status = ModalStatus::Remove;
|
||||
}
|
||||
if ui.button("Обновить").clicked() {
|
||||
self.update_material_category();
|
||||
}
|
||||
});
|
||||
if self.process_mcat_state.is_open {
|
||||
egui::Modal::new("process_mcat".into()).show(ui.ctx(), |ui| {
|
||||
if ui.button("Закрыть").clicked() {
|
||||
self.process_mcat_state.is_open = false;
|
||||
}
|
||||
egui::Grid::new("process_mcat_grid").show(ui, |ui| {
|
||||
let old = self.process_mcat_state.data.get("id").unwrap().clone();
|
||||
let iterr = self.mat_cats.read().clone();
|
||||
|
||||
let selected_id = self
|
||||
.process_mcat_state
|
||||
.data
|
||||
.get("id")
|
||||
.map(|s| s.as_str())
|
||||
.unwrap_or("");
|
||||
|
||||
let current_name = iterr
|
||||
.iter()
|
||||
.find(|mc| mc.id.to_string() == *selected_id)
|
||||
.map(|mc| mc.name.as_str())
|
||||
.unwrap_or("Выбрать");
|
||||
if self.process_mcat_state.status != ModalStatus::Add {
|
||||
ui.label("Тип");
|
||||
egui::ComboBox::new("process_mcat_grid_selector", "Выбрать")
|
||||
.selected_text(current_name)
|
||||
.show_ui(ui, |ui| {
|
||||
self.rt.block_on(async {
|
||||
for mcat in iterr {
|
||||
ui.selectable_value(
|
||||
self.process_mcat_state.data.get_mut("id").unwrap(),
|
||||
mcat.id.to_string(),
|
||||
format!("{}|{}", mcat.id, &mcat.name),
|
||||
);
|
||||
}
|
||||
});
|
||||
});
|
||||
ui.end_row();
|
||||
}
|
||||
let current_id = self.process_mcat_state.data.get("id").unwrap().clone();
|
||||
if self.process_mcat_state.data.get("id").unwrap() != &old {
|
||||
self.process_mcat_state.data.insert(
|
||||
"name".to_owned(),
|
||||
self.mat_cats
|
||||
.read()
|
||||
.iter()
|
||||
.find(|mc| mc.id.to_string() == current_id)
|
||||
.unwrap()
|
||||
.name
|
||||
.clone(),
|
||||
);
|
||||
}
|
||||
|
||||
if self.process_mcat_state.status != ModalStatus::Remove {
|
||||
ui.label("Название");
|
||||
let mut name = self.process_mcat_state.data.get_mut("name").unwrap();
|
||||
ui.text_edit_singleline(name);
|
||||
ui.end_row();
|
||||
}
|
||||
|
||||
match self.process_mcat_state.status {
|
||||
ModalStatus::Add => {
|
||||
if ui.button("Добавить").clicked() {
|
||||
let name =
|
||||
self.process_mcat_state.data.get("name").unwrap().clone();
|
||||
self.rt.block_on(async {
|
||||
self.db_oper
|
||||
.add_material_category(MaterialCategory { id: 0, name })
|
||||
.await
|
||||
.unwrap();
|
||||
});
|
||||
self.update_material_category();
|
||||
self.process_mcat_state.is_open = false;
|
||||
}
|
||||
}
|
||||
ModalStatus::Edit => {
|
||||
if ui.button("Сохранить").clicked() {
|
||||
let id = self.process_mcat_state.data.get("id").unwrap().clone();
|
||||
let name =
|
||||
self.process_mcat_state.data.get("name").unwrap().clone();
|
||||
self.rt.block_on(async {
|
||||
self.db_oper
|
||||
.update_material_category(MaterialCategory {
|
||||
id: id.parse::<i32>().unwrap(),
|
||||
name: name.clone(),
|
||||
})
|
||||
.await
|
||||
.unwrap()
|
||||
});
|
||||
println!("{}", &name);
|
||||
self.update_material_category();
|
||||
self.process_mcat_state.is_open = false;
|
||||
}
|
||||
}
|
||||
ModalStatus::Remove => {
|
||||
if ui.button("Удалить").clicked() {
|
||||
let idd = self.process_mcat_state.data.get("id").unwrap().clone();
|
||||
self.rt.block_on(async {
|
||||
self.db_oper
|
||||
.delete_material_category(MaterialCategory {
|
||||
id: idd.parse::<i32>().unwrap(),
|
||||
name: "".to_owned(),
|
||||
})
|
||||
.await
|
||||
.unwrap()
|
||||
});
|
||||
self.update_material_category();
|
||||
self.process_mcat_state.is_open = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
TableBuilder::new(ui)
|
||||
.striped(true)
|
||||
.column(Column::auto())
|
||||
.column(Column::auto())
|
||||
.sense(egui::Sense::click())
|
||||
.header(20.0, |mut header| {
|
||||
header.col(|ui| {
|
||||
ui.heading("ID");
|
||||
});
|
||||
header.col(|ui| {
|
||||
ui.heading("Название");
|
||||
});
|
||||
})
|
||||
.body(|mut body| {
|
||||
self.rt.block_on(async {
|
||||
for mcat in self.mat_cats.read().clone().iter() {
|
||||
body.row(20.0, |mut row| {
|
||||
row.col(|ui| {
|
||||
ui.label(mcat.id.to_string());
|
||||
});
|
||||
row.col(|ui| {
|
||||
ui.label(&mcat.name);
|
||||
});
|
||||
if row.response().double_clicked() {
|
||||
self.process_mcat_state.is_open = true;
|
||||
self.process_mcat_state.status = ModalStatus::Edit;
|
||||
self.process_mcat_state
|
||||
.data
|
||||
.insert("id".into(), mcat.id.to_string());
|
||||
self.process_mcat_state
|
||||
.data
|
||||
.insert("name".into(), mcat.name.clone());
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
impl egui_dock::TabViewer for MaterialTabViewer {
|
||||
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 {
|
||||
TabTypes::MaterialList => self.show_material(ui),
|
||||
TabTypes::MaterialTypeList => self.show_material_type(ui),
|
||||
_ => {
|
||||
ui.label("Каким образом?");
|
||||
}
|
||||
}
|
||||
}
|
||||
fn allowed_in_windows(&self, _tab: &mut Self::Tab) -> bool {
|
||||
TABS_CAN_BE_WINDOWS
|
||||
}
|
||||
fn is_closeable(&self, _tab: &Self::Tab) -> bool {
|
||||
false
|
||||
}
|
||||
}
|
||||
impl Default for MaterialTabViewer {
|
||||
fn default() -> Self {
|
||||
let rt = tokio::runtime::Runtime::new().unwrap();
|
||||
let db_oper = rt.block_on(async { DBOperator::new().await });
|
||||
let mat_cats = Arc::new(RwLock::new(
|
||||
rt.block_on(async { db_oper.get_mcat().await.unwrap() }),
|
||||
));
|
||||
let mats = Arc::new(RwLock::new(
|
||||
rt.block_on(async { db_oper.get_materials().await.unwrap() }),
|
||||
));
|
||||
Self {
|
||||
db_oper,
|
||||
rt,
|
||||
process_mcat_state: ModalWinState {
|
||||
data: HashMap::from([
|
||||
(
|
||||
String::from("id"),
|
||||
mat_cats.clone().read().clone()[0].id.to_string(),
|
||||
),
|
||||
(
|
||||
String::from("name"),
|
||||
mat_cats.clone().read().clone()[0].name.clone(),
|
||||
),
|
||||
]),
|
||||
status: ModalStatus::Add,
|
||||
..Default::default()
|
||||
},
|
||||
|
||||
process_material_state: ModalWinState {
|
||||
data: HashMap::from([
|
||||
(
|
||||
"id".to_owned(),
|
||||
mats.clone().read().clone()[0].id.to_string(),
|
||||
),
|
||||
(
|
||||
"name".to_owned(),
|
||||
mats.clone().read().clone()[0].name.clone(),
|
||||
),
|
||||
(
|
||||
"quantity".to_owned(),
|
||||
mats.clone().read().clone()[0].quantity.to_string(),
|
||||
),
|
||||
("category_id".to_owned(), "1".to_owned()),
|
||||
]),
|
||||
..Default::default()
|
||||
},
|
||||
mat_cats,
|
||||
mats,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,27 @@
|
|||
struct RecipeTabViewer {}
|
||||
|
||||
impl RecipeTabViewer {
|
||||
fn show_recipe_list(&mut self, ui: &mut egui::Ui) {}
|
||||
fn show_recipe_detail(&mut self, ui: &mut egui::Ui) {}
|
||||
}
|
||||
impl egui_dock::TabViewer for RecipeTabViewer {
|
||||
type Tab = Tab;
|
||||
|
||||
fn title(&mut self, tab: &mut Self::Tab) -> egui::WidgetText {
|
||||
tab.title.clone().into()
|
||||
}
|
||||
|
||||
fn ui(&mut self, ui: &mut egui::Ui, tab: &mut Self::Tab) {
|
||||
match &tab.tab_type {
|
||||
TabTypes::RecipeList => {
|
||||
self.show_recipe_list(ui);
|
||||
}
|
||||
TabTypes::RecipeDetail => {
|
||||
self.show_recipe_detail(ui);
|
||||
}
|
||||
_ => {
|
||||
ui.label("Помогите!!");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,25 @@
|
|||
pub static TABS_CAN_BE_WINDOWS: bool = false;
|
||||
|
||||
pub enum TabTypes {
|
||||
Equipment,
|
||||
Worker,
|
||||
Position,
|
||||
Salary,
|
||||
Material,
|
||||
Recipe,
|
||||
Product,
|
||||
Order,
|
||||
Settings,
|
||||
WorkerList,
|
||||
WorkerPosition,
|
||||
MaterialList,
|
||||
MaterialTypeList,
|
||||
RecipeList,
|
||||
RecipeDetail,
|
||||
ProductList,
|
||||
}
|
||||
|
||||
pub struct Tab {
|
||||
pub tab_type: TabTypes,
|
||||
pub title: String,
|
||||
}
|
||||
|
|
@ -0,0 +1,566 @@
|
|||
use std::collections::HashMap;
|
||||
use std::str::FromStr;
|
||||
use std::sync::{Arc};
|
||||
use bigdecimal::BigDecimal;
|
||||
use egui::mutex::RwLock;
|
||||
use egui_extras::{Column, TableBuilder};
|
||||
|
||||
use crate::models::{ModalStatus, ModalWinState, Position, Worker};
|
||||
use crate::database::*;
|
||||
use crate::tab::*;
|
||||
pub struct WorkerTabViewer {
|
||||
db_oper: DBOperator,
|
||||
workers: Arc<RwLock<Option<Vec<Worker>>>>,
|
||||
positions: Arc<RwLock<Vec<Position>>>,
|
||||
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_position_state: ModalWinState,
|
||||
}
|
||||
|
||||
impl WorkerTabViewer {
|
||||
fn update_workers(&mut self) {
|
||||
self.workers = Arc::new(RwLock::new(Option::Some(
|
||||
self.rt
|
||||
.block_on(async { self.db_oper.get_workers().await.unwrap() }),
|
||||
)));
|
||||
}
|
||||
fn update_positions(&mut self) {
|
||||
self.positions = Arc::new(RwLock::new(
|
||||
self.rt
|
||||
.block_on(async { self.db_oper.get_position().await.unwrap() }),
|
||||
));
|
||||
}
|
||||
|
||||
fn show_worker(&mut self, ui: &mut egui::Ui) {
|
||||
ui.horizontal(|ui| {
|
||||
if ui.button("Добавить").clicked() {
|
||||
self.show_worker_add_modal = true;
|
||||
self.add_worker_name = String::new();
|
||||
self.add_worker_position = Position::default();
|
||||
};
|
||||
if ui.button("Редактировать").clicked() {
|
||||
self.show_worker_edit_modal = true;
|
||||
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;
|
||||
});
|
||||
}
|
||||
if ui.button("Обновить").clicked() {
|
||||
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.db_oper.get_position().await.unwrap().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.db_oper.get_workers().await.unwrap().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.db_oper.get_position().await.unwrap().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;
|
||||
}
|
||||
});
|
||||
}
|
||||
TableBuilder::new(ui)
|
||||
.column(Column::auto())
|
||||
.column(Column::auto())
|
||||
.column(Column::auto())
|
||||
.column(Column::auto())
|
||||
.column(Column::auto())
|
||||
.sense(egui::Sense::click())
|
||||
.header(30.0, |mut header| {
|
||||
header.col(|ui| {
|
||||
ui.heading("Имя");
|
||||
});
|
||||
header.col(|ui| {
|
||||
ui.heading("Дата найма");
|
||||
});
|
||||
header.col(|ui| {
|
||||
ui.heading("Должность");
|
||||
});
|
||||
header.col(|ui| {
|
||||
ui.heading("Уволен");
|
||||
});
|
||||
})
|
||||
.body(|mut body| {
|
||||
body.ui_mut().style_mut().interaction.selectable_labels = false;
|
||||
|
||||
for wk in self.workers.read().clone().unwrap().iter() {
|
||||
body.row(25.0, |mut row| {
|
||||
row.col(|ui| {
|
||||
ui.label(&wk.full_name);
|
||||
});
|
||||
row.col(|ui| {
|
||||
ui.label(wk.hire_date.date_naive().format("%d-%m-%Y").to_string());
|
||||
});
|
||||
row.col(|ui| {
|
||||
ui.label(&wk.position.name);
|
||||
});
|
||||
row.col(|ui| {
|
||||
ui.label(if wk.is_fired { "Да" } else { "Нет" });
|
||||
});
|
||||
row.col(|ui| {
|
||||
if ui.button("Уволить").clicked() {
|
||||
todo!();
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
fn show_position(&mut self, ui: &mut egui::Ui) {
|
||||
ui.horizontal(|ui| {
|
||||
if ui.button("Добавить").clicked() {
|
||||
// self.show_position_add_modal = true;
|
||||
self.process_position_state.is_open = true;
|
||||
self.process_position_state.status = ModalStatus::Add;
|
||||
self.process_position_state
|
||||
.data
|
||||
.insert("id".into(), "0".to_string());
|
||||
self.process_position_state
|
||||
.data
|
||||
.insert("name".into(), String::new());
|
||||
self.process_position_state
|
||||
.data
|
||||
.insert("wage".into(), String::from("0"));
|
||||
}
|
||||
if ui.button("Обновить").clicked() {
|
||||
self.update_positions();
|
||||
}
|
||||
});
|
||||
TableBuilder::new(ui)
|
||||
.column(Column::auto())
|
||||
.column(Column::auto())
|
||||
.column(Column::auto())
|
||||
.sense(egui::Sense::click())
|
||||
.header(30.0, |mut header| {
|
||||
header.col(|ui| {
|
||||
ui.heading("Название");
|
||||
});
|
||||
header.col(|ui| {
|
||||
ui.heading("Оклад");
|
||||
});
|
||||
})
|
||||
.body(|mut body| {
|
||||
body.ui_mut().style_mut().interaction.selectable_labels = false;
|
||||
for pos in self.positions.read().clone().iter() {
|
||||
body.row(20.0, |mut row| {
|
||||
row.col(|ui| {
|
||||
ui.label(pos.name.clone());
|
||||
});
|
||||
row.col(|ui| {
|
||||
ui.label(format!("${}", pos.wage));
|
||||
});
|
||||
row.col(|ui| {
|
||||
let resp = ui.add(egui::Button::new("Удалить"));
|
||||
if resp.clicked() {
|
||||
self.process_position_state.is_open = true;
|
||||
self.process_position_state.status = ModalStatus::Remove;
|
||||
self.process_position_state
|
||||
.data
|
||||
.insert("id".into(), pos.id.to_string());
|
||||
self.process_position_state
|
||||
.data
|
||||
.insert("name".into(), pos.name.clone());
|
||||
self.process_position_state
|
||||
.data
|
||||
.insert("wage".into(), pos.wage.to_string());
|
||||
}
|
||||
});
|
||||
if row.response().double_clicked() {
|
||||
self.process_position_state.is_open = true;
|
||||
self.process_position_state.status = ModalStatus::Edit;
|
||||
self.process_position_state
|
||||
.data
|
||||
.insert("id".into(), pos.id.to_string());
|
||||
self.process_position_state
|
||||
.data
|
||||
.insert("name".into(), pos.name.clone());
|
||||
self.process_position_state
|
||||
.data
|
||||
.insert("wage".into(), pos.wage.to_string());
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
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() {
|
||||
self.process_position_state.is_open = false;
|
||||
}
|
||||
|
||||
if self.process_position_state.status != ModalStatus::Remove {
|
||||
egui::Grid::new("process_worker_pos_grid").show(ui, |ui| {
|
||||
ui.label("Название");
|
||||
let mut name = self.process_position_state.data.get_mut("name").unwrap();
|
||||
let mut spacing = ui.spacing().interact_size;
|
||||
spacing.x = 150.0;
|
||||
ui.add_sized(spacing, |ui: &mut egui::Ui| ui.text_edit_singleline(name));
|
||||
|
||||
ui.end_row();
|
||||
|
||||
ui.label("Оклад");
|
||||
let mut wage = self.process_position_state.data.get_mut("wage").unwrap();
|
||||
ui.text_edit_singleline(wage);
|
||||
});
|
||||
} else {
|
||||
ui.label("Вы уверены, что хотите удалить:");
|
||||
ui.label(format!(
|
||||
"{}?",
|
||||
self.process_position_state.data["name"].clone()
|
||||
));
|
||||
}
|
||||
let btext: String;
|
||||
match self.process_position_state.status {
|
||||
ModalStatus::Add => {
|
||||
btext = String::from("Добавить");
|
||||
self.process_position_state.can_finish = true;
|
||||
}
|
||||
ModalStatus::Edit => {
|
||||
btext = String::from("Сохранить");
|
||||
self.process_position_state.can_finish = true;
|
||||
}
|
||||
ModalStatus::Remove => {
|
||||
self.process_position_state.can_finish = self
|
||||
.workers
|
||||
.read()
|
||||
.clone()
|
||||
.unwrap()
|
||||
.iter()
|
||||
.find(|wrkr| wrkr.position.id == self.delete_position.id)
|
||||
.iter()
|
||||
.len()
|
||||
== 0;
|
||||
btext = String::from("Удалить");
|
||||
}
|
||||
}
|
||||
let button = ui.add_enabled(
|
||||
self.process_position_state.can_finish,
|
||||
egui::Button::new(btext),
|
||||
);
|
||||
if button.clicked() || ui.input(|i| i.key_pressed(egui::Key::Enter)) {
|
||||
match self.process_position_state.status {
|
||||
ModalStatus::Add => {
|
||||
let pos = self.process_position_state.data.clone();
|
||||
self.rt.block_on(async {
|
||||
self.db_oper
|
||||
.add_position(Position {
|
||||
id: pos["id"].parse::<i32>().unwrap(),
|
||||
name: pos["name"].clone(),
|
||||
wage: bigdecimal::BigDecimal::from_str(
|
||||
pos["wage"].as_str(),
|
||||
)
|
||||
.unwrap(),
|
||||
})
|
||||
.await;
|
||||
})
|
||||
}
|
||||
ModalStatus::Edit => {
|
||||
let pos = self.process_position_state.data.clone();
|
||||
self.rt.block_on(async {
|
||||
self.db_oper
|
||||
.update_position(Position {
|
||||
id: pos["id"].parse::<i32>().unwrap(),
|
||||
name: pos["name"].clone(),
|
||||
wage: bigdecimal::BigDecimal::from_str(
|
||||
pos["wage"].as_str(),
|
||||
)
|
||||
.unwrap(),
|
||||
})
|
||||
.await;
|
||||
})
|
||||
}
|
||||
ModalStatus::Remove => {
|
||||
let pos = self.process_position_state.data.clone();
|
||||
self.rt.block_on(async {
|
||||
self.db_oper
|
||||
.delete_position(Position {
|
||||
id: pos["id"].parse::<i32>().unwrap(),
|
||||
name: String::new(),
|
||||
wage: BigDecimal::from(0),
|
||||
})
|
||||
.await;
|
||||
});
|
||||
}
|
||||
}
|
||||
self.update_positions();
|
||||
self.process_position_state.is_open = false;
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl egui_dock::TabViewer for WorkerTabViewer {
|
||||
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 {
|
||||
TabTypes::WorkerList => {
|
||||
self.show_worker(ui)
|
||||
},
|
||||
TabTypes::WorkerPosition => self.show_position(ui),
|
||||
_ => {
|
||||
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 {
|
||||
false
|
||||
}
|
||||
}
|
||||
impl Default for WorkerTabViewer {
|
||||
fn default() -> Self {
|
||||
let rt = tokio::runtime::Runtime::new().unwrap();
|
||||
let db_oper = rt.block_on(async { DBOperator::new().await });
|
||||
let positions = Arc::new(RwLock::new(
|
||||
rt.block_on(async { db_oper.get_position().await.unwrap() }),
|
||||
));
|
||||
let mut pos_map: HashMap<String, String> = HashMap::new();
|
||||
pos_map.extend(|| -> Vec<(String, String)> {
|
||||
let pos = positions.read()[0].clone();
|
||||
vec![
|
||||
("id".to_string(), pos.id.to_string()),
|
||||
("name".to_string(), pos.name.clone()),
|
||||
("wage".to_string(), pos.wage.to_string()),
|
||||
]
|
||||
}());
|
||||
Self {
|
||||
process_position_state: ModalWinState {
|
||||
is_open: false,
|
||||
can_finish: false,
|
||||
data: pos_map,
|
||||
status: ModalStatus::Add,
|
||||
},
|
||||
workers: Arc::new(RwLock::new(Option::Some(
|
||||
rt.block_on(async { db_oper.get_workers().await.unwrap() }),
|
||||
))),
|
||||
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,
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
Reference in New Issue