152 lines
3.9 KiB
Go
152 lines
3.9 KiB
Go
package handlers
|
|
|
|
import (
|
|
"log"
|
|
"net/http"
|
|
|
|
"tankstopp/internal/models"
|
|
"tankstopp/internal/views/pages"
|
|
)
|
|
|
|
// HomeHandler serves the main dashboard page
|
|
func (h *Handler) HomeHandler(w http.ResponseWriter, r *http.Request) {
|
|
userID, username := h.getCurrentUser(r)
|
|
if userID == 0 {
|
|
http.Redirect(w, r, "/login", http.StatusSeeOther)
|
|
return
|
|
}
|
|
|
|
// Get the user object
|
|
user, err := h.db.GetUserByID(userID)
|
|
if err != nil {
|
|
log.Printf("Error getting user: %v", err)
|
|
http.Error(w, "Internal server error", http.StatusInternalServerError)
|
|
return
|
|
}
|
|
|
|
// Get fuel stops for the user
|
|
stops, err := h.db.GetFuelStops(userID)
|
|
if err != nil {
|
|
log.Printf("Error getting fuel stops: %v", err)
|
|
http.Error(w, "Internal server error", http.StatusInternalServerError)
|
|
return
|
|
}
|
|
|
|
// Get fuel stop statistics
|
|
stats, err := h.db.GetFuelStopStats(userID)
|
|
if err != nil {
|
|
log.Printf("Error getting fuel stop stats: %v", err)
|
|
http.Error(w, "Internal server error", http.StatusInternalServerError)
|
|
return
|
|
}
|
|
|
|
// Get vehicles for the user
|
|
vehicles, err := h.db.GetVehicles(userID)
|
|
if err != nil {
|
|
log.Printf("Error getting vehicles: %v", err)
|
|
http.Error(w, "Internal server error", http.StatusInternalServerError)
|
|
return
|
|
}
|
|
|
|
// Calculate dashboard statistics
|
|
totalStops := len(stops)
|
|
totalCost := stats.TotalSpent
|
|
|
|
// Calculate detailed consumption statistics
|
|
avgConsumption, _, _ := h.calculateConsumptionStats(stops)
|
|
if avgConsumption == 0 {
|
|
avgConsumption = stats.AverageConsumption // Fallback to basic stats
|
|
}
|
|
|
|
var lastFillUp *models.FuelStop
|
|
if len(stops) > 0 {
|
|
lastFillUp = &stops[0]
|
|
}
|
|
|
|
// Render dashboard using templ
|
|
component := pages.DashboardPage(user, username, stops, vehicles, totalStops, totalCost, avgConsumption, lastFillUp)
|
|
|
|
w.Header().Set("Content-Type", "text/html")
|
|
err = component.Render(r.Context(), w)
|
|
if err != nil {
|
|
log.Printf("Error rendering template: %v", err)
|
|
http.Error(w, "Internal server error", http.StatusInternalServerError)
|
|
}
|
|
}
|
|
|
|
// calculateConsumptionStats calculates consumption-related statistics
|
|
func (h *Handler) calculateConsumptionStats(stops []models.FuelStop) (float64, float64, float64) {
|
|
if len(stops) == 0 {
|
|
return 0, 0, 0
|
|
}
|
|
|
|
var totalLiters, totalKm float64
|
|
var consumptionReadings []float64
|
|
|
|
for _, stop := range stops {
|
|
totalLiters += stop.Liters
|
|
|
|
if stop.TripLength > 0 {
|
|
totalKm += stop.TripLength
|
|
|
|
// Calculate consumption for this stop (L/100km)
|
|
consumption := (stop.Liters / stop.TripLength) * 100
|
|
if consumption > 0 && consumption < 50 { // Filter out unrealistic values
|
|
consumptionReadings = append(consumptionReadings, consumption)
|
|
}
|
|
}
|
|
}
|
|
|
|
// Average consumption from individual readings
|
|
var avgConsumption float64
|
|
if len(consumptionReadings) > 0 {
|
|
var sum float64
|
|
for _, consumption := range consumptionReadings {
|
|
sum += consumption
|
|
}
|
|
avgConsumption = sum / float64(len(consumptionReadings))
|
|
}
|
|
|
|
// Overall consumption from totals
|
|
var overallConsumption float64
|
|
if totalKm > 0 {
|
|
overallConsumption = (totalLiters / totalKm) * 100
|
|
}
|
|
|
|
return avgConsumption, overallConsumption, totalKm
|
|
}
|
|
|
|
// calculateEfficiencyTrend calculates fuel efficiency trend over time
|
|
func (h *Handler) calculateEfficiencyTrend(stops []models.FuelStop) string {
|
|
if len(stops) < 2 {
|
|
return "insufficient_data"
|
|
}
|
|
|
|
// Get consumption for recent stops (last 5) vs older stops
|
|
recentStops := stops[:min(5, len(stops))]
|
|
olderStops := stops[min(5, len(stops)):]
|
|
|
|
recentAvg, _, _ := h.calculateConsumptionStats(recentStops)
|
|
olderAvg, _, _ := h.calculateConsumptionStats(olderStops)
|
|
|
|
if recentAvg == 0 || olderAvg == 0 {
|
|
return "insufficient_data"
|
|
}
|
|
|
|
diff := recentAvg - olderAvg
|
|
if diff < -0.5 {
|
|
return "improving" // Lower consumption is better
|
|
} else if diff > 0.5 {
|
|
return "worsening"
|
|
}
|
|
return "stable"
|
|
}
|
|
|
|
// min helper function
|
|
func min(a, b int) int {
|
|
if a < b {
|
|
return a
|
|
}
|
|
return b
|
|
}
|