Skip to content

feat: migrate track chair list and edit to mui components#918

Open
tomrndom wants to merge 3 commits intomasterfrom
fix/track-chair-list-mui
Open

feat: migrate track chair list and edit to mui components#918
tomrndom wants to merge 3 commits intomasterfrom
fix/track-chair-list-mui

Conversation

@tomrndom
Copy link
Copy Markdown

@tomrndom tomrndom commented May 6, 2026

ref: https://app.clickup.com/t/86b9pc89t

image image

Signed-off-by: Tomás Castillo tcastilloboireau@gmail.com

Summary by CodeRabbit

  • New Features

    • Added a modal dialog and inline form for creating/editing track chair assignments with member autocomplete and multi-track selection.
  • Refactor

    • Rewrote the track chair list as a functional component and migrated UI to Material-UI for improved consistency and usability.
  • Bug Fixes

    • Improved error feedback via snackbars, ensured loading state always clears, and fixed CSV export flow.
  • Documentation

    • Updated track chair deletion confirmation text.

Signed-off-by: Tomás Castillo <tcastilloboireau@gmail.com>
@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 6, 2026

Caution

Review failed

Failed to post review comments

📝 Walkthrough

Walkthrough

Refactors the Track Chairs UI from a class component to a hooks-based functional component, adds a new TrackChairDialog component, replaces authErrorHandler with snackbarErrorHandler in track-chair actions (adds member.id to requested fields and uses .finally()), adjusts reducer to reset on summit/logout and persist perPage, and tweaks a localization string.

Changes

Track Chairs UI Modernization & Error Handling

Layer / File(s) Summary
Data Shape / Requests
src/actions/track-chair-actions.js
Added member.id to requested fields; getTrackChairs now passes meta { trackId, term, order, orderDir, perPage }.
Error Handling / Control Flow
src/actions/track-chair-actions.js
Replaced authErrorHandler with snackbarErrorHandler and moved several .then() completions into .finally() to ensure stopLoading() runs.
Core UI Component
src/pages/track_chairs/components/track-chair-dialog.js
New TrackChairDialog component: Formik form, Yup validation (member + >=1 track), async member autocomplete, multi-select tracks with chips, dynamic add/edit title, onSave wiring, PropTypes, default export.
Page Wiring & Hooks
src/pages/track_chairs/track-chair-list-page.js
Replaced class-based TrackChairListPage with a functional component using hooks; implemented search, filter, sort, pagination, per-page handlers; integrated TrackChairDialog, Material-UI components, inline form and table actions.
State / Reducer
src/reducers/track_chairs/track-chair-list-reducer.js
Reducer resets to default on SET_CURRENT_SUMMIT and LOGOUT_USER; REQUEST_TRACK_CHAIRS consumes/stores perPage; RECEIVE_TRACK_CHAIRS uses property shorthand for trackChairs.
Localization
src/i18n/en.json
Updated track_chairs.delete_warning from "Are you sure you want to remove track chair " to "Are you sure you want to remove track chair for".

Sequence Diagram(s)

sequenceDiagram
participant UI as TrackChairListPage
participant Dialog as TrackChairDialog
participant Actions as track-chair-actions
participant Store as ReduxStore
participant API as BackendAPI

UI->>Actions: getTrackChairs(meta: trackId, term, order, perPage)
Actions->>API: GET /track-chairs?meta...
API-->>Actions: 200 + track chairs
Actions->>Store: dispatch RECEIVE_TRACK_CHAIRS
Store-->>UI: state updates (trackChairs, total, perPage)

UI->>Dialog: open (new/edit)
Dialog->>Actions: addTrackChair / saveTrackChair (payload)
Actions->>API: POST/PUT /track-chairs
API-->>Actions: 200/201 or error
Actions->>Store: dispatch REQUEST/RECEIVE or dispatch error action
Actions-->>UI: success -> refresh list
Actions-->>UI: error -> snackbarErrorHandler shows message
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Possibly related PRs

  • fntechgit/summit-admin#749: Prior changes to src/actions/track-chair-actions.js that modify action request patterns and constants; overlaps with this PR's action edits.
  • fntechgit/summit-admin#805: Also replaces authErrorHandler with snackbarErrorHandler and uses .finally() in action creators; closely related at the action-level pattern.

Suggested reviewers

  • martinquiroga-exo
  • smarcet

"I'm a rabbit in the code-filled glade,
I hop through dialogs that devs have made,
Hooks and snackbars, tracks in a row,
Chips that shimmer, save and go,
I nibble tests and leave a carrot-glow 🥕"

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately describes the main change: migrating the track chair list and edit functionality from legacy components to Material-UI (MUI) components, which is reflected across all modified files.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
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.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/track-chair-list-mui

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

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 2

Caution

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

⚠️ Outside diff range comments (1)
src/actions/track-chair-actions.js (1)

149-157: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Always clear loading state on add failures.

This path still dispatches stopLoading() only on success. If postRequest rejects, the global loading state stays active and the new dialog flow gets stuck after a failed create.

Suggested fix
     return postRequest(
       null,
       createAction(TRACK_CHAIR_ADDED),
       `${window.API_BASE_URL}/api/v1/summits/${currentSummit.id}/track-chairs`,
       { member_id: member.id, categories: trackIds },
       snackbarErrorHandler
-    )(params)(dispatch).then(() => {
+    )(params)(dispatch).finally(() => {
       dispatch(stopLoading());
     });
🤖 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/actions/track-chair-actions.js` around lines 149 - 157, The
add-track-chair flow only calls dispatch(stopLoading()) in the success .then,
leaving the global loading state active on postRequest rejection; update the
returned promise chain that wraps postRequest(...)(params)(dispatch) so that
dispatch(stopLoading()) runs regardless of outcome (use .finally or a .catch
that rethrows after dispatching stopLoading()). Reference the postRequest call
that uses createAction(TRACK_CHAIR_ADDED), snackbarErrorHandler, and ensure
stopLoading is dispatched in the failure path as well.
🤖 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/pages/track_chairs/track-chair-list-page.js`:
- Around line 125-131: The current handleSave treats a changed member in edit
mode as an add, causing duplicate assignments; update handleSave to perform an
explicit replace instead of add when dialogEntity?.originalMemberId !==
member?.value and id exists: either call a replaceTrackChair(member.value, id,
trackIds) helper (preferred) or sequentially call removeTrackChair(id) then
addTrackChair({ id: member.value }, trackIds), and finally clear the dialog;
alternatively, if reassignment is not allowed make the member field read-only in
edit mode (in the dialog render) so the branch to addTrackChair never runs for
edits. Ensure you reference dialogEntity.originalMemberId, handleSave,
addTrackChair, saveTrackChair and remove/replace helper names when implementing
the change.
- Around line 57-63: The early return based on currentSummit.id happens before
hooks run and can cause hook-order errors; keep the declarations (e.g., const
[dialogEntity, setDialogEntity] = useState(null)) and the useEffect hook in
place, move the render guard that checks currentSummit.id below the hooks (so
hooks always register), and change the effect to depend on currentSummit?.id
(useEffect(() => { if (currentSummit?.id) getTrackChairs(); },
[currentSummit?.id])) so getTrackChairs runs when the summit arrives.

---

Outside diff comments:
In `@src/actions/track-chair-actions.js`:
- Around line 149-157: The add-track-chair flow only calls
dispatch(stopLoading()) in the success .then, leaving the global loading state
active on postRequest rejection; update the returned promise chain that wraps
postRequest(...)(params)(dispatch) so that dispatch(stopLoading()) runs
regardless of outcome (use .finally or a .catch that rethrows after dispatching
stopLoading()). Reference the postRequest call that uses
createAction(TRACK_CHAIR_ADDED), snackbarErrorHandler, and ensure stopLoading is
dispatched in the failure path as well.
🪄 Autofix (Beta)

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

Run ID: f4ec317b-b43b-40a7-8d38-7a99aa796a4b

📥 Commits

Reviewing files that changed from the base of the PR and between 8607ac5 and e7841ab.

📒 Files selected for processing (5)
  • src/actions/track-chair-actions.js
  • src/i18n/en.json
  • src/pages/track_chairs/components/track-chair-dialog.js
  • src/pages/track_chairs/track-chair-list-page.js
  • src/reducers/track_chairs/track-chair-list-reducer.js

Comment thread src/pages/track_chairs/track-chair-list-page.js Outdated
Comment on lines +125 to +131
const handleSave = ({ id, member, trackIds }) => {
const newMember = dialogEntity?.originalMemberId !== member?.value;
const action =
!id || newMember
? addTrackChair({ id: member.value }, trackIds)
: saveTrackChair(id, trackIds);
action.then(() => setDialogEntity(null));
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Editing the member currently creates a second assignment.

saveTrackChair only updates categories, so this branch to addTrackChair(...) leaves the original record in place when the member changes. In edit mode that turns a reassignment into a duplicate track-chair entry.

Suggested fix
   const handleSave = ({ id, member, trackIds }) => {
-    const newMember = dialogEntity?.originalMemberId !== member?.value;
-    const action =
-      !id || newMember
-        ? addTrackChair({ id: member.value }, trackIds)
-        : saveTrackChair(id, trackIds);
+    const action = !id
+      ? addTrackChair({ id: member.value }, trackIds)
+      : saveTrackChair(id, trackIds);
     action.then(() => setDialogEntity(null));
   };

If member reassignment is supposed to be supported here, it needs an explicit replace flow; otherwise the member field should be read-only in edit mode.

🤖 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/pages/track_chairs/track-chair-list-page.js` around lines 125 - 131, The
current handleSave treats a changed member in edit mode as an add, causing
duplicate assignments; update handleSave to perform an explicit replace instead
of add when dialogEntity?.originalMemberId !== member?.value and id exists:
either call a replaceTrackChair(member.value, id, trackIds) helper (preferred)
or sequentially call removeTrackChair(id) then addTrackChair({ id: member.value
}, trackIds), and finally clear the dialog; alternatively, if reassignment is
not allowed make the member field read-only in edit mode (in the dialog render)
so the branch to addTrackChair never runs for edits. Ensure you reference
dialogEntity.originalMemberId, handleSave, addTrackChair, saveTrackChair and
remove/replace helper names when implementing the change.

Signed-off-by: Tomás Castillo <tcastilloboireau@gmail.com>
Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

♻️ Duplicate comments (1)
src/pages/track_chairs/track-chair-list-page.js (1)

57-63: ⚠️ Potential issue | 🔴 Critical | ⚡ Quick win

Runtime crash: currentSummit.tracks accessed before guard.

Line 63 accesses currentSummit.tracks before the guard at line 157. If currentSummit is undefined, this crashes. Additionally, the useEffect has an empty dependency array, so getTrackChairs won't be called when the summit loads after mount.

Move chairTracks derivation and the early return guard together, and add proper dependencies to the effect:

Proposed fix
   const [dialogEntity, setDialogEntity] = useState(null);

+  const chairTracks = currentSummit?.tracks?.filter((t) => t.chair_visible) ?? [];
+
   useEffect(() => {
-    if (currentSummit) getTrackChairs();
-  }, []);
+    if (currentSummit?.id) getTrackChairs();
+  }, [currentSummit?.id]);
 
-  const chairTracks = currentSummit.tracks.filter((t) => t.chair_visible);
+  if (!currentSummit?.id) return <div />;

Then remove the duplicate guard at line 157.

🤖 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/pages/track_chairs/track-chair-list-page.js` around lines 57 - 63, Move
the derivation of chairTracks so it runs only after the early-return guard that
checks currentSummit (i.e., return/loading when !currentSummit) to avoid
accessing currentSummit.tracks when currentSummit is undefined; update the
useEffect that calls getTrackChairs to include currentSummit and getTrackChairs
in its dependency array (useEffect(() => { if (currentSummit) getTrackChairs();
}, [currentSummit, getTrackChairs])) so the fetch runs when the summit loads,
and remove the now-duplicate early-return guard later in the component;
references: chairTracks, currentSummit, getTrackChairs, useEffect.
🤖 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.

Duplicate comments:
In `@src/pages/track_chairs/track-chair-list-page.js`:
- Around line 57-63: Move the derivation of chairTracks so it runs only after
the early-return guard that checks currentSummit (i.e., return/loading when
!currentSummit) to avoid accessing currentSummit.tracks when currentSummit is
undefined; update the useEffect that calls getTrackChairs to include
currentSummit and getTrackChairs in its dependency array (useEffect(() => { if
(currentSummit) getTrackChairs(); }, [currentSummit, getTrackChairs])) so the
fetch runs when the summit loads, and remove the now-duplicate early-return
guard later in the component; references: chairTracks, currentSummit,
getTrackChairs, useEffect.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 1b6b9930-5b7b-4fbd-8a77-4a9210e5efbe

📥 Commits

Reviewing files that changed from the base of the PR and between e7841ab and 0cb4096.

📒 Files selected for processing (1)
  • src/pages/track_chairs/track-chair-list-page.js

Signed-off-by: Tomás Castillo <tcastilloboireau@gmail.com>
@tomrndom tomrndom requested a review from smarcet May 6, 2026 21:47
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