From 9b22f9561b9521e63b2579a908a27cdf8da9afba Mon Sep 17 00:00:00 2001 From: Yuri Mauricio Date: Sun, 19 Jul 2026 00:06:45 +0800 Subject: [PATCH] Implement todo API --- backend/controllers/todoController.js | 129 ++++++++++++++++++++++++++ backend/index.js | 19 ++-- backend/middleware/errorHandler.js | 10 ++ backend/package.json | 4 + backend/routes/todoRoutes.js | 17 ++++ 5 files changed, 171 insertions(+), 8 deletions(-) create mode 100644 backend/controllers/todoController.js create mode 100644 backend/middleware/errorHandler.js create mode 100644 backend/routes/todoRoutes.js diff --git a/backend/controllers/todoController.js b/backend/controllers/todoController.js new file mode 100644 index 00000000..fe80077b --- /dev/null +++ b/backend/controllers/todoController.js @@ -0,0 +1,129 @@ +// In-memory storage +let todos = []; +let currentId = 1; + +// Get all todos +const getAllTodos = (req, res) => { + res.json({ + success: true, + data: todos, + count: todos.length + }); +}; + +// Get single todo by ID +const getTodoById = (req, res) => { + const id = parseInt(req.params.id); + const todo = todos.find(t => t.id === id); + + if (!todo) { + return res.status(404).json({ + success: false, + error: 'Todo not found' + }); + } + + res.json({ + success: true, + data: todo + }); +}; + +// Create a new todo +const createTodo = (req, res) => { + const { title } = req.body; + + // Title is required + if (!title || title.trim() === '') { + return res.status(400).json({ + success: false, + error: 'Title is required' + }); + } + + const newTodo = { + id: currentId++, + title: title.trim(), + completed: false, + createdAt: new Date().toISOString() + }; + + todos.push(newTodo); + + res.status(201).json({ + success: true, + data: newTodo, + message: 'Todo created successfully' + }); +}; + +// Update a todo +const updateTodo = (req, res) => { + const id = parseInt(req.params.id); + const { title, completed } = req.body; + + const todoIndex = todos.findIndex(t => t.id === id); + + if (todoIndex === -1) { + return res.status(404).json({ + success: false, + error: 'Todo not found' + }); + } + + // Update title if provided + if (title !== undefined) { + if (title.trim() === '') { + return res.status(400).json({ + success: false, + error: 'Title cannot be empty' + }); + } + todos[todoIndex].title = title.trim(); + } + + // Update completed status if provided + if (completed !== undefined) { + if (typeof completed !== 'boolean') { + return res.status(400).json({ + success: false, + error: 'Completed must be true or false' + }); + } + todos[todoIndex].completed = completed; + } + + res.json({ + success: true, + data: todos[todoIndex], + message: 'Todo updated successfully' + }); +}; + +// Delete a todo +const deleteTodo = (req, res) => { + const id = parseInt(req.params.id); + const todoIndex = todos.findIndex(t => t.id === id); + + if (todoIndex === -1) { + return res.status(404).json({ + success: false, + error: 'Todo not found' + }); + } + + todos.splice(todoIndex, 1); + + res.json({ + success: true, + message: 'Todo deleted successfully' + }); +}; + +module.exports = { + getAllTodos, + getTodoById, + createTodo, + updateTodo, + deleteTodo +}; \ No newline at end of file diff --git a/backend/index.js b/backend/index.js index ff6a6a3b..c75b5038 100644 --- a/backend/index.js +++ b/backend/index.js @@ -1,13 +1,16 @@ -const express = require("express"); +const express = require('express'); +const todoRoutes = require('./routes/todoRoutes'); +const errorHandler = require('./middleware/errorHandler'); + const app = express(); const PORT = process.env.PORT || 4000; -// Basic route -app.get("/", (req, res) => { - res.send("Hello from Express!"); -}); +app.use(express.json()); + +app.use('/api/todos', todoRoutes); + +app.use(errorHandler); -// Start server app.listen(PORT, () => { - console.log(`Backend is running on http://localhost:${PORT}`); -}); + console.log(`Server running on http://localhost:${PORT}`); +}); \ No newline at end of file diff --git a/backend/middleware/errorHandler.js b/backend/middleware/errorHandler.js new file mode 100644 index 00000000..273807d1 --- /dev/null +++ b/backend/middleware/errorHandler.js @@ -0,0 +1,10 @@ +const errorHandler = (err, req, res, next) => { + console.error(err.stack); + + res.status(500).json({ + success: false, + error: 'Something went wrong on the server' + }); +}; + +module.exports = errorHandler; \ No newline at end of file diff --git a/backend/package.json b/backend/package.json index c85981fa..e44f304a 100644 --- a/backend/package.json +++ b/backend/package.json @@ -5,6 +5,10 @@ "start": "node index.js" }, "dependencies": { + "cors": "^2.8.6", "express": "^4.18.2" + }, + "devDependencies": { + "nodemon": "^3.1.14" } } diff --git a/backend/routes/todoRoutes.js b/backend/routes/todoRoutes.js new file mode 100644 index 00000000..58491bd2 --- /dev/null +++ b/backend/routes/todoRoutes.js @@ -0,0 +1,17 @@ +const express = require('express'); +const router = express.Router(); +const { + getAllTodos, + getTodoById, + createTodo, + updateTodo, + deleteTodo +} = require('../controllers/todoController'); + +router.get('/', getAllTodos); +router.get('/:id', getTodoById); +router.post('/', createTodo); +router.put('/:id', updateTodo); +router.delete('/:id', deleteTodo); + +module.exports = router; \ No newline at end of file