package units import ( "encoding/json" "log/slog" "net/http" "github.com/food-ai/backend/internal/infra/locale" "github.com/food-ai/backend/internal/infra/middleware" "github.com/jackc/pgx/v5/pgxpool" ) type unitItem struct { Code string `json:"code"` Name string `json:"name"` } // NewListHandler returns an http.HandlerFunc for GET /units. // It queries the database directly, resolving translations via COALESCE. func NewListHandler(pool *pgxpool.Pool) http.HandlerFunc { return func(responseWriter http.ResponseWriter, request *http.Request) { lang := locale.FromContext(request.Context()) rows, queryError := pool.Query(request.Context(), ` SELECT u.code, COALESCE(ut.name, u.code) AS name FROM units u LEFT JOIN unit_translations ut ON ut.unit_code = u.code AND ut.lang = $1 ORDER BY u.sort_order`, lang) if queryError != nil { slog.ErrorContext(request.Context(), "list units", "err", queryError) writeErrorJSON(responseWriter, request, http.StatusInternalServerError, "failed to load units") return } defer rows.Close() items := make([]unitItem, 0) for rows.Next() { var item unitItem if scanError := rows.Scan(&item.Code, &item.Name); scanError != nil { slog.ErrorContext(request.Context(), "scan unit row", "err", scanError) writeErrorJSON(responseWriter, request, http.StatusInternalServerError, "failed to load units") return } items = append(items, item) } if rowsError := rows.Err(); rowsError != nil { slog.ErrorContext(request.Context(), "iterate unit rows", "err", rowsError) writeErrorJSON(responseWriter, request, http.StatusInternalServerError, "failed to load units") return } responseWriter.Header().Set("Content-Type", "application/json") _ = json.NewEncoder(responseWriter).Encode(map[string]any{"units": items}) } } func writeErrorJSON(responseWriter http.ResponseWriter, request *http.Request, status int, msg string) { responseWriter.Header().Set("Content-Type", "application/json") responseWriter.WriteHeader(status) _ = json.NewEncoder(responseWriter).Encode(map[string]any{"error": msg, "request_id": middleware.RequestIDFromCtx(request.Context())}) }