214 lines
6.9 KiB
Rust
214 lines
6.9 KiB
Rust
use crate::application::usecases::layouts::{
|
|
exportar_layout_json, importar_layout_json, salvar_layout,
|
|
};
|
|
use crate::domain::entities::layout::{Layout, TipoArquivo};
|
|
use crate::domain::errors::ErroLayout;
|
|
use crate::ui::app::{AcaoModal, App, EstadoApp};
|
|
use egui::{Context, Ui};
|
|
|
|
/// Renderiza a tela de gerenciamento de layouts.
|
|
pub fn renderizar(ui: &mut Ui, ctx: &Context, app: &mut App) {
|
|
ui.heading("Gerenciar Layouts");
|
|
ui.add_space(8.0);
|
|
|
|
ui.horizontal(|ui| {
|
|
if ui.button("< Voltar").clicked() {
|
|
app.estado = EstadoApp::Importando;
|
|
}
|
|
});
|
|
|
|
ui.add_space(12.0);
|
|
ui.separator();
|
|
|
|
// Salvar layout atual
|
|
ui.add_space(8.0);
|
|
ui.group(|ui| {
|
|
ui.label("Salvar Layout Atual");
|
|
ui.horizontal(|ui| {
|
|
ui.label("Nome:");
|
|
ui.text_edit_singleline(&mut app.nome_layout_atual);
|
|
if ui.button("💾 Salvar").clicked() {
|
|
salvar_layout_atual(app);
|
|
}
|
|
});
|
|
});
|
|
|
|
ui.add_space(12.0);
|
|
ui.separator();
|
|
ui.add_space(8.0);
|
|
|
|
// Layouts CSV
|
|
let layouts_csv: Vec<_> = app
|
|
.layouts_salvos
|
|
.iter()
|
|
.filter(|l| l.tipo() == TipoArquivo::Csv)
|
|
.cloned()
|
|
.collect();
|
|
|
|
let layouts_xlsx: Vec<_> = app
|
|
.layouts_salvos
|
|
.iter()
|
|
.filter(|l| l.tipo() == TipoArquivo::Xlsx)
|
|
.cloned()
|
|
.collect();
|
|
|
|
egui::ScrollArea::vertical().show(ui, |ui| {
|
|
renderizar_secao_layouts(ui, ctx, app, "Layouts CSV", &layouts_csv);
|
|
ui.add_space(12.0);
|
|
renderizar_secao_layouts(ui, ctx, app, "Layouts XLSX", &layouts_xlsx);
|
|
|
|
ui.add_space(16.0);
|
|
ui.separator();
|
|
ui.add_space(8.0);
|
|
|
|
// Importar de JSON
|
|
ui.horizontal(|ui| {
|
|
ui.label("Importar layout de arquivo JSON:");
|
|
if ui.button("📥 Importar JSON").clicked() {
|
|
if let Some(caminho) = rfd::FileDialog::new()
|
|
.add_filter("JSON", &["json"])
|
|
.pick_file()
|
|
{
|
|
match std::fs::read_to_string(&caminho) {
|
|
Ok(conteudo) => importar_json(app, &conteudo),
|
|
Err(e) => {
|
|
app.exibir_erro(format!("Erro ao ler arquivo JSON: {}", e));
|
|
}
|
|
}
|
|
}
|
|
}
|
|
});
|
|
});
|
|
}
|
|
|
|
fn renderizar_secao_layouts(
|
|
ui: &mut Ui,
|
|
_ctx: &Context,
|
|
app: &mut App,
|
|
titulo: &str,
|
|
layouts: &[Layout],
|
|
) {
|
|
ui.label(egui::RichText::new(titulo).strong());
|
|
ui.add_space(4.0);
|
|
|
|
if layouts.is_empty() {
|
|
ui.label("(nenhum layout salvo)");
|
|
return;
|
|
}
|
|
|
|
for layout in layouts {
|
|
ui.horizontal(|ui| {
|
|
ui.label(layout.nome());
|
|
ui.with_layout(egui::Layout::right_to_left(egui::Align::Center), |ui| {
|
|
// Excluir
|
|
if let Some(id) = layout.id() {
|
|
if ui.button("🗑 Excluir").clicked() {
|
|
app.exibir_confirmacao(
|
|
"Confirmar exclusão",
|
|
format!("Deseja excluir o layout '{}'?", layout.nome()),
|
|
AcaoModal::ConfirmarExclusaoLayout(id),
|
|
);
|
|
}
|
|
|
|
// Exportar
|
|
if ui.button("📤 Exportar JSON").clicked() {
|
|
match exportar_layout_json(layout) {
|
|
Ok((conteudo, nome_sugerido)) => {
|
|
if let Some(caminho) = rfd::FileDialog::new()
|
|
.set_file_name(&nome_sugerido)
|
|
.add_filter("JSON", &["json"])
|
|
.save_file()
|
|
{
|
|
if let Err(e) = std::fs::write(&caminho, &conteudo) {
|
|
app.exibir_erro(format!("Erro ao salvar JSON: {}", e));
|
|
}
|
|
}
|
|
}
|
|
Err(e) => {
|
|
app.exibir_erro(format!("Erro ao exportar layout: {}", e));
|
|
}
|
|
}
|
|
}
|
|
|
|
// Carregar
|
|
if ui.button("📂 Carregar").clicked() {
|
|
aplicar_layout(app, layout);
|
|
app.nome_layout_atual = layout.nome().to_string();
|
|
app.estado = EstadoApp::ConfigurandoColunas;
|
|
}
|
|
}
|
|
});
|
|
});
|
|
}
|
|
}
|
|
|
|
fn salvar_layout_atual(app: &mut App) {
|
|
if app.nome_layout_atual.trim().is_empty() {
|
|
app.exibir_aviso("Nome inválido", "Informe um nome para o layout.");
|
|
return;
|
|
}
|
|
|
|
let layout = match app.tipo_arquivo_atual.clone() {
|
|
TipoArquivo::Csv => Layout::Csv {
|
|
id: None,
|
|
nome: app.nome_layout_atual.trim().to_string(),
|
|
config: app.layout_csv_atual.clone(),
|
|
},
|
|
TipoArquivo::Xlsx => Layout::Xlsx {
|
|
id: None,
|
|
nome: app.nome_layout_atual.trim().to_string(),
|
|
config: app.layout_xlsx_atual.clone(),
|
|
},
|
|
};
|
|
|
|
if let Some(conn) = &app.conn {
|
|
match salvar_layout(conn, &layout) {
|
|
Ok(_) => {
|
|
app.recarregar_layouts();
|
|
app.exibir_aviso("Sucesso", "Layout salvo com sucesso.");
|
|
}
|
|
Err(e) => {
|
|
app.exibir_erro(format!("Erro ao salvar layout: {}", e));
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
fn importar_json(app: &mut App, conteudo: &str) {
|
|
if let Some(conn) = &app.conn {
|
|
match importar_layout_json(conn, conteudo, false, None) {
|
|
Ok(_) => {
|
|
app.recarregar_layouts();
|
|
app.exibir_aviso("Sucesso", "Layout importado com sucesso.");
|
|
}
|
|
Err(ErroLayout::NomeConflitante(nome)) => {
|
|
// Exibir opções: sobrescrever ou cancelar
|
|
app.exibir_aviso(
|
|
"Conflito de nome",
|
|
format!(
|
|
"Já existe um layout com o nome '{}'. Use 'Salvar com novo nome' ou cancele a importação.",
|
|
nome
|
|
),
|
|
);
|
|
// TODO: implementar fluxo completo de sobrescrever com entrada de novo nome
|
|
}
|
|
Err(e) => {
|
|
app.exibir_erro(format!("Erro ao importar layout: {}", e));
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
fn aplicar_layout(app: &mut App, layout: &Layout) {
|
|
match layout {
|
|
Layout::Csv { config, .. } => {
|
|
app.layout_csv_atual = config.clone();
|
|
app.tipo_arquivo_atual = TipoArquivo::Csv;
|
|
}
|
|
Layout::Xlsx { config, .. } => {
|
|
app.layout_xlsx_atual = config.clone();
|
|
app.tipo_arquivo_atual = TipoArquivo::Xlsx;
|
|
}
|
|
}
|
|
}
|