feat: Refactor activity and project handlers to use utility functions for ID parsing and response handling
This commit is contained in:
@@ -0,0 +1,136 @@
|
||||
package utils
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/timetracker/backend/internal/types"
|
||||
)
|
||||
|
||||
// ParseID parses an ID from the URL parameter and converts it to a types.ULID
|
||||
func ParseID(c *gin.Context, paramName string) (types.ULID, error) {
|
||||
idStr := c.Param(paramName)
|
||||
return types.ULIDFromString(idStr)
|
||||
}
|
||||
|
||||
// BindJSON binds the request body to the provided struct
|
||||
func BindJSON(c *gin.Context, obj interface{}) error {
|
||||
if err := c.ShouldBindJSON(obj); err != nil {
|
||||
return fmt.Errorf("invalid request body: %w", err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// ConvertToDTO converts a slice of models to a slice of DTOs using the provided conversion function
|
||||
func ConvertToDTO[M any, D any](models []M, convertFn func(*M) D) []D {
|
||||
dtos := make([]D, len(models))
|
||||
for i, model := range models {
|
||||
// Create a copy of the model to avoid issues with loop variable capture
|
||||
modelCopy := model
|
||||
dtos[i] = convertFn(&modelCopy)
|
||||
}
|
||||
return dtos
|
||||
}
|
||||
|
||||
// HandleGetAll is a generic function to handle GET all entities endpoints
|
||||
func HandleGetAll[M any, D any](
|
||||
c *gin.Context,
|
||||
getAllFn func(ctx context.Context) ([]M, error),
|
||||
convertFn func(*M) D,
|
||||
entityName string,
|
||||
) {
|
||||
// Get entities from the database
|
||||
entities, err := getAllFn(c.Request.Context())
|
||||
if err != nil {
|
||||
InternalErrorResponse(c, fmt.Sprintf("Error retrieving %s: %s", entityName, err.Error()))
|
||||
return
|
||||
}
|
||||
|
||||
// Convert to DTOs
|
||||
dtos := ConvertToDTO(entities, convertFn)
|
||||
|
||||
SuccessResponse(c, 200, dtos)
|
||||
}
|
||||
|
||||
// HandleGetByID is a generic function to handle GET entity by ID endpoints
|
||||
func HandleGetByID[M any, D any](
|
||||
c *gin.Context,
|
||||
getByIDFn func(ctx context.Context, id types.ULID) (*M, error),
|
||||
convertFn func(*M) D,
|
||||
entityName string,
|
||||
) {
|
||||
// Parse ID from URL
|
||||
id, err := ParseID(c, "id")
|
||||
if err != nil {
|
||||
BadRequestResponse(c, fmt.Sprintf("Invalid %s ID format", entityName))
|
||||
return
|
||||
}
|
||||
|
||||
// Get entity from the database
|
||||
entity, err := getByIDFn(c.Request.Context(), id)
|
||||
if err != nil {
|
||||
InternalErrorResponse(c, fmt.Sprintf("Error retrieving %s: %s", entityName, err.Error()))
|
||||
return
|
||||
}
|
||||
|
||||
if entity == nil {
|
||||
NotFoundResponse(c, fmt.Sprintf("%s not found", entityName))
|
||||
return
|
||||
}
|
||||
|
||||
// Convert to DTO
|
||||
dto := convertFn(entity)
|
||||
|
||||
SuccessResponse(c, 200, dto)
|
||||
}
|
||||
|
||||
// HandleCreate is a generic function to handle POST entity endpoints
|
||||
func HandleCreate[C any, M any, D any](
|
||||
c *gin.Context,
|
||||
createFn func(ctx context.Context, create C) (*M, error),
|
||||
convertFn func(*M) D,
|
||||
entityName string,
|
||||
) {
|
||||
// Parse request body
|
||||
var createDTO C
|
||||
if err := BindJSON(c, &createDTO); err != nil {
|
||||
BadRequestResponse(c, err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
// Create entity in the database
|
||||
entity, err := createFn(c.Request.Context(), createDTO)
|
||||
if err != nil {
|
||||
InternalErrorResponse(c, fmt.Sprintf("Error creating %s: %s", entityName, err.Error()))
|
||||
return
|
||||
}
|
||||
|
||||
// Convert to DTO
|
||||
dto := convertFn(entity)
|
||||
|
||||
SuccessResponse(c, 201, dto)
|
||||
}
|
||||
|
||||
// HandleDelete is a generic function to handle DELETE entity endpoints
|
||||
func HandleDelete(
|
||||
c *gin.Context,
|
||||
deleteFn func(ctx context.Context, id types.ULID) error,
|
||||
entityName string,
|
||||
) {
|
||||
// Parse ID from URL
|
||||
id, err := ParseID(c, "id")
|
||||
if err != nil {
|
||||
BadRequestResponse(c, fmt.Sprintf("Invalid %s ID format", entityName))
|
||||
return
|
||||
}
|
||||
|
||||
// Delete entity from the database
|
||||
err = deleteFn(c.Request.Context(), id)
|
||||
if err != nil {
|
||||
InternalErrorResponse(c, fmt.Sprintf("Error deleting %s: %s", entityName, err.Error()))
|
||||
return
|
||||
}
|
||||
|
||||
SuccessResponse(c, 204, nil)
|
||||
}
|
||||
Reference in New Issue
Block a user