Skip to content

Instantly share code, notes, and snippets.

@ganeshagrawal55
Created January 17, 2024 13:08
Show Gist options
  • Save ganeshagrawal55/8e5f404372a1113f26cd10876c6ed25e to your computer and use it in GitHub Desktop.
Save ganeshagrawal55/8e5f404372a1113f26cd10876c6ed25e to your computer and use it in GitHub Desktop.
Task Ayush - Todo Rest Service
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