бебебебе я дурачок

master
Алексей Алексей 2026-06-09 18:29:05 +10:00
parent 4840a136a1
commit 60ecbc5361
6 changed files with 210 additions and 265 deletions

View File

@ -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<Tab>,
material_tabs: MaterialTabViewer,
material_tree: egui_dock::DockState<Tab>,
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()
}
}

View File

@ -206,9 +206,9 @@ impl DBOperator {
}
}
pub async fn update_worker(&self, worker: Worker) -> Result<bool, sqlx::Error> {
pub async fn update_worker(&self, worker: WorkerRow) -> Result<bool, sqlx::Error> {
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)

View File

@ -3,6 +3,7 @@ mod app;
mod database;
mod material_tab;
mod models;
mod payment_tab;
mod recipe_tab;
mod tab;
mod worker_tab;

View File

@ -142,7 +142,7 @@ pub struct LoginModalState<'a> {
pub fail_message: String,
}
#[derive(Default)]
#[derive(Default, PartialEq)]
pub enum LoginStatus {
#[default]
Login,

51
code/src/payment_tab.rs Normal file
View File

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

View File

@ -14,27 +14,9 @@ pub struct WorkerTabViewer {
db_oper: DBOperator,
workers: Arc<RwLock<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_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::<bool>().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,7 +159,8 @@ impl WorkerTabViewer {
match self.process_worker_state.status {
ModalStatus::Add => {
self.rt.block_on(async {
self.db_oper.add_worker(WorkerRow {
self.db_oper
.add_worker(WorkerRow {
id: self
.process_worker_state
.data
@ -352,11 +168,12 @@ impl WorkerTabViewer {
.unwrap()
.parse::<i32>()
.unwrap(),
full_name: *self
full_name: self
.process_worker_state
.data
.get("full_name")
.unwrap(),
.unwrap()
.clone(),
position_id: self
.process_worker_state
.data
@ -365,7 +182,11 @@ impl WorkerTabViewer {
.parse::<i32>()
.unwrap(),
hire_date: chrono::NaiveDate::parse_from_str(
&self.edit_worker_hire_date,
&self
.process_worker_state
.data
.get("hire_date")
.unwrap(),
"%Y-%m-%d",
)
.unwrap()
@ -375,16 +196,68 @@ impl WorkerTabViewer {
.unwrap(),
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::<i32>()
.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::<i32>()
.unwrap(),
is_fired: self
.process_worker_state
.data
.get("is_fired")
.unwrap()
.parse::<bool>()
.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,12 +294,27 @@ 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::<i32>().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,