package web import ( "log/slog" "net/http" "strconv" "github.com/martinlehoux/biking_home/ride" "github.com/martinlehoux/kagamigo/kcore" ) func (s *Server) handleDataQuality(w http.ResponseWriter, r *http.Request) { items, err := ride.ListUncategorised(s.db) if err != nil { slog.Error("Failed to load uncategorised rides", "error", err) http.Error(w, "failed to load rides", http.StatusInternalServerError) return } views := make([]RideView, 0, len(items)) for _, item := range items { views = append(views, buildRideView(item)) } total, err := ride.CountUncategorised(s.db) if err != nil { slog.Warn("Failed to count uncategorised rides", "error", err) total = len(items) } slog.Info("Loaded data quality page", "uncategorised", total, "displayed", len(views)) kcore.RenderPage(r.Context(), DataQualityPage(DataQualityPageData{ Items: views, Total: total, Notice: dataQualityNotice(r), }), w) } func (s *Server) handleBulkUpdateCategories(w http.ResponseWriter, r *http.Request) { if err := r.ParseForm(); err != nil { http.Error(w, "invalid form", http.StatusBadRequest) return } bikeType := ride.BikeType(r.FormValue("bike_type")) rideType := ride.RideType(r.FormValue("ride_type")) if !ride.IsValidBikeType(string(bikeType)) { http.Error(w, "invalid bike_type", http.StatusBadRequest) return } if !ride.IsValidRideType(string(rideType)) { http.Error(w, "invalid ride_type", http.StatusBadRequest) return } rawIDs := r.Form["ride_ids"] if len(rawIDs) == 0 { http.Error(w, "no rides selected", http.StatusBadRequest) return } ids := make([]int64, 0, len(rawIDs)) for _, raw := range rawIDs { id, err := strconv.ParseInt(raw, 10, 64) if err != nil || id <= 0 { http.Error(w, "invalid ride id", http.StatusBadRequest) return } ids = append(ids, id) } affected, err := ride.BulkUpdateCategories(s.db, ids, bikeType, rideType) if err != nil { slog.Error("Failed to bulk update categories", "error", err) http.Error(w, "failed to update categories", http.StatusInternalServerError) return } slog.Info("Bulk updated ride categories", "count", affected, "bike_type", bikeType, "ride_type", rideType) http.Redirect(w, r, "/data-quality?bulk=updated&count="+strconv.FormatInt(affected, 10), http.StatusSeeOther) } func dataQualityNotice(r *http.Request) string { if r.URL.Query().Get("bulk") == "updated" { count := r.URL.Query().Get("count") if count != "" { return count + " rides categorised." } return "Rides categorised." } if r.URL.Query().Get("categories") == "updated" { return "Ride categories updated." } return "" } func dataQualityURL() string { return "/data-quality" } type DataQualityPageData struct { Items []RideView Total int Notice string } func formatRideID(id int64) string { return strconv.FormatInt(id, 10) }