Skip to content

feat: move admin access group grid to mui#911

Open
priscila-moneo wants to merge 2 commits into
masterfrom
feature/move-admin-access-group-grid-mui
Open

feat: move admin access group grid to mui#911
priscila-moneo wants to merge 2 commits into
masterfrom
feature/move-admin-access-group-grid-mui

Conversation

@priscila-moneo
Copy link
Copy Markdown

@priscila-moneo priscila-moneo commented May 4, 2026

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

Summary by CodeRabbit

  • New Features

    • Create/edit admin access now uses an in-app modal dialog and route-driven flows.
  • Style

    • Forms, tables, and controls updated to Material‑UI for a consistent modern UI.
  • Bug Fixes

    • Pagination/per-page/sorting persisted and list refreshes after save/delete.
    • Delete flow simplified (confirmation removed).
    • Save flow: unified success toast shown; creating no longer opens a modal or redirects.
  • Refactor

    • List, form, and layout converted to functional/hooks-based implementations.
  • Tests

    • Expanded tests covering list, form, save, delete, reducer, and action behaviors.

Review Change Stack

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 4, 2026

📝 Walkthrough

Walkthrough

Consolidates admin-access create/edit into a dialog on the list page, migrates the form to MUI + Formik with validation, updates actions to include pagination metadata and changes saveAdminAccess behavior, updates reducer pagination/total handling and deletion, removes the legacy edit page, and adds tests.

Changes

Admin Access Module Dialog-Based Refactor

Layer / File(s) Summary
List page: hooks, table, dialog
src/pages/admin_access/admin-access-list-page.js
Replaces class with hooks, uses MuiTable/MuiSearchInput, routes /new and /:access_id open the dialog, save/delete flows re-fetch list and handle paging; dialog tied to entity/errors props.
Form UI: Formik + MUI
src/components/forms/admin-access-form.js
Rewrites form as functional component using useFormik/FormikProvider, MUI layout, and a yup validation schema for title, members, and summits; server errors synced into Formik.
Actions: save/get metadata and tests
src/actions/admin-access-actions.js, src/actions/__tests__/admin-access-actions.test.js
getAdminAccesses now includes page and perPage in action metadata. saveAdminAccess signature removes noAlert, unifies loading teardown with .finally(), always shows showSuccessMessage on success, and removes the previous create-path modal+redirect; tests added for create/update thunk behavior.
Reducer: pagination totals & deletion
src/reducers/admin_access/admin-access-list-reducer.js, src/reducers/admin_access/__tests__/admin-access-list-reducer.test.js
DEFAULT_STATE gains totalAdminAccesses; REQUEST_ADMIN_ACCESSES and RECEIVE_ADMIN_ACCESSES persist currentPage/perPage/lastPage/totalAdminAccesses; ADMIN_ACCESS_DELETED filters item and conditionally decrements total; tests validate deletion behavior.
Layout & routing
src/layouts/admin-access-layout.js
Convert to functional layout, route /new and /:access_id to list page, remove EditAdminAccessPage import, and wrap layout directly with Restrict.
Tests: list page interactions
src/pages/admin_access/__tests__/admin-access-list-page.test.js
Expanded RTL/Jest tests covering dialog open/close by route, per-page fetch args, saving guard behavior, and list reloads after save/delete and on delete failure.
i18n
src/i18n/en.json
Updated admin_access.delete_warning phrasing.

Sequence Diagram(s)

sequenceDiagram
  participant Router
  participant AdminList as AdminAccessListPage
  participant Actions as admin-access-actions
  participant Reducer as adminAccessListReducer
  participant Dialog as AdminAccessDialog
  Router->>AdminList: navigate('/app/admin-access' | '/new' | '/:id')
  AdminList->>Actions: getAdminAccesses(term, page, perPage, order, orderDir)
  Actions->>Reducer: dispatch REQUEST/RECEIVE (with page/perPage)
  Reducer->>AdminList: state (admin_accesses + totalAdminAccesses)
  AdminList->>Dialog: open(entity/errors)
  Dialog->>Actions: saveAdminAccess(entity) / deleteAdminAccess(id)
  Actions->>Reducer: dispatch ADDED/UPDATED/DELETED
  Actions->>AdminList: refresh via getAdminAccesses in finally
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~50 minutes

Suggested reviewers

  • smarcet
  • martinquiroga-exo

Poem

A rabbit taps the keys with flair,
Dialogs blossom in MUI air,
Form and list now sing as one,
Pagination marches on and on,
🐇🌿✨

🚥 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 'feat: move admin access group grid to mui' accurately describes the primary change: migrating the admin access group grid UI component from Bootstrap to Material-UI (MUI).
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 feature/move-admin-access-group-grid-mui

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

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: 3

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@src/layouts/admin-access-layout.js`:
- Around line 30-36: The current Route path (`path={`${match.url}/:access_id?`}`
in the Switch) is too permissive and treats any single-segment suffix as an edit
route; replace it with explicit routes: add a Route for the "new" page using
`${match.url}/new` (rendering AdminAccessListPage or AdminAccessForm as
appropriate) and add a separate Route for numeric IDs using a constrained param
like `${match.url}/:access_id(\\d+)` that renders AdminAccessListPage for
editing; keep the Redirect to `match.url` after those Routes and ensure the
order is: new route, numeric-id route, then Redirect so invalid segments still
fall through to the redirect.

In `@src/pages/admin_access/admin-access-list-page.js`:
- Around line 63-79: The getAdminAccess(accessId).then(() => setOpen(true)) call
can reopen the modal with stale data; modify the effect around
useEffect/getAdminAccess to guard against late responses by sequencing or
cancellation: capture the current accessId/isNew (from match.params.access_id
and a flag from /new) or create a request token/AbortController before calling
getAdminAccess, and when the promise resolves verify the token matches the
latest accessId (and still not isNew) before calling setOpen(true) and applying
fetched data (or abort the fetch). Also ensure resetAdminAccessForm is only
applied for the intended /new route by checking the same guard.
- Around line 106-112: handleDeleteAdminAccess currently performs an optimistic
delete via deleteAdminAccess but never refetches the paginated data, leaving
currentPage pointing at an empty page after deleting the last item; change the
flow so that after deleteAdminAccess resolves (or in its success
callback/promise then), call the pagination refetch function (e.g.,
fetchAdminAccessPage or refetchAdminAccess) for the currentPage, and if the
returned page is empty and currentPage > 1, decrement currentPage and refetch
the previous page; update the state that holds currentPage and the page data
accordingly instead of relying only on the reducer’s local filter.
🪄 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: f9c84e8b-8dbe-47a6-856f-4041b0d8ca43

📥 Commits

Reviewing files that changed from the base of the PR and between 08e2650 and 2c47f00.

📒 Files selected for processing (8)
  • src/actions/admin-access-actions.js
  • src/components/forms/admin-access-form.js
  • src/layouts/admin-access-layout.js
  • src/pages/admin_access/__tests__/admin-access-list-page.test.js
  • src/pages/admin_access/admin-access-list-page.js
  • src/pages/admin_access/edit-admin-access-page.js
  • src/reducers/admin_access/__tests__/admin-access-list-reducer.test.js
  • src/reducers/admin_access/admin-access-list-reducer.js
💤 Files with no reviewable changes (1)
  • src/pages/admin_access/edit-admin-access-page.js

Comment thread src/layouts/admin-access-layout.js
Comment on lines +63 to +79
useEffect(() => {
const { access_id: accessId } = match.params;
const isNew = /\/new$/.test(history.location.pathname);

this.state = {};
}
if (isNew) {
resetAdminAccessForm();
setOpen(true);
return;
}

componentDidMount() {
this.props.getAdminAccesses();
}
if (accessId) {
getAdminAccess(accessId).then(() => setOpen(true));
return;
}

handleEdit(admin_access_id) {
const { history } = this.props;
history.push(`/app/admin-access/${admin_access_id}`);
}
setOpen(false);
}, [match.params.access_id, history.location.pathname]);
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 | 🏗️ Heavy lift

Guard against stale edit loads.

getAdminAccess(accessId).then(() => setOpen(true)) has no stale-request check. If the user closes the dialog or switches from /app/admin-access/1 to /app/admin-access/new before the fetch finishes, the late response can reopen the modal and repopulate the form with the old record. This needs request sequencing/cancellation, or at least a route/id guard before applying the result.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/pages/admin_access/admin-access-list-page.js` around lines 63 - 79, The
getAdminAccess(accessId).then(() => setOpen(true)) call can reopen the modal
with stale data; modify the effect around useEffect/getAdminAccess to guard
against late responses by sequencing or cancellation: capture the current
accessId/isNew (from match.params.access_id and a flag from /new) or create a
request token/AbortController before calling getAdminAccess, and when the
promise resolves verify the token matches the latest accessId (and still not
isNew) before calling setOpen(true) and applying fetched data (or abort the
fetch). Also ensure resetAdminAccessForm is only applied for the intended /new
route by checking the same guard.

Comment thread src/pages/admin_access/admin-access-list-page.js
Comment thread src/actions/admin-access-actions.js Outdated

dispatch(
showMessage(successMessage, () => {
history.push(`/app/admin-access/${payload.response.id}`);
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

redirectOnCreate if should go here, if not the noAlert flag is redundant

? `${member.first_name} ${member.last_name} (${member.email})`
: `${member.first_name} ${member.last_name} (${member.id})`;
}}
: `${member.first_name} ${member.last_name} (${member.id})`}
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

if the only thing that changes is the parenthesis, then the ternary condition should go there

path={`${match.url}/:access_id?`}
component={AdminAccessListPage}
/>
<Redirect to={match.url} />
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

before the routes would only match on / or digit, or new. Now it matches everything , for example app/admin-access/santi. it is not equivalent to what we had

this.handleDeleteAdminAccess = this.handleDeleteAdminAccess.bind(this);
useEffect(() => {
const { access_id: accessId } = match.params;
const isNew = /\/new$/.test(history.location.pathname);
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

so what if the url is app/admin-access/santi/new ?

const totalItems =
typeof totalAdminAccesses === "number"
? totalAdminAccesses
: admin_accesses.length;
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

admin_accesses is paginated, the length of this will rarely be the total

@priscila-moneo priscila-moneo force-pushed the feature/move-admin-access-group-grid-mui branch from 2c47f00 to e24b38c Compare May 4, 2026 19:53
Copy link
Copy Markdown

@santipalenque santipalenque left a comment

Choose a reason for hiding this comment

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

LGTM

@priscila-moneo priscila-moneo force-pushed the feature/move-admin-access-group-grid-mui branch 2 times, most recently from ee5e6d9 to c1ff274 Compare May 29, 2026 14:41
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: 1

🧹 Nitpick comments (1)
src/pages/admin_access/__tests__/admin-access-list-page.test.js (1)

43-45: ⚡ Quick win

Mock onDelete with the row id, not the full row, to match the real MuiTable contract.

The real MuiTable invokes onDelete with the primitive row id, whereas onEdit receives the full row. This mock fires onDelete(row), so the delete test only exercises the object branch of handleDeleteAdminAccess (typeof rowOrId === "object") while production hits the id branch. Passing row.id keeps the test green and faithful to the contract.

♻️ Align mock with the real callback payload
-          <button type="button" onClick={() => onDelete(row)}>
+          <button type="button" onClick={() => onDelete(row.id)}>
             delete
           </button>

Based on learnings: onDelete is called with the primitive row identifier (e.g., id/rowId), not the full row object, while onEdit and onSelect receive the full row object.

🤖 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/admin_access/__tests__/admin-access-list-page.test.js` around lines
43 - 45, The test mock currently calls onDelete(row) but the real MuiTable
passes the primitive row id; change the mock delete button to call
onDelete(row.id) so the test exercises the id branch in handleDeleteAdminAccess
(keep onEdit as-is since it expects the full row object). Update the mock in the
test file to pass the row.id identifier to onDelete and verify assertions still
target the id-based behavior.
🤖 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/forms/admin-access-form.js`:
- Around line 33-44: AdminAccessForm currently ignores server-side validation
errors because its props only include { entity, onSubmit, isSaving }; update the
component to accept an errors prop and, inside the component (after useFormik),
watch for changes to that errors prop and call formik.setErrors(errors) and set
relevant fields touched (e.g.,
formik.setTouched(Object.fromEntries(Object.keys(errors||{}).map(k=>[k,true]))))
so Formik displays backend field errors; reference AdminAccessForm, useFormik,
formik.setErrors and formik.setTouched when adding the effect.

---

Nitpick comments:
In `@src/pages/admin_access/__tests__/admin-access-list-page.test.js`:
- Around line 43-45: The test mock currently calls onDelete(row) but the real
MuiTable passes the primitive row id; change the mock delete button to call
onDelete(row.id) so the test exercises the id branch in handleDeleteAdminAccess
(keep onEdit as-is since it expects the full row object). Update the mock in the
test file to pass the row.id identifier to onDelete and verify assertions still
target the id-based behavior.
🪄 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: 4f222801-0811-48de-a064-e78c82e90c61

📥 Commits

Reviewing files that changed from the base of the PR and between 2c47f00 and c1ff274.

📒 Files selected for processing (8)
  • src/actions/__tests__/admin-access-actions.test.js
  • src/actions/admin-access-actions.js
  • src/components/forms/admin-access-form.js
  • src/i18n/en.json
  • src/layouts/admin-access-layout.js
  • src/pages/admin_access/__tests__/admin-access-list-page.test.js
  • src/pages/admin_access/admin-access-list-page.js
  • src/pages/admin_access/edit-admin-access-page.js
💤 Files with no reviewable changes (1)
  • src/pages/admin_access/edit-admin-access-page.js
✅ Files skipped from review due to trivial changes (1)
  • src/i18n/en.json

Comment thread src/components/forms/admin-access-form.js Outdated
@priscila-moneo priscila-moneo force-pushed the feature/move-admin-access-group-grid-mui branch from c1ff274 to 9e8890d Compare May 29, 2026 17:55
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: 1

Caution

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

⚠️ Outside diff range comments (2)
src/pages/admin_access/admin-access-list-page.js (2)

77-80: ⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Handle getAdminAccess rejection.

The promise chain lacks a .catch. If the fetch fails (e.g. invalid access_id), this produces an unhandled rejection and the dialog silently never opens, leaving the user on a dead URL. Add a catch that closes/returns to the list.

🛡️ Proposed fix
     if (accessId) {
-      getAdminAccess(accessId).then(() => setOpen(true));
+      getAdminAccess(accessId)
+        .then(() => setOpen(true))
+        .catch(() => {
+          history.push("/app/admin-access");
+        });
       return;
     }
🤖 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/admin_access/admin-access-list-page.js` around lines 77 - 80, The
current call to getAdminAccess(accessId).then(() => setOpen(true)) lacks error
handling; wrap it with a .catch to handle rejection by closing the dialog and
returning the user to the list. Specifically, update the branch that calls
getAdminAccess(accessId) so failures call setOpen(false) (or ensure the dialog
remains closed) and perform a navigation back to the admin-access list (e.g.,
via the app's router helper or history push/replace) and/or show a user-facing
error; keep getAdminAccess and setOpen as the referenced symbols when
implementing the .catch handler.

150-162: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Add a render formatter for the summits/members columns

getAdminAccesses expands summits/members and requests summits.name plus members.first_name/last_name, so these columnKeys receive arrays of objects. Since the columns define no render formatter, the table renders the raw row[col.columnKey] (invalid React children / [object Object]). Add a render that maps to display strings.

🐛 Proposed fix (confirm the column renderer prop name for MuiTable)
       { columnKey: "title", header: T.translate("admin_access.title"), sortable: true },
-      { columnKey: "summits", header: T.translate("admin_access.summits") },
-      { columnKey: "members", header: T.translate("admin_access.members") }
+      {
+        columnKey: "summits",
+        header: T.translate("admin_access.summits"),
+        render: (row) => (row.summits || []).map((s) => s.name).join(", ")
+      },
+      {
+        columnKey: "members",
+        header: T.translate("admin_access.members"),
+        render: (row) =>
+          (row.members || [])
+            .map((m) => `${m.first_name} ${m.last_name}`)
+            .join(", ")
+      }
🤖 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/admin_access/admin-access-list-page.js` around lines 150 - 162, The
summits and members table columns in the columns array created in useMemo lack
render formatters, so the table tries to render arrays of objects (causing
[object Object] or invalid React children); update the column definitions for
columnKey "summits" and "members" to add a render function (or the MuiTable
column renderer prop name used in this codebase) that maps each summit object to
summit.name (joined by commas) and each member object to a display name like
`${first_name} ${last_name}` (also joined by commas) before returning the
string/JSX for the cell; locate the columns definition in
admin-access-list-page.js (the useMemo that defines columns) and add these
renderers to those two column entries.
🤖 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/forms/admin-access-form.js`:
- Around line 84-88: The getOptionLabel callback uses
member.hasOwnProperty("email"), which triggers no-prototype-builtins warnings
and can fail for objects with a null prototype or shadowed methods; update the
check in getOptionLabel to use Object.prototype.hasOwnProperty.call(member,
"email") (or an equivalent safe check like Boolean(member.email)) so the label
generation for the member (first_name, last_name, email/id) remains identical
but avoids prototype-builtins issues.

---

Outside diff comments:
In `@src/pages/admin_access/admin-access-list-page.js`:
- Around line 77-80: The current call to getAdminAccess(accessId).then(() =>
setOpen(true)) lacks error handling; wrap it with a .catch to handle rejection
by closing the dialog and returning the user to the list. Specifically, update
the branch that calls getAdminAccess(accessId) so failures call setOpen(false)
(or ensure the dialog remains closed) and perform a navigation back to the
admin-access list (e.g., via the app's router helper or history push/replace)
and/or show a user-facing error; keep getAdminAccess and setOpen as the
referenced symbols when implementing the .catch handler.
- Around line 150-162: The summits and members table columns in the columns
array created in useMemo lack render formatters, so the table tries to render
arrays of objects (causing [object Object] or invalid React children); update
the column definitions for columnKey "summits" and "members" to add a render
function (or the MuiTable column renderer prop name used in this codebase) that
maps each summit object to summit.name (joined by commas) and each member object
to a display name like `${first_name} ${last_name}` (also joined by commas)
before returning the string/JSX for the cell; locate the columns definition in
admin-access-list-page.js (the useMemo that defines columns) and add these
renderers to those two column entries.
🪄 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: 8e636853-e8b9-4f12-9db6-0f33466cbd6e

📥 Commits

Reviewing files that changed from the base of the PR and between c1ff274 and 9e8890d.

📒 Files selected for processing (7)
  • src/actions/__tests__/admin-access-actions.test.js
  • src/actions/admin-access-actions.js
  • src/components/forms/admin-access-form.js
  • src/i18n/en.json
  • src/layouts/admin-access-layout.js
  • src/pages/admin_access/__tests__/admin-access-list-page.test.js
  • src/pages/admin_access/admin-access-list-page.js
✅ Files skipped from review due to trivial changes (1)
  • src/i18n/en.json
🚧 Files skipped from review as they are similar to previous changes (3)
  • src/layouts/admin-access-layout.js
  • src/pages/admin_access/tests/admin-access-list-page.test.js
  • src/actions/tests/admin-access-actions.test.js

Comment on lines +84 to +88
getOptionLabel={(member) =>
member.hasOwnProperty("email")
? `${member.first_name} ${member.last_name} (${member.email})`
: `${member.first_name} ${member.last_name} (${member.id})`;
}}
onChange={this.handleChange}
multi={true}
: `${member.first_name} ${member.last_name} (${member.id})`
}
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 | 🟡 Minor | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
fd -H -t f -g '.eslintrc*' | xargs -r cat
rg -nP "no-prototype-builtins"
rg -nP "\.hasOwnProperty\(" --type=js -g '!**/node_modules/**'

Repository: fntechgit/summit-admin

Length of output: 31424


Avoid calling member.hasOwnProperty("email") in getOptionLabel.

no-prototype-builtins is enabled in this repo (set to "warn"), and this exact pattern also appears in other files. Using Object.prototype.hasOwnProperty.call avoids issues with null-prototype/shadowed hasOwnProperty and keeps lint clean.

♻️ Proposed fix
-              getOptionLabel={(member) =>
-                member.hasOwnProperty("email")
+              getOptionLabel={(member) =>
+                Object.prototype.hasOwnProperty.call(member, "email")
                   ? `${member.first_name} ${member.last_name} (${member.email})`
                   : `${member.first_name} ${member.last_name} (${member.id})`
               }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
getOptionLabel={(member) =>
member.hasOwnProperty("email")
? `${member.first_name} ${member.last_name} (${member.email})`
: `${member.first_name} ${member.last_name} (${member.id})`;
}}
onChange={this.handleChange}
multi={true}
: `${member.first_name} ${member.last_name} (${member.id})`
}
getOptionLabel={(member) =>
Object.prototype.hasOwnProperty.call(member, "email")
? `${member.first_name} ${member.last_name} (${member.email})`
: `${member.first_name} ${member.last_name} (${member.id})`
}
🤖 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/components/forms/admin-access-form.js` around lines 84 - 88, The
getOptionLabel callback uses member.hasOwnProperty("email"), which triggers
no-prototype-builtins warnings and can fail for objects with a null prototype or
shadowed methods; update the check in getOptionLabel to use
Object.prototype.hasOwnProperty.call(member, "email") (or an equivalent safe
check like Boolean(member.email)) so the label generation for the member
(first_name, last_name, email/id) remains identical but avoids
prototype-builtins issues.

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.

2 participants