Skip to content

MXWAR-72 fix: login password cursor#81

Open
Mohit-Davar wants to merge 1 commit intoopenMF:devfrom
Mohit-Davar:MXWAR-72-fix-login-password-cursor
Open

MXWAR-72 fix: login password cursor#81
Mohit-Davar wants to merge 1 commit intoopenMF:devfrom
Mohit-Davar:MXWAR-72-fix-login-password-cursor

Conversation

@Mohit-Davar
Copy link

@Mohit-Davar Mohit-Davar commented Mar 9, 2026

Description

This change ensures that when the password visibility is toggled on the login page via the eye icon, the cursor remains at the end of the text and the input field remains focused.

Previously, changing the input type between password and text caused the browser to lose the selection state and focus, resetting the cursor to the beginning of the field. By using a React useRef and a setTimeout, we programmatically restore focus and set the selection range to the end of the string immediately after the DOM update.

Dependencies:

No new dependencies were added.

Demo

Recording 2026-03-09 043932

Summary by CodeRabbit

  • New Features

    • Added password visibility toggle on the login page that preserves cursor position and focus.
  • Style

    • Expanded summary displays to show separate group/client borrower and loan counts in centers and groups views.
    • Consistent JSX/markup formatting and layout refinements across client and group management pages (tables, headers, selects, tabs, and form labels).

@coderabbitai
Copy link

coderabbitai bot commented Mar 9, 2026

📝 Walkthrough

Walkthrough

Mostly JSX/formatting refactors across client, center, and group pages; summary panels expanded to show separate group/client metrics; one functional change adds a password visibility toggle that preserves cursor position in the login form.

Changes

Cohort / File(s) Summary
Summary & Metrics
src/pages/centers/centers-view/general-tab/CentersGeneralTab.tsx, src/pages/groups/groups-view/general-tab/GroupsGeneralTab.tsx
Reordered and expanded summary lines to show distinct metrics: Active Clients, Active Group Borrowers, Active Group Loans, Active Client Borrowers, Active Client Loans. Presentation-only changes to header rendering and conditional wrappers.
Login (behavioral)
src/pages/login/Login.tsx
Added password visibility toggle using a ref to preserve cursor/selection and focus; aria-pressed added for accessibility.
Clients pages — formatting
src/pages/clients/Clients.tsx, src/pages/clients/clients-view/ClientsView.tsx, src/pages/clients/clients-view/general-tab/ClientsGeneralTab.tsx
Moved translations and header text into multiline JSX blocks, reformatted pagination caption and table headers; no logic changes.
Clients — tabs & forms
src/pages/clients/clients-view/Identities-tab/ClientsidentitiesTab.tsx, src/pages/clients/clients-view/address-tab/ClientsAddressTab.tsx, src/pages/clients/clients-view/family-members-tab/ClientsFamilyMembersAddTab.tsx, src/pages/clients/clients-view/family-members-tab/ClientsFamilyMembersTab.tsx
Presentation changes: moved required asterisks to adjacent spans, wrapped SelectItem/SelectValue contents as children, and reformatted dropdown/tab object literals. Behavior unchanged.
Clients — charge view
src/pages/clients/clients-view/charges/view-charge/ViewCharge.tsx
Wrapped two label cells (chargeCalculationType, dueDate) in their own <td> blocks and adjusted line breaks; data bindings unchanged.
Groups pages — formatting & actions
src/pages/groups/groups-view/GroupsView.tsx, src/pages/groups/groups-view/group-actions/EditGroups.tsx, src/pages/groups/groups-view/group-actions/ManageGroupMembers.tsx, src/pages/groups/groups-view/group-actions/TransferClients.tsx, src/pages/groups/groups-view/group-actions/AttachMeeting.tsx
Widespread JSX wrapping and indentation changes (breadcrumbs, labels, selects, table headers). No control-flow or API changes.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~28 minutes

Possibly related PRs

Suggested reviewers

  • IOhacker

Poem

🐰 Hop, hop, the code looks bright,
Lines tucked neatly, tidy sight.
Password peeks without a stumble,
Metrics split so numbers rumble,
Tiny hops — a polished flight!

🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'MXWAR-72 fix: login password cursor' directly and specifically addresses the main functional change in the PR: fixing cursor position preservation when toggling password visibility on the login page.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

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

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment

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

@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/pages/groups/groups-view/group-actions/ManageGroupMembers.tsx (1)

117-126: ⚠️ Potential issue | 🟠 Major

Persist the member removal before updating local state.

This flow only filters clientMembers in memory. After a reload, the member will reappear because nothing is sent to the backend. Please call the group-member removal API here and update local state only after that request succeeds.

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

In `@src/pages/groups/groups-view/group-actions/ManageGroupMembers.tsx` around
lines 117 - 126, In removeClient, instead of immediately filtering clientMembers
in memory, call the backend group-member removal API (e.g., await
removeGroupMember or deleteGroupMember with the group id and client.id) after
user confirmation and before calling setClientMembers; only update state
(setClientMembers(prev => prev.filter(...))) once the API returns success,
handle failures by showing an error and not mutating state, and ensure
setBusy(true) is cleared in a finally block; use the existing symbols
removeClient, id, client.id, setClientMembers and setBusy to locate and
implement the change.
🧹 Nitpick comments (1)
src/pages/login/Login.tsx (1)

66-81: Add a regression test for focus and caret restoration.

This fix is browser-sensitive and easy to regress. A component test that types into the password field, toggles visibility, and asserts both focus retention and caret position would lock the bugfix in.

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

In `@src/pages/login/Login.tsx` around lines 66 - 81, Add a regression component
test for togglePasswordVisibility that ensures focus and caret are preserved:
render the Login component, type into the password input referenced by
passwordRef, move the caret to a non-edge position, trigger the visibility
toggle (the handler that calls setShowPassword and then focuses and calls
setSelectionRange inside setTimeout), and assert the input still has
document.activeElement and that its selectionStart/selectionEnd match the prior
caret positions; this test should fail if focus or selection restoration
regresses.
🤖 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/pages/groups/groups-view/GroupsView.tsx`:
- Around line 234-236: The center label is rendering the group name; update the
JSX in GroupsView.tsx to display the center's name instead by replacing
group?.name with group?.center?.name and, if that is undefined, fall back to
t('view.missingInOpenAPI') (e.g. use group?.center?.name ??
t('view.missingInOpenAPI')). Locate this change where the div currently contains
{t('view.centerName')} {group?.name} and keep the surrounding label text intact.

In `@src/pages/login/Login.tsx`:
- Around line 66-81: The togglePasswordVisibility handler currently always
refocuses the password input, stealing focus from the toggling control; update
togglePasswordVisibility to first detect whether the input had focus (e.g.,
const hadFocus = document.activeElement === passwordRef.current) before flipping
show state, then only call passwordRef.current.focus() and
setSelectionRange(...) inside the setTimeout when hadFocus is true; keep using
passwordRef, selectionStart/selectionEnd and setShowPassword as currently
implemented but gate the restore logic on hadFocus.

---

Outside diff comments:
In `@src/pages/groups/groups-view/group-actions/ManageGroupMembers.tsx`:
- Around line 117-126: In removeClient, instead of immediately filtering
clientMembers in memory, call the backend group-member removal API (e.g., await
removeGroupMember or deleteGroupMember with the group id and client.id) after
user confirmation and before calling setClientMembers; only update state
(setClientMembers(prev => prev.filter(...))) once the API returns success,
handle failures by showing an error and not mutating state, and ensure
setBusy(true) is cleared in a finally block; use the existing symbols
removeClient, id, client.id, setClientMembers and setBusy to locate and
implement the change.

---

Nitpick comments:
In `@src/pages/login/Login.tsx`:
- Around line 66-81: Add a regression component test for
togglePasswordVisibility that ensures focus and caret are preserved: render the
Login component, type into the password input referenced by passwordRef, move
the caret to a non-edge position, trigger the visibility toggle (the handler
that calls setShowPassword and then focuses and calls setSelectionRange inside
setTimeout), and assert the input still has document.activeElement and that its
selectionStart/selectionEnd match the prior caret positions; this test should
fail if focus or selection restoration regresses.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 3291637c-9dca-41e2-867e-d2277ab1b2cf

📥 Commits

Reviewing files that changed from the base of the PR and between 271cc0a and 5de72be.

📒 Files selected for processing (16)
  • src/pages/centers/centers-view/general-tab/CentersGeneralTab.tsx
  • src/pages/clients/Clients.tsx
  • src/pages/clients/clients-view/ClientsView.tsx
  • src/pages/clients/clients-view/Identities-tab/ClientsidentitiesTab.tsx
  • src/pages/clients/clients-view/address-tab/ClientsAddressTab.tsx
  • src/pages/clients/clients-view/charges/view-charge/ViewCharge.tsx
  • src/pages/clients/clients-view/family-members-tab/ClientsFamilyMembersAddTab.tsx
  • src/pages/clients/clients-view/family-members-tab/ClientsFamilyMembersTab.tsx
  • src/pages/clients/clients-view/general-tab/ClientsGeneralTab.tsx
  • src/pages/groups/groups-view/GroupsView.tsx
  • src/pages/groups/groups-view/general-tab/GroupsGeneralTab.tsx
  • src/pages/groups/groups-view/group-actions/AttachMeeting.tsx
  • src/pages/groups/groups-view/group-actions/EditGroups.tsx
  • src/pages/groups/groups-view/group-actions/ManageGroupMembers.tsx
  • src/pages/groups/groups-view/group-actions/TransferClients.tsx
  • src/pages/login/Login.tsx

Comment on lines +234 to +236
<div>
{t('view.centerName')} {group?.name}
</div>
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Render the actual center name here, not the group name.

Line 235 shows group?.name under the center label, so the UI repeats the group name and displays the wrong value for groups attached to a center. If this response does not include a center-name field, fall back to t('view.missingInOpenAPI') instead of duplicating the group name.

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

In `@src/pages/groups/groups-view/GroupsView.tsx` around lines 234 - 236, The
center label is rendering the group name; update the JSX in GroupsView.tsx to
display the center's name instead by replacing group?.name with
group?.center?.name and, if that is undefined, fall back to
t('view.missingInOpenAPI') (e.g. use group?.center?.name ??
t('view.missingInOpenAPI')). Locate this change where the div currently contains
{t('view.centerName')} {group?.name} and keep the surrounding label text intact.

@Mohit-Davar Mohit-Davar force-pushed the MXWAR-72-fix-login-password-cursor branch from 5de72be to 2fb665b Compare March 9, 2026 16:47
Copy link

@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

♻️ Duplicate comments (1)
src/pages/groups/groups-view/GroupsView.tsx (1)

234-236: ⚠️ Potential issue | 🟡 Minor

Render the center's name here, not the group's name.

Line 235 still binds {group?.name} under the center label, so the UI repeats the group name instead of showing the linked center. This should use the center name field and fall back to t('view.missingInOpenAPI') when it is absent.

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

In `@src/pages/groups/groups-view/GroupsView.tsx` around lines 234 - 236, Replace
the mistaken binding that shows the group's name under the center label: in
GroupsView (the JSX block rendering "{t('view.centerName')} {group?.name}") use
the linked center's name (e.g., group?.center?.name or center?.name depending on
how the center is exposed) and fall back to t('view.missingInOpenAPI') when
absent; update the expression in that div to display the center name with a
nullish/coalescing or conditional fallback to t('view.missingInOpenAPI').
🤖 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/pages/groups/groups-view/GroupsView.tsx`:
- Around line 96-99: The menu options are being created before group.id is
available causing transient paths like `groups/undefined/...`; update the logic
that builds `menuOptions` (the block that calls opts.push with label
t('view.menu.edit') and path `groups/${group?.id}/edit`) to only add
edit/view/delete entries when `group?.id` is truthy, or alternatively keep the
dropdown component disabled until the record loads (e.g., use the same group
loading boolean used by GroupsView to gate the menu rendering); ensure you apply
the same guard to the other pushes around lines where `groups/${group?.id}/...`
are created so no menu item is produced with an undefined id.

---

Duplicate comments:
In `@src/pages/groups/groups-view/GroupsView.tsx`:
- Around line 234-236: Replace the mistaken binding that shows the group's name
under the center label: in GroupsView (the JSX block rendering
"{t('view.centerName')} {group?.name}") use the linked center's name (e.g.,
group?.center?.name or center?.name depending on how the center is exposed) and
fall back to t('view.missingInOpenAPI') when absent; update the expression in
that div to display the center name with a nullish/coalescing or conditional
fallback to t('view.missingInOpenAPI').

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 560d0b30-bcdb-4e1f-a407-5d493efdac99

📥 Commits

Reviewing files that changed from the base of the PR and between 5de72be and 2fb665b.

📒 Files selected for processing (16)
  • src/pages/centers/centers-view/general-tab/CentersGeneralTab.tsx
  • src/pages/clients/Clients.tsx
  • src/pages/clients/clients-view/ClientsView.tsx
  • src/pages/clients/clients-view/Identities-tab/ClientsidentitiesTab.tsx
  • src/pages/clients/clients-view/address-tab/ClientsAddressTab.tsx
  • src/pages/clients/clients-view/charges/view-charge/ViewCharge.tsx
  • src/pages/clients/clients-view/family-members-tab/ClientsFamilyMembersAddTab.tsx
  • src/pages/clients/clients-view/family-members-tab/ClientsFamilyMembersTab.tsx
  • src/pages/clients/clients-view/general-tab/ClientsGeneralTab.tsx
  • src/pages/groups/groups-view/GroupsView.tsx
  • src/pages/groups/groups-view/general-tab/GroupsGeneralTab.tsx
  • src/pages/groups/groups-view/group-actions/AttachMeeting.tsx
  • src/pages/groups/groups-view/group-actions/EditGroups.tsx
  • src/pages/groups/groups-view/group-actions/ManageGroupMembers.tsx
  • src/pages/groups/groups-view/group-actions/TransferClients.tsx
  • src/pages/login/Login.tsx
✅ Files skipped from review due to trivial changes (2)
  • src/pages/groups/groups-view/group-actions/AttachMeeting.tsx
  • src/pages/groups/groups-view/group-actions/ManageGroupMembers.tsx
🚧 Files skipped from review as they are similar to previous changes (10)
  • src/pages/groups/groups-view/group-actions/EditGroups.tsx
  • src/pages/clients/clients-view/general-tab/ClientsGeneralTab.tsx
  • src/pages/clients/clients-view/family-members-tab/ClientsFamilyMembersTab.tsx
  • src/pages/login/Login.tsx
  • src/pages/clients/Clients.tsx
  • src/pages/clients/clients-view/ClientsView.tsx
  • src/pages/clients/clients-view/Identities-tab/ClientsidentitiesTab.tsx
  • src/pages/groups/groups-view/general-tab/GroupsGeneralTab.tsx
  • src/pages/groups/groups-view/group-actions/TransferClients.tsx
  • src/pages/clients/clients-view/charges/view-charge/ViewCharge.tsx

Comment on lines +96 to +99
opts.push({
label: t('view.menu.edit'),
path: `groups/${group?.id}/edit`,
})
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Hide or disable menu actions until group.id is available.

These entries are created on the initial render as well, so their paths can briefly become groups/undefined/... before the fetch completes. A fast click here will navigate to an invalid route. Guard menuOptions on group?.id or keep the dropdown disabled until the record is loaded.

Suggested guard
   const menuOptions = useMemo(() => {
+    if (!group?.id) {
+      return []
+    }
+
     const opts: any[] = []

Also applies to: 177-180

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

In `@src/pages/groups/groups-view/GroupsView.tsx` around lines 96 - 99, The menu
options are being created before group.id is available causing transient paths
like `groups/undefined/...`; update the logic that builds `menuOptions` (the
block that calls opts.push with label t('view.menu.edit') and path
`groups/${group?.id}/edit`) to only add edit/view/delete entries when
`group?.id` is truthy, or alternatively keep the dropdown component disabled
until the record loads (e.g., use the same group loading boolean used by
GroupsView to gate the menu rendering); ensure you apply the same guard to the
other pushes around lines where `groups/${group?.id}/...` are created so no menu
item is produced with an undefined id.

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