Skip to content

feat: Add Projects management feature with CRUD API and UI#475

Open
devin-ai-integration[bot] wants to merge 1 commit intomainfrom
devin/1776165587-add-projects-feature
Open

feat: Add Projects management feature with CRUD API and UI#475
devin-ai-integration[bot] wants to merge 1 commit intomainfrom
devin/1776165587-add-projects-feature

Conversation

@devin-ai-integration
Copy link
Copy Markdown
Contributor

@devin-ai-integration devin-ai-integration bot commented Apr 14, 2026

Summary

Adds a full "Projects" management feature to the timesheet app, following existing codebase patterns established by the Clients feature.

Backend:

  • New projects table in SQLite schema with fields: name, description, client_id (FK → clients, ON DELETE SET NULL), start_date, status (active/completed/on-hold), user_email, timestamps
  • Joi validation schemas (projectSchema, updateProjectSchema) with status enum validation
  • Full CRUD REST API at /api/projects (list, get, create, update, delete, delete-all)
  • Projects are scoped to the authenticated user; responses include client_name via LEFT JOIN
  • 30 unit tests mirroring the clients test structure

Frontend:

  • Project, CreateProjectRequest, UpdateProjectRequest TypeScript types
  • API client methods for all project CRUD operations
  • ProjectsPage with MUI table, create/edit dialog (client dropdown, status select, date picker), color-coded status chips, bulk delete
  • Route at /projects and sidebar nav item

Review & Testing Checklist for Human

  • Verify client_id FK behavior: The backend does NOT validate that client_id references an existing client when creating/updating a project — it only relies on the DB foreign key constraint. Confirm this is acceptable or if an explicit existence check should be added (like workEntries does for client_id)
  • Test the UI end-to-end: No manual browser testing was performed. Create a project with/without a client assignment, edit it, change status, delete it, and verify the table updates correctly
  • Check ON DELETE SET NULL behavior: When a client is deleted, associated projects should have client_id set to NULL (not cascade-deleted). Verify this matches your intended behavior
  • Date handling: The start_date field uses <input type="date"> which produces locale-dependent date strings. Verify dates display correctly across timezones

Notes

  • The database is in-memory so no migration is needed — the schema is created fresh on each server start.
  • Status values (active, completed, on-hold) are enforced at the Joi validation layer only, not via a SQLite CHECK constraint, consistent with how existing fields are handled.
  • All existing tests continue to pass (192 total including the 30 new project tests). TypeScript and ESLint checks pass cleanly.

Link to Devin session: https://partner-workshops.devinenterprise.com/sessions/807671b41b9a4aa182c652463e0cf4e1


Open with Devin

- Add projects table to database schema (name, description, client_id, start_date, status)
- Add Joi validation schemas for project create/update
- Add full CRUD REST API endpoints at /api/projects
- Add comprehensive backend tests (30 test cases)
- Add Project TypeScript types and API client methods
- Add ProjectsPage with table view, create/edit dialog, status chips
- Add Projects navigation item in sidebar layout
- Wire up /projects route in App.tsx
@devin-ai-integration
Copy link
Copy Markdown
Contributor Author

🤖 Devin AI Engineer

I'll be helping with this pull request! Here's what you should know:

✅ I will automatically:

  • Address comments on this PR. Add '(aside)' to your comment to have me ignore it.
  • Look at CI failures and help fix them

Note: I can only respond to comments from users who have write access to this repository.

⚙️ Control Options:

  • Disable automatic comment and CI monitoring

Copy link
Copy Markdown
Contributor Author

@devin-ai-integration devin-ai-integration bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Devin Review found 1 potential issue.

View 5 additional findings in Devin Review.

Open in Devin Review


const payload = {
name: formData.name,
description: formData.description || undefined,
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Clearing project description in edit form has no effect because undefined is stripped from JSON payload

In handleSubmit, description: formData.description || undefined (line 165) converts an empty description string to undefined. When JSON.stringify serializes the payload for the HTTP request, undefined values are stripped entirely. This means the backend never receives a description field, so value.description !== undefined at backend/src/routes/projects.js:149 is false and the description column is never updated.

This is inconsistent with how startDate and clientId are handled in the same payload object (lines 166-167), which use || nullnull survives JSON serialization and correctly triggers the backend update logic to clear the value. A user who opens a project with an existing description, clears the field, and submits will see no change on the server.

Suggested change
description: formData.description || undefined,
description: formData.description || '',
Open in Devin Review

Was this helpful? React with 👍 or 👎 to provide feedback.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

0 participants