package web import ( "log" "math" "net/http" "strconv" "time" "heating-monitor/internal/bot" "heating-monitor/internal/config" "heating-monitor/internal/repository" "github.com/labstack/echo/v4" "gorm.io/gorm" ) func GetEventsHandler(c echo.Context, db *gorm.DB) error { // Verificar que la base de datos esté correctamente inicializada if db == nil { log.Printf("Error: base de datos no inicializada") return c.JSON(http.StatusInternalServerError, "Error al conectar con la base de datos") } // Obtener los parámetros de entrada pageNum, sizeNum := getPaginationParams(c, 10) filter := c.QueryParam("filter") search := c.QueryParam("search") startDateStr := c.QueryParam("startDate") endDateStr := c.QueryParam("endDate") // Construir y aplicar filtros dinámicos query := applyFilters(db.Model(&bot.HeatingEvent{}), filter, search, startDateStr, endDateStr) // Crear una consulta separada para todos los eventos (sin paginación) var allEvents []bot.HeatingEvent err := query.Find(&allEvents).Error if err != nil { log.Printf("Error al obtener todos los eventos filtrados: %v", err) return c.JSON(http.StatusInternalServerError, "Error al obtener eventos completos") } // Calcular el tiempo total de encendido para todos los eventos filtrados totalHours, totalMinutes := calculateTotalOnHours(allEvents) // Obtener el total de resultados antes de la paginación var count int64 err = query.Count(&count).Error if err != nil { log.Printf("Error al contar eventos: %v", err) return c.JSON(http.StatusInternalServerError, "Error al contar eventos") } // Calcular offset y limitar resultados offset := (pageNum - 1) * sizeNum var events []bot.HeatingEvent //err = query.Offset(offset).Limit(sizeNum).Find(&events).Error err = query.Order("timestamp DESC").Offset(offset).Limit(sizeNum).Find(&events).Error if err != nil { log.Printf("Error al obtener eventos: %v", err) return c.JSON(http.StatusInternalServerError, "Error al obtener eventos") } // Calcular la gráfica de consumos consumptionData, isGroupedByMonth := calculateConsumptionData(allEvents) // Separar las etiquetas y los totales labels := make([]string, 0, len(consumptionData)) totals := make([]float64, 0, len(consumptionData)) for label, total := range consumptionData { labels = append(labels, label) totals = append(totals, total) } // Calcular paginación totalPages := int(math.Ceil(float64(count) / float64(sizeNum))) prevPage := pageNum - 1 if prevPage < 1 { prevPage = 1 } nextPage := pageNum + 1 if nextPage > totalPages { nextPage = totalPages } // Renderizar en la plantilla return LoadTemplate(c, "view.html", map[string]interface{}{ "events": events, "page": pageNum, "totalPages": totalPages, "size": sizeNum, "prevPage": prevPage, "nextPage": nextPage, "count": count, "filter": filter, "search": search, "startDate": startDateStr, "endDate": endDateStr, "totalHours": totalHours, "totalMinutes": totalMinutes, "labels": labels, "totals": totals, "isGroupedByMonth": isGroupedByMonth, }) } // GetEventHandler obtiene un evento por ID y muestra la página de edición func GetEventHandler(c echo.Context, db *gorm.DB) error { // Obtener el ID del evento id, err := strconv.Atoi(c.Param("id")) if err != nil { log.Printf("Error al convertir ID: %v", err) return c.JSON(http.StatusBadRequest, "ID inválido") } // Buscar el evento usando el repositorio event, err := repository.GetEventByID(db, id) if err != nil { log.Printf("Error al obtener evento con ID %d: %v", id, err) return c.JSON(http.StatusNotFound, "Evento no encontrado") } // Renderizar los eventos en la plantilla return LoadTemplate(c, "edit.html", event) } // UpdateEventHandler actualiza un evento en la base de datos func UpdateEventHandler(c echo.Context, db *gorm.DB) error { // Obtener el ID del evento id, err := strconv.Atoi(c.Param("id")) if err != nil { log.Printf("Error al convertir ID: %v", err) return c.JSON(http.StatusBadRequest, "ID inválido") } // Obtener los datos del evento desde el formulario event := new(bot.HeatingEvent) // Convertir el timestamp manualmente desde la cadena timestampStr := c.FormValue("timestamp") timestamp, err := time.Parse("2006-01-02T15:04", timestampStr) if err != nil { log.Printf("Error al convertir el timestamp: %v", err) return c.JSON(http.StatusBadRequest, "Formato de fecha inválido") } // Asignar el timestamp convertido event.Timestamp = timestamp event.EventType = c.FormValue("event_type") // Actualizar el evento usando el repositorio _, err = repository.UpdateEventByID(db, id, event) if err != nil { log.Printf("Error al actualizar evento con ID %d: %v", id, err) return c.JSON(http.StatusInternalServerError, "Error al actualizar evento") } return c.Redirect(http.StatusFound, "/") } // DeleteEventHandler elimina un evento de la base de datos func DeleteEventHandler(c echo.Context, db *gorm.DB) error { // Obtener el ID del evento desde los parámetros id, err := strconv.Atoi(c.Param("id")) if err != nil { log.Printf("Error al convertir ID: %v", err) return c.JSON(http.StatusBadRequest, "ID inválido") } // Eliminar el evento usando el repositorio err = repository.DeleteEventByID(db, id) if err != nil { log.Printf("Error al eliminar evento con ID %d: %v", id, err) return c.JSON(http.StatusInternalServerError, "Error al eliminar evento") } return c.Redirect(http.StatusFound, "/") } func AboutHandler(c echo.Context, db *gorm.DB) error { // Cargar configuración desde .env cfg, err := config.LoadConfig() if err != nil { log.Fatalf("Error al cargar la configuración: %v", err) } // Pasar los datos de configuración a la plantilla data := map[string]interface{}{ "ProgramAuthor": cfg.ProgramAuthor, "ProgramLink": cfg.ProgramLink, "ProgramAvatar": cfg.ProgramAvatar, "ProgramName": cfg.ProgramName, "ProgramVersion": cfg.ProgramVersion, "ProgramYear": cfg.ProgramYear, "ProgramTechnologies": cfg.ProgramTechnologies, } return LoadTemplate(c, "about.html", data) }