Разнёс вкладки по разным файлам, дабы не бояться app.rs на 100500 строк

master
Алексей Алексей 2026-06-06 14:11:05 +10:00
parent 07a8d64167
commit ec2cae91c0
6 changed files with 1205 additions and 1161 deletions

File diff suppressed because it is too large Load Diff

View File

@ -1,8 +1,11 @@
#![cfg_attr(not(debug_assertions), windows_subsystem = "windows")] #![cfg_attr(not(debug_assertions), windows_subsystem = "windows")]
mod app; mod app;
mod database; mod database;
mod material_tab;
mod models; mod models;
mod recipe_tab;
mod tab;
mod worker_tab;
// mod schema; // mod schema;
fn main() { fn main() {
dotenvy::dotenv().ok(); dotenvy::dotenv().ok();

581
code/src/material_tab.rs Normal file
View File

@ -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,
}
}
}

27
code/src/recipe_tab.rs Normal file
View File

@ -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("Помогите!!");
}
}
}
}

25
code/src/tab.rs Normal file
View File

@ -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,
}

566
code/src/worker_tab.rs Normal file
View File

@ -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,
}
}
}