From 0f728b96845eb1e80fd2c3b2c37421b6f8053e91 Mon Sep 17 00:00:00 2001 From: FelipeCN <57776624+felipecaninnovaes@users.noreply.github.com> Date: Tue, 3 Mar 2026 09:19:23 -0300 Subject: [PATCH] =?UTF-8?q?feat:=20adiciona=20modal=20para=20salvar=20layo?= =?UTF-8?q?ut=20com=20campo=20de=20texto=20e=20bot=C3=A3o=20na=20tela=20de?= =?UTF-8?q?=20configura=C3=A7=C3=A3o=20de=20colunas?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/ui/app.rs | 70 +++++++++++++++++++++++++- src/ui/screens/configuracao_colunas.rs | 4 ++ 2 files changed, 73 insertions(+), 1 deletion(-) diff --git a/src/ui/app.rs b/src/ui/app.rs index 2d3f454..fbbde75 100644 --- a/src/ui/app.rs +++ b/src/ui/app.rs @@ -50,6 +50,8 @@ pub struct Modal { pub tipo: TipoModal, /// Para modal de confirmação, a ação ao confirmar. pub acao_confirmacao: Option, + /// Para modal com campo de texto (InputTexto). + pub input_texto: String, } #[derive(Default, Clone, PartialEq)] @@ -59,6 +61,8 @@ pub enum TipoModal { Aviso, Erro, Confirmacao, + /// Modal com campo de texto para entrada do usuário. + InputTexto, } #[derive(Clone)] @@ -67,6 +71,8 @@ pub enum AcaoModal { ConfirmarExclusaoLayout(i64), SobrescreverLayout, ConfirmarNovaAnalise, + /// Salvar a configuração atual como novo layout, usando modal.input_texto como nome. + SalvarLayoutConfig, } /// Struct principal da aplicação egui. @@ -176,6 +182,7 @@ impl App { mensagem: msg.into(), tipo: TipoModal::Erro, acao_confirmacao: None, + input_texto: String::new(), }; } @@ -186,6 +193,7 @@ impl App { mensagem: msg.into(), tipo: TipoModal::Aviso, acao_confirmacao: None, + input_texto: String::new(), }; } @@ -201,10 +209,23 @@ impl App { mensagem: msg.into(), tipo: TipoModal::Confirmacao, acao_confirmacao: Some(acao), + input_texto: String::new(), }; } /// Recarrega a lista de layouts do banco. + /// Exibe modal com campo de texto para salvar o layout atual como novo preset. + pub fn exibir_modal_salvar_layout(&mut self) { + self.modal = Modal { + visivel: true, + titulo: "Salvar como layout...".to_string(), + mensagem: "Nome do layout:".to_string(), + tipo: TipoModal::InputTexto, + acao_confirmacao: Some(AcaoModal::SalvarLayoutConfig), + input_texto: self.nome_layout_atual.clone(), + }; + } + pub fn recarregar_layouts(&mut self) { if let Some(conn) = &self.conn { match listar_layouts(conn) { @@ -228,14 +249,26 @@ impl App { egui::Window::new(&titulo) .collapsible(false) .resizable(false) + .min_width(320.0) .anchor(egui::Align2::CENTER_CENTER, [0.0, 0.0]) .show(ctx, |ui| { ui.add_space(8.0); ui.label(&mensagem); + + if tipo == TipoModal::InputTexto { + ui.add_space(4.0); + let resp = ui.add( + egui::TextEdit::singleline(&mut self.modal.input_texto) + .desired_width(280.0) + .hint_text("Nome do layout"), + ); + resp.request_focus(); + } + ui.add_space(12.0); ui.horizontal(|ui| { - if tipo == TipoModal::Confirmacao { + if tipo == TipoModal::Confirmacao || tipo == TipoModal::InputTexto { if ui.button("✔ Confirmar").clicked() { self.modal.visivel = false; if let Some(acao) = acao.clone() { @@ -244,6 +277,7 @@ impl App { } if ui.button("✖ Cancelar").clicked() { self.modal.visivel = false; + self.modal.input_texto.clear(); } } else { if ui.button("OK").clicked() { @@ -279,6 +313,40 @@ impl App { self.notas_importadas.clear(); self.estado = EstadoApp::Importando; } + AcaoModal::SalvarLayoutConfig => { + let nome = self.modal.input_texto.trim().to_string(); + self.modal.input_texto.clear(); + if nome.is_empty() { + self.exibir_erro("O nome do layout não pode ser vazio."); + return; + } + let layout = match &self.tipo_arquivo_atual { + TipoArquivo::Csv => Layout::Csv { + id: None, + nome: nome.clone(), + config: self.layout_csv_atual.clone(), + }, + TipoArquivo::Xlsx => Layout::Xlsx { + id: None, + nome: nome.clone(), + config: self.layout_xlsx_atual.clone(), + }, + }; + let resultado = if let Some(conn) = &self.conn { + Some(salvar_layout(conn, &layout)) + } else { + None + }; + match resultado { + Some(Ok(_)) => { + self.nome_layout_atual = nome; + self.recarregar_layouts(); + self.exibir_aviso("Layout salvo", "Layout salvo com sucesso."); + } + Some(Err(e)) => self.exibir_erro(e), + None => {} + } + } } } diff --git a/src/ui/screens/configuracao_colunas.rs b/src/ui/screens/configuracao_colunas.rs index bac9ae7..9af8e31 100644 --- a/src/ui/screens/configuracao_colunas.rs +++ b/src/ui/screens/configuracao_colunas.rs @@ -88,6 +88,10 @@ pub fn renderizar(ui: &mut Ui, ctx: &Context, app: &mut App) { executar_importacao(app); } }); + + if ui.button("💾 Salvar como layout...").clicked() { + app.exibir_modal_salvar_layout(); + } }); }