first commit
This commit is contained in:
@@ -0,0 +1,342 @@
|
||||
package handlers
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"log"
|
||||
"net/http"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"tankstopp/internal/models"
|
||||
"tankstopp/internal/views/pages"
|
||||
|
||||
"github.com/gorilla/mux"
|
||||
)
|
||||
|
||||
// VehiclesHandler handles vehicle management page
|
||||
func (h *Handler) VehiclesHandler(w http.ResponseWriter, r *http.Request) {
|
||||
userID, username := h.getCurrentUser(r)
|
||||
if userID == 0 {
|
||||
http.Redirect(w, r, "/login", http.StatusSeeOther)
|
||||
return
|
||||
}
|
||||
|
||||
// Get 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 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
|
||||
}
|
||||
|
||||
// Render vehicles page using templ
|
||||
component := pages.VehiclesPage(user, username, vehicles)
|
||||
|
||||
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)
|
||||
}
|
||||
}
|
||||
|
||||
// AddVehicleHandler handles adding new vehicles
|
||||
func (h *Handler) AddVehicleHandler(w http.ResponseWriter, r *http.Request) {
|
||||
userID, _ := h.getCurrentUser(r)
|
||||
if userID == 0 {
|
||||
http.Redirect(w, r, "/login", http.StatusSeeOther)
|
||||
return
|
||||
}
|
||||
|
||||
switch r.Method {
|
||||
case "GET":
|
||||
// Get 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
|
||||
}
|
||||
|
||||
// Render add vehicle form using templ
|
||||
component := pages.AddVehiclePage(user, user.Username)
|
||||
|
||||
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)
|
||||
}
|
||||
case "POST":
|
||||
h.handleAddVehicle(w, r, userID)
|
||||
default:
|
||||
http.Error(w, "Method not allowed", http.StatusMethodNotAllowed)
|
||||
}
|
||||
}
|
||||
|
||||
// handleAddVehicle processes the form submission for adding vehicles
|
||||
func (h *Handler) handleAddVehicle(w http.ResponseWriter, r *http.Request, userID uint) {
|
||||
err := r.ParseForm()
|
||||
if err != nil {
|
||||
log.Printf("Error parsing form: %v", err)
|
||||
http.Error(w, "Bad request", http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
|
||||
// Parse form data
|
||||
form := models.VehicleForm{
|
||||
Name: strings.TrimSpace(r.FormValue("name")),
|
||||
Make: strings.TrimSpace(r.FormValue("make")),
|
||||
Model: strings.TrimSpace(r.FormValue("model")),
|
||||
LicensePlate: strings.TrimSpace(r.FormValue("license_plate")),
|
||||
FuelType: r.FormValue("fuel_type"),
|
||||
Notes: r.FormValue("notes"),
|
||||
IsActive: r.FormValue("is_active") == "on",
|
||||
}
|
||||
|
||||
// Parse year
|
||||
if yearStr := r.FormValue("year"); yearStr != "" {
|
||||
if year, err := strconv.Atoi(yearStr); err == nil {
|
||||
form.Year = year
|
||||
}
|
||||
}
|
||||
|
||||
// Validate form
|
||||
if err := h.validateVehicleForm(&form); err != nil {
|
||||
log.Printf("Validation error: %v", err)
|
||||
http.Redirect(w, r, "/vehicles/add?error="+err.Error(), http.StatusSeeOther)
|
||||
return
|
||||
}
|
||||
|
||||
// Convert form to vehicle
|
||||
vehicle := form.ToVehicle(userID)
|
||||
|
||||
// Save to database
|
||||
err = h.db.CreateVehicle(vehicle)
|
||||
if err != nil {
|
||||
log.Printf("Error creating vehicle: %v", err)
|
||||
http.Redirect(w, r, "/vehicles/add?error=Failed+to+create+vehicle", http.StatusSeeOther)
|
||||
return
|
||||
}
|
||||
|
||||
// Redirect to vehicles page with success message
|
||||
http.Redirect(w, r, "/vehicles?success=Vehicle+added+successfully", http.StatusSeeOther)
|
||||
}
|
||||
|
||||
// EditVehicleHandler handles editing existing vehicles
|
||||
func (h *Handler) EditVehicleHandler(w http.ResponseWriter, r *http.Request) {
|
||||
userID, _ := h.getCurrentUser(r)
|
||||
if userID == 0 {
|
||||
http.Redirect(w, r, "/login", http.StatusSeeOther)
|
||||
return
|
||||
}
|
||||
|
||||
vars := mux.Vars(r)
|
||||
idInt, err := strconv.Atoi(vars["id"])
|
||||
if err != nil {
|
||||
http.Error(w, "Invalid ID", http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
id := uint(idInt)
|
||||
|
||||
switch r.Method {
|
||||
case "GET":
|
||||
// Get vehicle
|
||||
vehicle, err := h.db.GetVehicleByID(id, userID)
|
||||
if err != nil {
|
||||
log.Printf("Error getting vehicle: %v", err)
|
||||
http.Error(w, "Internal server error", http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
if vehicle == nil {
|
||||
http.Error(w, "Vehicle not found", http.StatusNotFound)
|
||||
return
|
||||
}
|
||||
|
||||
// Get 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
|
||||
}
|
||||
|
||||
// Render edit vehicle form using templ
|
||||
component := pages.EditVehiclePage(user, user.Username, vehicle)
|
||||
|
||||
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)
|
||||
}
|
||||
case "POST":
|
||||
h.handleEditVehicle(w, r, id, userID)
|
||||
default:
|
||||
http.Error(w, "Method not allowed", http.StatusMethodNotAllowed)
|
||||
}
|
||||
}
|
||||
|
||||
// handleEditVehicle processes the form submission for editing vehicles
|
||||
func (h *Handler) handleEditVehicle(w http.ResponseWriter, r *http.Request, id, userID uint) {
|
||||
err := r.ParseForm()
|
||||
if err != nil {
|
||||
log.Printf("Error parsing form: %v", err)
|
||||
http.Error(w, "Bad request", http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
|
||||
// Get existing vehicle
|
||||
existingVehicle, err := h.db.GetVehicleByID(id, userID)
|
||||
if err != nil {
|
||||
log.Printf("Error getting vehicle: %v", err)
|
||||
http.Error(w, "Internal server error", http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
if existingVehicle == nil {
|
||||
http.Error(w, "Vehicle not found", http.StatusNotFound)
|
||||
return
|
||||
}
|
||||
|
||||
// Parse form data
|
||||
form := models.VehicleForm{
|
||||
Name: strings.TrimSpace(r.FormValue("name")),
|
||||
Make: strings.TrimSpace(r.FormValue("make")),
|
||||
Model: strings.TrimSpace(r.FormValue("model")),
|
||||
LicensePlate: strings.TrimSpace(r.FormValue("license_plate")),
|
||||
FuelType: r.FormValue("fuel_type"),
|
||||
Notes: r.FormValue("notes"),
|
||||
IsActive: r.FormValue("is_active") == "on",
|
||||
}
|
||||
|
||||
// Parse year
|
||||
if yearStr := r.FormValue("year"); yearStr != "" {
|
||||
if year, err := strconv.Atoi(yearStr); err == nil {
|
||||
form.Year = year
|
||||
}
|
||||
}
|
||||
|
||||
// Validate form
|
||||
if err := h.validateVehicleForm(&form); err != nil {
|
||||
log.Printf("Validation error: %v", err)
|
||||
http.Redirect(w, r, fmt.Sprintf("/vehicles/edit/%d?error=%s", id, err.Error()), http.StatusSeeOther)
|
||||
return
|
||||
}
|
||||
|
||||
// Convert form to vehicle
|
||||
updatedVehicle := form.ToVehicle(userID)
|
||||
updatedVehicle.ID = id
|
||||
updatedVehicle.CreatedAt = existingVehicle.CreatedAt
|
||||
|
||||
// Update in database
|
||||
err = h.db.UpdateVehicle(updatedVehicle)
|
||||
if err != nil {
|
||||
log.Printf("Error updating vehicle: %v", err)
|
||||
http.Redirect(w, r, fmt.Sprintf("/vehicles/edit/%d?error=Failed+to+update+vehicle", id), http.StatusSeeOther)
|
||||
return
|
||||
}
|
||||
|
||||
// Redirect to vehicles page with success message
|
||||
http.Redirect(w, r, "/vehicles?success=Vehicle+updated+successfully", http.StatusSeeOther)
|
||||
}
|
||||
|
||||
// DeleteVehicleHandler handles deleting vehicles
|
||||
func (h *Handler) DeleteVehicleHandler(w http.ResponseWriter, r *http.Request) {
|
||||
if r.Method != "POST" {
|
||||
http.Error(w, "Method not allowed", http.StatusMethodNotAllowed)
|
||||
return
|
||||
}
|
||||
|
||||
userID, _ := h.getCurrentUser(r)
|
||||
if userID == 0 {
|
||||
http.Redirect(w, r, "/login", http.StatusSeeOther)
|
||||
return
|
||||
}
|
||||
|
||||
vars := mux.Vars(r)
|
||||
idInt, err := strconv.Atoi(vars["id"])
|
||||
if err != nil {
|
||||
http.Error(w, "Invalid ID", http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
id := uint(idInt)
|
||||
|
||||
// Verify vehicle exists and belongs to user
|
||||
vehicle, err := h.db.GetVehicleByID(id, userID)
|
||||
if err != nil {
|
||||
log.Printf("Error getting vehicle: %v", err)
|
||||
http.Error(w, "Internal server error", http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
if vehicle == nil {
|
||||
http.Error(w, "Vehicle not found", http.StatusNotFound)
|
||||
return
|
||||
}
|
||||
|
||||
// Note: In a full implementation, we would check for associated fuel stops
|
||||
// For now, we'll allow deletion and rely on database constraints
|
||||
|
||||
// Delete vehicle
|
||||
err = h.db.DeleteVehicle(id, userID)
|
||||
if err != nil {
|
||||
log.Printf("Error deleting vehicle: %v", err)
|
||||
http.Redirect(w, r, "/vehicles?error=Failed+to+delete+vehicle", http.StatusSeeOther)
|
||||
return
|
||||
}
|
||||
|
||||
// Redirect to vehicles page with success message
|
||||
http.Redirect(w, r, "/vehicles?success=Vehicle+deleted+successfully", http.StatusSeeOther)
|
||||
}
|
||||
|
||||
// validateVehicleForm validates the vehicle form data
|
||||
func (h *Handler) validateVehicleForm(form *models.VehicleForm) error {
|
||||
if form.Name == "" {
|
||||
return fmt.Errorf("Vehicle name is required")
|
||||
}
|
||||
|
||||
if len(form.Name) < 2 {
|
||||
return fmt.Errorf("Vehicle name must be at least 2 characters long")
|
||||
}
|
||||
|
||||
if form.Make == "" {
|
||||
return fmt.Errorf("Vehicle make is required")
|
||||
}
|
||||
|
||||
if form.Model == "" {
|
||||
return fmt.Errorf("Vehicle model is required")
|
||||
}
|
||||
|
||||
if form.FuelType == "" {
|
||||
return fmt.Errorf("Fuel type is required")
|
||||
}
|
||||
|
||||
// Validate year if provided
|
||||
if form.Year != 0 {
|
||||
currentYear := 2024 // You might want to use time.Now().Year()
|
||||
if form.Year < 1900 || form.Year > currentYear+1 {
|
||||
return fmt.Errorf("Year must be between 1900 and %d", currentYear+1)
|
||||
}
|
||||
}
|
||||
|
||||
// Validate license plate format if provided
|
||||
if form.LicensePlate != "" {
|
||||
if len(form.LicensePlate) > 20 {
|
||||
return fmt.Errorf("License plate cannot be longer than 20 characters")
|
||||
}
|
||||
}
|
||||
|
||||
// Validate notes length if provided
|
||||
if len(form.Notes) > 500 {
|
||||
return fmt.Errorf("Notes cannot be longer than 500 characters")
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
Reference in New Issue
Block a user