package main import ( "encoding/json" "log" "net/http" "strconv" "sync" "time" "github.com/go-chi/chi/v5" "github.com/go-chi/chi/v5/middleware" "github.com/go-chi/cors" ) type Task struct { ID int `json:"id"` Title string `json:"title"` Description string `json:"description"` Status string `json:"status"` Priority string `json:"priority"` CreatedAt time.Time `json:"createdAt"` UpdatedAt time.Time `json:"updatedAt"` } type TaskStore struct { mu sync.RWMutex tasks map[int]Task nextID int } func NewTaskStore() *TaskStore { return &TaskStore{ tasks: make(map[int]Task), nextID: 1, } } func (s *TaskStore) GetAll() []Task { s.mu.RLock() defer s.mu.RUnlock() tasks := make([]Task, 0, len(s.tasks)) for _, task := range s.tasks { tasks = append(tasks, task) } return tasks } func (s *TaskStore) Get(id int) (Task, bool) { s.mu.RLock() defer s.mu.RUnlock() task, ok := s.tasks[id] return task, ok } func (s *TaskStore) Create(title, description, status, priority string) Task { s.mu.Lock() defer s.mu.Unlock() if status == "" { status = "pending" } if priority == "" { priority = "medium" } now := time.Now() task := Task{ ID: s.nextID, Title: title, Description: description, Status: status, Priority: priority, CreatedAt: now, UpdatedAt: now, } s.tasks[s.nextID] = task s.nextID++ return task } func (s *TaskStore) Delete(id int) bool { s.mu.Lock() defer s.mu.Unlock() if _, ok := s.tasks[id]; ok { delete(s.tasks, id) return true } return false } type APIResponse struct { Success bool `json:"success"` Data interface{} `json:"data,omitempty"` Error string `json:"error,omitempty"` } func jsonResponse(w http.ResponseWriter, status int, resp APIResponse) { w.Header().Set("Content-Type", "application/json") w.WriteHeader(status) json.NewEncoder(w).Encode(resp) } func main() { store := NewTaskStore() // Add some sample tasks store.Create("Set up development environment", "Install all necessary tools and dependencies for the project", "completed", "high") store.Create("Design database schema", "Create the initial database schema for the application", "in-progress", "high") store.Create("Write unit tests", "Add comprehensive unit tests for all core functionality", "pending", "medium") store.Create("Deploy to production", "Set up CI/CD pipeline and deploy to cloud", "pending", "low") r := chi.NewRouter() // Middleware r.Use(middleware.Logger) r.Use(middleware.Recoverer) r.Use(cors.Handler(cors.Options{ AllowedOrigins: []string{"http://localhost:3000", "http://localhost:8080", "*"}, AllowedMethods: []string{"GET", "POST", "PUT", "DELETE", "OPTIONS"}, AllowedHeaders: []string{"Accept", "Authorization", "Content-Type", "X-CSRF-Token"}, ExposedHeaders: []string{"Link"}, AllowCredentials: true, MaxAge: 300, })) // Routes r.Route("/api", func(r chi.Router) { // Health check r.Get("/health", func(w http.ResponseWriter, r *http.Request) { jsonResponse(w, http.StatusOK, APIResponse{Success: true, Data: "OK"}) }) // Hello World r.Get("/hello", func(w http.ResponseWriter, r *http.Request) { jsonResponse(w, http.StatusOK, APIResponse{Success: true, Data: "Hello World"}) }) r.Get("/tasks", func(w http.ResponseWriter, r *http.Request) { tasks := store.GetAll() jsonResponse(w, http.StatusOK, APIResponse{Success: true, Data: tasks}) }) r.Post("/tasks", func(w http.ResponseWriter, r *http.Request) { var input struct { Title string `json:"title"` Description string `json:"description"` Status string `json:"status"` Priority string `json:"priority"` } if err := json.NewDecoder(r.Body).Decode(&input); err != nil { jsonResponse(w, http.StatusBadRequest, APIResponse{Success: false, Error: "Invalid request body"}) return } if input.Title == "" { jsonResponse(w, http.StatusBadRequest, APIResponse{Success: false, Error: "Title is required"}) return } task := store.Create(input.Title, input.Description, input.Status, input.Priority) jsonResponse(w, http.StatusCreated, APIResponse{Success: true, Data: task}) }) r.Get("/tasks/{id}", func(w http.ResponseWriter, r *http.Request) { idStr := chi.URLParam(r, "id") id, err := strconv.Atoi(idStr) if err != nil { jsonResponse(w, http.StatusBadRequest, APIResponse{Success: false, Error: "Invalid task ID"}) return } task, ok := store.Get(id) if !ok { jsonResponse(w, http.StatusNotFound, APIResponse{Success: false, Error: "Task not found"}) return } jsonResponse(w, http.StatusOK, APIResponse{Success: true, Data: task}) }) r.Delete("/tasks/{id}", func(w http.ResponseWriter, r *http.Request) { idStr := chi.URLParam(r, "id") id, err := strconv.Atoi(idStr) if err != nil { jsonResponse(w, http.StatusBadRequest, APIResponse{Success: false, Error: "Invalid task ID"}) return } if !store.Delete(id) { jsonResponse(w, http.StatusNotFound, APIResponse{Success: false, Error: "Task not found"}) return } jsonResponse(w, http.StatusOK, APIResponse{Success: true, Data: "Task deleted"}) }) }) // Health check r.Get("/health", func(w http.ResponseWriter, r *http.Request) { jsonResponse(w, http.StatusOK, APIResponse{Success: true, Data: "OK"}) }) port := ":8080" log.Printf("Backend server starting on %s", port) if err := http.ListenAndServe(port, r); err != nil { log.Fatal(err) } }