206 lines
5.8 KiB
Go
206 lines
5.8 KiB
Go
package stats
|
|
|
|
import (
|
|
"encoding/json"
|
|
"net/http"
|
|
"strconv"
|
|
|
|
"rideaware/internal/config"
|
|
"rideaware/internal/middleware"
|
|
)
|
|
|
|
type Handler struct {
|
|
service *Service
|
|
}
|
|
|
|
func NewHandler() *Handler {
|
|
return &Handler{
|
|
service: NewService(),
|
|
}
|
|
}
|
|
|
|
// GetSummary GET /api/protected/stats/summary
|
|
func (h *Handler) GetSummary(w http.ResponseWriter, r *http.Request) {
|
|
claims := r.Context().Value(middleware.UserContextKey).(*config.CustomClaims)
|
|
if claims == nil {
|
|
w.Header().Set("Content-Type", "application/json")
|
|
w.WriteHeader(http.StatusUnauthorized)
|
|
json.NewEncoder(w).Encode(map[string]string{"error": "unauthorized"})
|
|
return
|
|
}
|
|
|
|
summary, err := h.service.GetSummary(claims.UserID)
|
|
if err != nil {
|
|
w.Header().Set("Content-Type", "application/json")
|
|
w.WriteHeader(http.StatusInternalServerError)
|
|
json.NewEncoder(w).Encode(map[string]string{"error": "failed to fetch stats"})
|
|
return
|
|
}
|
|
|
|
w.Header().Set("Content-Type", "application/json")
|
|
w.WriteHeader(http.StatusOK)
|
|
json.NewEncoder(w).Encode(summary)
|
|
}
|
|
|
|
// GetWeeklyStats GET /api/protected/stats/weekly?weeks=12
|
|
func (h *Handler) GetWeeklyStats(w http.ResponseWriter, r *http.Request) {
|
|
claims := r.Context().Value(middleware.UserContextKey).(*config.CustomClaims)
|
|
if claims == nil {
|
|
w.Header().Set("Content-Type", "application/json")
|
|
w.WriteHeader(http.StatusUnauthorized)
|
|
json.NewEncoder(w).Encode(map[string]string{"error": "unauthorized"})
|
|
return
|
|
}
|
|
|
|
weeks := 12
|
|
if w_str := r.URL.Query().Get("weeks"); w_str != "" {
|
|
if parsed, err := strconv.Atoi(w_str); err == nil {
|
|
weeks = parsed
|
|
}
|
|
}
|
|
|
|
stats, err := h.service.GetWeeklyStats(claims.UserID, weeks)
|
|
if err != nil {
|
|
w.Header().Set("Content-Type", "application/json")
|
|
w.WriteHeader(http.StatusInternalServerError)
|
|
json.NewEncoder(w).Encode(map[string]string{"error": "failed to fetch weekly stats"})
|
|
return
|
|
}
|
|
|
|
if stats == nil {
|
|
stats = []PeriodStats{}
|
|
}
|
|
|
|
w.Header().Set("Content-Type", "application/json")
|
|
w.WriteHeader(http.StatusOK)
|
|
json.NewEncoder(w).Encode(stats)
|
|
}
|
|
|
|
// GetMonthlyStats GET /api/protected/stats/monthly?months=12
|
|
func (h *Handler) GetMonthlyStats(w http.ResponseWriter, r *http.Request) {
|
|
claims := r.Context().Value(middleware.UserContextKey).(*config.CustomClaims)
|
|
if claims == nil {
|
|
w.Header().Set("Content-Type", "application/json")
|
|
w.WriteHeader(http.StatusUnauthorized)
|
|
json.NewEncoder(w).Encode(map[string]string{"error": "unauthorized"})
|
|
return
|
|
}
|
|
|
|
months := 12
|
|
if m_str := r.URL.Query().Get("months"); m_str != "" {
|
|
if parsed, err := strconv.Atoi(m_str); err == nil {
|
|
months = parsed
|
|
}
|
|
}
|
|
|
|
stats, err := h.service.GetMonthlyStats(claims.UserID, months)
|
|
if err != nil {
|
|
w.Header().Set("Content-Type", "application/json")
|
|
w.WriteHeader(http.StatusInternalServerError)
|
|
json.NewEncoder(w).Encode(map[string]string{"error": "failed to fetch monthly stats"})
|
|
return
|
|
}
|
|
|
|
if stats == nil {
|
|
stats = []PeriodStats{}
|
|
}
|
|
|
|
w.Header().Set("Content-Type", "application/json")
|
|
w.WriteHeader(http.StatusOK)
|
|
json.NewEncoder(w).Encode(stats)
|
|
}
|
|
|
|
// GetTrainingLoad GET /api/protected/stats/training-load?days=180
|
|
func (h *Handler) GetTrainingLoad(w http.ResponseWriter, r *http.Request) {
|
|
claims := r.Context().Value(middleware.UserContextKey).(*config.CustomClaims)
|
|
if claims == nil {
|
|
w.Header().Set("Content-Type", "application/json")
|
|
w.WriteHeader(http.StatusUnauthorized)
|
|
json.NewEncoder(w).Encode(map[string]string{"error": "unauthorized"})
|
|
return
|
|
}
|
|
|
|
days := 180
|
|
if dStr := r.URL.Query().Get("days"); dStr != "" {
|
|
if parsed, err := strconv.Atoi(dStr); err == nil {
|
|
days = parsed
|
|
}
|
|
}
|
|
|
|
data, ftp, err := h.service.GetTrainingLoad(claims.UserID, days)
|
|
if err != nil {
|
|
w.Header().Set("Content-Type", "application/json")
|
|
w.WriteHeader(http.StatusInternalServerError)
|
|
json.NewEncoder(w).Encode(map[string]string{"error": "failed to fetch training load"})
|
|
return
|
|
}
|
|
|
|
w.Header().Set("Content-Type", "application/json")
|
|
w.WriteHeader(http.StatusOK)
|
|
json.NewEncoder(w).Encode(map[string]interface{}{
|
|
"ftp": ftp,
|
|
"daily_tss": data,
|
|
})
|
|
}
|
|
|
|
// GetPowerHistory GET /api/protected/stats/power-history?days=365
|
|
func (h *Handler) GetPowerHistory(w http.ResponseWriter, r *http.Request) {
|
|
claims := r.Context().Value(middleware.UserContextKey).(*config.CustomClaims)
|
|
if claims == nil {
|
|
w.Header().Set("Content-Type", "application/json")
|
|
w.WriteHeader(http.StatusUnauthorized)
|
|
json.NewEncoder(w).Encode(map[string]string{"error": "unauthorized"})
|
|
return
|
|
}
|
|
|
|
days := 365
|
|
if dStr := r.URL.Query().Get("days"); dStr != "" {
|
|
if parsed, err := strconv.Atoi(dStr); err == nil {
|
|
days = parsed
|
|
}
|
|
}
|
|
|
|
data, err := h.service.GetPowerHistory(claims.UserID, days)
|
|
if err != nil {
|
|
w.Header().Set("Content-Type", "application/json")
|
|
w.WriteHeader(http.StatusInternalServerError)
|
|
json.NewEncoder(w).Encode(map[string]string{"error": "failed to fetch power history"})
|
|
return
|
|
}
|
|
|
|
if data == nil {
|
|
data = []PowerPoint{}
|
|
}
|
|
|
|
w.Header().Set("Content-Type", "application/json")
|
|
w.WriteHeader(http.StatusOK)
|
|
json.NewEncoder(w).Encode(data)
|
|
}
|
|
|
|
// GetPersonalBests GET /api/protected/stats/personal-bests
|
|
func (h *Handler) GetPersonalBests(w http.ResponseWriter, r *http.Request) {
|
|
claims := r.Context().Value(middleware.UserContextKey).(*config.CustomClaims)
|
|
if claims == nil {
|
|
w.Header().Set("Content-Type", "application/json")
|
|
w.WriteHeader(http.StatusUnauthorized)
|
|
json.NewEncoder(w).Encode(map[string]string{"error": "unauthorized"})
|
|
return
|
|
}
|
|
|
|
pbs, err := h.service.GetPersonalBests(claims.UserID)
|
|
if err != nil {
|
|
w.Header().Set("Content-Type", "application/json")
|
|
w.WriteHeader(http.StatusInternalServerError)
|
|
json.NewEncoder(w).Encode(map[string]string{"error": "failed to fetch personal bests"})
|
|
return
|
|
}
|
|
|
|
if pbs == nil {
|
|
pbs = []PersonalBest{}
|
|
}
|
|
|
|
w.Header().Set("Content-Type", "application/json")
|
|
w.WriteHeader(http.StatusOK)
|
|
json.NewEncoder(w).Encode(pbs)
|
|
}
|