From b557161917908184d77b19239ebd5251bd2be44f Mon Sep 17 00:00:00 2001 From: leonard Date: Sun, 28 Jun 2026 21:42:41 +0800 Subject: [PATCH] Todo api --- backend/index.js | 8 ++++ backend/routes/todos.js | 81 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 89 insertions(+) create mode 100644 backend/routes/todos.js diff --git a/backend/index.js b/backend/index.js index ff6a6a3b..b6890a5e 100644 --- a/backend/index.js +++ b/backend/index.js @@ -1,12 +1,20 @@ +// file: index.js + const express = require("express"); const app = express(); const PORT = process.env.PORT || 4000; +const todosRoutes = require('./routes/todos'); +app.use(express.json()) // lets us read JSON from req.body + // Basic route app.get("/", (req, res) => { res.send("Hello from Express!"); }); +// all todo routes under /api/todos +app.use('/api/todos', todosRoutes); + // Start server app.listen(PORT, () => { console.log(`Backend is running on http://localhost:${PORT}`); diff --git a/backend/routes/todos.js b/backend/routes/todos.js new file mode 100644 index 00000000..8dfa8c23 --- /dev/null +++ b/backend/routes/todos.js @@ -0,0 +1,81 @@ +// file: routes/todos.js + +const express = require('express'); +const router = express.Router(); + +// Data in memory +let todos = [ + { id: 1, title: "Todo one", completed: false, createdAt: new Date().toISOString() }, + { id: 2, title: "Todo two", completed: false, createdAt: new Date().toISOString() } +]; +let nextId = 3; // next id to give a todo(auto increment) + +// GET /api/todos - get all todos +router.get('/', (req, res) => { + return res.status(200).json(todos); +}); + +// GET /api/todos/:id - get one todo by id +router.get('/:id', (req, res) => { + const task = todos.find(task => task.id === Number(req.params.id)); + + // no todo with that id + if (!task) { + return res.status(404).json({ error: "Task not found."}); + } + + return res.json(task); +}); + +// POST /api/todos - create a new todo +router.post('/', (req, res) => { + const { title } = req.body; + + // check if title exist and be text + if (!title || typeof title !== 'string') { + return res.status(400).json({ error: "Title is required and title must be a string." }); + } + + // build the new todo + const newTask = { id: nextId++, title: title, completed: false , createdAt: new Date().toISOString() }; + + // save new todo + todos.push(newTask); + + return res.status(201).json(newTask); +}); + +// PUT /api/todos/:id - update a todo +router.put('/:id', (req, res) => { + const task = todos.find(task => task.id === Number(req.params.id)); + + // no todo with that id + if (!task) { + return res.status(404).json({ error: "Task not found." }); + } + + const { title, completed } = req.body; + + // only update the fields that were sent + if (title !== undefined) task.title = title; + if (completed !== undefined) task.completed = completed; + + return res.status(200).json(task); +}); + +// DELETE /api/todos/:id - delete a todo +router.delete('/:id', (req, res) => { + const taskIndex = todos.findIndex(task => task.id === Number(req.params.id)); + + // no todo with that id + if (taskIndex === -1) { + return res.status(404).json({ error: "Task not found." }); + } + + // remove it from the array + const deletedTask = todos.splice(taskIndex, 1)[0]; + + return res.status(200).json({ message: "Task deleted", task: deletedTask }); +}); + +module.exports = router;