feat: implement main application structure with UI and layout management
- Added main application logic in `src/ui/app.rs` to handle state and modal dialogs. - Created module structure for UI components in `src/ui/mod.rs`. - Implemented column configuration screen in `src/ui/screens/configuracao_colunas.rs`. - Developed file import screen in `src/ui/screens/import.rs` for CSV and XLSX files. - Added layout management screen in `src/ui/screens/layouts.rs` for saving and importing layouts. - Created result display screen in `src/ui/screens/resultado.rs` to show analysis results. - Introduced modular organization for screens in `src/ui/screens/mod.rs`.
This commit is contained in:
@@ -0,0 +1,211 @@
|
||||
use crate::domain::entities::layout::{Layout, LayoutCsv, LayoutXlsx};
|
||||
use rusqlite::{params, Connection, Result};
|
||||
|
||||
/// Salva um layout no banco. Retorna o id gerado.
|
||||
pub fn salvar(conn: &Connection, layout: &Layout) -> Result<i64> {
|
||||
match layout {
|
||||
Layout::Csv { nome, config, .. } => {
|
||||
conn.execute(
|
||||
"INSERT INTO layouts
|
||||
(nome, tipo, delimitador, encoding, linha_cabecalho,
|
||||
indice_numero, indice_serie, indice_valor, indice_data)
|
||||
VALUES (?1, 'csv', ?2, ?3, ?4, ?5, ?6, ?7, ?8)",
|
||||
params![
|
||||
nome,
|
||||
config.delimitador.to_string(),
|
||||
config.encoding,
|
||||
config.linha_cabecalho as i64,
|
||||
config.indice_numero as i64,
|
||||
config.indice_serie as i64,
|
||||
config.indice_valor.map(|v| v as i64),
|
||||
config.indice_data.map(|v| v as i64),
|
||||
],
|
||||
)?;
|
||||
Ok(conn.last_insert_rowid())
|
||||
}
|
||||
Layout::Xlsx { nome, config, .. } => {
|
||||
conn.execute(
|
||||
"INSERT INTO layouts
|
||||
(nome, tipo, aba, pos_numero, pos_serie, pos_valor, pos_data)
|
||||
VALUES (?1, 'xlsx', ?2, ?3, ?4, ?5, ?6)",
|
||||
params![
|
||||
nome,
|
||||
config.aba,
|
||||
config.pos_numero,
|
||||
config.pos_serie,
|
||||
config.pos_valor,
|
||||
config.pos_data,
|
||||
],
|
||||
)?;
|
||||
Ok(conn.last_insert_rowid())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Atualiza um layout existente no banco.
|
||||
pub fn atualizar(conn: &Connection, layout: &Layout) -> Result<()> {
|
||||
let id = layout
|
||||
.id()
|
||||
.ok_or_else(|| rusqlite::Error::InvalidParameterName("id ausente".to_string()))?;
|
||||
|
||||
match layout {
|
||||
Layout::Csv { nome, config, .. } => {
|
||||
conn.execute(
|
||||
"UPDATE layouts SET
|
||||
nome = ?1, delimitador = ?2, encoding = ?3,
|
||||
linha_cabecalho = ?4, indice_numero = ?5, indice_serie = ?6,
|
||||
indice_valor = ?7, indice_data = ?8
|
||||
WHERE id = ?9",
|
||||
params![
|
||||
nome,
|
||||
config.delimitador.to_string(),
|
||||
config.encoding,
|
||||
config.linha_cabecalho as i64,
|
||||
config.indice_numero as i64,
|
||||
config.indice_serie as i64,
|
||||
config.indice_valor.map(|v| v as i64),
|
||||
config.indice_data.map(|v| v as i64),
|
||||
id,
|
||||
],
|
||||
)?;
|
||||
}
|
||||
Layout::Xlsx { nome, config, .. } => {
|
||||
conn.execute(
|
||||
"UPDATE layouts SET
|
||||
nome = ?1, aba = ?2, pos_numero = ?3, pos_serie = ?4,
|
||||
pos_valor = ?5, pos_data = ?6
|
||||
WHERE id = ?7",
|
||||
params![
|
||||
nome,
|
||||
config.aba,
|
||||
config.pos_numero,
|
||||
config.pos_serie,
|
||||
config.pos_valor,
|
||||
config.pos_data,
|
||||
id,
|
||||
],
|
||||
)?;
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Lista todos os layouts salvos.
|
||||
pub fn listar(conn: &Connection) -> Result<Vec<Layout>> {
|
||||
let mut stmt = conn.prepare(
|
||||
"SELECT id, nome, tipo,
|
||||
delimitador, encoding, linha_cabecalho,
|
||||
indice_numero, indice_serie, indice_valor, indice_data,
|
||||
aba, pos_numero, pos_serie, pos_valor, pos_data
|
||||
FROM layouts ORDER BY nome ASC",
|
||||
)?;
|
||||
|
||||
let layouts: Result<Vec<Layout>> = stmt
|
||||
.query_map([], |row| {
|
||||
let id: i64 = row.get(0)?;
|
||||
let nome: String = row.get(1)?;
|
||||
let tipo: String = row.get(2)?;
|
||||
|
||||
if tipo == "csv" {
|
||||
let delim_str: String = row.get(3)?;
|
||||
let delimitador = delim_str.chars().next().unwrap_or(';');
|
||||
Ok(Layout::Csv {
|
||||
id: Some(id),
|
||||
nome,
|
||||
config: LayoutCsv {
|
||||
delimitador,
|
||||
encoding: row.get(4)?,
|
||||
linha_cabecalho: row.get::<_, i64>(5)? as usize,
|
||||
indice_numero: row.get::<_, i64>(6)? as usize,
|
||||
indice_serie: row.get::<_, i64>(7)? as usize,
|
||||
indice_valor: row
|
||||
.get::<_, Option<i64>>(8)?
|
||||
.map(|v| v as usize),
|
||||
indice_data: row
|
||||
.get::<_, Option<i64>>(9)?
|
||||
.map(|v| v as usize),
|
||||
},
|
||||
})
|
||||
} else {
|
||||
Ok(Layout::Xlsx {
|
||||
id: Some(id),
|
||||
nome,
|
||||
config: LayoutXlsx {
|
||||
aba: row.get(10)?,
|
||||
pos_numero: row.get(11)?,
|
||||
pos_serie: row.get(12)?,
|
||||
pos_valor: row.get(13)?,
|
||||
pos_data: row.get(14)?,
|
||||
},
|
||||
})
|
||||
}
|
||||
})?
|
||||
.collect();
|
||||
|
||||
layouts
|
||||
}
|
||||
|
||||
/// Busca um layout pelo id.
|
||||
pub fn buscar_por_id(conn: &Connection, id: i64) -> Result<Option<Layout>> {
|
||||
let mut stmt = conn.prepare(
|
||||
"SELECT id, nome, tipo,
|
||||
delimitador, encoding, linha_cabecalho,
|
||||
indice_numero, indice_serie, indice_valor, indice_data,
|
||||
aba, pos_numero, pos_serie, pos_valor, pos_data
|
||||
FROM layouts WHERE id = ?1",
|
||||
)?;
|
||||
|
||||
let mut results = stmt.query_map([id], |row| {
|
||||
let id: i64 = row.get(0)?;
|
||||
let nome: String = row.get(1)?;
|
||||
let tipo: String = row.get(2)?;
|
||||
|
||||
if tipo == "csv" {
|
||||
let delim_str: String = row.get(3)?;
|
||||
let delimitador = delim_str.chars().next().unwrap_or(';');
|
||||
Ok(Layout::Csv {
|
||||
id: Some(id),
|
||||
nome,
|
||||
config: LayoutCsv {
|
||||
delimitador,
|
||||
encoding: row.get(4)?,
|
||||
linha_cabecalho: row.get::<_, i64>(5)? as usize,
|
||||
indice_numero: row.get::<_, i64>(6)? as usize,
|
||||
indice_serie: row.get::<_, i64>(7)? as usize,
|
||||
indice_valor: row.get::<_, Option<i64>>(8)?.map(|v| v as usize),
|
||||
indice_data: row.get::<_, Option<i64>>(9)?.map(|v| v as usize),
|
||||
},
|
||||
})
|
||||
} else {
|
||||
Ok(Layout::Xlsx {
|
||||
id: Some(id),
|
||||
nome,
|
||||
config: LayoutXlsx {
|
||||
aba: row.get(10)?,
|
||||
pos_numero: row.get(11)?,
|
||||
pos_serie: row.get(12)?,
|
||||
pos_valor: row.get(13)?,
|
||||
pos_data: row.get(14)?,
|
||||
},
|
||||
})
|
||||
}
|
||||
})?;
|
||||
|
||||
results.next().transpose()
|
||||
}
|
||||
|
||||
/// Remove um layout pelo id.
|
||||
pub fn excluir(conn: &Connection, id: i64) -> Result<()> {
|
||||
conn.execute("DELETE FROM layouts WHERE id = ?1", [id])?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Verifica se já existe um layout com o nome fornecido.
|
||||
pub fn existe_nome(conn: &Connection, nome: &str) -> Result<bool> {
|
||||
let count: i64 = conn.query_row(
|
||||
"SELECT COUNT(*) FROM layouts WHERE nome = ?1",
|
||||
[nome],
|
||||
|row| row.get(0),
|
||||
)?;
|
||||
Ok(count > 0)
|
||||
}
|
||||
Reference in New Issue
Block a user