2025-11-23 22:49:46 +07:00

223 lines
6.6 KiB
Go

// internal/controllers/item_controller.go
package controllers
import (
"lost-and-found/internal/models"
"lost-and-found/internal/services"
"lost-and-found/internal/utils"
"net/http"
"strconv"
"github.com/gin-gonic/gin"
"gorm.io/gorm"
)
type ItemController struct {
itemService *services.ItemService
matchService *services.MatchService
}
func NewItemController(db *gorm.DB) *ItemController {
return &ItemController{
itemService: services.NewItemService(db),
matchService: services.NewMatchService(db),
}
}
// GetAllItems gets all items (public)
// GET /api/items
func (c *ItemController) GetAllItems(ctx *gin.Context) {
page, _ := strconv.Atoi(ctx.DefaultQuery("page", "1"))
limit, _ := strconv.Atoi(ctx.DefaultQuery("limit", "10"))
status := ctx.Query("status")
category := ctx.Query("category")
search := ctx.Query("search")
items, total, err := c.itemService.GetAllItems(page, limit, status, category, search)
if err != nil {
utils.ErrorResponse(ctx, http.StatusInternalServerError, "Failed to get items", err.Error())
return
}
utils.SendPaginatedResponse(ctx, http.StatusOK, "Items retrieved", items, total, page, limit)
}
// GetItemByID gets item by ID
// GET /api/items/:id
func (c *ItemController) GetItemByID(ctx *gin.Context) {
id, err := strconv.ParseUint(ctx.Param("id"), 10, 32)
if err != nil {
utils.ErrorResponse(ctx, http.StatusBadRequest, "Invalid item ID", err.Error())
return
}
// Check if user is manager or admin
isManager := false
if userObj, exists := ctx.Get("user"); exists {
user := userObj.(*models.User)
isManager = user.IsManager() || user.IsAdmin()
}
item, err := c.itemService.GetItemByID(uint(id), isManager)
if err != nil {
utils.ErrorResponse(ctx, http.StatusNotFound, "Item not found", err.Error())
return
}
utils.SuccessResponse(ctx, http.StatusOK, "Item retrieved", item)
}
// CreateItem creates a new item
// POST /api/items
func (c *ItemController) CreateItem(ctx *gin.Context) {
userObj, _ := ctx.Get("user")
user := userObj.(*models.User)
var req services.CreateItemRequest
if err := ctx.ShouldBindJSON(&req); err != nil {
utils.ErrorResponse(ctx, http.StatusBadRequest, "Invalid request data", err.Error())
return
}
ipAddress := ctx.ClientIP()
userAgent := ctx.Request.UserAgent()
item, err := c.itemService.CreateItem(user.ID, req, ipAddress, userAgent)
if err != nil {
utils.ErrorResponse(ctx, http.StatusBadRequest, "Failed to create item", err.Error())
return
}
// Auto-match with lost items
go c.matchService.AutoMatchNewItem(item.ID)
utils.SuccessResponse(ctx, http.StatusCreated, "Item created", item.ToDetailResponse())
}
// UpdateItem updates an item
// PUT /api/items/:id
func (c *ItemController) UpdateItem(ctx *gin.Context) {
userObj, _ := ctx.Get("user")
user := userObj.(*models.User)
itemID, err := strconv.ParseUint(ctx.Param("id"), 10, 32)
if err != nil {
utils.ErrorResponse(ctx, http.StatusBadRequest, "Invalid item ID", err.Error())
return
}
var req services.UpdateItemRequest
if err := ctx.ShouldBindJSON(&req); err != nil {
utils.ErrorResponse(ctx, http.StatusBadRequest, "Invalid request data", err.Error())
return
}
ipAddress := ctx.ClientIP()
userAgent := ctx.Request.UserAgent()
item, err := c.itemService.UpdateItem(user.ID, uint(itemID), req, ipAddress, userAgent)
if err != nil {
utils.ErrorResponse(ctx, http.StatusBadRequest, "Failed to update item", err.Error())
return
}
utils.SuccessResponse(ctx, http.StatusOK, "Item updated", item.ToDetailResponse())
}
// UpdateItemStatus updates item status
// PATCH /api/items/:id/status
func (c *ItemController) UpdateItemStatus(ctx *gin.Context) {
userObj, _ := ctx.Get("user")
user := userObj.(*models.User)
itemID, err := strconv.ParseUint(ctx.Param("id"), 10, 32)
if err != nil {
utils.ErrorResponse(ctx, http.StatusBadRequest, "Invalid item ID", err.Error())
return
}
var req struct {
Status string `json:"status" binding:"required"`
}
if err := ctx.ShouldBindJSON(&req); err != nil {
utils.ErrorResponse(ctx, http.StatusBadRequest, "Invalid request data", err.Error())
return
}
ipAddress := ctx.ClientIP()
userAgent := ctx.Request.UserAgent()
if err := c.itemService.UpdateItemStatus(user.ID, uint(itemID), req.Status, ipAddress, userAgent); err != nil {
utils.ErrorResponse(ctx, http.StatusBadRequest, "Failed to update status", err.Error())
return
}
utils.SuccessResponse(ctx, http.StatusOK, "Item status updated", nil)
}
// DeleteItem deletes an item
// DELETE /api/items/:id
func (c *ItemController) DeleteItem(ctx *gin.Context) {
userObj, _ := ctx.Get("user")
user := userObj.(*models.User)
itemID, err := strconv.ParseUint(ctx.Param("id"), 10, 32)
if err != nil {
utils.ErrorResponse(ctx, http.StatusBadRequest, "Invalid item ID", err.Error())
return
}
ipAddress := ctx.ClientIP()
userAgent := ctx.Request.UserAgent()
if err := c.itemService.DeleteItem(user.ID, uint(itemID), ipAddress, userAgent); err != nil {
utils.ErrorResponse(ctx, http.StatusBadRequest, "Failed to delete item", err.Error())
return
}
utils.SuccessResponse(ctx, http.StatusOK, "Item deleted", nil)
}
// GetItemsByReporter gets items by reporter
// GET /api/user/items
func (c *ItemController) GetItemsByReporter(ctx *gin.Context) {
userObj, _ := ctx.Get("user")
user := userObj.(*models.User)
page, _ := strconv.Atoi(ctx.DefaultQuery("page", "1"))
limit, _ := strconv.Atoi(ctx.DefaultQuery("limit", "10"))
items, total, err := c.itemService.GetItemsByReporter(user.ID, page, limit)
if err != nil {
utils.ErrorResponse(ctx, http.StatusInternalServerError, "Failed to get items", err.Error())
return
}
var responses []models.ItemDetailResponse
for _, item := range items {
responses = append(responses, item.ToDetailResponse())
}
utils.SendPaginatedResponse(ctx, http.StatusOK, "Items retrieved", responses, total, page, limit)
}
// GetItemRevisionHistory gets revision history for an item
// GET /api/items/:id/revisions
func (c *ItemController) GetItemRevisionHistory(ctx *gin.Context) {
itemID, err := strconv.ParseUint(ctx.Param("id"), 10, 32)
if err != nil {
utils.ErrorResponse(ctx, http.StatusBadRequest, "Invalid item ID", err.Error())
return
}
page, _ := strconv.Atoi(ctx.DefaultQuery("page", "1"))
limit, _ := strconv.Atoi(ctx.DefaultQuery("limit", "10"))
revisions, total, err := c.itemService.GetItemRevisionHistory(uint(itemID), page, limit)
if err != nil {
utils.ErrorResponse(ctx, http.StatusInternalServerError, "Failed to get revision history", err.Error())
return
}
utils.SendPaginatedResponse(ctx, http.StatusOK, "Revision history retrieved", revisions, total, page, limit)
}