feat: Full-stack task manager with React+Tailwind, Express, MongoDB, JWT auth#6
Conversation
…JWT auth - Backend: Express server with MongoDB (Mongoose), JWT authentication, task CRUD API with validation (express-validator) - Frontend: React 18 + Tailwind CSS + Vite, auth pages (login/register), task dashboard with create/edit/delete, status filters, due dates - Models: User (bcrypt hashed passwords) and Task (title, description, status, dueDate, user reference) - Auth: JWT middleware, register/login/me endpoints - README: setup instructions, API docs, Vercel + Render deployment guide
🤖 Devin AI EngineerI'll be helping with this pull request! Here's what you should know: ✅ I will automatically:
Note: I can only respond to comments from users who have write access to this repository. ⚙️ Control Options:
|
| (error) => { | ||
| if (error.response?.status === 401) { | ||
| localStorage.removeItem('token'); | ||
| window.location.href = '/login'; | ||
| } |
There was a problem hiding this comment.
🔴 401 response interceptor hijacks login failures, causing page reload instead of showing error message
The Axios response interceptor at frontend/src/services/api.js:18-21 catches all 401 responses and does window.location.href = '/login', causing a full page reload. However, the login endpoint (backend/routes/auth.js:55,60) returns 401 for invalid credentials. When a user enters a wrong password on the login page, the interceptor fires before the Login component's catch block (frontend/src/pages/Login.jsx:21-22) can display the error message. The result: the page reloads to /login instead of showing "Invalid credentials", making it impossible for users to see why login failed.
Detailed flow
- User submits wrong password on
/login POST /api/auth/loginreturns401 { message: 'Invalid credentials' }- Axios response interceptor runs: removes token from localStorage, sets
window.location.href = '/login' Promise.reject(error)is returned, but the navigation triggers a full page reload- The Login component's
setError(...)either never executes or is immediately lost to the reload
Prompt for agents
The 401 response interceptor in frontend/src/services/api.js should not redirect on 401 responses from authentication endpoints (/auth/login, /auth/register). These endpoints return 401 to mean "invalid credentials", not "expired token".
Approach 1: Check the request URL before redirecting. For example, skip the redirect if the request URL includes '/auth/login' or '/auth/register'.
Approach 2: Only redirect if a token was previously stored in localStorage (i.e., the user was logged in and the token expired), and skip the redirect otherwise.
Either approach would allow the Login and Register components to properly catch and display the error message to the user.
Was this helpful? React with 👍 or 👎 to provide feedback.
| const todoCount = tasks.filter((t) => t.status === 'todo').length; | ||
| const inProgressCount = tasks.filter((t) => t.status === 'in-progress').length; | ||
| const doneCount = tasks.filter((t) => t.status === 'done').length; |
There was a problem hiding this comment.
🟡 Dashboard status counts are computed from filtered task list, showing misleading zeros
In Dashboard.jsx, the status counts (todoCount, inProgressCount, doneCount at lines 59-61) are computed from the tasks array, which is fetched with the currently active status filter (line 22-24). When a user filters by e.g. "In Progress", the API only returns in-progress tasks, so todoCount and doneCount will both show 0 in the stats panel — even though the user may have many such tasks. The stats cards give no indication they are filtered, making them misleading.
Was this helpful? React with 👍 or 👎 to provide feedback.
Summary
Replaces the in-memory vanilla JS todo prototype with a production-oriented full-stack task manager.
Backend (
backend/): Express + MongoDB (Mongoose) + JWT authenticationUsermodel with bcrypt-hashed passwords;Taskmodel with title, description, status (todo/in-progress/done), dueDate, and user reference/me— returns signed JWT on successmiddleware/auth.jsFrontend (
frontend/): React 18 + Vite + Tailwind CSS + React Router v6AuthContextmanages JWT in localStorage; Axios interceptors attach token and redirect on 401Other: Updated README with setup instructions, env var tables, API endpoint reference, and Vercel/Render deployment guide.
Review & Testing Checklist for Human
backend/middleware/auth.jsandbackend/routes/auth.js— confirm tokens are not leaking sensitive data and password is excluded from responses (select: falseon User model)backend/routes/tasks.jsfilter byuser: req.user.id— a user must not be able to read/update/delete another user's tasksfrontend/src/services/api.js) doeswindow.location.href = '/login'on 401. Verify this doesn't cause an infinite reload if/auth/mefires on the login page (thePublicRoutewrapper should prevent this, but worth confirming)cors({ origin: process.env.CLIENT_URL || '*' })defaults to open. ConfirmCLIENT_URLis set correctly when deploying to Render/VercelNotes
npm run build) and lint (npm run lint) pass cleanly (1 non-blocking warning about fast refresh in AuthContext)Link to Devin session: https://partner-workshops.devinenterprise.com/sessions/dc05c804f6ba473bba92b3d4e49136e1