Created
January 17, 2024 13:08
-
-
Save ganeshagrawal55/8e5f404372a1113f26cd10876c6ed25e to your computer and use it in GitHub Desktop.
Task Ayush - Todo Rest Service
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package main | |
import ( | |
"encoding/json" | |
"fmt" | |
"log" | |
"math/rand" | |
"net/http" | |
"sort" | |
"strconv" | |
"time" | |
"github.com/gorilla/mux" | |
) | |
/* | |
Todo: | |
Task: Text | |
Complected: Bool | |
CreatedAt: timestamp | |
UpdatedAt: timestamp | |
create todo | |
edit todo | |
mark/unmark completed todo | |
list todos | |
delete todo | |
list todos with filter | |
*/ | |
type Todo struct { | |
ID int64 `json:"id"` | |
Task string `json:"task"` | |
Completed bool `json:"completed"` | |
CreatedAt time.Time `json:"created_at"` | |
UpdatedAt time.Time `json:"updated_at"` | |
} | |
func main() { | |
var db = make(map[int64]Todo) | |
SeedTodos(db) | |
router := mux.NewRouter() | |
todoService := NewTodoService(db) | |
router.HandleFunc("/todos/{id}", todoService.UpdateHandler).Methods("PATCH") | |
router.HandleFunc("/todos", todoService.CreateHandler).Methods("POST") | |
router.HandleFunc("/todos", todoService.ListHandler).Methods("GET") | |
router.HandleFunc("/ping", func(w http.ResponseWriter, r *http.Request) { | |
w.Write([]byte("pong")) | |
}) | |
log.Fatal(http.ListenAndServe(":8080", router)) | |
} | |
type TodoService struct { | |
db map[int64]Todo | |
} | |
func NewTodoService(db map[int64]Todo) ITodoService { | |
return &TodoService{ | |
db: db, | |
} | |
} | |
type ITodoService interface { | |
CreateHandler(resp http.ResponseWriter, req *http.Request) | |
ListHandler(resp http.ResponseWriter, req *http.Request) | |
UpdateHandler(resp http.ResponseWriter, req *http.Request) | |
// DeleteHandler(resp http.ResponseWriter, req *http.Request) | |
// MarkTodoHandler(resp http.ResponseWriter, req *http.Request) | |
} | |
// Create a new todo | |
func (t *TodoService) CreateHandler(resp http.ResponseWriter, req *http.Request) { | |
var todo Todo | |
if err := json.NewDecoder(req.Body).Decode(&todo); err != nil { | |
writeError(resp, http.StatusBadRequest, err) | |
return | |
} | |
if todo.Task == "" { | |
writeError(resp, http.StatusBadRequest, fmt.Errorf("task is required")) | |
} | |
todo.CreatedAt = time.Now() | |
todo.UpdatedAt = time.Now() | |
todo.ID = int64(len(t.db)) + rand.Int63n(100) | |
todo.Completed = false | |
t.db[todo.ID] = todo | |
writeResponse(resp, http.StatusCreated, todo) | |
} | |
func (t *TodoService) ListHandler(resp http.ResponseWriter, req *http.Request) { | |
var todos []Todo = make([]Todo, 0, len(t.db)) | |
for _, todo := range t.db { | |
todos = append(todos, todo) | |
} | |
sort.Slice(todos, func(i, j int) bool { | |
return todos[i].CreatedAt.After(todos[j].CreatedAt) | |
}) | |
writeResponse(resp, http.StatusOK, todos) | |
} | |
func (t *TodoService) UpdateHandler(resp http.ResponseWriter, req *http.Request) { | |
params := mux.Vars(req) | |
idStr, ok := params["id"] | |
if !ok { | |
writeError(resp, http.StatusBadRequest, fmt.Errorf("id is required")) | |
return | |
} | |
id, err := strconv.ParseInt(idStr, 10, 64) | |
if err != nil { | |
writeError(resp, http.StatusBadRequest, fmt.Errorf("id is invalid")) | |
return | |
} | |
var todo Todo | |
if err := json.NewDecoder(req.Body).Decode(&todo); err != nil { | |
writeError(resp, http.StatusBadRequest, err) | |
return | |
} | |
if todo.Task == "" { | |
writeError(resp, http.StatusBadRequest, fmt.Errorf("task is required")) | |
} | |
if _, ok := t.db[id]; !ok { | |
writeError(resp, http.StatusNotFound, fmt.Errorf("id is invalid")) | |
return | |
} | |
todo.ID = t.db[id].ID | |
todo.CreatedAt = t.db[id].CreatedAt | |
todo.Completed = t.db[id].Completed | |
todo.UpdatedAt = time.Now() | |
t.db[todo.ID] = todo | |
writeResponse(resp, http.StatusOK, todo) | |
} | |
func writeResponse(resp http.ResponseWriter, statusCode int, body interface{}) { | |
resp.WriteHeader(statusCode) | |
json.NewEncoder(resp).Encode(body) | |
} | |
func writeError(resp http.ResponseWriter, statusCode int, err error) { | |
resp.WriteHeader(statusCode) | |
json.NewEncoder(resp).Encode(map[string]string{ | |
"error": err.Error(), | |
}) | |
} | |
func SeedTodos(db map[int64]Todo) { | |
db[1] = Todo{ | |
ID: 1, | |
Task: "Buy Milk", | |
Completed: false, | |
CreatedAt: time.Now(), | |
UpdatedAt: time.Now(), | |
} | |
db[2] = Todo{ | |
ID: 2, | |
Task: "Buy Eggs", | |
Completed: false, | |
CreatedAt: time.Now(), | |
UpdatedAt: time.Now(), | |
} | |
db[3] = Todo{ | |
ID: 3, | |
Task: "Buy Bread", | |
Completed: false, | |
CreatedAt: time.Now(), | |
UpdatedAt: time.Now(), | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment