262 lines
7.4 KiB
Rust
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));
|
|
}
|
|
}
|
|
}
|
|
}
|