diff --git a/internal/handlers/groups_handlers.go b/internal/handlers/groups_handlers.go new file mode 100644 index 0000000..f8185cf --- /dev/null +++ b/internal/handlers/groups_handlers.go @@ -0,0 +1,107 @@ +package handlers + +import ( + "encoding/json" + "net/http" + "prak-03-todo/internal/db" + "strconv" + + "github.com/gorilla/mux" +) + +// CreateGroupHandler handles POST /groups +func CreateGroupHandler(w http.ResponseWriter, r *http.Request) { + var groupRequest struct { + GroupName string `json:"group_name"` + } + + err := json.NewDecoder(r.Body).Decode(&groupRequest) + if err != nil { + http.Error(w, "Invalid request body", http.StatusBadRequest) + return + } + + // Validate input + if groupRequest.GroupName == "" { + http.Error(w, "Group name is required", http.StatusBadRequest) + return + } + + // Create group using query function + group, err := db.CreateGroup(groupRequest.GroupName) + if err != nil { + http.Error(w, "Failed to create group", http.StatusInternalServerError) + return + } + + w.Header().Set("Content-Type", "application/json") + w.WriteHeader(http.StatusCreated) + json.NewEncoder(w).Encode(group) +} + +// RemoveGroupHandler handles DELETE /groups/{groupId} +func RemoveGroupHandler(w http.ResponseWriter, r *http.Request) { + vars := mux.Vars(r) + groupID, err := strconv.Atoi(vars["groupId"]) + if err != nil { + http.Error(w, "Invalid group ID", http.StatusBadRequest) + return + } + + // Delete group using query function + err = db.DeleteGroup(groupID) + if err != nil { + if err.Error() == "group not found" { + http.Error(w, "Group not found", http.StatusNotFound) + return + } + http.Error(w, "Failed to delete group", http.StatusInternalServerError) + return + } + + w.WriteHeader(http.StatusOK) + w.Write([]byte("Group ID " + vars["groupId"] + " Removed")) +} + +// GetGroupHandler handles GET /groups/{groupId} +func GetGroupHandler(w http.ResponseWriter, r *http.Request) { + vars := mux.Vars(r) + groupID, err := strconv.Atoi(vars["groupId"]) + if err != nil { + http.Error(w, "Invalid group ID", http.StatusBadRequest) + return + } + + // Get group using query function + group, err := db.GetGroupByID(groupID) + if err != nil { + if err.Error() == "group not found" { + http.Error(w, "Group not found", http.StatusNotFound) + return + } + http.Error(w, "Failed to fetch group", http.StatusInternalServerError) + return + } + + w.Header().Set("Content-Type", "application/json") + w.WriteHeader(http.StatusOK) + json.NewEncoder(w).Encode(group) +} + +// GetAllGroupsHandler handles GET /groups +func GetAllGroupsHandler(w http.ResponseWriter, r *http.Request) { + groups, err := db.GetAllGroups() + if err != nil { + http.Error(w, "Failed to fetch groups", http.StatusInternalServerError) + return + } + + w.Header().Set("Content-Type", "application/json") + w.WriteHeader(http.StatusOK) + json.NewEncoder(w).Encode(groups) +} + +// Home handles GET / +func Home(w http.ResponseWriter, r *http.Request) { + w.Write([]byte("Hello from Task Management API")) +} diff --git a/internal/handlers/tasks_handlers.go b/internal/handlers/tasks_handlers.go new file mode 100644 index 0000000..cbf48a9 --- /dev/null +++ b/internal/handlers/tasks_handlers.go @@ -0,0 +1,223 @@ +package handlers + +import ( + "encoding/json" + "net/http" + "prak-03-todo/internal/db" + "strconv" + + "github.com/gorilla/mux" +) + +// CreateTaskHandler handles POST /groups/{groupId}/tasks +func CreateTaskHandler(w http.ResponseWriter, r *http.Request) { + vars := mux.Vars(r) + groupID, err := strconv.Atoi(vars["groupId"]) + if err != nil { + http.Error(w, "Invalid group ID", http.StatusBadRequest) + return + } + + var taskRequest struct { + TaskName string `json:"task_name"` + TaskDescription *string `json:"task_description,omitempty"` + } + + err = json.NewDecoder(r.Body).Decode(&taskRequest) + if err != nil { + http.Error(w, "Invalid request body", http.StatusBadRequest) + return + } + + // Validate input + if taskRequest.TaskName == "" { + http.Error(w, "Task name is required", http.StatusBadRequest) + return + } + + // Verify group exists + _, err = db.GetGroupByID(groupID) + if err != nil { + if err.Error() == "group not found" { + http.Error(w, "Group not found", http.StatusNotFound) + return + } + http.Error(w, "Failed to verify group", http.StatusInternalServerError) + return + } + + // Create task using query function + task, err := db.CreateTask(taskRequest.TaskName, taskRequest.TaskDescription, groupID) + if err != nil { + http.Error(w, "Failed to create task", http.StatusInternalServerError) + return + } + + w.Header().Set("Content-Type", "application/json") + w.WriteHeader(http.StatusCreated) + json.NewEncoder(w).Encode(task) +} + +// DisplayTasksHandler handles GET /tasks +func DisplayTasksHandler(w http.ResponseWriter, r *http.Request) { + tasks, err := db.GetAllTasks() + if err != nil { + http.Error(w, "Failed to fetch tasks", http.StatusInternalServerError) + return + } + + w.Header().Set("Content-Type", "application/json") + w.WriteHeader(http.StatusOK) + json.NewEncoder(w).Encode(tasks) +} + +// DisplayTasksByGroupHandler handles GET /groups/{groupId}/tasks +func DisplayTasksByGroupHandler(w http.ResponseWriter, r *http.Request) { + vars := mux.Vars(r) + groupID, err := strconv.Atoi(vars["groupId"]) + if err != nil { + http.Error(w, "Invalid group ID", http.StatusBadRequest) + return + } + + // Verify group exists + _, err = db.GetGroupByID(groupID) + if err != nil { + if err.Error() == "group not found" { + http.Error(w, "Group not found", http.StatusNotFound) + return + } + http.Error(w, "Failed to verify group", http.StatusInternalServerError) + return + } + + // Get tasks for the group + tasks, err := db.GetTasksByGroupID(groupID) + if err != nil { + http.Error(w, "Failed to fetch tasks", http.StatusInternalServerError) + return + } + + w.Header().Set("Content-Type", "application/json") + w.WriteHeader(http.StatusOK) + json.NewEncoder(w).Encode(tasks) +} + +// GetTaskHandler handles GET /tasks/{taskId} +func GetTaskHandler(w http.ResponseWriter, r *http.Request) { + vars := mux.Vars(r) + taskID, err := strconv.Atoi(vars["taskId"]) + if err != nil { + http.Error(w, "Invalid task ID", http.StatusBadRequest) + return + } + + task, err := db.GetTaskByID(taskID) + if err != nil { + if err.Error() == "task not found" { + http.Error(w, "Task not found", http.StatusNotFound) + return + } + http.Error(w, "Failed to fetch task", http.StatusInternalServerError) + return + } + + w.Header().Set("Content-Type", "application/json") + w.WriteHeader(http.StatusOK) + json.NewEncoder(w).Encode(task) +} + +// UpdateTaskHandler handles PUT /tasks/{taskId} +func UpdateTaskHandler(w http.ResponseWriter, r *http.Request) { + vars := mux.Vars(r) + taskID, err := strconv.Atoi(vars["taskId"]) + if err != nil { + http.Error(w, "Invalid task ID", http.StatusBadRequest) + return + } + + var taskRequest struct { + TaskName string `json:"task_name"` + TaskDescription *string `json:"task_description,omitempty"` + } + + err = json.NewDecoder(r.Body).Decode(&taskRequest) + if err != nil { + http.Error(w, "Invalid request body", http.StatusBadRequest) + return + } + + // Validate input + if taskRequest.TaskName == "" { + http.Error(w, "Task name is required", http.StatusBadRequest) + return + } + + // Update task using query function + err = db.UpdateTask(taskID, taskRequest.TaskName, taskRequest.TaskDescription) + if err != nil { + if err.Error() == "task not found" { + http.Error(w, "Task not found", http.StatusNotFound) + return + } + http.Error(w, "Failed to update task", http.StatusInternalServerError) + return + } + + // Get updated task + task, err := db.GetTaskByID(taskID) + if err != nil { + http.Error(w, "Failed to fetch updated task", http.StatusInternalServerError) + return + } + + w.Header().Set("Content-Type", "application/json") + w.WriteHeader(http.StatusOK) + json.NewEncoder(w).Encode(task) +} + +// MarkTaskDoneHandler handles PUT /tasks/{taskId}/done +func MarkTaskDoneHandler(w http.ResponseWriter, r *http.Request) { + vars := mux.Vars(r) + taskID, err := strconv.Atoi(vars["taskId"]) + if err != nil { + http.Error(w, "Invalid task ID", http.StatusBadRequest) + return + } + + err = db.MarkTaskDone(taskID) + if err != nil { + if err.Error() == "task not found" { + http.Error(w, "Task not found", http.StatusNotFound) + return + } + http.Error(w, "Failed to mark task as done", http.StatusInternalServerError) + return + } + + w.WriteHeader(http.StatusOK) + w.Write([]byte("Task ID " + vars["taskId"] + " Marked as Done")) +} + +// RemoveTaskHandler handles DELETE /tasks/{taskId} +func RemoveTaskHandler(w http.ResponseWriter, r *http.Request) { + vars := mux.Vars(r) + taskID, err := strconv.Atoi(vars["taskId"]) + if err != nil { + http.Error(w, "Invalid task ID", http.StatusBadRequest) + return + } + + err = db.DeleteTask(taskID) + if err != nil { + if err.Error() == "task not found" { + http.Error(w, "Task not found", http.StatusNotFound) + return + } + http.Error(w, "Failed to delete task", http.StatusInternalServerError) + return + } + + w.WriteHeader(http.StatusOK) + w.Write([]byte("Task ID " + vars["taskId"] + " Removed")) +}