30 28 23 8 4 2 furqan bodarni - #342
Open
Furqan-7 wants to merge 6 commits into
Open
Conversation
added 6 commits
July 18, 2026 18:43
- client eslint.config.js had eslint-plugin-react in devDependencies but never wired into the flat config, so plain no-unused-vars couldn't see that imported components are used via JSX and flagged every single component import as unused (40 errors). Added just the jsx-uses-vars rule (not the full recommended set, which would pull in react-in-jsx-scope/prop-types that don't apply to this React 19 / PropTypes-free codebase). - package-lock.json was out of sync with package.json (locked eslint 10.x / missing eslint-plugin-react's tree entirely while package.json declared eslint ^9.7.0 + eslint-plugin-react). Regenerated via npm install so npm ci works cleanly again. - AuthContext.jsx exported both a component (AuthProvider) and a hook (useAuth) from one file, which react-refresh/only-export-components flags. Split into authContextInstance.js (the context object), AuthContext.jsx (just the AuthProvider component), and useAuth.js (the hook) — updated all six importers accordingly. - server/middleware/authMiddleware.js had an unused catch binding (no-unused-vars); now logs it instead of swallowing it silently. None of this touches application behavior — it's what's needed for 'npm run lint --max-warnings 0' to pass at all on either package, which the assigned issues below build on top of.
…bles middleware/upload.js accepted any file type with no validation — an attacker (or an unwitting talent) could upload a .exe, .sh, etc. through the submission upload endpoint. Added a multer fileFilter that only accepts PDF and common image types, checked by BOTH MIME type and extension so a renamed file (malware.exe renamed to .pdf) or a spoofed Content-Type can't slip through on either check alone. Also added an Express error-handling middleware in index.js, since a fileFilter rejection surfaces as a thrown error that previously had nowhere to go but Express's default HTML error page — now it returns a clean 400 JSON response instead.
…t + notify talents on assignment Grouped together since both live in the same createTask/updateTask assignment code path. modelsuite-ai#2 — Task Assignment Allows Admin-to-Admin Assignment: The frontend's assign-to dropdown only ever lists Talent users (via fetchTalents), but the backend never validated assignedTo at all, so a direct API call (Postman, curl, etc.) could assign a task to an Admin. Added validateAssignee(), called from both createTask and updateTask, which 404s on a missing user and 400s if the user's role isn't 'Talent'. modelsuite-ai#23 — Simulate Assignment Notifications: Talents had no way of knowing a task had been assigned to them. Added utils/notifications.js with a notifyAssignment() helper (console-logs a clearly structured notification, easy to swap for real email/push later) and call it from createTask when a task is created with an assignee, and from updateTask only when assignedTo actually changes to a new value (compares against the previous assignee so edits that don't touch assignment, or reassign to the same person, don't spam duplicate notifications).
…n is approved reviewSubmission updated Submission.reviewStatus but never touched the parent Task — approving a submission left the task stuck on 'Submitted' forever, with no way to tell completed work apart from work still awaiting review. - Added 'Completed' to Task's status enum, and a matching status-badge CSS class + STATUS_CLASS entries everywhere a task's status renders (TasksTable, MyTasksList, TaskCard) plus the admin status filter/edit dropdowns. - reviewSubmission now sets the parent Task's status to 'Completed' when reviewStatus is 'Approved'. (A rejection intentionally leaves the task as 'Submitted' — that already lets the talent resubmit, so no separate cascade is needed there.) - Constrained Submission.reviewStatus to an enum of ['Pending','Approved','Rejected'] — it previously accepted any string, which the cascade logic depends on being one of those three. - The Admin dashboard's 'Approved' stat card would now always read 0 (tasks move straight to Completed on approval instead), so swapped it to track Completed instead — otherwise the fix here would've quietly broken that card.
Both sidebars had nav items pointing at routes that were never registered in App.jsx: - Admin Sidebar's 'Talents' -> /admin/talents (backend endpoint GET /api/users/talents already existed and is already used by the assign-to dropdown, but no page consumed it directly) - Talent Sidebar's 'My Tasks' -> /talent/tasks (TalentDashboard was only mounted at /talent/dashboard) Clicking either nav item hit the catch-all NotFoundPage, which doesn't render the sidebar at all — so those items could never show an active state, since the route highlighting logic (location.pathname === path) had nothing valid to ever match against. - Added /talent/tasks as a second route onto TalentDashboard, mirroring the existing /admin/dashboard + /admin/tasks pattern that already maps two routes onto AdminDashboard. - Added a new TalentsPage (admin-only) listing all Talent-role users via the existing fetchTalents() API call, and registered it at /admin/talents, styled to match the existing SubmissionsPage table.
Login and Register both had plain type=password inputs with no way to
check what you'd typed before submitting.
Added a reusable PasswordInput component (components/common/) with an
eye-icon button that toggles the input between type='password' and
type='text'. Matches the existing input styling exactly (takes the same
inputCls used elsewhere) and is keyboard/screen-reader friendly
(type='button' so it can't submit the form, aria-label/aria-pressed
reflect the current state, tabIndex={-1} so it doesn't interrupt the
email->password->submit tab order). Used it in both LoginPage and
RegisterPage in place of the raw <input type="password">.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Fixes all 6 assigned issues. Also fixes a pre-existing broken ESLint config
that was failing Client Lint on a clean checkout — left as the first commit
since it's a prerequisite for CI to pass at all.
Changes
#4 — Unrestricted File Uploads
Added a multer
fileFilterthat checks both MIME type and file extensionagainst an allowlist (PDF + common image formats), so executables can't be
uploaded — including renamed ones. Added error-handling middleware so a
rejected upload returns a clean 400 JSON response instead of crashing.
#2 — Admin-to-Admin Assignment
Backend now validates that
assignedTorefers to a Talent-role user on bothcreate and update, rejecting with 400 otherwise. The UI dropdown already
filtered to Talents only — this closes the API-level gap.
#8 — Approval Doesn't Cascade to Parent Task
Approving a submission now sets the parent task's status to a new
Completedstate, wired through every place task status is shown (table,task list, filters, dashboard stats).
#23 — Simulated Assignment Notifications
Added a
notifyAssignmenthelper that fires when a task is assigned to atalent — on create, and on update only when the assignee actually changes.
#28 — Missing Active Nav Highlighting
Root cause: two sidebar links ("Talents", "My Tasks") pointed at routes
that were never registered, so they 404'd and could never show an active
state. Registered both — "My Tasks" reuses the existing dashboard route
pattern, "Talents" is a new page built on an API call that already existed
elsewhere in the app.
#30 — Password Visibility Toggle
Added a reusable
PasswordInputcomponent with a show/hide eye icon, usedon both Login and Register.
Issues
Closes #4, Closes #2, Closes #8, Closes #23, Closes #28, Closes #30
Testing
npm run lint— clean, 0 warnings/errors (client + server)npm run build— cleanVideo
https://drive.google.com/file/d/1wHgbt_ode6PG4G8e7yRcQ_ma_x3P-MmN/view?usp=sharing