Add admin settings page with seed data and limitations toggle

- Add settings handler with endpoints for:
  - GET/PUT /api/admin/settings (enable_limitations toggle)
  - POST /api/admin/settings/seed-lookups (run 001_lookups.sql)
  - POST /api/admin/settings/seed-test-data (run 002_test_data.sql)

- Add settings page to admin panel with:
  - Toggle switch to enable/disable subscription limitations
  - Button to seed lookup data (categories, priorities, etc.)
  - Button to seed test data (with warning for non-production use)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
Trey t
2025-11-28 08:47:49 -06:00
parent 218e79220c
commit f02c1e6a64
4 changed files with 396 additions and 0 deletions

View File

@@ -0,0 +1,128 @@
package handlers
import (
"net/http"
"os"
"path/filepath"
"github.com/gin-gonic/gin"
"gorm.io/gorm"
"github.com/treytartt/mycrib-api/internal/models"
)
// AdminSettingsHandler handles system settings management
type AdminSettingsHandler struct {
db *gorm.DB
}
// NewAdminSettingsHandler creates a new handler
func NewAdminSettingsHandler(db *gorm.DB) *AdminSettingsHandler {
return &AdminSettingsHandler{db: db}
}
// SettingsResponse represents the settings response
type SettingsResponse struct {
EnableLimitations bool `json:"enable_limitations"`
}
// GetSettings handles GET /api/admin/settings
func (h *AdminSettingsHandler) GetSettings(c *gin.Context) {
var settings models.SubscriptionSettings
if err := h.db.First(&settings, 1).Error; err != nil {
if err == gorm.ErrRecordNotFound {
// Create default settings
settings = models.SubscriptionSettings{ID: 1, EnableLimitations: false}
h.db.Create(&settings)
} else {
c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to fetch settings"})
return
}
}
c.JSON(http.StatusOK, SettingsResponse{
EnableLimitations: settings.EnableLimitations,
})
}
// UpdateSettingsRequest represents the update request
type UpdateSettingsRequest struct {
EnableLimitations *bool `json:"enable_limitations"`
}
// UpdateSettings handles PUT /api/admin/settings
func (h *AdminSettingsHandler) UpdateSettings(c *gin.Context) {
var req UpdateSettingsRequest
if err := c.ShouldBindJSON(&req); err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
return
}
var settings models.SubscriptionSettings
if err := h.db.First(&settings, 1).Error; err != nil {
if err == gorm.ErrRecordNotFound {
settings = models.SubscriptionSettings{ID: 1}
} else {
c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to fetch settings"})
return
}
}
if req.EnableLimitations != nil {
settings.EnableLimitations = *req.EnableLimitations
}
if err := h.db.Save(&settings).Error; err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to update settings"})
return
}
c.JSON(http.StatusOK, SettingsResponse{
EnableLimitations: settings.EnableLimitations,
})
}
// SeedLookups handles POST /api/admin/settings/seed-lookups
func (h *AdminSettingsHandler) SeedLookups(c *gin.Context) {
if err := h.runSeedFile("001_lookups.sql"); err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to seed lookups: " + err.Error()})
return
}
c.JSON(http.StatusOK, gin.H{"message": "Lookup data seeded successfully"})
}
// SeedTestData handles POST /api/admin/settings/seed-test-data
func (h *AdminSettingsHandler) SeedTestData(c *gin.Context) {
if err := h.runSeedFile("002_test_data.sql"); err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to seed test data: " + err.Error()})
return
}
c.JSON(http.StatusOK, gin.H{"message": "Test data seeded successfully"})
}
// runSeedFile executes a seed SQL file
func (h *AdminSettingsHandler) runSeedFile(filename string) error {
// Check multiple possible locations
possiblePaths := []string{
filepath.Join("seeds", filename),
filepath.Join("./seeds", filename),
filepath.Join("/app/seeds", filename),
}
var sqlContent []byte
var err error
for _, path := range possiblePaths {
sqlContent, err = os.ReadFile(path)
if err == nil {
break
}
}
if err != nil {
return err
}
return h.db.Exec(string(sqlContent)).Error
}

View File

@@ -249,6 +249,16 @@ func SetupRoutes(router *gin.Engine, db *gorm.DB, cfg *config.Config, deps *Depe
notifPrefs.DELETE("/:id", notifPrefsHandler.Delete)
notifPrefs.GET("/user/:user_id", notifPrefsHandler.GetByUser)
}
// System settings management
settingsHandler := handlers.NewAdminSettingsHandler(db)
settings := protected.Group("/settings")
{
settings.GET("", settingsHandler.GetSettings)
settings.PUT("", settingsHandler.UpdateSettings)
settings.POST("/seed-lookups", settingsHandler.SeedLookups)
settings.POST("/seed-test-data", settingsHandler.SeedTestData)
}
}
}