first commit
This commit is contained in:
359
backend/api/tasks.go
Normal file
359
backend/api/tasks.go
Normal file
@@ -0,0 +1,359 @@
|
||||
package api
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"project-dashboard/api/utils"
|
||||
"project-dashboard/models"
|
||||
"time"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
type CreateTaskRequest struct {
|
||||
Title string `json:"title" binding:"required"`
|
||||
Description string `json:"description"`
|
||||
Priority string `json:"priority"`
|
||||
DueDate string `json:"due_date"`
|
||||
AssignedToID *uint `json:"assigned_to_id"`
|
||||
}
|
||||
|
||||
type UpdateTaskRequest struct {
|
||||
Title string `json:"title"`
|
||||
Description string `json:"description"`
|
||||
Status string `json:"status"`
|
||||
Priority string `json:"priority"`
|
||||
DueDate string `json:"due_date"`
|
||||
AssignedToID *uint `json:"assigned_to_id"`
|
||||
Position *int `json:"position"`
|
||||
}
|
||||
|
||||
type CreateSubtaskRequest struct {
|
||||
Title string `json:"title" binding:"required"`
|
||||
Description string `json:"description"`
|
||||
AssignedToID *uint `json:"assigned_to_id"`
|
||||
}
|
||||
|
||||
type CreateCommentRequest struct {
|
||||
Content string `json:"content" binding:"required"`
|
||||
}
|
||||
|
||||
// CreateTask creates a new task
|
||||
func CreateTask(c *gin.Context) {
|
||||
user, exists := c.Get("user")
|
||||
if !exists {
|
||||
utils.ErrorResponse(c, http.StatusUnauthorized, "User not authenticated")
|
||||
return
|
||||
}
|
||||
|
||||
userObj := user.(*models.User)
|
||||
project, _ := c.Get("project")
|
||||
projectObj := project.(*models.Project)
|
||||
|
||||
var req CreateTaskRequest
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
utils.ValidationErrorResponse(c, gin.H{
|
||||
"error": err.Error(),
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
task := models.Task{
|
||||
Title: req.Title,
|
||||
Description: req.Description,
|
||||
Priority: req.Priority,
|
||||
ProjectID: projectObj.ID,
|
||||
CreatedByID: userObj.ID,
|
||||
AssignedToID: req.AssignedToID,
|
||||
Status: "todo",
|
||||
}
|
||||
|
||||
if task.Priority == "" {
|
||||
task.Priority = "medium"
|
||||
}
|
||||
|
||||
// Parse due date if provided
|
||||
if req.DueDate != "" {
|
||||
if dueDate, err := time.Parse("2006-01-02T15:04:05Z07:00", req.DueDate); err == nil {
|
||||
task.DueDate = &dueDate
|
||||
}
|
||||
}
|
||||
|
||||
if err := models.GetDB().Create(&task).Error; err != nil {
|
||||
utils.ErrorResponse(c, http.StatusInternalServerError, "Failed to create task")
|
||||
return
|
||||
}
|
||||
|
||||
// Load task with relationships
|
||||
models.GetDB().
|
||||
Preload("Project").
|
||||
Preload("AssignedTo").
|
||||
Preload("CreatedBy").
|
||||
First(&task, task.ID)
|
||||
|
||||
utils.SuccessResponse(c, http.StatusCreated, "Task created successfully", task)
|
||||
}
|
||||
|
||||
// GetTasks returns all tasks for a project
|
||||
func GetTasks(c *gin.Context) {
|
||||
project, exists := c.Get("project")
|
||||
if !exists {
|
||||
utils.ErrorResponse(c, http.StatusNotFound, "Project not found")
|
||||
return
|
||||
}
|
||||
|
||||
projectObj := project.(*models.Project)
|
||||
|
||||
var tasks []models.Task
|
||||
|
||||
if err := models.GetDB().
|
||||
Preload("AssignedTo").
|
||||
Preload("CreatedBy").
|
||||
Preload("Comments").
|
||||
Preload("Files").
|
||||
Preload("Subtasks").
|
||||
Preload("Labels").
|
||||
Where("project_id = ?", projectObj.ID).
|
||||
Order("position ASC, created_at DESC").
|
||||
Find(&tasks).Error; err != nil {
|
||||
utils.ErrorResponse(c, http.StatusInternalServerError, "Failed to fetch tasks")
|
||||
return
|
||||
}
|
||||
|
||||
utils.SuccessResponse(c, http.StatusOK, "Tasks retrieved successfully", tasks)
|
||||
}
|
||||
|
||||
// GetTask returns a specific task
|
||||
func GetTask(c *gin.Context) {
|
||||
project, _ := c.Get("project")
|
||||
projectObj := project.(*models.Project)
|
||||
|
||||
taskID := c.Param("task_id")
|
||||
if taskID == "" {
|
||||
utils.ErrorResponse(c, http.StatusBadRequest, "Task ID required")
|
||||
return
|
||||
}
|
||||
|
||||
var task models.Task
|
||||
if err := models.GetDB().
|
||||
Preload("Project").
|
||||
Preload("AssignedTo").
|
||||
Preload("CreatedBy").
|
||||
Preload("Comments").
|
||||
Preload("Comments.User").
|
||||
Preload("Files").
|
||||
Preload("Subtasks").
|
||||
Preload("Subtasks.AssignedTo").
|
||||
Preload("Labels").
|
||||
Where("id = ? AND project_id = ?", taskID, projectObj.ID).
|
||||
First(&task).Error; err != nil {
|
||||
utils.ErrorResponse(c, http.StatusNotFound, "Task not found")
|
||||
return
|
||||
}
|
||||
|
||||
utils.SuccessResponse(c, http.StatusOK, "Task retrieved successfully", task)
|
||||
}
|
||||
|
||||
// UpdateTask updates a task
|
||||
func UpdateTask(c *gin.Context) {
|
||||
project, _ := c.Get("project")
|
||||
projectObj := project.(*models.Project)
|
||||
|
||||
taskID := c.Param("task_id")
|
||||
if taskID == "" {
|
||||
utils.ErrorResponse(c, http.StatusBadRequest, "Task ID required")
|
||||
return
|
||||
}
|
||||
|
||||
var task models.Task
|
||||
if err := models.GetDB().
|
||||
Where("id = ? AND project_id = ?", taskID, projectObj.ID).
|
||||
First(&task).Error; err != nil {
|
||||
utils.ErrorResponse(c, http.StatusNotFound, "Task not found")
|
||||
return
|
||||
}
|
||||
|
||||
var req UpdateTaskRequest
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
utils.ValidationErrorResponse(c, gin.H{
|
||||
"error": err.Error(),
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
// Update fields
|
||||
if req.Title != "" {
|
||||
task.Title = req.Title
|
||||
}
|
||||
if req.Description != "" {
|
||||
task.Description = req.Description
|
||||
}
|
||||
if req.Status != "" {
|
||||
task.Status = req.Status
|
||||
if req.Status == "done" {
|
||||
task.MarkAsCompleted()
|
||||
}
|
||||
}
|
||||
if req.Priority != "" {
|
||||
task.Priority = req.Priority
|
||||
}
|
||||
if req.AssignedToID != nil {
|
||||
task.AssignedToID = req.AssignedToID
|
||||
}
|
||||
if req.Position != nil {
|
||||
task.Position = *req.Position
|
||||
}
|
||||
|
||||
// Parse due date if provided
|
||||
if req.DueDate != "" {
|
||||
if dueDate, err := time.Parse("2006-01-02T15:04:05Z07:00", req.DueDate); err == nil {
|
||||
task.DueDate = &dueDate
|
||||
}
|
||||
}
|
||||
|
||||
if err := models.GetDB().Save(&task).Error; err != nil {
|
||||
utils.ErrorResponse(c, http.StatusInternalServerError, "Failed to update task")
|
||||
return
|
||||
}
|
||||
|
||||
// Load updated task with relationships
|
||||
models.GetDB().
|
||||
Preload("AssignedTo").
|
||||
Preload("CreatedBy").
|
||||
Preload("Comments").
|
||||
Preload("Files").
|
||||
Preload("Subtasks").
|
||||
Preload("Labels").
|
||||
First(&task, task.ID)
|
||||
|
||||
utils.SuccessResponse(c, http.StatusOK, "Task updated successfully", task)
|
||||
}
|
||||
|
||||
// DeleteTask deletes a task
|
||||
func DeleteTask(c *gin.Context) {
|
||||
project, _ := c.Get("project")
|
||||
projectObj := project.(*models.Project)
|
||||
|
||||
taskID := c.Param("task_id")
|
||||
if taskID == "" {
|
||||
utils.ErrorResponse(c, http.StatusBadRequest, "Task ID required")
|
||||
return
|
||||
}
|
||||
|
||||
var task models.Task
|
||||
if err := models.GetDB().
|
||||
Where("id = ? AND project_id = ?", taskID, projectObj.ID).
|
||||
First(&task).Error; err != nil {
|
||||
utils.ErrorResponse(c, http.StatusNotFound, "Task not found")
|
||||
return
|
||||
}
|
||||
|
||||
if err := models.GetDB().Delete(&task).Error; err != nil {
|
||||
utils.ErrorResponse(c, http.StatusInternalServerError, "Failed to delete task")
|
||||
return
|
||||
}
|
||||
|
||||
utils.SuccessResponse(c, http.StatusOK, "Task deleted successfully", nil)
|
||||
}
|
||||
|
||||
// CreateSubtask creates a new subtask
|
||||
func CreateSubtask(c *gin.Context) {
|
||||
project, _ := c.Get("project")
|
||||
projectObj := project.(*models.Project)
|
||||
|
||||
taskID := c.Param("task_id")
|
||||
if taskID == "" {
|
||||
utils.ErrorResponse(c, http.StatusBadRequest, "Task ID required")
|
||||
return
|
||||
}
|
||||
|
||||
// Verify task exists and belongs to project
|
||||
var task models.Task
|
||||
if err := models.GetDB().
|
||||
Where("id = ? AND project_id = ?", taskID, projectObj.ID).
|
||||
First(&task).Error; err != nil {
|
||||
utils.ErrorResponse(c, http.StatusNotFound, "Task not found")
|
||||
return
|
||||
}
|
||||
|
||||
var req CreateSubtaskRequest
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
utils.ValidationErrorResponse(c, gin.H{
|
||||
"error": err.Error(),
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
subtask := models.Subtask{
|
||||
Title: req.Title,
|
||||
Description: req.Description,
|
||||
ParentTaskID: task.ID,
|
||||
AssignedToID: req.AssignedToID,
|
||||
Status: "todo",
|
||||
}
|
||||
|
||||
if err := models.GetDB().Create(&subtask).Error; err != nil {
|
||||
utils.ErrorResponse(c, http.StatusInternalServerError, "Failed to create subtask")
|
||||
return
|
||||
}
|
||||
|
||||
// Load subtask with relationships
|
||||
models.GetDB().
|
||||
Preload("AssignedTo").
|
||||
First(&subtask, subtask.ID)
|
||||
|
||||
utils.SuccessResponse(c, http.StatusCreated, "Subtask created successfully", subtask)
|
||||
}
|
||||
|
||||
// AddComment adds a comment to a task
|
||||
func AddComment(c *gin.Context) {
|
||||
user, exists := c.Get("user")
|
||||
if !exists {
|
||||
utils.ErrorResponse(c, http.StatusUnauthorized, "User not authenticated")
|
||||
return
|
||||
}
|
||||
|
||||
userObj := user.(*models.User)
|
||||
project, _ := c.Get("project")
|
||||
projectObj := project.(*models.Project)
|
||||
|
||||
taskID := c.Param("task_id")
|
||||
if taskID == "" {
|
||||
utils.ErrorResponse(c, http.StatusBadRequest, "Task ID required")
|
||||
return
|
||||
}
|
||||
|
||||
// Verify task exists and belongs to project
|
||||
var task models.Task
|
||||
if err := models.GetDB().
|
||||
Where("id = ? AND project_id = ?", taskID, projectObj.ID).
|
||||
First(&task).Error; err != nil {
|
||||
utils.ErrorResponse(c, http.StatusNotFound, "Task not found")
|
||||
return
|
||||
}
|
||||
|
||||
var req CreateCommentRequest
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
utils.ValidationErrorResponse(c, gin.H{
|
||||
"error": err.Error(),
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
comment := models.Comment{
|
||||
Content: req.Content,
|
||||
TaskID: task.ID,
|
||||
UserID: userObj.ID,
|
||||
}
|
||||
|
||||
if err := models.GetDB().Create(&comment).Error; err != nil {
|
||||
utils.ErrorResponse(c, http.StatusInternalServerError, "Failed to create comment")
|
||||
return
|
||||
}
|
||||
|
||||
// Load comment with user
|
||||
models.GetDB().
|
||||
Preload("User").
|
||||
First(&comment, comment.ID)
|
||||
|
||||
utils.SuccessResponse(c, http.StatusCreated, "Comment added successfully", comment)
|
||||
}
|
Reference in New Issue
Block a user