package api import ( "encoding/json" "errors" "net/http" "git.fabledsword.com/bvandeusen/minstrel/internal/apierror" "git.fabledsword.com/bvandeusen/minstrel/internal/db/dbq" "git.fabledsword.com/bvandeusen/minstrel/internal/notifications" ) // notificationEmailBody is the wire shape for GET and PUT // /api/admin/notification-email (M489 #5346): when the grouped emails go out. type notificationEmailBody struct { SummaryHour int32 `json:"summary_hour"` BatchWindowMinutes int32 `json:"batch_window_minutes"` } func notificationEmailBodyOf(s notifications.EmailSettings) notificationEmailBody { return notificationEmailBody{SummaryHour: s.SummaryHour, BatchWindowMinutes: s.BatchWindowMinutes} } // handleGetNotificationEmail implements GET /api/admin/notification-email. func (h *handlers) handleGetNotificationEmail(w http.ResponseWriter, r *http.Request) { s, err := notifications.LoadEmailSettings(r.Context(), dbq.New(h.pool)) if err != nil { writeErrWithLog(w, h.logger, "admin notification email: load failed", apierror.Internal(err)) return } writeJSON(w, http.StatusOK, notificationEmailBodyOf(s)) } // handleUpdateNotificationEmail implements PUT /api/admin/notification-email. // A whole-row write; the digest reads it on its next tick. func (h *handlers) handleUpdateNotificationEmail(w http.ResponseWriter, r *http.Request) { var req notificationEmailBody if err := json.NewDecoder(r.Body).Decode(&req); err != nil { writeErr(w, apierror.BadRequest("invalid_body", "malformed JSON")) return } saved, err := notifications.SaveEmailSettings(r.Context(), dbq.New(h.pool), notifications.EmailSettings{ SummaryHour: req.SummaryHour, BatchWindowMinutes: req.BatchWindowMinutes, }) if err != nil { if errors.Is(err, notifications.ErrEmailSettingOutOfRange) { writeErr(w, apierror.BadRequest("invalid_setting", err.Error())) return } writeErrWithLog(w, h.logger, "admin notification email: update failed", apierror.Internal(err)) return } writeJSON(w, http.StatusOK, notificationEmailBodyOf(saved)) }