use std::{collections::HashMap, default::Default, sync::Arc}; use egui::mutex::RwLock; use egui_extras::{Column, TableBuilder}; use crate::{ database::DBOperator, misc::ELEMENTS_PER_PAGE, 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>>, mats: Arc>>, is_admin: bool, mat_page: i32, mcat_page: i32, } impl MaterialTabViewer { pub fn new(is_admin: bool) -> Self { Self { is_admin, ..Default::default() } } 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(self.mat_page * ELEMENTS_PER_PAGE, ELEMENTS_PER_PAGE) .await .unwrap() }))); } fn show_material(&mut self, ui: &mut egui::Ui) { ui.horizontal(|ui| { if self.is_admin { 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::() .unwrap(), name: self .process_material_state .data .get("name") .unwrap() .to_string(), quantity: self .process_material_state .data .get("quantity") .unwrap() .parse::() .unwrap(), category_id: self .process_material_state .data .get("category_id") .unwrap() .parse::() .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::() .unwrap(), name: self .process_material_state .data .get("name") .unwrap() .to_string(), quantity: self .process_material_state .data .get("quantity") .unwrap() .parse::() .unwrap(), category_id: self .process_material_state .data .get("category_id") .unwrap() .parse::() .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::() .unwrap(), name: "".to_owned(), quantity: 0, category_id: 0, }) .await .unwrap(); }); self.update_materials(); self.process_material_state.is_open = false; } } } }); } } fn show_material_category(&mut self, ui: &mut egui::Ui) { ui.horizontal(|ui| { if self.is_admin { if ui.button("Добавить").clicked() { self.process_mcat_state.is_open = true; self.process_mcat_state.status = ModalStatus::Add; } } 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::().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::().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_category(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(0, ELEMENTS_PER_PAGE).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, is_admin: false, mat_page: 0, mcat_page: 0, } } }