Files
comparador-notas/src/ui/screens/resultado.rs
T

262 lines
7.4 KiB
Rust

use crate::application::usecases::exportar_pdf::exportar_pdf;
use crate::domain::{
entities::resultado_analise::ResultadoAnalise,
services::parser_monetario::formatar_valor_br,
};
use crate::infrastructure::pdf_generator::GenpdfGenerator;
use crate::ui::app::{AcaoModal, App, EstadoApp};
use egui::{Context, Ui};
const OPCOES_PAGINA: &[usize] = &[50, 100, 200, 1000];
/// Renderiza a tela de resultados.
pub fn renderizar(ui: &mut Ui, _ctx: &Context, app: &mut App) {
// Extrair resultado do estado (sem mover)
let resultado = match &app.estado {
EstadoApp::ExibindoResultado(r) => r.clone(),
_ => return,
};
ui.heading("Resultado da Análise");
ui.add_space(8.0);
ui.horizontal(|ui| {
if ui.button("< Nova Análise").clicked() {
app.exibir_confirmacao(
"Nova Análise",
"Deseja iniciar uma nova análise? O resultado atual será descartado.",
AcaoModal::ConfirmarNovaAnalise,
);
}
if ui.button("⚙ Reconfigurar Colunas").clicked() {
app.estado = EstadoApp::ConfigurandoColunas;
return;
}
if ui.button("📄 Exportar PDF").clicked() {
exportar_para_pdf(app, &resultado);
}
});
ui.add_space(8.0);
// Controle de itens por página
ui.horizontal(|ui| {
ui.label("Itens por página:");
for &opcao in OPCOES_PAGINA {
if ui
.selectable_label(app.itens_por_pagina == opcao, opcao.to_string())
.clicked()
{
app.itens_por_pagina = opcao;
app.pagina_faltantes = 0;
app.pagina_duplicatas = 0;
}
}
});
ui.add_space(12.0);
ui.separator();
egui::ScrollArea::vertical().show(ui, |ui| {
// Faltantes
renderizar_faltantes(ui, app, &resultado);
ui.add_space(12.0);
ui.separator();
// Duplicatas
renderizar_duplicatas(ui, app, &resultado);
ui.add_space(12.0);
ui.separator();
// Totais
renderizar_totais(ui, &resultado);
});
}
fn renderizar_totais(ui: &mut Ui, resultado: &ResultadoAnalise) {
ui.label(egui::RichText::new("Totais").heading().strong());
ui.add_space(4.0);
ui.label(format!(
"Total Geral: R$ {}",
formatar_valor_br(&resultado.soma_total)
));
let mut series: Vec<&String> = resultado.soma_por_serie.keys().collect();
series.sort();
for serie in series {
let soma = &resultado.soma_por_serie[serie];
let total_notas = resultado.total_por_serie.get(serie).copied().unwrap_or(0);
ui.label(format!(
" Série {}: {} nota(s) — R$ {}",
serie,
total_notas,
formatar_valor_br(soma)
));
}
}
fn renderizar_faltantes(ui: &mut Ui, app: &mut App, resultado: &ResultadoAnalise) {
let total_faltantes = resultado.total_faltantes();
ui.label(
egui::RichText::new(format!(
"Notas Faltantes ({} total)",
total_faltantes
))
.heading()
.strong(),
);
ui.add_space(4.0);
if total_faltantes == 0 {
ui.label("✔ Nenhuma nota faltante.");
return;
}
let mut series: Vec<&String> = resultado.faltantes_por_serie.keys().collect();
series.sort();
for serie in series {
let faltantes = &resultado.faltantes_por_serie[serie];
if faltantes.is_empty() {
continue;
}
ui.label(format!(
"Série {}{} faltante(s):",
serie,
faltantes.len()
));
// Paginação
let total_paginas = (faltantes.len() + app.itens_por_pagina - 1) / app.itens_por_pagina;
if app.pagina_faltantes >= total_paginas {
app.pagina_faltantes = 0;
}
let inicio = app.pagina_faltantes * app.itens_por_pagina;
let fim = (inicio + app.itens_por_pagina).min(faltantes.len());
for numero in &faltantes[inicio..fim] {
ui.label(format!(" • {}", numero));
}
if total_paginas > 1 {
ui.horizontal(|ui| {
if ui.button("◀").clicked() && app.pagina_faltantes > 0 {
app.pagina_faltantes -= 1;
}
ui.label(format!(
"Página {} / {}",
app.pagina_faltantes + 1,
total_paginas
));
if ui.button("▶").clicked() && app.pagina_faltantes + 1 < total_paginas {
app.pagina_faltantes += 1;
}
});
}
}
}
fn renderizar_duplicatas(ui: &mut Ui, app: &mut App, resultado: &ResultadoAnalise) {
let total_dup = resultado.total_duplicatas();
ui.label(
egui::RichText::new(format!(
"Notas Duplicadas ({} grupo(s))",
total_dup
))
.heading()
.strong(),
);
ui.add_space(4.0);
if total_dup == 0 {
ui.label("✔ Nenhuma nota duplicada.");
return;
}
let mut series: Vec<&String> = resultado.duplicadas_por_serie.keys().collect();
series.sort();
for serie in series {
let duplicatas = &resultado.duplicadas_por_serie[serie];
if duplicatas.is_empty() {
continue;
}
ui.label(format!(
"Série {}{} grupo(s) duplicado(s):",
serie,
duplicatas.len()
));
let total_paginas =
(duplicatas.len() + app.itens_por_pagina - 1) / app.itens_por_pagina;
if app.pagina_duplicatas >= total_paginas {
app.pagina_duplicatas = 0;
}
let inicio = app.pagina_duplicatas * app.itens_por_pagina;
let fim = (inicio + app.itens_por_pagina).min(duplicatas.len());
for (numero, count) in &duplicatas[inicio..fim] {
ui.label(format!(
" • NF {} / Série {}{} ocorrências",
numero, serie, count
));
}
if total_paginas > 1 {
ui.horizontal(|ui| {
if ui.button("◀").clicked() && app.pagina_duplicatas > 0 {
app.pagina_duplicatas -= 1;
}
ui.label(format!(
"Página {} / {}",
app.pagina_duplicatas + 1,
total_paginas
));
if ui.button("▶").clicked() && app.pagina_duplicatas + 1 < total_paginas {
app.pagina_duplicatas += 1;
}
});
}
}
}
fn exportar_para_pdf(app: &mut App, resultado: &ResultadoAnalise) {
if let Some(caminho) = rfd::FileDialog::new()
.set_file_name("relatorio.pdf")
.add_filter("PDF", &["pdf"])
.save_file()
{
let gerador = GenpdfGenerator;
let nome_layout = if app.nome_layout_atual.is_empty() {
None
} else {
Some(app.nome_layout_atual.as_str())
};
match exportar_pdf(
&gerador,
resultado,
&app.nome_arquivo,
nome_layout,
&caminho,
) {
Ok(_) => {
app.exibir_aviso("Sucesso", format!("PDF exportado para: {}", caminho.display()));
}
Err(e) => {
app.exibir_erro(format!("Erro ao exportar PDF: {}", e));
}
}
}
}