package handler import ( "me-fit/service" "me-fit/template" "me-fit/template/workout" "me-fit/types" "me-fit/utils" "database/sql" "log/slog" "net/http" "strconv" "time" ) type WorkoutHandler interface { handle(router *http.ServeMux) } type WorkoutHandlerImpl struct { db *sql.DB service service.WorkoutService auth service.AuthService serverSettings *types.ServerSettings } func NewWorkoutHandler(db *sql.DB, service service.WorkoutService, auth service.AuthService, serverSettings *types.ServerSettings) HandlerAuth { return WorkoutHandlerImpl{ db: db, service: service, auth: auth, serverSettings: serverSettings, } } func (handler WorkoutHandlerImpl) handle(router *http.ServeMux) { router.Handle("/workout", handler.handleWorkoutPage()) router.Handle("POST /api/workout", handler.handleAddWorkout()) router.Handle("GET /api/workout", handler.handleGetWorkout()) router.Handle("DELETE /api/workout/{id}", handler.handleDeleteWorkout()) } func (handler WorkoutHandlerImpl) handleWorkoutPage() http.HandlerFunc { return func(w http.ResponseWriter, r *http.Request) { user, err := handler.auth.GetUserFromSessionId(utils.GetSessionID(r)) if err != nil { utils.DoRedirect(w, r, "/auth/signin") return } currentDate := time.Now().Format("2006-01-02") inner := workout.WorkoutComp(currentDate) userComp := service.UserInfoComp(user) err = template.Layout(inner, userComp, handler.serverSettings.Environment).Render(r.Context(), w) if err != nil { utils.LogError("Failed to render workout page", err) http.Error(w, "Internal Server Error", http.StatusInternalServerError) } } } func (handler WorkoutHandlerImpl) handleAddWorkout() http.HandlerFunc { return func(w http.ResponseWriter, r *http.Request) { user, err := handler.auth.GetUserFromSessionId(utils.GetSessionID(r)) if err != nil { utils.DoRedirect(w, r, "/auth/signin") return } var dateStr = r.FormValue("date") var typeStr = r.FormValue("type") var setsStr = r.FormValue("sets") var repsStr = r.FormValue("reps") wo := service.NewWorkoutDto("", dateStr, typeStr, setsStr, repsStr) wo, err = handler.service.AddWorkout(user, wo) if err != nil { utils.TriggerToast(w, r, "error", "Invalid input values") http.Error(w, "Invalid input values", http.StatusBadRequest) return } wor := workout.Workout{Id: wo.RowId, Date: wo.Date, Type: wo.Type, Sets: wo.Sets, Reps: wo.Reps} err = workout.WorkoutItemComp(wor, true).Render(r.Context(), w) if err != nil { utils.LogError("Could not render workoutitem", err) utils.TriggerToast(w, r, "error", "Internal Server Error") http.Error(w, err.Error(), http.StatusInternalServerError) } } } func (handler WorkoutHandlerImpl) handleGetWorkout() http.HandlerFunc { return func(w http.ResponseWriter, r *http.Request) { user, err := handler.auth.GetUserFromSessionId(utils.GetSessionID(r)) if err != nil { utils.DoRedirect(w, r, "/auth/signin") return } workouts, err := handler.service.GetWorkouts(user) if err != nil { return } wos := make([]workout.Workout, 0) for _, wo := range workouts { wos = append(wos, workout.Workout{Id: wo.RowId, Date: wo.Date, Type: wo.Type, Sets: wo.Sets, Reps: wo.Reps}) } workout.WorkoutListComp(wos).Render(r.Context(), w) } } func (handler WorkoutHandlerImpl) handleDeleteWorkout() http.HandlerFunc { return func(w http.ResponseWriter, r *http.Request) { user, err := handler.auth.GetUserFromSessionId(utils.GetSessionID(r)) if err != nil { utils.DoRedirect(w, r, "/auth/signin") return } rowId := r.PathValue("id") if rowId == "" { http.Error(w, "Missing required fields", http.StatusBadRequest) slog.Warn("Missing required fields for workout delete") utils.TriggerToast(w, r, "error", "Missing ID field") return } rowIdInt, err := strconv.Atoi(rowId) if err != nil { http.Error(w, "Invalid ID", http.StatusBadRequest) slog.Warn("Invalid ID for workout delete") utils.TriggerToast(w, r, "error", "Invalid ID") return } err = handler.service.DeleteWorkout(user, rowIdInt) if err != nil { http.Error(w, "Internal Server Error", http.StatusInternalServerError) slog.Error("Could not delete workout: " + err.Error()) utils.TriggerToast(w, r, "error", "Internal Server Error") return } } }