feat: Add Projects management feature with CRUD API and frontend UI#460
feat: Add Projects management feature with CRUD API and frontend UI#460devin-ai-integration[bot] wants to merge 1 commit intomainfrom
Conversation
- Add projects table to database with name, description, client_id, start_date, status fields - Add Joi validation schemas for project creation and updates - Add CRUD API endpoints at /api/projects with client ownership verification - Add comprehensive backend tests (34 test cases) - Add ProjectsPage React component with MUI table, create/edit dialog, status chips - Add project types and API client methods in frontend - Add Projects navigation item in sidebar layout - Support active/completed/on-hold status with color-coded chips - Support optional client assignment with dropdown selector
🤖 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:
|
|
|
||
| const payload = { | ||
| name: formData.name, | ||
| description: formData.description || undefined, |
There was a problem hiding this comment.
🟡 Users cannot clear project description when editing due to || undefined coercion
In handleSubmit, the payload is constructed with description: formData.description || undefined at line 161. When a user edits a project and clears the description field, formData.description becomes '', which is falsy, so it gets coerced to undefined. Since JSON.stringify strips undefined values, the description key is omitted from the request body entirely. The backend's updateProjectSchema then doesn't see a description field, so performUpdate (backend/src/routes/projects.js:200-203) skips updating it, leaving the old description in the database. In contrast, client_id and start_date use || null which correctly serializes and allows clearing those fields. The fix is to use description: formData.description || null (and add .allow(null) to the Joi schema) or simply send description: formData.description since the backend already handles empty strings via value.description || null in performUpdate, and the Joi schema already has .allow('').
| description: formData.description || undefined, | |
| description: formData.description || '', |
Was this helpful? React with 👍 or 👎 to provide feedback.
Summary
Adds a full "Projects" management feature to the timesheet app, covering backend API and frontend UI. Each project has a name, description, optional client assignment, start date, and status (
active/completed/on-hold).Backend:
projectstable in SQLite schema with foreign keys toclientsandusers, plus indexes onuser_email,client_id, andstatusprojectSchema,updateProjectSchema) with status enum constraint/api/projects(list, get, create, update, delete, delete-all) following the existing clients patternclient_idto a projectclients.test.jsstructureFrontend:
Project,CreateProjectRequest,UpdateProjectRequestTypeScript interfacesProjectsPagecomponent with MUI table, create/edit dialog (client dropdown, status select, date picker), color-coded status chips, and bulk delete/projectsand sidebar nav entry withAccountTreeiconReview & Testing Checklist for Human
LEFT JOIN clientsqueries inprojects.js(GET list, GET by id, POST retrieve, PUT retrieve) have not been validated against a real database. Spin up the backend and create/list projects to confirm the join works andclient_namepopulates correctly.client_idis set toNULL(viaON DELETE SET NULL) and the UI handles the now-missing client gracefully.start_dateround-trip — create a project with a start date, edit it, clear the date, and save. Confirm the empty-string-to-null conversion works correctly through Joi validation and the DB layer.shrinklabel behavior.CreateProjectRequest/UpdateProjectRequesttypes — these are defined intypes/api.tsbut the API client methods use inline types instead; consider whether to wire them up or remove the unused interfaces.Notes
projects.jstoclients.js,ProjectsPage.tsxtoClientsPage.tsx).insertProjectandperformUpdateinprojects.jsare module-level functions (not on the router) to keep the route handlers readable; this diverges slightly from the clients pattern which inlines everything.Link to Devin session: https://partner-workshops.devinenterprise.com/sessions/a2c863d12c03470d997d617cb5941a28