diff --git a/pom.xml b/pom.xml index 1e8db5e..bea9307 100644 --- a/pom.xml +++ b/pom.xml @@ -6,7 +6,7 @@ mx.gob.jumapacelaya sistema-mantenimiento sistema-mantenimiento - 1.0-SNAPSHOT + 2.1 jar diff --git a/src/main/bundles/dev.bundle b/src/main/bundles/dev.bundle index d5ed96b..59467d7 100644 Binary files a/src/main/bundles/dev.bundle and b/src/main/bundles/dev.bundle differ diff --git a/src/main/bundles/prod.bundle b/src/main/bundles/prod.bundle index 5b09e78..6f55075 100644 Binary files a/src/main/bundles/prod.bundle and b/src/main/bundles/prod.bundle differ diff --git a/src/main/frontend/themes/sistema-mantenimiento/styles.css b/src/main/frontend/themes/sistema-mantenimiento/styles.css index 7b0226b..94ddbd4 100644 --- a/src/main/frontend/themes/sistema-mantenimiento/styles.css +++ b/src/main/frontend/themes/sistema-mantenimiento/styles.css @@ -126,6 +126,18 @@ vaadin-popover-overlay::part(overlay) { box-shadow: 0 4px 8px rgba(0, 0, 0, 0.2); } +.dashboard-widget-content { + padding: 1.5rem; +} + +.pregunta-widget-container { + border-top: 3px solid #a02142; +} + +.pregunta-widget-container span { + line-height: 1.2; +} + @media (max-width: 900px) { diff --git a/src/main/java/mx/gob/jumapacelaya/models/encuestas/ConteoEncuestas.java b/src/main/java/mx/gob/jumapacelaya/models/encuestas/ConteoEncuestas.java new file mode 100644 index 0000000..6664ea6 --- /dev/null +++ b/src/main/java/mx/gob/jumapacelaya/models/encuestas/ConteoEncuestas.java @@ -0,0 +1,38 @@ +package mx.gob.jumapacelaya.models.encuestas; + +public class ConteoEncuestas { + + private int totalEnviadas; + private int totalRespondidas; + private Double porcentajeRespondidas; + + public ConteoEncuestas(int totalEnviadas, int totalRespondidas, Double porcentajeRespondidas) { + this.totalEnviadas = totalEnviadas; + this.totalRespondidas = totalRespondidas; + this.porcentajeRespondidas = porcentajeRespondidas; + } + + public int getTotalEnviadas() { + return totalEnviadas; + } + + public void setTotalEnviadas(int totalEnviadas) { + this.totalEnviadas = totalEnviadas; + } + + public int getTotalRespondidas() { + return totalRespondidas; + } + + public void setTotalRespondidas(int totalRespondidas) { + this.totalRespondidas = totalRespondidas; + } + + public Double getPorcentajeRespondidas() { + return porcentajeRespondidas; + } + + public void setPorcentajeRespondidas(Double porcentajeRespondidas) { + this.porcentajeRespondidas = porcentajeRespondidas; + } +} diff --git a/src/main/java/mx/gob/jumapacelaya/models/encuestas/ConteoRespuestas.java b/src/main/java/mx/gob/jumapacelaya/models/encuestas/ConteoRespuestas.java new file mode 100644 index 0000000..fc6ac63 --- /dev/null +++ b/src/main/java/mx/gob/jumapacelaya/models/encuestas/ConteoRespuestas.java @@ -0,0 +1,68 @@ +package mx.gob.jumapacelaya.models.encuestas; + +public class ConteoRespuestas { + + private int preguntaId; + private String pregunta; + private int totalRespuestas; + private int totalSi; + private int totalNo; + private Double porcentaje; + + public ConteoRespuestas(int preguntaId, String pregunta, int totalRespuestas, int totalSi, int totalNo, Double porcentaje) { + this.preguntaId = preguntaId; + this.pregunta = pregunta; + this.totalRespuestas = totalRespuestas; + this.totalSi = totalSi; + this.totalNo = totalNo; + this.porcentaje = porcentaje; + } + + public int getPreguntaId() { + return preguntaId; + } + + public void setPreguntaId(int preguntaId) { + this.preguntaId = preguntaId; + } + + public String getPregunta() { + return pregunta; + } + + public void setPregunta(String pregunta) { + this.pregunta = pregunta; + } + + public int getTotalRespuestas() { + return totalRespuestas; + } + + public void setTotalRespuestas(int totalRespuestas) { + this.totalRespuestas = totalRespuestas; + } + + public int getTotalSi() { + return totalSi; + } + + public void setTotalSi(int totalSi) { + this.totalSi = totalSi; + } + + public int getTotalNo() { + return totalNo; + } + + public void setTotalNo(int totalNo) { + this.totalNo = totalNo; + } + + public Double getPorcentaje() { + return porcentaje; + } + + public void setPorcentaje(Double porcentaje) { + this.porcentaje = porcentaje; + } +} diff --git a/src/main/java/mx/gob/jumapacelaya/services/DatabaseService.java b/src/main/java/mx/gob/jumapacelaya/services/DatabaseService.java index 1369815..068d185 100644 --- a/src/main/java/mx/gob/jumapacelaya/services/DatabaseService.java +++ b/src/main/java/mx/gob/jumapacelaya/services/DatabaseService.java @@ -1,9 +1,7 @@ package mx.gob.jumapacelaya.services; import mx.gob.jumapacelaya.models.*; -import mx.gob.jumapacelaya.models.encuestas.MantenimientosSinEncuesta; -import mx.gob.jumapacelaya.models.encuestas.Pregunta; -import mx.gob.jumapacelaya.models.encuestas.Respuesta; +import mx.gob.jumapacelaya.models.encuestas.*; import org.apache.poi.ss.usermodel.Cell; import org.apache.poi.ss.usermodel.Row; import org.apache.poi.ss.usermodel.Sheet; @@ -204,7 +202,6 @@ public class DatabaseService { ); planAnualList.add(planAnual); } - System.out.println("Registros obtenidos: " + planAnualList.size()); } catch (SQLException e) { logger.error("Error al obtener plan anual: ", e); } @@ -944,6 +941,7 @@ public class DatabaseService { } + /*************************************** ENCUESTAS ******************************************************************************************************/ public List getPreguntas() { List preguntas = new ArrayList<>(); @@ -1072,5 +1070,52 @@ public class DatabaseService { } return null; } + + public List getTotalEncuestas() { + List totalEncuestas = new ArrayList<>(); + String query = "SELECT * FROM VW_CONTEO_ENCUESTAS"; + + try (Connection conn = getMysqlConnection(); + Statement stmt = conn.createStatement(); + ResultSet rs = stmt.executeQuery(query)) { + + while (rs.next()) { + ConteoEncuestas conteo = new ConteoEncuestas( + rs.getInt("TOTAL_ENVIADAS"), + rs.getInt("TOTAL_RESPONDIDAS"), + rs.getDouble("PORCENTAJE_TOTAL") + ); + totalEncuestas.add(conteo); + } + } catch (SQLException e) { + logger.error("Error al obtener el total de encuestas: ", e); + } + return totalEncuestas; + } + + public List getTotalRespuestas() { + List totalRespuestas = new ArrayList<>(); + String query = "SELECT * FROM VW_CONTEO_RESPUESTAS"; + + try (Connection conn = getMysqlConnection(); + Statement stmt = conn.createStatement(); + ResultSet rs = stmt.executeQuery(query)) { + + while (rs.next()) { + ConteoRespuestas conteo = new ConteoRespuestas( + rs.getInt("PREGUNTAID"), + rs.getString("PREGUNTA"), + rs.getInt("TOTALREGISTROS"), + rs.getInt("TOTALSI"), + rs.getInt("TOTALNO"), + rs.getDouble("PORCENTAJE") + ); + totalRespuestas.add(conteo); + } + } catch (SQLException e) { + logger.error("Error al obtener el total de respuestas: ", e); + } + return totalRespuestas; + } /***************************************************************************************************************************************/ } diff --git a/src/main/java/mx/gob/jumapacelaya/ui/ConfiguracionView.java b/src/main/java/mx/gob/jumapacelaya/ui/ConfiguracionView.java index 8506f17..6d068bb 100644 --- a/src/main/java/mx/gob/jumapacelaya/ui/ConfiguracionView.java +++ b/src/main/java/mx/gob/jumapacelaya/ui/ConfiguracionView.java @@ -16,7 +16,7 @@ import jakarta.annotation.security.PermitAll; import java.util.List; @PermitAll -@PageTitle("Configuración del sistema") +@PageTitle("Preferencias del Sistema") @Route(value = "configuracion", layout = MainLayout.class) public class ConfiguracionView extends VerticalLayout { @@ -42,7 +42,7 @@ public class ConfiguracionView extends VerticalLayout { public ConfiguracionView() { setSpacing(true); - add(new H2("⚙\uFE0F Configuración del Sistema")); + add(new H2("⚙\uFE0F Preferencias del Sistema")); loadCssVariablesFromLocalStorage(); diff --git a/src/main/java/mx/gob/jumapacelaya/ui/MainLayout.java b/src/main/java/mx/gob/jumapacelaya/ui/MainLayout.java index 1b6b85a..b6eb979 100644 --- a/src/main/java/mx/gob/jumapacelaya/ui/MainLayout.java +++ b/src/main/java/mx/gob/jumapacelaya/ui/MainLayout.java @@ -93,7 +93,8 @@ public class MainLayout extends AppLayout implements BeforeEnterObserver { nav.addItem(new SideNavItem("Plan Anual", PlanAnualView.class, VaadinIcon.CALENDAR.create())); nav.addItem(new SideNavItem("Listado de Actividades", ActDiariaView.class, VaadinIcon.EDIT.create())); nav.addItem(new SideNavItem("Mantenimiento Correctivo", MantCorrectivoView.class, VaadinIcon.WRENCH.create())); - nav.addItem(new SideNavItem("Configuración del sistema", ConfiguracionView.class, VaadinIcon.COG.create())); + nav.addItem(new SideNavItem("Resultados de Encuestas", ResultEncuestasView.class, VaadinIcon.CLIPBOARD_TEXT.create())); + nav.addItem(new SideNavItem("Preferencias del Sistema", ConfiguracionView.class, VaadinIcon.COG.create())); nav.getStyle().set("border-radius", "5px"); return nav; diff --git a/src/main/java/mx/gob/jumapacelaya/ui/ResultEncuestasView.java b/src/main/java/mx/gob/jumapacelaya/ui/ResultEncuestasView.java new file mode 100644 index 0000000..bf8e392 --- /dev/null +++ b/src/main/java/mx/gob/jumapacelaya/ui/ResultEncuestasView.java @@ -0,0 +1,200 @@ +package mx.gob.jumapacelaya.ui; + +import com.vaadin.flow.component.button.Button; +import com.vaadin.flow.component.button.ButtonVariant; +import com.vaadin.flow.component.dashboard.Dashboard; +import com.vaadin.flow.component.dashboard.DashboardSection; +import com.vaadin.flow.component.dashboard.DashboardWidget; +import com.vaadin.flow.component.grid.Grid; +import com.vaadin.flow.component.html.Div; +import com.vaadin.flow.component.html.Span; +import com.vaadin.flow.component.icon.Icon; +import com.vaadin.flow.component.icon.SvgIcon; +import com.vaadin.flow.component.icon.VaadinIcon; +import com.vaadin.flow.component.orderedlayout.HorizontalLayout; +import com.vaadin.flow.component.orderedlayout.VerticalLayout; +import com.vaadin.flow.router.PageTitle; +import com.vaadin.flow.router.Route; +import jakarta.annotation.security.PermitAll; +import mx.gob.jumapacelaya.models.encuestas.ConteoEncuestas; +import mx.gob.jumapacelaya.models.encuestas.ConteoRespuestas; +import mx.gob.jumapacelaya.services.DatabaseService; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.vaadin.lineawesome.LineAwesomeIcon; + +import java.util.List; + +@PermitAll +@PageTitle("Resultados de Encuestas") +@Route(value = "resultados-encuestas", layout = MainLayout.class) +public class ResultEncuestasView extends VerticalLayout { + + private static final Logger logger = LoggerFactory.getLogger(ResultEncuestasView.class); + private final DatabaseService databaseService; + private DashboardWidget totalEncu; + private DashboardWidget totalResp; + private DashboardWidget porcentajeResp; + private DashboardWidget pregunta1; + private DashboardWidget pregunta2; + private DashboardWidget pregunta3; + private DashboardWidget pregunta4; + private DashboardWidget pregunta5; + private DashboardWidget pregunta6; + + public ResultEncuestasView(DatabaseService databaseService) { + this.databaseService = databaseService; + createToolbar(); + createDashboard(); + } + + public HorizontalLayout createToolbar() { + Button btnExport = new Button("Exportar a PDF", LineAwesomeIcon.FILE_PDF.create()); + btnExport.addThemeVariants(ButtonVariant.LUMO_SMALL); + + HorizontalLayout toolbar = new HorizontalLayout(btnExport); + toolbar.setAlignItems(Alignment.BASELINE); + toolbar.setWidthFull(); + + add(toolbar); + return toolbar; + } + + public Dashboard createDashboard() { + Dashboard dashboard = new Dashboard(); + dashboard.setMinimumColumnWidth("150px"); + dashboard.setMaximumColumnCount(3); + + // Secciónes del dashboard + DashboardSection generalSection = dashboard.addSection("General"); + DashboardSection preguntasSection = dashboard.addSection("Preguntas"); + + // Widgets para la sección General + totalEncu = new DashboardWidget("Total Encuestas"); + totalResp = new DashboardWidget("Total Respuestas"); + porcentajeResp = new DashboardWidget("Porcentaje de Respuestas"); + + generalSection.add(totalEncu); + generalSection.add(totalResp); + generalSection.add(porcentajeResp); + + + // Widget para la sección Preguntas + pregunta1 = new DashboardWidget("Pregunta 1"); + pregunta2 = new DashboardWidget("Pregunta 2"); + pregunta3 = new DashboardWidget("Pregunta 3"); + pregunta4 = new DashboardWidget("Pregunta 4"); + pregunta5 = new DashboardWidget("Pregunta 5"); + pregunta6 = new DashboardWidget("Pregunta 6"); + + preguntasSection.add(pregunta1); + preguntasSection.add(pregunta2); + preguntasSection.add(pregunta3); + preguntasSection.add(pregunta4); + preguntasSection.add(pregunta5); + preguntasSection.add(pregunta6); + + mostrarTotales(); + mostrarPreguntas(); + add(dashboard); + return dashboard; + } + + private Div createDiv(String valor, LineAwesomeIcon icon, String color) { + Div content = new Div(); + content.setClassName("dashboard-widget-content"); + content.getStyle() + .set("display", "flex") + .set("align-items", "center") + .set("justify-content", "center") + .set("gap", "15px"); + + SvgIcon vIcon = icon.create(); + vIcon.getStyle().set("color", color); + vIcon.setSize("40px"); + + Span text = new Span(valor); + text.getStyle().set("font-size", "2.2rem"); + text.getStyle().set("font-weight", "800"); + + content.add(vIcon, text); + return content; + } + + private Div createPreguntaContent(ConteoRespuestas data) { + Div container = new Div(); + container.setClassName("pregunta-widget-container"); + container.getStyle().set("padding", "10px"); + + Span txtPregunta = new Span(data.getPregunta()); + txtPregunta.getStyle().set("font-size", "0.9em") + .set("display", "block") + .set("margin-bottom", "15px") + .set("height", "45px") + .set("overflow", "hidden"); + + HorizontalLayout metrics = new HorizontalLayout(); + metrics.setJustifyContentMode(JustifyContentMode.BETWEEN); + metrics.setWidthFull(); + + metrics.add( + createStat("Si", String.valueOf(data.getTotalSi()), "#27ae60"), + createStat("No", String.valueOf(data.getTotalNo()), "#e74c3c"), + createStat("%", String.format("%.0f", data.getPorcentaje()), "#BC955B") + ); + + container.add(txtPregunta, metrics); + return container; + } + + private VerticalLayout createStat(String label, String value, String color) { + Span l = new Span(label); + l.getStyle().set("font-size", "0.7em").set("color", "gray"); + Span v = new Span(value); + v.getStyle().set("font-weight", "bold").set("color", color); + + VerticalLayout vl = new VerticalLayout(l,v); + vl.setAlignItems(Alignment.CENTER); + vl.setSpacing(false); + vl.setPadding(false); + return vl; + } + + public void mostrarTotales() { + List datos = databaseService.getTotalEncuestas(); + + if (!datos.isEmpty()) { + ConteoEncuestas totales = datos.get(0); + + totalEncu.setContent(createDiv( + String.valueOf(totales.getTotalEnviadas()), + LineAwesomeIcon.CLIPBOARD_LIST_SOLID, "#BC955B" + )); + + totalResp.setContent(createDiv( + String.valueOf(totales.getTotalRespondidas()), + LineAwesomeIcon.CHECK_CIRCLE, "#BC955B" + )); + + porcentajeResp.setContent(createDiv( + String.valueOf(totales.getPorcentajeRespondidas()), + LineAwesomeIcon.PERCENT_SOLID, "#BC955B" + )); + } + } + + public void mostrarPreguntas() { + List lista = databaseService.getTotalRespuestas(); + + DashboardWidget[] widgets = {pregunta1,pregunta2,pregunta3,pregunta4,pregunta5,pregunta6}; + + for (int i = 0; i < lista.size() && i < widgets.length; i++) { + ConteoRespuestas data = lista.get(i); + DashboardWidget widget = widgets[i]; + + widget.setTitle("Pregunta #" + data.getPreguntaId()); + + widget.setContent(createPreguntaContent(data)); + } + } +}