Skip to content

Feature/mutations - #36

Merged
Alejandroq12 merged 4 commits into
devfrom
feature/mutations
Aug 7, 2026
Merged

Feature/mutations#36
Alejandroq12 merged 4 commits into
devfrom
feature/mutations

Conversation

@Alejandroq12

@Alejandroq12 Alejandroq12 commented Aug 7, 2026

Copy link
Copy Markdown
Owner

Summary by CodeRabbit

  • New Features

    • Added header notifications with unread indicators, notification lists, and mark-all-as-read behavior.
    • Added task editing and deletion actions with confirmation and feedback.
    • Added grid and list viewing options.
    • Added detailed task lists with tags, estimates, assignees, due dates, and actions.
    • Improved task creation and editing with shared validation and responsive controls.
    • Added retry options for task-loading errors.
    • Added My Task filtering based on the current profile.
  • Bug Fixes

    • Due-date colors now highlight overdue and upcoming tasks.
    • Task ordering is consistent when positions match.
    • Point labels now display as “Points.”

  Notifications are the app's first custom context — the first value
  needing tree-wide reach. The provider owns a ten-entry history with
  read tracking; useNotify serves the mutation call sites and
  useNotifications serves the header bell. Provider and hooks live in
  separate files so react-refresh keeps hot reload. Transient toasts were
  prototyped and deliberately dropped: two presentations of one event
  prototyped and deliberately dropped: two presentations of one event
  stream duplicated a function, and failures already surface inline in
  the dialog that caused them.
…audit fixes the bell, delete-dialog inline alert, and

  doc updates
@vercel

vercel Bot commented Aug 7, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
task-flow Ready Ready Preview Aug 7, 2026 9:46pm

@coderabbitai

coderabbitai Bot commented Aug 7, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

The PR adds reusable task forms and CRUD modals, board/list layouts, task list rendering, profile-based task loading, shared display helpers, and a notification provider with a header notification center.

Changes

Task management and notifications

Layer / File(s) Summary
Task contracts and display data
src/features/tasks/types.ts, src/features/tasks/task-display.ts, src/features/tasks/queries.ts, src/features/tasks/icons.tsx
Task layout types, GraphQL documents, due-date and tag metadata, sorting, point labels, and task action icons are added or updated.
Notification provider and header bell
src/components/ui/notifications-context.ts, src/components/ui/notifications.tsx, src/components/layout/NotificationsBell.tsx, src/components/layout/Header.tsx, src/main.tsx, src/app/router.test.tsx
The application adds notification state, capped unread storage, read-state management, and a header dropdown with accessible controls.
Reusable task form and CRUD actions
src/features/tasks/TaskForm.tsx, src/features/tasks/CreateTaskModal.tsx, src/features/tasks/EditTaskModal.tsx, src/features/tasks/DeleteTaskDialog.tsx, src/features/tasks/TaskActions.tsx, src/features/tasks/TaskCard.tsx, src/features/tasks/DatePicker.tsx, src/components/ui/use-dialog-focus.ts
Task creation, editing, and deletion use shared form controls, GraphQL mutations, query invalidation, validation, focus management, modal behavior, and notifications.
Task loading and board or list views
src/features/tasks/Dashboard.tsx, src/features/tasks/Toolbar.tsx, src/features/tasks/TasksView.tsx, src/features/tasks/TaskList.tsx, src/features/tasks/MyTask.tsx, src/features/tasks/QueryErrorAlert.tsx, src/test/fixtures.ts, src/app/router.test.tsx, README.md
Task views support filtered React Query loading, board/list switching, profile loading, retryable errors, list rows, updated fixtures, and implementation notes.

Estimated code review effort: 4 (Complex) | ~60 minutes

Sequence Diagram(s)

sequenceDiagram
  participant User
  participant CreateTaskModal
  participant TaskForm
  participant GraphQLClient
  participant NotificationsContext
  User->>CreateTaskModal: Submit task form
  CreateTaskModal->>TaskForm: Collect validated task fields
  CreateTaskModal->>GraphQLClient: Create task mutation
  GraphQLClient-->>CreateTaskModal: Return mutation result
  CreateTaskModal->>NotificationsContext: Add success or error notification
Loading

Possibly related PRs

Suggested labels: ui

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title identifies task mutations, which are a central part of the changeset, but it does not describe the related UI and notification changes.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches 💡 1
📝 Generate docstrings 💡
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feature/mutations

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 6

🧹 Nitpick comments (3)
src/features/tasks/TaskForm.tsx (1)

231-232: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Align aria-haspopup with the rendered popup roles.

The estimate, label, assignee, and status triggers declare aria-haspopup="listbox", but MenuPanel renders a plain div that contains button elements. No listbox or option role exists. The date trigger at Line 416 declares aria-haspopup="dialog", but DatePicker and DatePickerDialog use role="group". Screen readers announce a popup type that the user never receives.

TaskCard already uses the matching pattern: aria-haspopup="menu" with role="menu" and role="menuitem". Reuse it here.

♻️ Proposed change for the estimate trigger and panel
             <button
               type="button"
-              aria-haspopup="listbox"
+              aria-haspopup="menu"
               aria-expanded={openMenu === 'estimate'}

Apply the same change to the label, assignee, and status triggers. Then add the matching roles in MenuPanel and its items:

     <div
+      role="menu"
       className={`absolute top-full left-0 z-10 mt-2 flex flex-col rounded-lg border border-neutral-2 bg-neutral-3 py-2 shadow-drop-large ${className}`}
     >

For the date trigger, either change it to aria-haspopup="true" or give DatePicker and DatePickerDialog role="dialog".

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/features/tasks/TaskForm.tsx` around lines 231 - 232, Align popup
accessibility semantics in TaskForm: change the estimate, label, assignee, and
status triggers to aria-haspopup="menu", and update MenuPanel plus its button
items to use matching menu and menuitem roles, following TaskCard’s pattern. For
the date trigger, either use aria-haspopup="true" or update DatePicker and
DatePickerDialog to expose role="dialog".
src/app/router.test.tsx (1)

19-23: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Make the mock reject unknown documents instead of returning tasks.

The fallback branch returns { tasks: ... } for every document that is not ProfileDocument. UsersDocument, CreateTaskDocument, UpdateTaskDocument, and DeleteTaskDocument all resolve to a task list. A future test that opens TaskForm would receive { tasks: [...] } for the users query, and users.data?.users would be undefined. The assignee menu would render empty and the test would pass for the wrong reason.

Map each document explicitly and reject the rest.

♻️ Proposed change to the request mock
-  tasksRequestMock().mockImplementation((document: unknown) =>
-    document === ProfileDocument
-      ? Promise.resolve({ profile: makeFixtureProfile() })
-      : Promise.resolve({ tasks: makeFixtureTasks() }),
-  )
+  tasksRequestMock().mockImplementation((document: unknown) => {
+    if (document === ProfileDocument) return Promise.resolve({ profile: makeFixtureProfile() })
+    if (document === TasksDocument) return Promise.resolve({ tasks: makeFixtureTasks() })
+    return Promise.reject(new Error('Unmocked GraphQL document'))
+  })

Import TasksDocument from @/features/tasks/queries.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/app/router.test.tsx` around lines 19 - 23, Update the tasksRequestMock
implementation to handle ProfileDocument and TasksDocument explicitly, returning
the corresponding profile or task fixtures. Reject any other document, including
user and task mutation documents, instead of falling through to the tasks
response; import TasksDocument from the tasks queries module.
src/test/fixtures.ts (1)

19-19: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Add a fixture pair that exercises the createdAt tie-breaker.

groupTasksByStatus now falls back to a.createdAt.localeCompare(b.createdAt) when positions match (task-display.ts Line 19). No two fixture tasks share both a status and a position, so the new comparator branch never runs in the tests. Give two IN_PROGRESS tasks the same position to cover it.

Also applies to: 30-30, 41-41, 52-56

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/test/fixtures.ts` at line 19, Update the task fixtures around createdAt
and the related entries so two IN_PROGRESS tasks share the same position while
retaining distinct createdAt values. Ensure the fixture pair exercises the
createdAt tie-breaker in groupTasksByStatus without changing unrelated statuses
or ordering expectations.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/components/layout/NotificationsBell.tsx`:
- Line 20: Remove the aria-haspopup attribute from the notification bell control
in NotificationsBell, since its notification panel is not a menu and does not
provide menu interaction behavior.

In `@src/features/tasks/DeleteTaskDialog.tsx`:
- Around line 40-84: Update the DeleteTaskDialog component’s focus handling to
match TaskForm: focus the “Go back” button on open, trap Tab and Shift+Tab
within the dialog controls, and restore focus to the element that opened the
dialog when dismissing or closing. Reuse the existing TaskForm focus-management
pattern and preserve the current delete/error behavior.

In `@src/features/tasks/TaskCard.tsx`:
- Around line 116-131: Update TaskCard’s dialog handling to store the “Task
options” trigger element in a ref and use a shared closeDialog callback to close
the dialog and restore focus to that trigger after unmount. Wire both
EditTaskModal and DeleteTaskDialog onClose handlers to closeDialog, while
preserving TaskForm’s existing generic cleanup behavior for CreateTaskModal.

In `@src/features/tasks/TaskForm.tsx`:
- Around line 109-121: Update src/features/tasks/TaskForm.tsx lines 109-121 in
the existing keydown effect to clear openMenu and return when a menu is open,
call onClose only when no menu is open, and include openMenu in the
dependencies. Update src/features/tasks/TaskCard.tsx lines 44-54 by adding
Escape handling to the role="menu" element that calls setMenuOpen(false).
Consider sharing a useDismissOnEscape(active, onDismiss) hook between both
sites.
- Around line 343-364: Update the assignee menu rendering around users.data in
TaskForm to handle users.isPending and users.isError explicitly instead of
always falling back to an empty list. Show a short loading message while pending
and an error message with a retry action after failure, using the query’s
existing refetch mechanism; retain the user list rendering for successful
results.

In `@src/features/tasks/TaskList.tsx`:
- Around line 36-83: Update TaskRow to expose task actions by adding an actions
cell or reusing the TaskCard action menu, wired to open EditTaskModal and
DeleteTaskDialog for the current task. Preserve the existing list columns and
ensure the controls are available when TasksView renders the list layout.

---

Nitpick comments:
In `@src/app/router.test.tsx`:
- Around line 19-23: Update the tasksRequestMock implementation to handle
ProfileDocument and TasksDocument explicitly, returning the corresponding
profile or task fixtures. Reject any other document, including user and task
mutation documents, instead of falling through to the tasks response; import
TasksDocument from the tasks queries module.

In `@src/features/tasks/TaskForm.tsx`:
- Around line 231-232: Align popup accessibility semantics in TaskForm: change
the estimate, label, assignee, and status triggers to aria-haspopup="menu", and
update MenuPanel plus its button items to use matching menu and menuitem roles,
following TaskCard’s pattern. For the date trigger, either use
aria-haspopup="true" or update DatePicker and DatePickerDialog to expose
role="dialog".

In `@src/test/fixtures.ts`:
- Line 19: Update the task fixtures around createdAt and the related entries so
two IN_PROGRESS tasks share the same position while retaining distinct createdAt
values. Ensure the fixture pair exercises the createdAt tie-breaker in
groupTasksByStatus without changing unrelated statuses or ordering expectations.
🪄 Autofix

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 463ced64-6f02-4bf3-aa19-77a9e54a68f7

📥 Commits

Reviewing files that changed from the base of the PR and between 6f533e7 and d68623e.

⛔ Files ignored due to path filters (2)
  • src/graphql/generated/gql.ts is excluded by !**/generated/**
  • src/graphql/generated/graphql.ts is excluded by !**/generated/**
📒 Files selected for processing (25)
  • README.md
  • src/app/router.test.tsx
  • src/components/layout/Header.tsx
  • src/components/layout/NotificationsBell.tsx
  • src/components/ui/notifications-context.ts
  • src/components/ui/notifications.tsx
  • src/features/tasks/CreateTaskModal.tsx
  • src/features/tasks/Dashboard.tsx
  • src/features/tasks/DatePicker.tsx
  • src/features/tasks/DeleteTaskDialog.tsx
  • src/features/tasks/EditTaskModal.tsx
  • src/features/tasks/MyTask.tsx
  • src/features/tasks/QueryErrorAlert.tsx
  • src/features/tasks/TaskCard.tsx
  • src/features/tasks/TaskForm.tsx
  • src/features/tasks/TaskList.tsx
  • src/features/tasks/TasksView.tsx
  • src/features/tasks/Toolbar.tsx
  • src/features/tasks/icons.tsx
  • src/features/tasks/queries.ts
  • src/features/tasks/task-display.ts
  • src/features/tasks/types.ts
  • src/features/tasks/useTasks.ts
  • src/main.tsx
  • src/test/fixtures.ts
💤 Files with no reviewable changes (1)
  • src/features/tasks/useTasks.ts

Comment thread src/components/layout/NotificationsBell.tsx Outdated
Comment thread src/features/tasks/DeleteTaskDialog.tsx
Comment thread src/features/tasks/TaskForm.tsx Outdated
Comment thread src/features/tasks/TaskForm.tsx
Comment thread src/features/tasks/TaskList.tsx
@claude

claude Bot commented Aug 7, 2026

Copy link
Copy Markdown

Code review

No issues found. Checked for bugs and CLAUDE.md compliance.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
src/features/tasks/TaskForm.tsx (1)

122-130: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Validate position before submission.

min="1" does not validate this custom submission flow. A user can enter 0, a negative value, or a decimal value. canSubmit accepts these values. EditTaskModal then omits nonpositive values, so the mutation can succeed while leaving the position unchanged.

Require a whole number greater than or equal to one when showPosition is true. Show a position-specific validation error.

Proposed fix
+  const positionNumber = Number(position)
+  const positionIsValid =
+    !showPosition || (Number.isInteger(positionNumber) && positionNumber >= 1)
-  const canSubmit = name.trim().length > 0 && estimate !== null && dueDate !== ''
+  const canSubmit =
+    name.trim().length > 0 && estimate !== null && dueDate !== '' && positionIsValid
...
               <input
                 type="number"
                 min="1"
+                step="1"
...
-            {canSubmit ? errorMessage : 'An estimate and a due date are required.'}
+            {canSubmit
+              ? errorMessage
+              : !positionIsValid
+                ? 'Position must be a whole number of at least 1.'
+                : 'An estimate and a due date are required.'}

Also applies to: 381-388, 433-439

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/features/tasks/TaskForm.tsx` around lines 122 - 130, Update canSubmit and
submit in TaskForm so that when showPosition is true, position must be a whole
number greater than or equal to 1; reject zero, negative, decimal, and invalid
values before calling onSubmit. When this validation fails, enable
showPosition-specific validation feedback alongside the existing showValidation
handling, and preserve the current behavior when showPosition is false.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Outside diff comments:
In `@src/features/tasks/TaskForm.tsx`:
- Around line 122-130: Update canSubmit and submit in TaskForm so that when
showPosition is true, position must be a whole number greater than or equal to
1; reject zero, negative, decimal, and invalid values before calling onSubmit.
When this validation fails, enable showPosition-specific validation feedback
alongside the existing showValidation handling, and preserve the current
behavior when showPosition is false.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: d0d80041-d88b-4c62-9ff0-c0d404e71907

📥 Commits

Reviewing files that changed from the base of the PR and between d68623e and 5be4dc8.

📒 Files selected for processing (8)
  • README.md
  • src/components/layout/NotificationsBell.tsx
  • src/components/ui/use-dialog-focus.ts
  • src/features/tasks/DeleteTaskDialog.tsx
  • src/features/tasks/TaskActions.tsx
  • src/features/tasks/TaskCard.tsx
  • src/features/tasks/TaskForm.tsx
  • src/features/tasks/TaskList.tsx
🚧 Files skipped from review as they are similar to previous changes (3)
  • src/components/layout/NotificationsBell.tsx
  • src/features/tasks/DeleteTaskDialog.tsx
  • src/features/tasks/TaskList.tsx

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/features/tasks/TaskForm.tsx`:
- Around line 122-125: Update the position validation in the canSubmit flow
using positionNumber so values below the declared minimum are rejected; require
positionNumber to be at least 1 while preserving the existing showPosition and
finite-value checks.
🪄 Autofix

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: ebe4f584-e650-4125-9f01-6e243004f333

📥 Commits

Reviewing files that changed from the base of the PR and between 5be4dc8 and 1dcd0b8.

📒 Files selected for processing (2)
  • src/features/tasks/EditTaskModal.tsx
  • src/features/tasks/TaskForm.tsx
🚧 Files skipped from review as they are similar to previous changes (1)
  • src/features/tasks/EditTaskModal.tsx

Comment thread src/features/tasks/TaskForm.tsx
Repository owner deleted a comment from coderabbitai Bot Aug 7, 2026
Repository owner deleted a comment from coderabbitai Bot Aug 7, 2026
@Alejandroq12
Alejandroq12 merged commit 97b32b2 into dev Aug 7, 2026
12 checks passed
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.

1 participant