-
Notifications
You must be signed in to change notification settings - Fork 46
Hcmpre 3049 #3183
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Hcmpre 3049 #3183
Conversation
Important Review skippedReview was skipped due to path filters ⛔ Files ignored due to path filters (1)
CodeRabbit blocks several paths by default. You can override this behavior by explicitly including those paths in the path filters. For example, including You can disable this status message by setting the 📝 WalkthroughWalkthroughAdds attendance enroll/de‑enroll/search clients and hooks, payment + HRMS UI components/pages (inbox, edit register, popups, boundary selection), new proxy routes and URLs, example UI customizations, and extensive campaign‑manager conditional navigation/display editor enhancements. Changes
Sequence Diagram(s)sequenceDiagram
autonumber
actor User
participant Table as EditAttendanceManagementTable
participant Confirm as AlertPopUp
participant HookDel as useDeleteAttendeeFromRegister
participant APIdel as AttendeeService.delete
participant Toast as UI_Toast
User->>Table: Click "Disable User"
Table->>Confirm: Open confirmation
User->>Confirm: Confirm
Confirm->>Table: onConfirm
Table->>HookDel: mutate(deEnrollPayload)
HookDel->>APIdel: POST /health-attendance/attendee/v1/_delete
APIdel-->>HookDel: Success / Error
alt Success
HookDel-->>Table: onSuccess
Table->>Toast: show success
Table->>Table: refresh list callback
else Error
HookDel-->>Table: onError
Table->>Toast: show error
end
sequenceDiagram
autonumber
actor User
participant PopUp as SearchUserPopUp
participant HookSearch as useSearchIndividualForRegister
participant APIsearch as AttendeeService.search
participant HookCreate as useCreateAttendeeFromRegister
participant APIcreate as AttendeeService.create
participant Toast as UI_Toast
User->>PopUp: Enter name + Submit
PopUp->>HookSearch: mutate(searchParams)
HookSearch->>APIsearch: POST /health-individual/v1/_search
APIsearch-->>HookSearch: Individuals
HookSearch-->>PopUp: results
User->>PopUp: Select individual & Enroll
PopUp->>HookCreate: mutate(enrollPayload)
HookCreate->>APIcreate: POST /health-attendance/attendee/v1/_create
APIcreate-->>HookCreate: Success / Error
alt Success
HookCreate-->>PopUp: onSuccess
PopUp->>Toast: show success
PopUp->>PopUp: clear/close
else Error
HookCreate-->>PopUp: onError
PopUp->>Toast: show error
end
sequenceDiagram
autonumber
actor User
participant Inbox as AttendanceInboxTable
participant Session as Digit.SessionStorage
participant Router as History.push
User->>Inbox: Click Register ID
Inbox->>Session: Read paymentInbox.selectedProject.endDate
alt endDate exists
Inbox->>Inbox: compare Date.now() to endDate
alt expired
Inbox->>Router: navigate to /view-attendance?registerNumber&boundaryCode
else active
Inbox->>Router: navigate to /edit-register?registerNumber&boundaryCode®isterId
end
else missing endDate
Inbox->>Router: navigate to /view-attendance (fallback)
end
Estimated code review effort🎯 5 (Critical) | ⏱️ ~120 minutes Poem
Pre-merge checks and finishing touches❌ Failed checks (2 warnings, 1 inconclusive)
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. Comment |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 91
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (15)
health/micro-ui/web/micro-ui-internals/packages/modules/health-payments/src/components/attendance_inbox/table_inbox.js (2)
71-74
: Centralize navigation and harden date handling (ms/sec, ISO) + URL-encode paramsPrevents ms/sec bugs, unifies logic for both link and row-click, and avoids duplicated route strings.
@@ const onCommentLogClose = () => { setCommentLogs(false); }; + // Centralized navigation based on register end date + const navigateForRow = (row, e) => { + e?.stopPropagation?.(); + e?.preventDefault?.(); + const existingPaymentInbox = Digit.SessionStorage.get("paymentInbox"); + const rawEnd = + selectedProject?.endDate ?? existingPaymentInbox?.selectedProject?.endDate; + let endMs; + if (typeof rawEnd === "number") { + endMs = rawEnd < 1e12 ? rawEnd * 1000 : rawEnd; // support epoch seconds + } else if (rawEnd instanceof Date) { + endMs = rawEnd.getTime(); + } else if (rawEnd) { + const parsed = Date.parse(rawEnd); // support ISO strings + endMs = Number.isNaN(parsed) ? undefined : parsed; + } + + const base = `/${window?.contextPath}/employee/payments`; + const registerNumber = encodeURIComponent(row?.id ?? ""); + const boundaryCode = encodeURIComponent(row?.boundary ?? ""); + + // Allow edit until and including end date; otherwise view-only + if (endMs && Date.now() <= endMs && row?.registerId) { + history.push( + `${base}/edit-register?registerNumber=${registerNumber}&boundaryCode=${boundaryCode}®isterId=${encodeURIComponent( + row.registerId + )}` + ); + } else { + history.push( + `${base}/view-attendance?registerNumber=${registerNumber}&boundaryCode=${boundaryCode}` + ); + } + };
194-198
: Align row-click behavior with link behavior to avoid inconsistent UXUse the same gating function for row clicks.
const handleRowClick = (row) => { - history.push( - `/${window?.contextPath}/employee/payments/view-attendance?registerNumber=${row?.id}&boundaryCode=${row?.boundary}` - ) + navigateForRow(row); };health/micro-ui/web/micro-ui-internals/packages/modules/health-payments/src/pages/employee/project_selection.js (7)
34-41
: Potential crash when boundaryHierarchyOrder is undefined; ensure AGGREGATION_LEVEL_OPTIONS is always an arrayAGGREGATION_LEVEL_OPTIONS can become undefined, but later code calls .find/.filter on it. Provide a safe fallback and robust max-order handling.
-const AGGREGATION_LEVEL_OPTIONS = boundaryHierarchyOrder - ?.filter(item => item.order <= boundaryHierarchyOrder?.find(d => d.code === lowestLevelBoundaryType)?.order) - ?.map(b => ({ - name: `HCM_AM_${b?.code}_LEVEL`, - code: b?.code, - order: b?.order, - })); +const maxOrder = + boundaryHierarchyOrder?.find((d) => d.code === lowestLevelBoundaryType)?.order; +const source = Array.isArray(boundaryHierarchyOrder) ? boundaryHierarchyOrder : []; +const AGGREGATION_LEVEL_OPTIONS = source + .filter((item) => (maxOrder == null ? true : item.order <= maxOrder)) + .map((b) => ({ + name: `HCM_AM_${b?.code}_LEVEL`, + code: b?.code, + order: b?.order, + }));
43-55
: Falsy check on boundaryTypeOrder breaks when order is 0; use nullish checkIf order can be 0, current truthy check falls back incorrectly to all options.
-const boundaryTypeOrder = AGGREGATION_LEVEL_OPTIONS.find(option => option.code === selectedProject?.address?.boundaryType)?.order; - -if (boundaryTypeOrder) { +const boundaryTypeOrder = AGGREGATION_LEVEL_OPTIONS.find( + (option) => option.code === selectedProject?.address?.boundaryType +)?.order; + +if (boundaryTypeOrder != null) { setFilteredAggregationOptions(AGGREGATION_LEVEL_OPTIONS.filter(option => option.order >= boundaryTypeOrder)); } else { setFilteredAggregationOptions(AGGREGATION_LEVEL_OPTIONS); }
58-64
: Don’t overwrite a previously selected project on mountOnly default to the first project if there’s no prior selection.
-const projectData = Digit?.SessionStorage.get("staffProjects") || []; -setProject(projectData); -handleProjectSelect(projectData?.[0]); // Default to the first project +const projectData = Digit?.SessionStorage.get("staffProjects") || []; +setProject(projectData); +if (!selectedProject && projectData?.length) { + handleProjectSelect(projectData[0]); // Default to the first project +}
73-81
: Compare aggregation level by identity key, not object referenceObject reference inequality will always clear boundary even when the same level is re-selected. Compare by code.
- if (value !== Digit.SessionStorage.get("selectedLevel")) { + if (value?.code !== Digit.SessionStorage.get("selectedLevel")?.code) { Digit.SessionStorage.del("selectedBoundaryCode"); Digit.SessionStorage.del("boundary"); Digit.SessionStorage.del("selectedValues"); }
24-31
: Harden SessionStorage access; use optional chaining consistentlyMixing Digit? and Digit can cause runtime errors in non-standard boot paths. Be consistent and safe.
-const [selectedProject, setSelectedProject] = useState(() => Digit.SessionStorage.get("selectedProject") || null); -const [selectedLevel, setSelectedLevel] = useState(() => Digit.SessionStorage.get("selectedLevel") || null); -const boundaryHierarchyOrder = Digit.SessionStorage.get("boundaryHierarchyOrder"); -const lowestLevelBoundaryType = Digit.SessionStorage.get("paymentsConfig")?.lowestLevelBoundary || "DISTRICT"; +const [selectedProject, setSelectedProject] = useState(() => Digit?.SessionStorage.get("selectedProject") || null); +const [selectedLevel, setSelectedLevel] = useState(() => Digit?.SessionStorage.get("selectedLevel") || null); +const boundaryHierarchyOrder = Digit?.SessionStorage.get("boundaryHierarchyOrder"); +const lowestLevelBoundaryType = Digit?.SessionStorage.get("paymentsConfig")?.lowestLevelBoundary || "DISTRICT";
136-146
: Drop redundant braces around wrapper divReduces noise; no functional change.
- {<div className="label-text"> + <div className="label-text"> <Dropdown t={t} option={filteredAggregationOptions} name={"code"} optionKey={"name"} selected={selectedLevel} select={handleAggregationLevelChange} /> - </div>} + </div>
150-171
: Fix stray comma rendering and unnecessary braces around ActionBarA literal comma after the first Button will render in the UI. Also, wrapping in braces is unnecessary.
- {<ActionBar className="mc_back"> + <ActionBar className="mc_back"> <Button icon="ArrowBack" label={t("HCM_AM_BACK_LABEL")} onClick={() => history.push(`/${window.contextPath}/employee`)} style={{ marginLeft: "2.5rem", minWidth: "14rem" }} type="button" variation="secondary" - />, + /> <Button icon="ArrowForward" isSuffix label={t("HCM_AM_NEXT_LABEL")} onClick={handleNextClick} style={{ minWidth: "14rem" }} type="button" variation="primary" /> - - </ActionBar>} + </ActionBar>health/micro-ui/web/micro-ui-internals/packages/modules/health-hrms/src/services/service.js (1)
69-76
: Avoid persisting literal "undefined" for reportingTo
In service.js:
- In the
createdAssignments
payload (around line 73), replace- reportingTo: data?.UserAssignment?.code || "undefined" + ...(data?.UserAssignment?.code && { reportingTo: data.UserAssignment.code })- In
formPayloadToUpdateUser
(export at ~line 124), addassignment.reportingTo = data?.UserAssignment?.code ?? assignment.reportingTo;- In
editDefaultUserValue
(export at ~line 198), prefill:UserAssignment: data?.[0]?.assignments?.[0]?.reportingTo ? { code: data[0].assignments[0].reportingTo } : null,health/micro-ui/web/micro-ui-internals/packages/modules/health-hrms/src/pages/employee/createEmployee.js (1)
360-387
: Ensure UserAssignment is part of submit gatingWith
reportingTo
added to the payload, includeformData?.UserAssignment?.code
in the readiness check to prevent sending incomplete data.Add outside this hunk (in the same function):
// In the big if-condition that computes canSubmit: && formData?.UserAssignment?.codehealth/micro-ui/web/micro-ui-internals/packages/modules/health-payments/src/pages/employee/index.js (1)
17-58
: Fix undefined variable ‘location’ passed to ProjectBreadCrumb.
App
passeslocation
but it’s not defined in this scope; this will throw. LetProjectBreadCrumb
derive location viauseLocation()
and remove the prop.-const ProjectBreadCrumb = ({ location }) => { +const ProjectBreadCrumb = () => { const { t } = useTranslation(); - const local = useLocation(); + const local = useLocation(); const { fromCampaignSupervisor } = local?.state || false; const crumbs = [ @@ - show: - Digit.Utils.locale.getTransformedLocale(location.pathname.split("/").pop()) === "REGISTERS_INBOX" || ((Digit.Utils.locale.getTransformedLocale(location.pathname.split("/").pop()) === "VIEW_ATTENDANCE" || - Digit.Utils.locale.getTransformedLocale(location.pathname.split("/").pop()) === "EDIT_ATTENDANCE") && !fromCampaignSupervisor) + show: + Digit.Utils.locale.getTransformedLocale(local.pathname.split("/").pop()) === "REGISTERS_INBOX" || ((Digit.Utils.locale.getTransformedLocale(local.pathname.split("/").pop()) === "VIEW_ATTENDANCE" || + Digit.Utils.locale.getTransformedLocale(local.pathname.split("/").pop()) === "EDIT_ATTENDANCE") && !fromCampaignSupervisor) @@ - show: - Digit.Utils.locale.getTransformedLocale(location.pathname.split("/").pop()) === "GENERATE_BILL" || ((Digit.Utils.locale.getTransformedLocale(location.pathname.split("/").pop()) === "VIEW_ATTENDANCE" || - Digit.Utils.locale.getTransformedLocale(location.pathname.split("/").pop()) === "EDIT_ATTENDANCE") && fromCampaignSupervisor) + show: + Digit.Utils.locale.getTransformedLocale(local.pathname.split("/").pop()) === "GENERATE_BILL" || ((Digit.Utils.locale.getTransformedLocale(local.pathname.split("/").pop()) === "VIEW_ATTENDANCE" || + Digit.Utils.locale.getTransformedLocale(local.pathname.split("/").pop()) === "EDIT_ATTENDANCE") && fromCampaignSupervisor) @@ - show: - Digit.Utils.locale.getTransformedLocale(location.pathname.split("/").pop()) === "VIEW_ATTENDANCE" || - Digit.Utils.locale.getTransformedLocale(location.pathname.split("/").pop()) === "EDIT_ATTENDANCE" || - Digit.Utils.locale.getTransformedLocale(location.pathname.split("/").pop()) === "EDIT_REGISTER" + show: + Digit.Utils.locale.getTransformedLocale(local.pathname.split("/").pop()) === "VIEW_ATTENDANCE" || + Digit.Utils.locale.getTransformedLocale(local.pathname.split("/").pop()) === "EDIT_ATTENDANCE" || + Digit.Utils.locale.getTransformedLocale(local.pathname.split("/").pop()) === "EDIT_REGISTER" @@ - content: t(`HCM_AM_BREADCRUMBS_${Digit.Utils.locale.getTransformedLocale(location.pathname.split("/").pop())}`), + content: t(`HCM_AM_BREADCRUMBS_${Digit.Utils.locale.getTransformedLocale(local.pathname.split("/").pop())}`), @@ - <ProjectBreadCrumb location={location} /> + <ProjectBreadCrumb />Also applies to: 66-70
health/micro-ui/web/micro-ui-internals/example/src/UICustomizations.js (3)
54-60
: Comment contradicts implementation: returns milliseconds, not secondsThe function returns
getTime()
(ms). Update the comment to avoid misuse.- // Convert the date to epoch time (seconds) + // Convert the date to epoch time (milliseconds) return Math.floor(date.getTime());
2223-2236
: Duplicate getCustomActionLabel keys
getCustomActionLabel
is defined twice in several configs; later definitions shadow earlier ones. Clean up duplicates.Remove the first occurrence and keep a single
getCustomActionLabel
per config.Also applies to: 2298-2311, 2374-2387, 2449-2462, 2524-2537, 2598-2611
1587-1641
: PGR preProcess: ensure consistent clearing of filtersGood cleanup overall. Minor nits:
- Coalesce
localityArray
with a default empty array;- Avoid leaving
complaintType
as undefined.No diff required; optional tighten-ups.
Also applies to: 1624-1630
📜 Review details
Configuration used: CodeRabbit UI
Review profile: ASSERTIVE
Plan: Pro
⛔ Files ignored due to path filters (2)
health/micro-ui/web/micro-ui-internals/example/package.json
is excluded by!**/*.json
health/micro-ui/web/micro-ui-internals/packages/modules/health-payments/package.json
is excluded by!**/*.json
📒 Files selected for processing (37)
health/micro-ui/web/micro-ui-internals/example/src/UICustomizations.js
(24 hunks)health/micro-ui/web/micro-ui-internals/example/src/index.js
(2 hunks)health/micro-ui/web/micro-ui-internals/example/src/setupProxy.js
(1 hunks)health/micro-ui/web/micro-ui-internals/packages/modules/health-hrms/src/Module.js
(2 hunks)health/micro-ui/web/micro-ui-internals/packages/modules/health-hrms/src/components/config/createEmployeeConfig.js
(1 hunks)health/micro-ui/web/micro-ui-internals/packages/modules/health-hrms/src/components/pageComponents/UserAssigment.js
(1 hunks)health/micro-ui/web/micro-ui-internals/packages/modules/health-hrms/src/pages/employee/HierarchySelection.js
(2 hunks)health/micro-ui/web/micro-ui-internals/packages/modules/health-hrms/src/pages/employee/createEmployee.js
(2 hunks)health/micro-ui/web/micro-ui-internals/packages/modules/health-hrms/src/services/service.js
(5 hunks)health/micro-ui/web/micro-ui-internals/packages/modules/health-hrms/src/services/urls.js
(1 hunks)health/micro-ui/web/micro-ui-internals/packages/modules/health-payments/src/Module.js
(5 hunks)health/micro-ui/web/micro-ui-internals/packages/modules/health-payments/src/components/BoundaryComponent.js
(1 hunks)health/micro-ui/web/micro-ui-internals/packages/modules/health-payments/src/components/EditAttendanceManagementTable.js
(1 hunks)health/micro-ui/web/micro-ui-internals/packages/modules/health-payments/src/components/HierachySelection.js
(1 hunks)health/micro-ui/web/micro-ui-internals/packages/modules/health-payments/src/components/PaymentsCard.js
(1 hunks)health/micro-ui/web/micro-ui-internals/packages/modules/health-payments/src/components/SearchAttendeeBoundary.js
(1 hunks)health/micro-ui/web/micro-ui-internals/packages/modules/health-payments/src/components/SearchUserPopUp.js
(1 hunks)health/micro-ui/web/micro-ui-internals/packages/modules/health-payments/src/components/SelectableList.js
(1 hunks)health/micro-ui/web/micro-ui-internals/packages/modules/health-payments/src/components/attendance_inbox/table_inbox.js
(1 hunks)health/micro-ui/web/micro-ui-internals/packages/modules/health-payments/src/components/editAttendeesPopUp.js
(1 hunks)health/micro-ui/web/micro-ui-internals/packages/modules/health-payments/src/components/table_inbox_custom_style.js
(1 hunks)health/micro-ui/web/micro-ui-internals/packages/modules/health-payments/src/config/AttendeeInboxConfig.js
(1 hunks)health/micro-ui/web/micro-ui-internals/packages/modules/health-payments/src/hooks/attendance/create_attendee_register.js
(1 hunks)health/micro-ui/web/micro-ui-internals/packages/modules/health-payments/src/hooks/attendance/delete_attendee_register.js
(1 hunks)health/micro-ui/web/micro-ui-internals/packages/modules/health-payments/src/hooks/attendance/search_individual.js
(1 hunks)health/micro-ui/web/micro-ui-internals/packages/modules/health-payments/src/hooks/index.js
(1 hunks)health/micro-ui/web/micro-ui-internals/packages/modules/health-payments/src/pages/employee/AttendeeSearchAssign.js
(1 hunks)health/micro-ui/web/micro-ui-internals/packages/modules/health-payments/src/pages/employee/EditRegister.js
(1 hunks)health/micro-ui/web/micro-ui-internals/packages/modules/health-payments/src/pages/employee/ViewAttendance.js
(5 hunks)health/micro-ui/web/micro-ui-internals/packages/modules/health-payments/src/pages/employee/index.js
(3 hunks)health/micro-ui/web/micro-ui-internals/packages/modules/health-payments/src/pages/employee/project_selection.js
(6 hunks)health/micro-ui/web/micro-ui-internals/packages/modules/health-payments/src/services/PaymentsInitialization.js
(1 hunks)health/micro-ui/web/micro-ui-internals/packages/modules/health-payments/src/services/attendance/attendanceService.js
(1 hunks)health/micro-ui/web/micro-ui-internals/packages/modules/health-payments/src/services/attendance/attendee_service/attendeeService.js
(1 hunks)health/micro-ui/web/micro-ui-internals/packages/modules/health-payments/src/services/urls.js
(1 hunks)health/micro-ui/web/micro-ui-internals/packages/modules/health-payments/src/utils/constants.js
(1 hunks)health/micro-ui/web/micro-ui-internals/packages/modules/health-payments/src/utils/update_attendance_summary.js
(1 hunks)
🧰 Additional context used
📓 Path-based instructions (1)
**/*.js
⚙️ CodeRabbit configuration file
check
Files:
health/micro-ui/web/micro-ui-internals/example/src/setupProxy.js
health/micro-ui/web/micro-ui-internals/packages/modules/health-payments/src/components/PaymentsCard.js
health/micro-ui/web/micro-ui-internals/packages/modules/health-payments/src/components/SelectableList.js
health/micro-ui/web/micro-ui-internals/packages/modules/health-payments/src/components/BoundaryComponent.js
health/micro-ui/web/micro-ui-internals/packages/modules/health-payments/src/hooks/attendance/search_individual.js
health/micro-ui/web/micro-ui-internals/packages/modules/health-payments/src/hooks/attendance/create_attendee_register.js
health/micro-ui/web/micro-ui-internals/packages/modules/health-payments/src/services/attendance/attendee_service/attendeeService.js
health/micro-ui/web/micro-ui-internals/example/src/index.js
health/micro-ui/web/micro-ui-internals/packages/modules/health-payments/src/components/SearchAttendeeBoundary.js
health/micro-ui/web/micro-ui-internals/packages/modules/health-payments/src/services/PaymentsInitialization.js
health/micro-ui/web/micro-ui-internals/packages/modules/health-payments/src/utils/constants.js
health/micro-ui/web/micro-ui-internals/packages/modules/health-payments/src/components/EditAttendanceManagementTable.js
health/micro-ui/web/micro-ui-internals/packages/modules/health-payments/src/config/AttendeeInboxConfig.js
health/micro-ui/web/micro-ui-internals/packages/modules/health-payments/src/components/table_inbox_custom_style.js
health/micro-ui/web/micro-ui-internals/packages/modules/health-payments/src/hooks/attendance/delete_attendee_register.js
health/micro-ui/web/micro-ui-internals/packages/modules/health-payments/src/pages/employee/index.js
health/micro-ui/web/micro-ui-internals/packages/modules/health-hrms/src/pages/employee/createEmployee.js
health/micro-ui/web/micro-ui-internals/packages/modules/health-payments/src/pages/employee/AttendeeSearchAssign.js
health/micro-ui/web/micro-ui-internals/packages/modules/health-hrms/src/services/urls.js
health/micro-ui/web/micro-ui-internals/packages/modules/health-payments/src/components/attendance_inbox/table_inbox.js
health/micro-ui/web/micro-ui-internals/packages/modules/health-hrms/src/components/config/createEmployeeConfig.js
health/micro-ui/web/micro-ui-internals/packages/modules/health-payments/src/pages/employee/ViewAttendance.js
health/micro-ui/web/micro-ui-internals/packages/modules/health-payments/src/hooks/index.js
health/micro-ui/web/micro-ui-internals/packages/modules/health-payments/src/components/HierachySelection.js
health/micro-ui/web/micro-ui-internals/packages/modules/health-payments/src/services/urls.js
health/micro-ui/web/micro-ui-internals/packages/modules/health-payments/src/services/attendance/attendanceService.js
health/micro-ui/web/micro-ui-internals/packages/modules/health-payments/src/components/SearchUserPopUp.js
health/micro-ui/web/micro-ui-internals/packages/modules/health-payments/src/pages/employee/EditRegister.js
health/micro-ui/web/micro-ui-internals/packages/modules/health-payments/src/components/editAttendeesPopUp.js
health/micro-ui/web/micro-ui-internals/packages/modules/health-hrms/src/Module.js
health/micro-ui/web/micro-ui-internals/packages/modules/health-hrms/src/pages/employee/HierarchySelection.js
health/micro-ui/web/micro-ui-internals/packages/modules/health-payments/src/Module.js
health/micro-ui/web/micro-ui-internals/packages/modules/health-hrms/src/services/service.js
health/micro-ui/web/micro-ui-internals/packages/modules/health-payments/src/utils/update_attendance_summary.js
health/micro-ui/web/micro-ui-internals/packages/modules/health-hrms/src/components/pageComponents/UserAssigment.js
health/micro-ui/web/micro-ui-internals/packages/modules/health-payments/src/pages/employee/project_selection.js
health/micro-ui/web/micro-ui-internals/example/src/UICustomizations.js
🧠 Learnings (10)
📚 Learning: 2024-11-28T11:34:27.480Z
Learnt from: rachana-egov
PR: egovernments/DIGIT-Frontend#1925
File: health/micro-ui/web/micro-ui-internals/packages/modules/microplan/src/components/UserUpload.js:267-269
Timestamp: 2024-11-28T11:34:27.480Z
Learning: In the `downloadTemplate` function of `health/micro-ui/web/micro-ui-internals/packages/modules/microplan/src/components/UserUpload.js`, the scenario where `state?.hierarchyType` is undefined will not occur.
Applied to files:
health/micro-ui/web/micro-ui-internals/packages/modules/health-payments/src/components/BoundaryComponent.js
health/micro-ui/web/micro-ui-internals/packages/modules/health-payments/src/services/PaymentsInitialization.js
health/micro-ui/web/micro-ui-internals/packages/modules/health-payments/src/components/HierachySelection.js
health/micro-ui/web/micro-ui-internals/packages/modules/health-hrms/src/pages/employee/HierarchySelection.js
📚 Learning: 2025-07-15T04:58:30.634Z
Learnt from: Hari-egov
PR: egovernments/DIGIT-Frontend#2788
File: micro-ui/web/micro-ui-internals/packages/modules/hrms/src/components/pageComponents/jurisdiction.js:26-26
Timestamp: 2025-07-15T04:58:30.634Z
Learning: In the HRMS module (micro-ui/web/micro-ui-internals/packages/modules/hrms/src/components/pageComponents/jurisdiction.js), the team has moved away from using MDMS hooks for boundary data fetching and now uses direct API calls to the boundary service endpoint `/boundary-service/boundary-relationships/_search` instead of the `useHrmsMDMS` hook with "FetchBoundaries" parameter.
Applied to files:
health/micro-ui/web/micro-ui-internals/packages/modules/health-payments/src/components/BoundaryComponent.js
health/micro-ui/web/micro-ui-internals/packages/modules/health-payments/src/config/AttendeeInboxConfig.js
health/micro-ui/web/micro-ui-internals/packages/modules/health-hrms/src/Module.js
health/micro-ui/web/micro-ui-internals/packages/modules/health-payments/src/Module.js
📚 Learning: 2024-06-10T19:25:42.992Z
Learnt from: siddhant-nawale-egov
PR: egovernments/DIGIT-Frontend#698
File: micro-ui/web/micro-ui-internals/packages/modules/hcm-microplanning/src/components/MicroplanPreview.js:1-1
Timestamp: 2024-06-10T19:25:42.992Z
Learning: The imports in `MicroplanPreview.js` are from different libraries: `egovernments/digit-ui-components` and `egovernments/digit-ui-react-components`.
Applied to files:
health/micro-ui/web/micro-ui-internals/example/src/index.js
health/micro-ui/web/micro-ui-internals/example/src/UICustomizations.js
📚 Learning: 2025-03-25T10:47:10.916Z
Learnt from: Tulika-eGov
PR: egovernments/DIGIT-Frontend#2288
File: micro-ui/web/micro-ui-internals/packages/modules/core/src/pages/employee/Landing/LandingComponent.js:33-33
Timestamp: 2025-03-25T10:47:10.916Z
Learning: In DIGIT-Frontend, window.contextPath is dynamically determined and cannot be given a static fallback value like 'digit-ui'. The application relies on this dynamic context path for proper routing.
Applied to files:
health/micro-ui/web/micro-ui-internals/packages/modules/health-payments/src/services/PaymentsInitialization.js
📚 Learning: 2024-11-07T11:02:33.520Z
Learnt from: rachana-egov
PR: egovernments/DIGIT-Frontend#1770
File: health/micro-ui/web/micro-ui-internals/packages/modules/microplan/src/pages/employee/viewVillage.js:320-322
Timestamp: 2024-11-07T11:02:33.520Z
Learning: In `health/micro-ui/web/micro-ui-internals/packages/modules/microplan/src/pages/employee/viewVillage.js`, the `data?.additionalFields` object is guaranteed to be defined, so checking for its existence before accessing its keys is unnecessary.
Applied to files:
health/micro-ui/web/micro-ui-internals/packages/modules/health-hrms/src/pages/employee/createEmployee.js
health/micro-ui/web/micro-ui-internals/packages/modules/health-hrms/src/components/config/createEmployeeConfig.js
health/micro-ui/web/micro-ui-internals/packages/modules/health-hrms/src/pages/employee/HierarchySelection.js
📚 Learning: 2025-02-05T10:01:29.668Z
Learnt from: Tulika-eGov
PR: egovernments/DIGIT-Frontend#2188
File: micro-ui/web/micro-ui-internals/packages/modules/core/src/pages/employee/Login/login.js:72-78
Timestamp: 2025-02-05T10:01:29.668Z
Learning: In the employee login form, defaultValues are dynamically generated from config[0].body based on populators.defaultValue, so spreading the entire defaultValues object is required rather than cherry-picking specific fields.
Applied to files:
health/micro-ui/web/micro-ui-internals/packages/modules/health-hrms/src/pages/employee/createEmployee.js
📚 Learning: 2025-06-27T05:52:33.156Z
Learnt from: Hari-egov
PR: egovernments/DIGIT-Frontend#2644
File: micro-ui/web/micro-ui-internals/packages/modules/core/src/components/PrivacyComponent.js:0-0
Timestamp: 2025-06-27T05:52:33.156Z
Learning: The PrivacyComponent in `micro-ui/web/micro-ui-internals/packages/modules/core/src/components/PrivacyComponent.js` is mostly used in login and signup pages, especially in formcomposer where the UI is stable, making layout changes less likely to cause regressions.
Applied to files:
health/micro-ui/web/micro-ui-internals/packages/modules/health-payments/src/components/SearchUserPopUp.js
📚 Learning: 2024-06-10T19:25:42.992Z
Learnt from: siddhant-nawale-egov
PR: egovernments/DIGIT-Frontend#0
File: :0-0
Timestamp: 2024-06-10T19:25:42.992Z
Learning: The Button component from `egovernments/digit-ui-components` has compatibility issues with the ActionBar, leading to the preference for using the Button from `egovernments/digit-ui-react-components` in certain scenarios.
Applied to files:
health/micro-ui/web/micro-ui-internals/packages/modules/health-payments/src/pages/employee/project_selection.js
📚 Learning: 2024-06-10T19:25:42.992Z
Learnt from: siddhant-nawale-egov
PR: egovernments/DIGIT-Frontend#0
File: :0-0
Timestamp: 2024-06-10T19:25:42.992Z
Learning: The `Toast` component's styling is managed internally within the component, ensuring consistency and adaptability across different contexts without the need for additional external styling.
Applied to files:
health/micro-ui/web/micro-ui-internals/packages/modules/health-payments/src/pages/employee/project_selection.js
📚 Learning: 2024-11-07T07:17:27.636Z
Learnt from: jagankumar-egov
PR: egovernments/DIGIT-Frontend#1763
File: health/micro-ui/web/micro-ui-internals/packages/modules/campaign-manager/src/pages/employee/MyCampaign.js:65-75
Timestamp: 2024-11-07T07:17:27.636Z
Learning: In `MyCampaign.js`, when suggesting code improvements for the `onClickRow` function, keep suggestions simple and avoid unnecessary complexity.
Applied to files:
health/micro-ui/web/micro-ui-internals/example/src/UICustomizations.js
🧬 Code graph analysis (25)
health/micro-ui/web/micro-ui-internals/packages/modules/health-payments/src/components/SelectableList.js (1)
health/micro-ui/web/micro-ui-internals/packages/modules/health-payments/src/components/SearchUserPopUp.js (1)
onSelect
(71-75)
health/micro-ui/web/micro-ui-internals/packages/modules/health-payments/src/components/BoundaryComponent.js (3)
health/micro-ui/web/micro-ui-internals/packages/modules/health-payments/src/Module.js (1)
hierarchyType
(21-21)health/micro-ui/web/micro-ui-internals/packages/modules/health-hrms/src/services/urls.js (1)
hierarchyType
(6-6)health/micro-ui/web/micro-ui-internals/packages/modules/health-payments/src/services/PaymentsInitialization.js (1)
hierarchyType
(26-26)
health/micro-ui/web/micro-ui-internals/packages/modules/health-payments/src/hooks/attendance/search_individual.js (2)
health/micro-ui/web/micro-ui-internals/packages/modules/campaign-manager/src/hooks/useUpdateAppConfigForFeatures.js (1)
useMutation
(151-155)health/micro-ui/web/micro-ui-internals/packages/modules/health-payments/src/services/attendance/attendanceService.js (2)
AttendanceService
(4-108)AttendanceService
(4-108)
health/micro-ui/web/micro-ui-internals/packages/modules/health-payments/src/hooks/attendance/create_attendee_register.js (1)
health/micro-ui/web/micro-ui-internals/packages/modules/health-payments/src/services/attendance/attendanceService.js (2)
AttendanceService
(4-108)AttendanceService
(4-108)
health/micro-ui/web/micro-ui-internals/packages/modules/health-payments/src/services/attendance/attendee_service/attendeeService.js (1)
health/micro-ui/web/micro-ui-internals/packages/modules/health-payments/src/services/urls.js (1)
Urls
(9-55)
health/micro-ui/web/micro-ui-internals/packages/modules/health-payments/src/components/SearchAttendeeBoundary.js (4)
health/micro-ui/web/micro-ui-internals/packages/modules/health-payments/src/pages/employee/AttendeeSearchAssign.js (2)
Digit
(9-9)config
(31-31)health/micro-ui/web/micro-ui-internals/packages/modules/health-payments/src/pages/employee/project_selection.js (2)
selectedProject
(24-24)lowestLevelBoundaryType
(31-31)health/micro-ui/web/micro-ui-internals/packages/modules/health-payments/src/Module.js (1)
hierarchyType
(21-21)micro-ui/web/micro-ui-internals/packages/react-components/src/atoms/Dropdown.js (1)
Dropdown
(94-281)
health/micro-ui/web/micro-ui-internals/packages/modules/health-payments/src/services/PaymentsInitialization.js (3)
health/micro-ui/web/micro-ui-internals/packages/modules/health-payments/src/Module.js (1)
hierarchyType
(21-21)health/micro-ui/web/micro-ui-internals/packages/modules/health-hrms/src/services/urls.js (1)
hierarchyType
(6-6)health/micro-ui/web/micro-ui-internals/packages/modules/health-payments/src/components/BoundaryComponent.js (1)
hierarchyType
(16-16)
health/micro-ui/web/micro-ui-internals/packages/modules/health-payments/src/components/EditAttendanceManagementTable.js (3)
health/micro-ui/web/micro-ui-internals/packages/modules/health-payments/src/utils/constants.js (4)
defaultRowsPerPageForEditAttendee
(19-19)defaultRowsPerPageForEditAttendee
(19-19)defaultPaginationValuesForEditAttendee
(22-22)defaultPaginationValuesForEditAttendee
(22-22)health/micro-ui/web/micro-ui-internals/packages/modules/health-payments/src/components/table_inbox_custom_style.js (2)
editAttendeetableCustomStyle
(227-334)editAttendeetableCustomStyle
(227-334)health/micro-ui/web/micro-ui-internals/packages/modules/health-payments/src/components/alertPopUp.js (1)
AlertPopUp
(19-57)
health/micro-ui/web/micro-ui-internals/packages/modules/health-payments/src/hooks/attendance/delete_attendee_register.js (2)
health/micro-ui/web/micro-ui-internals/packages/modules/health-payments/src/pages/employee/ViewAttendance.js (2)
data
(47-47)tenantId
(34-34)health/micro-ui/web/micro-ui-internals/packages/modules/health-payments/src/services/attendance/attendanceService.js (2)
AttendanceService
(4-108)AttendanceService
(4-108)
health/micro-ui/web/micro-ui-internals/packages/modules/health-payments/src/pages/employee/index.js (2)
health/micro-ui/web/micro-ui-internals/packages/modules/health-payments/src/pages/employee/AttendeeSearchAssign.js (2)
Digit
(9-9)InboxAttendeesSearch
(7-64)health/micro-ui/web/micro-ui-internals/packages/modules/health-payments/src/pages/employee/EditRegister.js (4)
Digit
(32-32)location
(23-23)location
(33-33)EditRegister
(22-420)
health/micro-ui/web/micro-ui-internals/packages/modules/health-hrms/src/pages/employee/createEmployee.js (1)
health/micro-ui/web/micro-ui-internals/packages/modules/health-hrms/src/components/config/createEmployeeConfig.js (2)
CreateEmployeeConfig
(6-321)CreateEmployeeConfig
(6-321)
health/micro-ui/web/micro-ui-internals/packages/modules/health-payments/src/pages/employee/AttendeeSearchAssign.js (3)
health/micro-ui/web/micro-ui-internals/packages/modules/health-payments/src/pages/employee/EditRegister.js (2)
useTranslation
(24-24)Digit
(32-32)health/micro-ui/web/micro-ui-internals/packages/modules/health-payments/src/config/AttendeeInboxConfig.js (1)
inboxAttendeeSearchConfig
(13-219)micro-ui/web/micro-ui-internals/packages/react-components/src/hoc/InboxSearchComposer.js (1)
InboxSearchComposer
(19-322)
health/micro-ui/web/micro-ui-internals/packages/modules/health-payments/src/components/attendance_inbox/table_inbox.js (2)
health/micro-ui/web/micro-ui-internals/packages/modules/health-payments/src/pages/employee/EditRegister.js (1)
Digit
(32-32)health/micro-ui/web/micro-ui-internals/packages/modules/health-payments/src/pages/employee/ViewAttendance.js (1)
Digit
(32-32)
health/micro-ui/web/micro-ui-internals/packages/modules/health-payments/src/pages/employee/ViewAttendance.js (2)
health/micro-ui/web/micro-ui-internals/packages/modules/health-payments/src/pages/employee/EditRegister.js (3)
showDeEnrollPopup
(54-54)handleDeEnrollClick
(225-227)onDeEnrollClose
(229-231)health/micro-ui/web/micro-ui-internals/packages/modules/health-payments/src/components/editAttendeesPopUp.js (1)
EditAttendeePopUp
(14-235)
health/micro-ui/web/micro-ui-internals/packages/modules/health-payments/src/components/HierachySelection.js (1)
micro-ui/web/micro-ui-internals/packages/react-components/src/atoms/Dropdown.js (1)
Dropdown
(94-281)
health/micro-ui/web/micro-ui-internals/packages/modules/health-payments/src/services/urls.js (1)
health/micro-ui/web/micro-ui-internals/example/src/UICustomizations.js (1)
projectContextPath
(1898-1898)
health/micro-ui/web/micro-ui-internals/packages/modules/health-payments/src/services/attendance/attendanceService.js (1)
health/micro-ui/web/micro-ui-internals/packages/modules/health-payments/src/services/attendance/attendee_service/attendeeService.js (1)
AttendeeService
(3-46)
health/micro-ui/web/micro-ui-internals/packages/modules/health-payments/src/components/SearchUserPopUp.js (3)
health/micro-ui/web/micro-ui-internals/example/src/UICustomizations.js (19)
tenantId
(391-391)tenantId
(757-757)tenantId
(840-840)tenantId
(1387-1387)tenantId
(1442-1442)tenantId
(1689-1689)tenantId
(1897-1897)tenantId
(2162-2162)tenantId
(2194-2194)tenantId
(2239-2239)tenantId
(2269-2269)tenantId
(2314-2314)tenantId
(2345-2345)tenantId
(2390-2390)Digit
(1443-1443)Digit
(2722-2722)createMapping
(2721-2721)result
(64-64)boundaryCode
(2660-2661)health/micro-ui/web/micro-ui-internals/packages/modules/health-payments/src/services/attendance/attendanceService.js (3)
result
(79-100)AttendanceService
(4-108)AttendanceService
(4-108)health/micro-ui/web/micro-ui-internals/packages/modules/health-payments/src/components/SelectableList.js (1)
SelectableList
(3-37)
health/micro-ui/web/micro-ui-internals/packages/modules/health-payments/src/pages/employee/EditRegister.js (3)
health/micro-ui/web/micro-ui-internals/packages/modules/health-payments/src/pages/employee/ViewAttendance.js (26)
location
(22-22)location
(33-33)useTranslation
(23-23)history
(24-24)attendanceContextPath
(27-27)individualContextPath
(29-29)Digit
(32-32)attendanceDuration
(35-35)attendanceSummary
(36-36)initialAttendanceSummary
(37-37)isSubmitEnabled
(38-38)disabledAction
(40-40)openEditAlertPopUp
(41-41)openApproveCommentPopUp
(42-42)openApproveAlertPopUp
(43-43)individualIds
(48-48)showToast
(51-51)AttendancereqCri
(62-74)isAttendanceLoading
(76-76)allIndividualReqCriteria
(312-331)isAllIndividualsLoading
(333-333)individualReqCriteria
(335-357)closeActionBarPopUp
(428-430)handleDeEnrollClick
(441-443)onDeEnrollClose
(445-447)renderLabelPair
(450-455)health/micro-ui/web/micro-ui-internals/packages/modules/health-payments/src/components/editAttendeesPopUp.js (13)
useTranslation
(24-24)history
(15-15)attendanceContextPath
(17-19)individualContextPath
(20-22)tenantId
(25-25)attendanceSummary
(32-32)individualIds
(33-33)AttendancereqCri
(42-53)isAttendanceLoading
(55-56)allIndividualReqCriteria
(69-86)isAllIndividualsLoading
(88-89)closeActionBarPopUp
(171-173)EditAttendeePopUp
(14-235)health/micro-ui/web/micro-ui-internals/packages/modules/health-payments/src/components/EditAttendanceManagementTable.js (5)
useTranslation
(33-33)history
(34-34)tenantId
(40-40)showToast
(36-36)EditAttendanceManagementTable
(31-274)
health/micro-ui/web/micro-ui-internals/packages/modules/health-payments/src/components/editAttendeesPopUp.js (3)
health/micro-ui/web/micro-ui-internals/packages/modules/health-payments/src/components/SearchUserPopUp.js (6)
attendanceContextPath
(18-20)individualContextPath
(21-23)useTranslation
(25-25)tenantId
(14-14)searchQuery
(32-32)SearchUserPopUp
(12-176)health/micro-ui/web/micro-ui-internals/packages/modules/health-payments/src/components/EditAttendanceManagementTable.js (3)
useTranslation
(33-33)tenantId
(40-40)EditAttendanceManagementTable
(31-274)health/micro-ui/web/micro-ui-internals/packages/modules/health-payments/src/utils/update_attendance_summary.js (7)
attendanceContextPath
(4-6)individualContextPath
(7-9)attendanceSummary
(12-12)individualIds
(11-11)isAttendanceLoading
(27-28)allIndividualReqCriteria
(41-58)isAllIndividualsLoading
(60-61)
health/micro-ui/web/micro-ui-internals/packages/modules/health-hrms/src/pages/employee/HierarchySelection.js (2)
health/micro-ui/web/micro-ui-internals/packages/modules/pgr/src/components/HierarchySelection.js (2)
HierarchySelection
(15-167)selectedHierarchy
(24-26)health/micro-ui/web/micro-ui-internals/packages/modules/health-hrms/src/components/pageComponents/Jurisdictions.js (1)
selectedHierarchy
(8-8)
health/micro-ui/web/micro-ui-internals/packages/modules/health-hrms/src/services/service.js (2)
health/micro-ui/web/micro-ui-internals/packages/modules/health-hrms/src/constants/constants.js (2)
HRMS_CONSTANTS
(1-7)HRMS_CONSTANTS
(1-7)health/micro-ui/web/micro-ui-internals/packages/modules/health-hrms/src/utils/utlis.js (2)
convertEpochToDate
(2-15)convertEpochToDate
(2-15)
health/micro-ui/web/micro-ui-internals/packages/modules/health-payments/src/utils/update_attendance_summary.js (6)
health/micro-ui/web/micro-ui-internals/packages/modules/health-payments/src/components/editAttendeesPopUp.js (8)
attendanceContextPath
(17-19)individualContextPath
(20-22)individualIds
(33-33)attendanceSummary
(32-32)tenantId
(25-25)isAttendanceLoading
(55-56)allIndividualReqCriteria
(69-86)isAllIndividualsLoading
(88-89)health/micro-ui/web/micro-ui-internals/packages/modules/health-payments/src/services/PaymentsInitialization.js (2)
individualContextPath
(25-25)individual
(155-155)health/micro-ui/web/micro-ui-internals/packages/modules/health-payments/src/Module.js (1)
tenantId
(19-19)health/micro-ui/web/micro-ui-internals/packages/modules/health-payments/src/components/EditAttendanceManagementTable.js (1)
tenantId
(40-40)health/micro-ui/web/micro-ui-internals/packages/modules/health-payments/src/components/BoundaryComponent.js (1)
tenantId
(15-15)health/micro-ui/web/micro-ui-internals/packages/modules/health-payments/src/components/HierachySelection.js (1)
tenantId
(17-17)
health/micro-ui/web/micro-ui-internals/packages/modules/health-hrms/src/components/pageComponents/UserAssigment.js (3)
health/micro-ui/web/micro-ui-internals/example/src/UICustomizations.js (38)
options
(890-890)options
(1721-1724)boundaryCode
(2660-2661)Digit
(1443-1443)Digit
(2722-2722)tenantId
(391-391)tenantId
(757-757)tenantId
(840-840)tenantId
(1387-1387)tenantId
(1442-1442)tenantId
(1689-1689)tenantId
(1897-1897)tenantId
(2162-2162)tenantId
(2194-2194)tenantId
(2239-2239)tenantId
(2269-2269)tenantId
(2314-2314)tenantId
(2345-2345)tenantId
(2390-2390)tenantId
(2420-2420)tenantId
(2465-2465)data
(415-415)data
(517-517)data
(734-734)data
(794-794)data
(811-811)data
(1071-1071)data
(1333-1333)data
(1350-1350)data
(1351-1351)data
(1352-1352)data
(2164-2164)data
(2165-2165)data
(2241-2241)data
(2242-2242)data
(2316-2316)data
(2317-2317)result
(64-64)health/micro-ui/web/micro-ui-internals/packages/modules/health-hrms/src/services/service.js (3)
result
(18-18)result
(43-43)result
(303-303)micro-ui/web/micro-ui-internals/packages/react-components/src/atoms/Dropdown.js (1)
Dropdown
(94-281)
health/micro-ui/web/micro-ui-internals/packages/modules/health-payments/src/pages/employee/project_selection.js (3)
micro-ui/web/micro-ui-internals/packages/react-components/src/atoms/Dropdown.js (1)
Dropdown
(94-281)health/micro-ui/web/micro-ui-internals/packages/modules/health-payments/src/pages/employee/EditRegister.js (1)
project
(56-56)health/micro-ui/web/micro-ui-internals/packages/modules/health-payments/src/components/SearchAttendeeBoundary.js (1)
selectedProject
(22-22)
🪛 Biome (2.1.2)
health/micro-ui/web/micro-ui-internals/packages/modules/health-payments/src/components/SelectableList.js
[error] 20-31: Static Elements should not be interactive.
To add interactivity such as a mouse or key event listener to a static element, give the element an appropriate role value.
(lint/a11y/noStaticElementInteractions)
[error] 20-31: Enforce to have the onClick mouse event with the onKeyUp, the onKeyDown, or the onKeyPress keyboard event.
Actions triggered using mouse events should have corresponding keyboard events to account for keyboard-only navigation.
(lint/a11y/useKeyWithClickEvents)
health/micro-ui/web/micro-ui-internals/packages/modules/health-payments/src/components/SearchAttendeeBoundary.js
[error] 228-233: Static Elements should not be interactive.
To add interactivity such as a mouse or key event listener to a static element, give the element an appropriate role value.
(lint/a11y/noStaticElementInteractions)
[error] 228-233: Enforce to have the onClick mouse event with the onKeyUp, the onKeyDown, or the onKeyPress keyboard event.
Actions triggered using mouse events should have corresponding keyboard events to account for keyboard-only navigation.
(lint/a11y/useKeyWithClickEvents)
health/micro-ui/web/micro-ui-internals/packages/modules/health-payments/src/services/urls.js
[error] 10-15: This property is later overwritten by an object member with the same name.
Overwritten with this property.
If an object property with the same name is defined multiple times (except when combining a getter with a setter), only the last definition makes it into the object and previous definitions are ignored.
Unsafe fix: Remove this property.
(lint/suspicious/noDuplicateObjectKeys)
health/micro-ui/web/micro-ui-internals/packages/modules/health-payments/src/components/SearchUserPopUp.js
[error] 136-136: Avoid passing children using a prop
The canonical way to pass children in React is to use JSX elements
(lint/correctness/noChildrenProp)
health/micro-ui/web/micro-ui-internals/packages/modules/health-payments/src/pages/employee/EditRegister.js
[error] 270-271: Provide screen reader accessible content when using heading elements.
All headings on a page should have content that is accessible to screen readers.
(lint/a11y/useHeadingContent)
health/micro-ui/web/micro-ui-internals/packages/modules/health-payments/src/components/editAttendeesPopUp.js
[error] 183-183: Avoid passing children using a prop
The canonical way to pass children in React is to use JSX elements
(lint/correctness/noChildrenProp)
health/micro-ui/web/micro-ui-internals/example/src/UICustomizations.js
[error] 887-887: Other switch clauses can erroneously access this declaration.
Wrap the declaration in a block to restrict its access to the switch clause.
The declaration is defined in this switch clause:
Safe fix: Wrap the declaration in a block.
(lint/correctness/noSwitchDeclarations)
[error] 888-888: Other switch clauses can erroneously access this declaration.
Wrap the declaration in a block to restrict its access to the switch clause.
The declaration is defined in this switch clause:
Safe fix: Wrap the declaration in a block.
(lint/correctness/noSwitchDeclarations)
[error] 889-889: Other switch clauses can erroneously access this declaration.
Wrap the declaration in a block to restrict its access to the switch clause.
The declaration is defined in this switch clause:
Safe fix: Wrap the declaration in a block.
(lint/correctness/noSwitchDeclarations)
[error] 890-890: Other switch clauses can erroneously access this declaration.
Wrap the declaration in a block to restrict its access to the switch clause.
The declaration is defined in this switch clause:
Safe fix: Wrap the declaration in a block.
(lint/correctness/noSwitchDeclarations)
[error] 902-916: Other switch clauses can erroneously access this declaration.
Wrap the declaration in a block to restrict its access to the switch clause.
The declaration is defined in this switch clause:
Safe fix: Wrap the declaration in a block.
(lint/correctness/noSwitchDeclarations)
[error] 918-962: Other switch clauses can erroneously access this declaration.
Wrap the declaration in a block to restrict its access to the switch clause.
The declaration is defined in this switch clause:
Safe fix: Wrap the declaration in a block.
(lint/correctness/noSwitchDeclarations)
[error] 964-966: Other switch clauses can erroneously access this declaration.
Wrap the declaration in a block to restrict its access to the switch clause.
The declaration is defined in this switch clause:
Safe fix: Wrap the declaration in a block.
(lint/correctness/noSwitchDeclarations)
⏰ Context from checks skipped due to timeout of 10000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
- GitHub Check: Analyze (javascript-typescript)
🔇 Additional comments (16)
health/micro-ui/web/micro-ui-internals/packages/modules/health-payments/src/components/attendance_inbox/table_inbox.js (1)
87-117
: Ensure endDate is normalized to milliseconds
Convert or parseselectedProject.endDate
into a millisecond timestamp (e.g. viaDate.parse(endDate)
or multiplying seconds by 1000) before comparing it toDate.now()
.health/micro-ui/web/micro-ui-internals/packages/modules/health-payments/src/components/PaymentsCard.js (1)
12-12
: No-op whitespace change. LGTM.
No functional impact.health/micro-ui/web/micro-ui-internals/example/src/index.js (1)
17-17
: Module wiring addition looks correct.
ImportinginitPaymentComponents
is fine and consistent with other modules.health/micro-ui/web/micro-ui-internals/packages/modules/health-payments/src/utils/constants.js (1)
19-22
: New pagination constants look good.
Naming/values are clear and scoped to the edit-attendee table.health/micro-ui/web/micro-ui-internals/packages/modules/health-hrms/src/services/service.js (1)
89-94
: LGTM: Phone number normalization covers +91 and +258The substring logic correctly strips known country codes and falls back safely.
Also applies to: 147-152
health/micro-ui/web/micro-ui-internals/packages/modules/health-hrms/src/pages/employee/HierarchySelection.js (1)
15-15
: LGTM: Cleaned prop signatureWhitespace cleanup improves readability without behavioral change.
health/micro-ui/web/micro-ui-internals/packages/modules/health-hrms/src/pages/employee/createEmployee.js (2)
75-77
: No-op whitespaceNo functional impact.
322-323
: Restore MDMS-driven form config with local fallback
IncreateEmployee.js
, update thefConfig
assignment:- const fConfig = CreateEmployeeConfig?.CreateEmployeeConfig?.[0]; + const fConfig = mdmsData || CreateEmployeeConfig?.CreateEmployeeConfig?.[0];Verify any
Digit.Hooks.useCommonMDMS(…)
calls useenabled: true
(notenable
) when toggling MDMS fetching.health/micro-ui/web/micro-ui-internals/packages/modules/health-payments/src/components/HierachySelection.js (1)
33-39
: Confirm hook name and spelling
All usages ofDigit.Hooks.hrms.useBoundriesFetch
are internally consistent but no local definition exists. Verify in the external Digit.Hooks.hrms API that the hook is indeed nameduseBoundriesFetch
; if it’s actuallyuseFetchBoundaries
, update the references (e.g. in both HierarchySelection.js files and SelectEmployeeBoundary.js).health/micro-ui/web/micro-ui-internals/packages/modules/health-hrms/src/Module.js (1)
20-20
: Verify import/export name alignment for UserAssignment.Import path is
UserAssigment
(missing “n”). Ensure the file name and default export match (UserAssignment
). Mismatches will break registry at runtime.health/micro-ui/web/micro-ui-internals/packages/modules/health-payments/src/pages/employee/ViewAttendance.js (1)
440-447
: Dead code: popup toggles have no trigger.The only opener button is commented out. Either restore a trigger or remove the popup state/effects.
health/micro-ui/web/micro-ui-internals/packages/modules/health-payments/src/hooks/index.js (1)
10-18
: LGTM: hooks are properly exposed under payments.Exports look consistent; no further action.
health/micro-ui/web/micro-ui-internals/packages/modules/health-payments/src/pages/employee/EditRegister.js (4)
245-247
: Loader condition is fine.Good guard to avoid rendering before all data is ready.
285-286
: Table rendered read-only here; actionable edits handled via popup.Consistent with UX—no action column when editAction is false.
292-300
: De-enroll popup wiring looks correct.Props passed match component expectations (registerNumber, registerId, boundaryCode).
33-33
: Fix unsafe destructuring of location.state.Destructuring from
false
throws. Use optional chaining/nullish coalescing.Apply:
- const { fromCampaignSupervisor } = location.state || false; + const fromCampaignSupervisor = location.state?.fromCampaignSupervisor ?? false;Likely an incorrect or invalid review comment.
initMicroplanComponents(); | ||
initHRMSComponents(); | ||
initPGRComponents(); | ||
initPaymentComponents(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
💡 Verification agent
🧩 Analysis chain
Call order OK; verify module key consistency.
Ensure the Payments module registers itself with the key expected by enabledModules
("Payments").
Use this to confirm:
🏁 Script executed:
#!/bin/bash
rg -nP --type=js -C2 '(initPaymentComponents)|(moduleName\s*:\s*"Payments")|ComponentRegistryService'
Length of output: 45698
🏁 Script executed:
#!/bin/bash
grep -R "const componentsToRegister" -n health/micro-ui/web/micro-ui-internals/packages/modules/health-payments/src/Module.js
Length of output: 33
🏁 Script executed:
#!/bin/bash
sed -n '80,120p' health/micro-ui/web/micro-ui-internals/packages/modules/health-payments/src/Module.js
Length of output: 458
🏁 Script executed:
#!/bin/bash
grep -R "setupRegistry" -n health/micro-ui/web/micro-ui-internals
Length of output: 119
Mismatch in Payments module registry key
The health-payments module registers under PaymentsModule
(componentsToRegister in health-payments/src/Module.js:83) but enabledModules
is looking for "Payments"
. Rename the registration key to "Payments"
or update enabledModules
to use "PaymentsModule"
.
🤖 Prompt for AI Agents
In health/micro-ui/web/micro-ui-internals/example/src/index.js around line 85,
there is a mismatch between the payments module registry key and the
enabledModules lookup: the payments package registers as "PaymentsModule"
(health-payments/src/Module.js line ~83) while enabledModules expects
"Payments". Fix by making the keys consistent—either rename the registration key
in health-payments/src/Module.js from "PaymentsModule" to "Payments", or update
enabledModules in this file to include "PaymentsModule" instead; apply the
change in the single place where componentsToRegister is defined or where
enabledModules is declared so both sides use the exact same string.
// attendee delete | ||
"/health-attendance/attendee/v1/_delete", | ||
"/health-attendance/attendee/v1/_create", | ||
"/health-hrms/employees/_search", | ||
].forEach((location) => app.use(location, createProxy)); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
💡 Verification agent
🧩 Analysis chain
Redundant proxy entry; keep only the broader prefix.
/health-hrms/employees
already proxies /health-hrms/employees/_search
. The explicit _search
entry is redundant.
- "/health-attendance/attendee/v1/_delete",
- "/health-attendance/attendee/v1/_create",
- "/health-hrms/employees/_search",
+ "/health-attendance/attendee/v1/_delete",
+ "/health-attendance/attendee/v1/_create",
Confirm the prefix covers subpaths:
🏁 Script executed:
#!/bin/bash
# http-proxy-middleware mounts middleware at the given path prefix.
rg -n 'app\.use\(.+createProxyMiddleware' example/src/setupProxy.js -n -C2
Length of output: 65
🏁 Script executed:
#!/bin/bash
# Locate setupProxy.js and inspect proxy entries
setup_file=$(find . -type f -name setupProxy.js)
echo "Found: $setup_file"
rg -n -C2 '\.forEach' "$setup_file"
Length of output: 446
🏁 Script executed:
#!/bin/bash
file="./health/micro-ui/web/micro-ui-internals/example/src/setupProxy.js"
sed -n '100,140p' "$file"
Length of output: 820
🏁 Script executed:
#!/bin/bash
file="./health/micro-ui/web/micro-ui-internals/example/src/setupProxy.js"
sed -n '1,80p' "$file"
Length of output: 2313
Remove redundant /health-hrms/employees/_search
entry.
app.use("/health-hrms/employees", createProxy)
already matches all subpaths.
- "/health-hrms/employees/_search",
📝 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.
// attendee delete | |
"/health-attendance/attendee/v1/_delete", | |
"/health-attendance/attendee/v1/_create", | |
"/health-hrms/employees/_search", | |
].forEach((location) => app.use(location, createProxy)); | |
// attendee delete | |
"/health-attendance/attendee/v1/_delete", | |
"/health-attendance/attendee/v1/_create", | |
].forEach((location) => app.use(location, createProxy)); |
🤖 Prompt for AI Agents
In health/micro-ui/web/micro-ui-internals/example/src/setupProxy.js around lines
114 to 118, the array passed to forEach includes a redundant
"/health-hrms/employees/_search" entry because app.use("/health-hrms/employees",
createProxy) already covers that subpath; remove the
"/health-hrms/employees/_search" string from the list so the proxy locations
array only contains unique, necessary paths and leave the existing
app.use("/health-hrms/employees", createProxy) intact.
// INFO:: testing | ||
|
||
{ | ||
type: "component", | ||
isMandatory: true, | ||
component: "UserAssignment", | ||
key: "UserAssignment", | ||
withoutLabel: true, | ||
populators: { | ||
name: "UserAssignment", | ||
}, | ||
}, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
💡 Verification agent
🧩 Analysis chain
Remove leftover “testing” comment and confirm component registration.
The inline // INFO:: testing
should not ship. Ensure UserAssignment
is registered and its file name/spelling matches the import path.
Apply:
- // INFO:: testing
Verify registration:
🏁 Script executed:
#!/bin/bash
rg -nP --type=js '(componentsToRegister|ComponentRegistryService).*UserAssignment|component:\s*"UserAssignment"'
fd -t f -a 'UserAssigment.js' 2>/dev/null || true
Length of output: 294
Remove leftover “testing” comment and correct UserAssignment
filename
- Remove the
// INFO:: testing
line fromcreateEmployeeConfig.js
. - Rename
pageComponents/UserAssigment.js
→pageComponents/UserAssignment.js
to match thecomponent: "UserAssignment"
reference. - Update all imports and registry entries to use the corrected filename and path.
🤖 Prompt for AI Agents
In
health/micro-ui/web/micro-ui-internals/packages/modules/health-hrms/src/components/config/createEmployeeConfig.js
around lines 304 to 315, remove the leftover comment line "// INFO:: testing"
and ensure the referenced component filename matches the component key: rename
the physical file pageComponents/UserAssigment.js to
pageComponents/UserAssignment.js, then update every import, export and
registry/registration entry across the module to use "UserAssignment" and the
corrected path/filename so imports, dynamic loads and any component map keys
align with component: "UserAssignment".
const reqCri = { | ||
url: `/health-individual/v1/_search`, | ||
params: { | ||
tenantId: tenantId, | ||
limit: 4, | ||
offset: 0, | ||
}, | ||
body: { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion
Avoid hard-coded service name; honor INDIVIDUAL_CONTEXT_PATH
Keep endpoints configurable like the rest of the codebase.
+ const individualContextPath = window?.globalConfigs?.getConfig("INDIVIDUAL_CONTEXT_PATH") || "health-individual";
@@
- url: `/health-individual/v1/_search`,
+ url: `/${individualContextPath}/v1/_search`,
@@
- select: (data) => {
-
- console.log("data", data);
- return data.Individual;
- },
+ select: (data) => data.Individual,
Also applies to: 45-55
🤖 Prompt for AI Agents
In
health/micro-ui/web/micro-ui-internals/packages/modules/health-hrms/src/components/pageComponents/UserAssigment.js
around lines 24-31 (and similarly at lines 45-55), the request URL is hard-coded
to "/health-individual/v1/_search"; replace that hard-coded service path with
the shared INDIVIDUAL_CONTEXT_PATH constant (e.g. construct the URL as
`${INDIVIDUAL_CONTEXT_PATH}/v1/_search`) so the endpoint stays configurable; if
INDIVIDUAL_CONTEXT_PATH is not imported in this file, import it from the project
constants/config where other modules read it, and add a sensible fallback (or
throw) to avoid undefined values.
...cro-ui-internals/packages/modules/health-hrms/src/components/pageComponents/UserAssigment.js
Outdated
Show resolved
Hide resolved
const projectContextPath = window?.globalConfigs?.getConfig("PROJECT_CONTEXT_PATH") || "health-project"; | ||
const individualContextPath = window?.globalConfigs?.getConfig("INDIVIDUAL_CONTEXT_PATH") || "health-individual"; | ||
const hierarchyType = window?.globalConfigs?.getConfig("HIERARCHY_TYPE") || "MICROPLAN"; | ||
const hierarchyType = "NEWTEST00222"; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
💡 Verification agent
🧩 Analysis chain
Remove hard-coded hierarchyType.
Hard-coding "NEWTEST00222" risks deploying with the wrong hierarchy. Use the configured value and keep it consistent with other modules.
- const hierarchyType = "NEWTEST00222";
+ const hierarchyType = window?.globalConfigs?.getConfig("HIERARCHY_TYPE");
+ if (!hierarchyType) {
+ throw new Error("HIERARCHY_TYPE not configured");
+ }
Find any remaining occurrences:
🏁 Script executed:
#!/bin/bash
rg -n --hidden -S 'NEWTEST00222' -g '!**/node_modules/**'
Length of output: 148
🏁 Script executed:
#!/bin/bash
rg -n --no-ignore 'NEWTEST00222' -g '!node_modules/**'
Length of output: 148
🏁 Script executed:
#!/bin/bash
# Search all files, including hidden, ignoring no patterns
rg -n --no-ignore --hidden 'NEWTEST00222'
Length of output: 570
Remove all hard-coded and fallback “NEWTEST00222” hierarchyType defaults
Replace every occurrence of the literal or fallback default with the configured value and fail fast if it’s missing:
- In
src/services/PaymentsInitialization.js:26
, removeand use:const hierarchyType = "NEWTEST00222";
const hierarchyType = window?.globalConfigs?.getConfig("HIERARCHY_TYPE"); if (!hierarchyType) throw new Error("HIERARCHY_TYPE not configured");
- In
src/components/BoundaryComponent.js:16
andsrc/components/SearchAttendeeBoundary.js:27
, remove the|| "NEWTEST00222"
fallback so they read:const hierarchyType = window?.globalConfigs?.getConfig("HIERARCHY_TYPE"); if (!hierarchyType) throw new Error("HIERARCHY_TYPE not configured");
Ensures no deployments slip through with the wrong hierarchy.
🤖 Prompt for AI Agents
In
health/micro-ui/web/micro-ui-internals/packages/modules/health-payments/src/services/PaymentsInitialization.js
around line 26, remove the hard-coded const hierarchyType = "NEWTEST00222" and
instead read the configured value via
window?.globalConfigs?.getConfig("HIERARCHY_TYPE") and throw an Error if it is
missing; likewise update src/components/BoundaryComponent.js (line ~16) and
src/components/SearchAttendeeBoundary.js (line ~27) to remove any ||
"NEWTEST00222" fallback and replace with the same getConfig call followed by a
fail-fast throw when the value is not present so the app fails fast on missing
configuration.
const healthHrms = window?.globalConfigs?.getConfig("HRMS_CONTEXT_PATH") || "health-hrms"; | ||
const mdmsPath = window?.globalConfigs?.getConfig("MDMS_CONTEXT_PATH") || "mdms-v2"; | ||
const boundarySearchPath = window?.globalConfigs?.getConfig("BOUNDARY_CONTEXT") || "boundary-service/boundary-relationships/_search?"; | ||
const hierarchyType = window?.globalConfigs?.getConfig("HIERARCHY_TYPE") || "HIERARCHYTEST"; | ||
const projectContextPath = window?.globalConfigs?.getConfig("PROJECT_SERVICE_PATH") || "health-project"; | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
💡 Verification agent
🧩 Analysis chain
Parameterize attendee/individual endpoints via global configs (no hard-coded service names)
Hard-coded paths block environment overrides. Also, attendee.search actually hits individual search; make intent clear while preserving key names to avoid breakage.
const healthHrms = window?.globalConfigs?.getConfig("HRMS_CONTEXT_PATH") || "health-hrms";
const mdmsPath = window?.globalConfigs?.getConfig("MDMS_CONTEXT_PATH") || "mdms-v2";
+const attendanceContextPath = window?.globalConfigs?.getConfig("ATTENDANCE_CONTEXT_PATH") || "health-attendance";
+const individualContextPath = window?.globalConfigs?.getConfig("INDIVIDUAL_CONTEXT_PATH") || "health-individual";
const projectContextPath = window?.globalConfigs?.getConfig("PROJECT_SERVICE_PATH") || "health-project";
@@
attendee:{
- deenrollAttendee:`/health-attendance/attendee/v1/_delete`,
- search: `/health-individual/v1/_search`,
- enrollAttendee:`/health-attendance/attendee/v1/_create`,
+ deenrollAttendee:`/${attendanceContextPath}/attendee/v1/_delete`,
+ enrollAttendee:`/${attendanceContextPath}/attendee/v1/_create`,
+ // search is for Individuals; keep key for backward-compat
+ search: `/${individualContextPath}/v1/_search`,
Run to find and validate all references to these keys:
Also applies to: 49-54
🏁 Script executed:
#!/bin/bash
rg -nP 'Urls\.attendee\.(search|enrollAttendee|deenrollAttendee)' -C2
Length of output: 2407
🏁 Script executed:
#!/bin/bash
# Inspect the Urls.attendee block in urls.js to confirm existing paths
rg -nP -C5 'Urls\.attendee' health/micro-ui/web/micro-ui-internals/packages/modules/health-payments/src/services/urls.js
Length of output: 0
🏁 Script executed:
#!/bin/bash
# Display the contents of urls.js to locate the Urls.attendee configuration
cat health/micro-ui/web/micro-ui-internals/packages/modules/health-payments/src/services/urls.js
Length of output: 2058
Parameterize attendee and individual service paths
In health/micro-ui/.../urls.js, replace hard-coded “health-attendance” and “health-individual” segments with globalConfigs:
const projectContextPath = window?.globalConfigs?.getConfig("PROJECT_SERVICE_PATH") || "health-project";
+const attendanceContextPath = window?.globalConfigs?.getConfig("ATTENDANCE_CONTEXT_PATH") || "health-attendance";
+const individualContextPath = window?.globalConfigs?.getConfig("INDIVIDUAL_CONTEXT_PATH") || "health-individual";
const Urls = {
…
attendee:{
- deenrollAttendee:`/health-attendance/attendee/v1/_delete`,
- search: `/health-individual/v1/_search`,
- enrollAttendee:`/health-attendance/attendee/v1/_create`,
+ deenrollAttendee: `/${attendanceContextPath}/attendee/v1/_delete`,
+ enrollAttendee: `/${attendanceContextPath}/attendee/v1/_create`,
+ // search targets Individuals; retain key for backward compatibility
+ search: `/${individualContextPath}/v1/_search`,
}
};
📝 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.
const healthHrms = window?.globalConfigs?.getConfig("HRMS_CONTEXT_PATH") || "health-hrms"; | |
const mdmsPath = window?.globalConfigs?.getConfig("MDMS_CONTEXT_PATH") || "mdms-v2"; | |
const boundarySearchPath = window?.globalConfigs?.getConfig("BOUNDARY_CONTEXT") || "boundary-service/boundary-relationships/_search?"; | |
const hierarchyType = window?.globalConfigs?.getConfig("HIERARCHY_TYPE") || "HIERARCHYTEST"; | |
const projectContextPath = window?.globalConfigs?.getConfig("PROJECT_SERVICE_PATH") || "health-project"; | |
const healthHrms = window?.globalConfigs?.getConfig("HRMS_CONTEXT_PATH") || "health-hrms"; | |
const mdmsPath = window?.globalConfigs?.getConfig("MDMS_CONTEXT_PATH") || "mdms-v2"; | |
const boundarySearchPath = window?.globalConfigs?.getConfig("BOUNDARY_CONTEXT") || "boundary-service/boundary-relationships/_search?"; | |
const hierarchyType = window?.globalConfigs?.getConfig("HIERARCHY_TYPE") || "HIERARCHYTEST"; | |
const projectContextPath = window?.globalConfigs?.getConfig("PROJECT_SERVICE_PATH") || "health-project"; | |
const attendanceContextPath = window?.globalConfigs?.getConfig("ATTENDANCE_CONTEXT_PATH") || "health-attendance"; | |
const individualContextPath = window?.globalConfigs?.getConfig("INDIVIDUAL_CONTEXT_PATH") || "health-individual"; | |
const Urls = { | |
… | |
attendee: { | |
- deenrollAttendee: `/health-attendance/attendee/v1/_delete`, | |
- search: `/health-individual/v1/_search`, | |
deenrollAttendee: `/${attendanceContextPath}/attendee/v1/_delete`, | |
enrollAttendee: `/${attendanceContextPath}/attendee/v1/_create`, | |
// search targets Individuals; retain key for backward compatibility | |
search: `/${individualContextPath}/v1/_search`, | |
} | |
}; |
🤖 Prompt for AI Agents
In
health/micro-ui/web/micro-ui-internals/packages/modules/health-payments/src/services/urls.js
around lines 3 to 8, the code currently uses hard-coded service path segments
for attendance and individual; add two new constants that read from
window?.globalConfigs?.getConfig("ATTENDANCE_SERVICE_PATH") and
window?.globalConfigs?.getConfig("INDIVIDUAL_SERVICE_PATH") with sensible
defaults "health-attendance" and "health-individual" respectively, and replace
any hard-coded "health-attendance" and "health-individual" usages in this file
with these new constants so the service paths are parameterized via
globalConfigs.
const boundarySearchPath = window?.globalConfigs?.getConfig("BOUNDARY_CONTEXT") || "boundary-service/boundary-relationships/_search?"; | ||
const hierarchyType = window?.globalConfigs?.getConfig("HIERARCHY_TYPE") || "HIERARCHYTEST"; | ||
const projectContextPath = window?.globalConfigs?.getConfig("PROJECT_SERVICE_PATH") || "health-project"; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion
Remove unused constants and mock endpoint
boundarySearchPath
and hierarchyType
aren’t used. filter_data
points to an external mock endpoint; keep it out of production bundles.
-const boundarySearchPath = window?.globalConfigs?.getConfig("BOUNDARY_CONTEXT") || "boundary-service/boundary-relationships/_search?";
-const hierarchyType = window?.globalConfigs?.getConfig("HIERARCHY_TYPE") || "HIERARCHYTEST";
+// (removed unused BOUNDARY_CONTEXT and HIERARCHY_TYPE; re-add when wired)
@@
- filter_data: `https://run.mocky.io/v3/597a50a0-90e5-4a45-b82e-8a2186b760bd`,
+ // filter_data: '...mock-url...', // keep mocks in dev-only code paths if required
Also applies to: 20-21
🤖 Prompt for AI Agents
In
health/micro-ui/web/micro-ui-internals/packages/modules/health-payments/src/services/urls.js
around lines 5-7 (and also address lines 20-21), remove the unused constants
boundarySearchPath and hierarchyType, and replace the external mock filter_data
endpoint with a production-safe source: either read the URL from globalConfigs
(or an environment/config value) or point to an internal stub file; update
imports/usages accordingly and ensure no hard-coded external mock URLs remain in
the bundle.
hrms: { | ||
search: `/${healthHrms}/employees/_search`, | ||
count: `/${healthHrms}/employees/_count`, | ||
create: `/${healthHrms}/employees/_create`, | ||
update: `/${healthHrms}/employees/_update`, | ||
}, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Duplicate "hrms" key — first definition is shadowed and dead code
Object key duplication makes the first hrms
block inert and triggers lints. Keep a single hrms
block.
Apply:
const Urls = {
- hrms: {
- search: `/${healthHrms}/employees/_search`,
- count: `/${healthHrms}/employees/_count`,
- create: `/${healthHrms}/employees/_create`,
- update: `/${healthHrms}/employees/_update`,
- },
+ // hrms block defined once below
Also applies to: 34-39
🧰 Tools
🪛 Biome (2.1.2)
[error] 10-15: This property is later overwritten by an object member with the same name.
Overwritten with this property.
If an object property with the same name is defined multiple times (except when combining a getter with a setter), only the last definition makes it into the object and previous definitions are ignored.
Unsafe fix: Remove this property.
(lint/suspicious/noDuplicateObjectKeys)
🤖 Prompt for AI Agents
In
health/micro-ui/web/micro-ui-internals/packages/modules/health-payments/src/services/urls.js
around lines 10-15 (and similarly at 34-39) there are duplicate object keys
named "hrms" so the first block is shadowed and triggers lints; remove or merge
the duplicate entries so only one "hrms" property remains containing all
required routes (search, count, create, update), ensure no key collisions remain
and update any references if needed.
EmployeeSearch: `/${healthHrms}/employees/_search`, | ||
|
||
InboxSearch: "/works-inbox-service/v2/_search", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion
Avoid redundant top-level "EmployeeSearch" — use Urls.hrms.search
This duplicates hrms.search
and increases surface area for drift.
- EmployeeSearch: `/${healthHrms}/employees/_search`,
+ // Use Urls.hrms.search instead of duplicating
📝 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.
EmployeeSearch: `/${healthHrms}/employees/_search`, | |
InboxSearch: "/works-inbox-service/v2/_search", | |
// Use Urls.hrms.search instead of duplicating | |
InboxSearch: "/works-inbox-service/v2/_search", |
🤖 Prompt for AI Agents
In
health/micro-ui/web/micro-ui-internals/packages/modules/health-payments/src/services/urls.js
around lines 25 to 27, the top-level EmployeeSearch URL duplicates hrms.search;
remove the redundant EmployeeSearch property from this file and update any code
that references Urls.EmployeeSearch to use Urls.hrms.search instead (search and
replace references, run tests/linters to ensure no remaining usages).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Review continued from previous batch...
import React, { useEffect, useState } from "react"; | ||
import { useTranslation } from "react-i18next"; | ||
import { | ||
Dropdown, | ||
Loader, | ||
HeaderComponent, | ||
Card, | ||
LabelFieldPair, | ||
Button, | ||
Toast, | ||
CardLabel | ||
} from "@egovernments/digit-ui-components"; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion
Prune unused imports
useTranslation
, HeaderComponent
, Card
, Button
, Toast
are not used.
-import React, { useEffect, useState } from "react";
-import { useTranslation } from "react-i18next";
-import {
- Dropdown,
- Loader,
- HeaderComponent,
- Card,
- LabelFieldPair,
- Button,
- Toast,
- CardLabel
-} from "@egovernments/digit-ui-components";
+import React, { useEffect, useState } from "react";
+import { Dropdown, Loader, LabelFieldPair, CardLabel } from "@egovernments/digit-ui-components";
📝 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.
import React, { useEffect, useState } from "react"; | |
import { useTranslation } from "react-i18next"; | |
import { | |
Dropdown, | |
Loader, | |
HeaderComponent, | |
Card, | |
LabelFieldPair, | |
Button, | |
Toast, | |
CardLabel | |
} from "@egovernments/digit-ui-components"; | |
import React, { useEffect, useState } from "react"; | |
import { Dropdown, Loader, LabelFieldPair, CardLabel } from "@egovernments/digit-ui-components"; |
🤖 Prompt for AI Agents
In
health/micro-ui/web/micro-ui-internals/packages/modules/health-hrms/src/components/pageComponents/UserAssigment.js
around lines 1 to 12, there are unused imports (useTranslation, HeaderComponent,
Card, Button, Toast) that should be removed to clean up the file; update the
import statement from "@egovernments/digit-ui-components" to only include the
components actually used (Dropdown, Loader, LabelFieldPair, CardLabel) and run a
quick lint/format to ensure the import line is properly formatted after removal.
@@ -0,0 +1,104 @@ | |||
import React, { useEffect, useState } from "react"; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
💡 Verification agent
🧩 Analysis chain
Filename typo: UserAssigment.js
Consider renaming file to UserAssignment.js
for consistency with the component name.
If you opt to rename, update imports:
🏁 Script executed:
#!/bin/bash
rg -nP 'UserAssigment' -g '!**/node_modules/**'
Length of output: 148
🏁 Script executed:
#!/bin/bash
# Locate file with potential typo
find . -type f -iname '*UserAssigment*'
# Search codebase for any references to the misspelled component
rg -n 'UserAssigment' --ignore-dir node_modules
Length of output: 559
🏁 Script executed:
#!/bin/bash
# Find all references to the typo across the codebase
rg -n 'UserAssigment' --glob '!node_modules/**'
# Inspect the component’s name and export in the file
head -n 100 health/micro-ui/web/micro-ui-internals/packages/modules/health-hrms/src/components/pageComponents/UserAssigment.js
Length of output: 2857
🏁 Script executed:
# Search for any occurrences of the misspelled filename in code or imports
grep -R "UserAssigment" -n . --exclude-dir=node_modules
grep -R "from .*UserAssigment" -n . --exclude-dir=node_modules
Length of output: 357
Rename UserAssigment.js
to UserAssignment.js
and update imports
File health/micro-ui/web/micro-ui-internals/packages/modules/health-hrms/src/components/pageComponents/UserAssigment.js
has a typo in its name—rename it to UserAssignment.js
and update the import in health/micro-ui/web/micro-ui-internals/packages/modules/health-hrms/src/Module.js
(line 20).
🤖 Prompt for AI Agents
In
health/micro-ui/web/micro-ui-internals/packages/modules/health-hrms/src/components/pageComponents/UserAssigment.js
(line 1) the filename contains a typo; rename the file to UserAssignment.js and
update any references to it—specifically change the import in
health/micro-ui/web/micro-ui-internals/packages/modules/health-hrms/src/Module.js
at line 20 to import from './components/pageComponents/UserAssignment' (and
adjust any other imports/exports that reference the old name).
const boundaryCode = Digit?.SessionStorage.get("selectedBoundary")?.code; | ||
//const { t } = useTranslation(); | ||
const tenantId = Digit.ULBService.getStateId(); | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
💡 Verification agent
🧩 Analysis chain
Use environment-consistent tenant getter
Elsewhere the app predominantly uses getCurrentTenantId()
for API calls. Align unless this screen explicitly needs state-level tenant.
- const tenantId = Digit.ULBService.getStateId();
+ const tenantId = Digit.ULBService.getCurrentTenantId();
Verify usage across HRMS:
🏁 Script executed:
#!/bin/bash
rg -nP 'ULBService\.get(StateId|getCurrentTenantId)\(' -C2 health/micro-ui/web/micro-ui-internals/packages/modules/health-hrms
Length of output: 4796
🏁 Script executed:
#!/bin/bash
rg -nP "getStateId\(" -C3 micro-ui/web/micro-ui-internals/packages/modules/core/src
rg -nP "getCurrentTenantId\(" -C3 micro-ui/web/micro-ui-internals/packages/modules/core/src
Length of output: 17928
Use getCurrentTenantId()
for tenantId in UserAssigment.js
Align with other HRMS API calls (e.g., Inbox.js) by replacing the state-level getter:
- const tenantId = Digit.ULBService.getStateId();
+ const tenantId = Digit.ULBService.getCurrentTenantId();
📝 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.
const boundaryCode = Digit?.SessionStorage.get("selectedBoundary")?.code; | |
//const { t } = useTranslation(); | |
const tenantId = Digit.ULBService.getStateId(); | |
const boundaryCode = Digit?.SessionStorage.get("selectedBoundary")?.code; | |
//const { t } = useTranslation(); | |
const tenantId = Digit.ULBService.getCurrentTenantId(); |
🤖 Prompt for AI Agents
In
health/micro-ui/web/micro-ui-internals/packages/modules/health-hrms/src/components/pageComponents/UserAssigment.js
around lines 20 to 23, the code uses Digit.ULBService.getStateId() for tenantId
which is inconsistent with other HRMS API calls; replace that call with
Digit.ULBService.getCurrentTenantId() so tenantId is derived at the tenant scope
like Inbox.js, and keep boundaryCode retrieval as-is.
const result = individualData.map(item => ({ | ||
code: item.id, | ||
name: item.name?.givenName || null | ||
})); | ||
setOptions(result); | ||
}, [individualData]); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🧹 Nitpick (assertive)
Harden option mapping against missing names
Prevent blank labels by falling back to username or a translated NA.
- const result = individualData.map(item => ({
- code: item.id,
- name: item.name?.givenName || null
- }));
+ const result = individualData.map((item) => ({
+ code: item.id,
+ name: item?.name?.givenName || item?.userDetails?.username || t("NA"),
+ }));
📝 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.
const result = individualData.map(item => ({ | |
code: item.id, | |
name: item.name?.givenName || null | |
})); | |
setOptions(result); | |
}, [individualData]); | |
const result = individualData.map((item) => ({ | |
code: item.id, | |
name: item?.name?.givenName || item?.userDetails?.username || t("NA"), | |
})); | |
setOptions(result); | |
}, [individualData]); |
🤖 Prompt for AI Agents
In
health/micro-ui/web/micro-ui-internals/packages/modules/health-hrms/src/components/pageComponents/UserAssigment.js
around lines 62 to 67, the option mapping can produce blank labels when
givenName is missing; update the mapping so name is resolved to
item.name?.givenName || item.username || a translated "N/A" (or a sensible
fallback string). If your codebase uses i18n, call the appropriate translation
helper (e.g. t('common.na')) for the final fallback; otherwise use a constant
like 'N/A'. Keep the rest of the structure (code -> id, name -> resolved label)
and ensure setOptions(result) still receives the updated array.
...cro-ui-internals/packages/modules/health-hrms/src/components/pageComponents/UserAssigment.js
Show resolved
Hide resolved
const attendanceContextPath = | ||
window?.globalConfigs?.getConfig("ATTENDANCE_CONTEXT_PATH") || | ||
"health-attendance"; | ||
const individualContextPath = | ||
window?.globalConfigs?.getConfig("INDIVIDUAL_CONTEXT_PATH") || | ||
"health-individual"; | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🧹 Nitpick (assertive)
Centralize context paths via Urls to avoid duplication
This file re-reads globals; consider importing from the centralized Urls
module to keep one source of truth.
I can provide a small helper to export resolved base paths (attendance/individual) from urls.js
if you want.
🤖 Prompt for AI Agents
In
health/micro-ui/web/micro-ui-internals/packages/modules/health-payments/src/utils/update_attendance_summary.js
around lines 4 to 10, the file re-reads globals for ATTENDANCE_CONTEXT_PATH and
INDIVIDUAL_CONTEXT_PATH; replace those window.globalConfigs calls by importing
the centralized Urls helper and using its exported resolved base paths (e.g.
Urls.attendanceBasePath and Urls.individualBasePath or the helper names your
team provides). Remove the duplicated fallback logic and rely on Urls to provide
the canonical values (or add a small export in urls.js that resolves those
globals and import that instead).
useEffect(() => { | ||
if (attendanceData?.attendanceRegister?.length > 0) { | ||
const ids = attendanceData.attendanceRegister[0].attendees.map( | ||
(a) => a.individualId | ||
); | ||
setIndividualIds(ids); | ||
} | ||
}, [attendanceData]); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion
Reset and de-duplicate individual IDs
Prevents stale IDs when register changes and avoids duplicate lookups.
- useEffect(() => {
- if (attendanceData?.attendanceRegister?.length > 0) {
- const ids = attendanceData.attendanceRegister[0].attendees.map(
- (a) => a.individualId
- );
- setIndividualIds(ids);
- }
- }, [attendanceData]);
+ useEffect(() => {
+ if (attendanceData?.attendanceRegister?.length > 0) {
+ const ids = Array.from(
+ new Set(attendanceData.attendanceRegister[0]?.attendees?.map((a) => a.individualId).filter(Boolean))
+ );
+ setIndividualIds(ids);
+ } else {
+ setIndividualIds([]);
+ }
+ }, [attendanceData]);
📝 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.
useEffect(() => { | |
if (attendanceData?.attendanceRegister?.length > 0) { | |
const ids = attendanceData.attendanceRegister[0].attendees.map( | |
(a) => a.individualId | |
); | |
setIndividualIds(ids); | |
} | |
}, [attendanceData]); | |
useEffect(() => { | |
if (attendanceData?.attendanceRegister?.length > 0) { | |
const ids = Array.from( | |
new Set( | |
attendanceData.attendanceRegister[0] | |
?.attendees | |
?.map((a) => a.individualId) | |
.filter(Boolean) | |
) | |
); | |
setIndividualIds(ids); | |
} else { | |
setIndividualIds([]); | |
} | |
}, [attendanceData]); |
🤖 Prompt for AI Agents
In
health/micro-ui/web/micro-ui-internals/packages/modules/health-payments/src/utils/update_attendance_summary.js
around lines 31 to 38, the effect only reads the first register and can leave
stale or duplicate individualIds when registers change; update the effect to (1)
bail to setIndividualIds([]) when attendanceRegister is empty, (2) flatten all
attendanceRegister entries to collect every attendee.individualId, (3) remove
duplicates (use a Set) before calling setIndividualIds, and (4) ensure the
effect tracks the actual register (attendanceData.attendanceRegister) in its
dependency array so it runs when the register content changes.
limit: individualIds.length, | ||
offset: 0, | ||
}, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🧹 Nitpick (assertive)
Guard against very large ID lists (server max limit/pagination)
Using limit: individualIds.length
can exceed server caps. Consider chunked fetch or a sane upper bound.
Would you like me to propose a chunking helper that batches IDs (e.g., 50 per request) and merges results?
const attendanceLogData = | ||
attendanceData.attendanceRegister[0].attendees.map((individualEntry) => { | ||
const individualId = individualEntry.individualId; | ||
const matchingIndividual = individualsData?.Individual?.find( | ||
(individual) => individual.id === individualId | ||
); | ||
|
||
if (matchingIndividual) { | ||
const userName = matchingIndividual.name?.givenName || t("NA"); | ||
const userId = matchingIndividual?.userDetails?.username || t("NA"); | ||
const userRole = t(matchingIndividual.skills?.[0]?.type) || t("NA"); | ||
const noOfDaysWorked = | ||
individualEntry?.denrollmentDate == null ? true : false; | ||
|
||
const id = individualEntry.individualId || 0; | ||
|
||
return [id, userName, userId, userRole, noOfDaysWorked]; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
💡 Verification agent
🧩 Analysis chain
Fix typo in field name and avoid misnamed "noOfDaysWorked" boolean
denrollmentDate
looks like a typo. Also the variable is a boolean flagged as a count.
- const userRole = t(matchingIndividual.skills?.[0]?.type) || t("NA");
- const noOfDaysWorked =
- individualEntry?.denrollmentDate == null ? true : false;
+ const userRole = t(matchingIndividual.skills?.[0]?.type) || t("NA");
+ const isActive = individualEntry?.deEnrollmentDate == null;
@@
- return [id, userName, userId, userRole, noOfDaysWorked];
+ return [id, userName, userId, userRole, isActive];
@@
- return [
- "N/A",
- "Unknown",
- "N/A",
- "Unassigned",
- individualEntry?.denrollmentDate == null ? true : false,
- ];
+ return [
+ "N/A",
+ t("UNKNOWN"),
+ "N/A",
+ t("UNASSIGNED"),
+ individualEntry?.deEnrollmentDate == null,
+ ];
Confirm the correct field name from the attendance API schema. If it’s disEnrollmentDate
or similar, update accordingly.
Also applies to: 83-90
🌐 Web query:
What is the correct field name for an attendee's end-of-enrollment date in the DIGIT Health Attendance Register API? (e.g., deEnrollmentDate vs denrollmentDate)
💡 Result:
The correct field name is deEnrollmentDate. [1][2]
Sources:
[1] DIGIT Attendance API (spec & API contract). (health.digit.org)
[2] DIGIT Attendance documentation. (docs.digit.org)
Citations:
- 1: https://health.digit.org/technology/architecture/low-level-design/registries/attendance?utm_source=openai
- 2: https://docs.digit.org/health/setup/configuration/ui-configuration/attendance-management?utm_source=openai
Use deEnrollmentDate
and rename noOfDaysWorked
to isActive
- Replace all
individualEntry?.denrollmentDate
withindividualEntry.deEnrollmentDate
(the API schema’s correct field isdeEnrollmentDate
). - Rename the boolean
noOfDaysWorked
toisActive
and simplify its assignment toconst isActive = individualEntry.deEnrollmentDate == null
. - Update both the main and fallback return arrays (lines 65–81 and 83–90) to use
deEnrollmentDate
andisActive
.
🤖 Prompt for AI Agents
In
health/micro-ui/web/micro-ui-internals/packages/modules/health-payments/src/utils/update_attendance_summary.js
around lines 65 to 81 and also covering the fallback return at 83 to 90, replace
any use of individualEntry?.denrollmentDate with
individualEntry.deEnrollmentDate, rename the boolean variable noOfDaysWorked to
isActive and simplify its assignment to const isActive =
individualEntry.deEnrollmentDate == null, and update both the main returned
array and the fallback returned array to return isActive in place of the old
noOfDaysWorked variable.
useEffect(() => { | ||
if ( | ||
attendanceData?.attendanceRegister?.length > 0 && | ||
allIndividualsData?.Individual?.length > 0 | ||
) { | ||
const summary = getUserAttendanceSummary( | ||
attendanceData, | ||
allIndividualsData, | ||
t | ||
); | ||
setAttendanceSummary(summary); | ||
} | ||
}, [allIndividualsData, attendanceData, t]); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion
Ensure summary resets when data becomes unavailable
Avoid showing stale rows if either dataset empties out.
useEffect(() => {
if (
attendanceData?.attendanceRegister?.length > 0 &&
allIndividualsData?.Individual?.length > 0
) {
const summary = getUserAttendanceSummary(
attendanceData,
allIndividualsData,
t
);
setAttendanceSummary(summary);
- }
+ } else {
+ setAttendanceSummary([]);
+ }
}, [allIndividualsData, attendanceData, t]);
📝 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.
useEffect(() => { | |
if ( | |
attendanceData?.attendanceRegister?.length > 0 && | |
allIndividualsData?.Individual?.length > 0 | |
) { | |
const summary = getUserAttendanceSummary( | |
attendanceData, | |
allIndividualsData, | |
t | |
); | |
setAttendanceSummary(summary); | |
} | |
}, [allIndividualsData, attendanceData, t]); | |
useEffect(() => { | |
if ( | |
attendanceData?.attendanceRegister?.length > 0 && | |
allIndividualsData?.Individual?.length > 0 | |
) { | |
const summary = getUserAttendanceSummary( | |
attendanceData, | |
allIndividualsData, | |
t | |
); | |
setAttendanceSummary(summary); | |
} else { | |
setAttendanceSummary([]); | |
} | |
}, [allIndividualsData, attendanceData, t]); |
🤖 Prompt for AI Agents
In
health/micro-ui/web/micro-ui-internals/packages/modules/health-payments/src/utils/update_attendance_summary.js
around lines 99 to 111, the effect only sets attendanceSummary when both
datasets have length > 0, so stale rows remain if one dataset becomes empty;
update the useEffect to explicitly reset attendanceSummary (e.g.,
setAttendanceSummary([]) or null) in the else branch when attendanceData or
allIndividualsData are missing or have zero length, keeping the existing
dependency array.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Review continued from previous batch...
preProcess: (data, additionalDetails) => { | ||
const { name, status } = data?.state?.searchForm || {}; | ||
data.body.PlanConfigurationSearchCriteria = {}; | ||
data.body.PlanConfigurationSearchCriteria.limit = data?.state?.tableForm?.limit; | ||
// data.body.PlanConfigurationSearchCriteria.limit = 10 | ||
data.body.PlanConfigurationSearchCriteria.offset = data?.state?.tableForm?.offset; | ||
data.body.PlanConfigurationSearchCriteria.name = name; | ||
data.body.PlanConfigurationSearchCriteria.tenantId = Digit.ULBService.getCurrentTenantId(); | ||
data.body.PlanConfigurationSearchCriteria.userUuid = Digit.UserService.getUser().info.uuid; | ||
// delete data.body.PlanConfigurationSearchCriteria.pagination | ||
data.body.PlanConfigurationSearchCriteria.status = status?.status; | ||
data.body.PlanConfigurationSearchCriteria.name = data?.state?.searchForm?.microplanName; | ||
cleanObject(data.body.PlanConfigurationSearchCriteria); | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🧹 Nitpick (assertive)
Duplicate/overwritten fields in MicroplanSearchConfig.preProcess
name
is assigned twice; status
is first read from form and later overridden by tab filter. Simplify to avoid confusion.
- const { name, status } = data?.state?.searchForm || {};
+ const { name } = data?.state?.searchForm || {};
...
- data.body.PlanConfigurationSearchCriteria.name = name;
+ data.body.PlanConfigurationSearchCriteria.name = name;
...
- data.body.PlanConfigurationSearchCriteria.status = status?.status;
- data.body.PlanConfigurationSearchCriteria.name = data?.state?.searchForm?.microplanName;
+ // status set below using tab filter
+ if (data?.state?.searchForm?.microplanName) {
+ data.body.PlanConfigurationSearchCriteria.name = data.state.searchForm.microplanName;
+ }
Confirm expected precedence between name
and microplanName
.
Committable suggestion skipped: line range outside the PR's diff.
🤖 Prompt for AI Agents
In health/micro-ui/web/micro-ui-internals/example/src/UICustomizations.js around
lines 810 to 823, the preProcess block assigns the same fields twice which
causes ambiguity (name is set from searchForm then from microplanName, and
status may be coming from two sources); remove the duplicate assignment and make
explicit which source has precedence: set
data.body.PlanConfigurationSearchCriteria.name once (use microplanName if the UI
expects that to override the generic name, otherwise use name), and ensure
status is sourced from the intended place (either keep status from the form or
from the tab filter) — update the code to assign each field only once, remove
the commented/duplicate lines, and add a short inline comment noting the chosen
precedence so future reviewers know which source wins.
const [showToast, setShowToast] = useState(false); | ||
const tenantId = Digit.ULBService.getCurrentTenantId(); | ||
const microplanId = row?.id; | ||
|
||
const { data: rootEstimationApprover } = Digit.Hooks.microplanv1.usePlanSearchEmployeeWithTagging({ | ||
tenantId: tenantId, | ||
body: { | ||
PlanEmployeeAssignmentSearchCriteria: { | ||
tenantId: tenantId, | ||
planConfigurationId: microplanId, | ||
role: ["ROOT_PLAN_ESTIMATION_APPROVER"], | ||
active: true, | ||
}, | ||
}); | ||
}, | ||
config: { | ||
enabled: true, | ||
}, | ||
}); | ||
|
||
const { data: rootPopulationApprover } = Digit.Hooks.microplanv1.usePlanSearchEmployeeWithTagging({ | ||
tenantId, | ||
body: { | ||
PlanEmployeeAssignmentSearchCriteria: { | ||
tenantId, | ||
planConfigurationId: microplanId, | ||
role: ["ROOT_POPULATION_DATA_APPROVER"], | ||
active: true, | ||
}, | ||
const { data: rootPopulationApprover } = Digit.Hooks.microplanv1.usePlanSearchEmployeeWithTagging({ | ||
tenantId, | ||
body: { | ||
PlanEmployeeAssignmentSearchCriteria: { | ||
tenantId, | ||
planConfigurationId: microplanId, | ||
role: ["ROOT_POPULATION_DATA_APPROVER"], | ||
active: true, | ||
}, | ||
config: { enabled: true }, | ||
}); | ||
}, | ||
config: { enabled: true }, | ||
}); | ||
|
||
const { data: rootFacilityMapper } = Digit.Hooks.microplanv1.usePlanSearchEmployeeWithTagging({ | ||
tenantId, | ||
body: { | ||
PlanEmployeeAssignmentSearchCriteria: { | ||
tenantId, | ||
planConfigurationId: microplanId, | ||
role: ["ROOT_FACILITY_CATCHMENT_MAPPER"], | ||
active: true, | ||
}, | ||
const { data: rootFacilityMapper } = Digit.Hooks.microplanv1.usePlanSearchEmployeeWithTagging({ | ||
tenantId, | ||
body: { | ||
PlanEmployeeAssignmentSearchCriteria: { | ||
tenantId, | ||
planConfigurationId: microplanId, | ||
role: ["ROOT_FACILITY_CATCHMENT_MAPPER"], | ||
active: true, | ||
}, | ||
config: { enabled: true }, | ||
}); | ||
|
||
switch (key) { | ||
case "ACTIONS": | ||
// TODO : Replace dummy file id with real file id when API is ready | ||
const dummyFile = "c22a7676-d5d7-49b6-bcdb-83e9519f58df" | ||
const microplanFileId = row?.campaignDetails?.additionalDetails?.microplanFileId || dummyFile; | ||
const EstimationsfileId = row?.files.find((item) => item.templateIdentifier === "Estimations")?.filestoreId; | ||
let options = []; | ||
|
||
if (row?.status == "DRAFT") { | ||
options = [ | ||
{ code: "1", name: "MP_ACTIONS_EDIT_SETUP" }, | ||
{ code: "2", name: "MP_ACTIONS_DOWNLOAD_DRAFT" }, | ||
{ code: "3", name: "MP_ACTIONS_FREEZE_MICROPLAN" }, | ||
]; | ||
} else { | ||
options = [{ code: "1", name: "MP_ACTIONS_VIEW_SUMMARY" }]; | ||
}, | ||
config: { enabled: true }, | ||
}); | ||
|
||
switch (key) { | ||
case "ACTIONS": | ||
// TODO : Replace dummy file id with real file id when API is ready | ||
const dummyFile = "c22a7676-d5d7-49b6-bcdb-83e9519f58df" | ||
const microplanFileId = row?.campaignDetails?.additionalDetails?.microplanFileId || dummyFile; | ||
const EstimationsfileId = row?.files.find((item) => item.templateIdentifier === "Estimations")?.filestoreId; | ||
let options = []; | ||
|
||
if (row?.status == "DRAFT") { | ||
options = [ | ||
{ code: "1", name: "MP_ACTIONS_EDIT_SETUP" }, | ||
{ code: "2", name: "MP_ACTIONS_DOWNLOAD_DRAFT" }, | ||
{ code: "3", name: "MP_ACTIONS_FREEZE_MICROPLAN" }, | ||
]; | ||
} else { | ||
options = [{ code: "1", name: "MP_ACTIONS_VIEW_SUMMARY" }]; | ||
} | ||
|
||
const handleDownload = ({ type }) => { | ||
|
||
const template = type === "Estimations" ? "Estimations" : "DraftComplete"; | ||
const fileId = row?.files.find((item) => item.templateIdentifier === template)?.filestoreId; | ||
if (!fileId) { | ||
setShowToast({ label: t("NO_DRAFT_FILE_FOUND") }); | ||
return; | ||
} | ||
|
||
const handleDownload = ({type}) => { | ||
|
||
const template = type === "Estimations" ? "Estimations" : "DraftComplete"; | ||
const fileId = row?.files.find((item) => item.templateIdentifier === template)?.filestoreId; | ||
if (!fileId) { | ||
setShowToast({ label: t("NO_DRAFT_FILE_FOUND") }); | ||
return; | ||
} | ||
const campaignName = row?.name || ""; | ||
const customName = type === "Estimations" ? campaignName : `${campaignName}_DRAFT`; | ||
Digit.Utils.campaign.downloadExcelWithCustomName({ | ||
fileStoreId: fileId, | ||
customName: customName, | ||
}); | ||
}; | ||
|
||
const onActionSelect = async (e,row) => { | ||
if (e.name === "MP_ACTIONS_EDIT_SETUP") { | ||
const key = parseInt(row?.additionalDetails?.key); | ||
const resolvedKey = key === 8 ? 7 : key === 10 ? 11 : key || 2; | ||
const url = `/${window.contextPath}/employee/microplan/setup-microplan?key=${resolvedKey}µplanId=${row.id}&campaignId=${row.campaignDetails.id}`; | ||
window.location.href = url; | ||
const campaignName = row?.name || ""; | ||
const customName = type === "Estimations" ? campaignName : `${campaignName}_DRAFT`; | ||
Digit.Utils.campaign.downloadExcelWithCustomName({ | ||
fileStoreId: fileId, | ||
customName: customName, | ||
}); | ||
}; | ||
|
||
const onActionSelect = async (e, row) => { | ||
if (e.name === "MP_ACTIONS_EDIT_SETUP") { | ||
const key = parseInt(row?.additionalDetails?.key); | ||
const resolvedKey = key === 8 ? 7 : key === 10 ? 11 : key || 2; | ||
const url = `/${window.contextPath}/employee/microplan/setup-microplan?key=${resolvedKey}µplanId=${row.id}&campaignId=${row.campaignDetails.id}`; | ||
window.location.href = url; | ||
} | ||
if (e.name === "MP_ACTIONS_DOWNLOAD_DRAFT") { | ||
if (row?.status == "DRAFT" && row?.assumptions.length > 0 && row?.operations.length > 0) { | ||
handleDownload({ type: "Draft" }); | ||
} else { | ||
setShowToast({ label: t("PLEASE_UPDATE_THE_SETUP_INFORMATION_BEFORE_DOWNLOADING_DRAFT") }); | ||
} | ||
if (e.name === "MP_ACTIONS_DOWNLOAD_DRAFT") { | ||
if (row?.status == "DRAFT" && row?.assumptions.length > 0 && row?.operations.length > 0) { | ||
handleDownload({ type: "Draft" }); | ||
} else { | ||
setShowToast({ label: t("PLEASE_UPDATE_THE_SETUP_INFORMATION_BEFORE_DOWNLOADING_DRAFT") }); | ||
} | ||
if (e.name === "MP_ACTIONS_FREEZE_MICROPLAN") { | ||
if ( | ||
row?.status == "DRAFT" && | ||
row?.assumptions.length > 0 && | ||
row?.operations.length > 0 && | ||
rootEstimationApprover?.data?.length > 0 && | ||
rootPopulationApprover?.data?.length > 0 && | ||
rootFacilityMapper?.data?.length > 0 | ||
) { | ||
const triggeredFromMain = "OPEN_MICROPLANS"; | ||
const response = await Digit.Hooks.microplanv1.useCompleteSetUpFlow({ | ||
tenantId, | ||
microplanId, | ||
triggeredFrom: triggeredFromMain, | ||
}); | ||
if (response && !response?.isError) { | ||
window.history.pushState(response?.state, "", response?.redirectTo); | ||
window.dispatchEvent(new PopStateEvent("popstate", { state: response?.state })); | ||
} | ||
} | ||
if (e.name === "MP_ACTIONS_FREEZE_MICROPLAN") { | ||
if ( | ||
row?.status == "DRAFT" && | ||
row?.assumptions.length > 0 && | ||
row?.operations.length > 0 && | ||
rootEstimationApprover?.data?.length > 0 && | ||
rootPopulationApprover?.data?.length > 0 && | ||
rootFacilityMapper?.data?.length > 0 | ||
) { | ||
const triggeredFromMain = "OPEN_MICROPLANS"; | ||
const response = await Digit.Hooks.microplanv1.useCompleteSetUpFlow({ | ||
tenantId, | ||
microplanId, | ||
triggeredFrom: triggeredFromMain, | ||
}); | ||
if (response && !response?.isError) { | ||
window.history.pushState(response?.state, "", response?.redirectTo); | ||
window.dispatchEvent(new PopStateEvent("popstate", { state: response?.state })); | ||
} | ||
if (response && response?.isError) { | ||
console.error(`ERR_FAILED_TO_COMPLETE_SETUP`); | ||
} | ||
} else { | ||
setShowToast({ label:t("PLEASE_FINISH_THE_DRAFT_BEFORE_FREEZING") }); | ||
if (response && response?.isError) { | ||
console.error(`ERR_FAILED_TO_COMPLETE_SETUP`); | ||
} | ||
} else { | ||
setShowToast({ label: t("PLEASE_FINISH_THE_DRAFT_BEFORE_FREEZING") }); | ||
} | ||
if (e.name == "MP_ACTIONS_VIEW_SUMMARY") { | ||
window.location.href = `/${window.contextPath}/employee/microplan/setup-microplan?key=${11}µplanId=${row.id}&campaignId=${ | ||
row.campaignDetails.id | ||
} | ||
if (e.name == "MP_ACTIONS_VIEW_SUMMARY") { | ||
window.location.href = `/${window.contextPath}/employee/microplan/setup-microplan?key=${11}µplanId=${row.id}&campaignId=${row.campaignDetails.id | ||
}&setup-completed=true`; | ||
} | ||
}; | ||
|
||
const handleToast = () => { | ||
setShowToast(false); | ||
}; | ||
} | ||
}; | ||
|
||
return ( | ||
<> | ||
const handleToast = () => { | ||
setShowToast(false); | ||
}; | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion
Invalid Hook usage inside cell renderer; and switch-case declarations leak scope
useState
and data hooks are called directly inside additionalCustomizations
and within a switch
case. This violates React Hook rules and triggers Biome noSwitchDeclarations.
Refactor the ACTIONS cell into a small component and reference it from the switch; also wraps case scope.
- additionalCustomizations: (row, key, column, value, t, searchResult) => {
- const [showToast, setShowToast] = useState(false);
- const tenantId = Digit.ULBService.getCurrentTenantId();
- const microplanId = row?.id;
- const { data: rootEstimationApprover } = Digit.Hooks.microplanv1.usePlanSearchEmployeeWithTagging({ ... });
- const { data: rootPopulationApprover } = Digit.Hooks.microplanv1.usePlanSearchEmployeeWithTagging({ ... });
- const { data: rootFacilityMapper } = Digit.Hooks.microplanv1.usePlanSearchEmployeeWithTagging({ ... });
- switch (key) {
- case "ACTIONS":
- // ... lots of declarations and hooks ...
- return (<> ... </>);
+ additionalCustomizations: (row, key, column, value, t, searchResult) => {
+ switch (key) {
+ case "ACTIONS": {
+ return <MicroplanActionsCell row={row} t={t} />;
+ }
case "NAME_OF_MICROPLAN":
...
}
},
Add this component (outside the object, anywhere in module scope):
function MicroplanActionsCell({ row, t }) {
const [showToast, setShowToast] = useState(false);
const tenantId = Digit.ULBService.getCurrentTenantId();
const microplanId = row?.id;
const { data: rootEstimationApprover } = Digit.Hooks.microplanv1.usePlanSearchEmployeeWithTagging({ /* as-is */ });
const { data: rootPopulationApprover } = Digit.Hooks.microplanv1.usePlanSearchEmployeeWithTagging({ /* as-is */ });
const { data: rootFacilityMapper } = Digit.Hooks.microplanv1.usePlanSearchEmployeeWithTagging({ /* as-is */ });
// existing handleDownload / onActionSelect / handleToast logic unchanged
// but remove dummy file id and rely on real availability
const EstimationsfileId = row?.files?.find((it) => it.templateIdentifier === "Estimations")?.filestoreId;
// return the same JSX previously returned for the case
return (/* same JSX */);
}
Also remove the hard-coded dummyFile
and rely on real file presence; disable download button if fileId is absent.
This resolves both hook rules and noSwitchDeclarations warnings.
🧰 Tools
🪛 Biome (2.1.2)
[error] 887-887: Other switch clauses can erroneously access this declaration.
Wrap the declaration in a block to restrict its access to the switch clause.
The declaration is defined in this switch clause:
Safe fix: Wrap the declaration in a block.
(lint/correctness/noSwitchDeclarations)
[error] 888-888: Other switch clauses can erroneously access this declaration.
Wrap the declaration in a block to restrict its access to the switch clause.
The declaration is defined in this switch clause:
Safe fix: Wrap the declaration in a block.
(lint/correctness/noSwitchDeclarations)
[error] 889-889: Other switch clauses can erroneously access this declaration.
Wrap the declaration in a block to restrict its access to the switch clause.
The declaration is defined in this switch clause:
Safe fix: Wrap the declaration in a block.
(lint/correctness/noSwitchDeclarations)
[error] 890-890: Other switch clauses can erroneously access this declaration.
Wrap the declaration in a block to restrict its access to the switch clause.
The declaration is defined in this switch clause:
Safe fix: Wrap the declaration in a block.
(lint/correctness/noSwitchDeclarations)
[error] 902-916: Other switch clauses can erroneously access this declaration.
Wrap the declaration in a block to restrict its access to the switch clause.
The declaration is defined in this switch clause:
Safe fix: Wrap the declaration in a block.
(lint/correctness/noSwitchDeclarations)
[error] 918-962: Other switch clauses can erroneously access this declaration.
Wrap the declaration in a block to restrict its access to the switch clause.
The declaration is defined in this switch clause:
Safe fix: Wrap the declaration in a block.
(lint/correctness/noSwitchDeclarations)
[error] 964-966: Other switch clauses can erroneously access this declaration.
Wrap the declaration in a block to restrict its access to the switch clause.
The declaration is defined in this switch clause:
Safe fix: Wrap the declaration in a block.
(lint/correctness/noSwitchDeclarations)
const dummyFile = "c22a7676-d5d7-49b6-bcdb-83e9519f58df" | ||
const microplanFileId = row?.campaignDetails?.additionalDetails?.microplanFileId || dummyFile; | ||
const EstimationsfileId = row?.files.find((item) => item.templateIdentifier === "Estimations")?.filestoreId; | ||
let options = []; | ||
|
||
if (row?.status == "DRAFT") { | ||
options = [ | ||
{ code: "1", name: "MP_ACTIONS_EDIT_SETUP" }, | ||
{ code: "2", name: "MP_ACTIONS_DOWNLOAD_DRAFT" }, | ||
{ code: "3", name: "MP_ACTIONS_FREEZE_MICROPLAN" }, | ||
]; | ||
} else { | ||
options = [{ code: "1", name: "MP_ACTIONS_VIEW_SUMMARY" }]; | ||
} | ||
|
||
const handleDownload = ({ type }) => { | ||
|
||
const template = type === "Estimations" ? "Estimations" : "DraftComplete"; | ||
const fileId = row?.files.find((item) => item.templateIdentifier === template)?.filestoreId; | ||
if (!fileId) { | ||
setShowToast({ label: t("NO_DRAFT_FILE_FOUND") }); | ||
return; | ||
} | ||
|
||
const handleDownload = ({type}) => { | ||
|
||
const template = type === "Estimations" ? "Estimations" : "DraftComplete"; | ||
const fileId = row?.files.find((item) => item.templateIdentifier === template)?.filestoreId; | ||
if (!fileId) { | ||
setShowToast({ label: t("NO_DRAFT_FILE_FOUND") }); | ||
return; | ||
} | ||
const campaignName = row?.name || ""; | ||
const customName = type === "Estimations" ? campaignName : `${campaignName}_DRAFT`; | ||
Digit.Utils.campaign.downloadExcelWithCustomName({ | ||
fileStoreId: fileId, | ||
customName: customName, | ||
}); | ||
}; | ||
|
||
const onActionSelect = async (e,row) => { | ||
if (e.name === "MP_ACTIONS_EDIT_SETUP") { | ||
const key = parseInt(row?.additionalDetails?.key); | ||
const resolvedKey = key === 8 ? 7 : key === 10 ? 11 : key || 2; | ||
const url = `/${window.contextPath}/employee/microplan/setup-microplan?key=${resolvedKey}µplanId=${row.id}&campaignId=${row.campaignDetails.id}`; | ||
window.location.href = url; | ||
const campaignName = row?.name || ""; | ||
const customName = type === "Estimations" ? campaignName : `${campaignName}_DRAFT`; | ||
Digit.Utils.campaign.downloadExcelWithCustomName({ | ||
fileStoreId: fileId, | ||
customName: customName, | ||
}); | ||
}; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🧹 Nitpick (assertive)
noSwitchDeclarations: wrap declarations in block scopes
Even if you don’t adopt the component refactor immediately, wrap each case with {}
to scope const
declarations and satisfy Biome.
- case "ACTIONS":
+ case "ACTIONS": {
const dummyFile = ...
const microplanFileId = ...
let options = [];
...
- return ( ... );
+ return ( ... );
+ }
Repeat for other cases with inline declarations.
Also applies to: 918-962, 964-966
🧰 Tools
🪛 Biome (2.1.2)
[error] 887-887: Other switch clauses can erroneously access this declaration.
Wrap the declaration in a block to restrict its access to the switch clause.
The declaration is defined in this switch clause:
Safe fix: Wrap the declaration in a block.
(lint/correctness/noSwitchDeclarations)
[error] 888-888: Other switch clauses can erroneously access this declaration.
Wrap the declaration in a block to restrict its access to the switch clause.
The declaration is defined in this switch clause:
Safe fix: Wrap the declaration in a block.
(lint/correctness/noSwitchDeclarations)
[error] 889-889: Other switch clauses can erroneously access this declaration.
Wrap the declaration in a block to restrict its access to the switch clause.
The declaration is defined in this switch clause:
Safe fix: Wrap the declaration in a block.
(lint/correctness/noSwitchDeclarations)
[error] 890-890: Other switch clauses can erroneously access this declaration.
Wrap the declaration in a block to restrict its access to the switch clause.
The declaration is defined in this switch clause:
Safe fix: Wrap the declaration in a block.
(lint/correctness/noSwitchDeclarations)
[error] 902-916: Other switch clauses can erroneously access this declaration.
Wrap the declaration in a block to restrict its access to the switch clause.
The declaration is defined in this switch clause:
Safe fix: Wrap the declaration in a block.
(lint/correctness/noSwitchDeclarations)
🤖 Prompt for AI Agents
In health/micro-ui/web/micro-ui-internals/example/src/UICustomizations.js around
lines 887-916 (and also apply same change to 918-962 and 964-966), the
switch/case-like inline branches declare consts in the outer scope; wrap each
case branch in its own block scope by adding { } around the code for that branch
so each const/let is scoped to that block and Biome noSwitchDeclarations is
satisfied; apply the same wrapping to the other listed ranges where inline
declarations occur.
const handleFileDownload = () => { | ||
const fileId = row?.files.find((item) => item.templateIdentifier === "Estimations")?.filestoreId; | ||
if (!fileId) { | ||
console.error("Estimation template file not found"); | ||
return; | ||
} | ||
return; | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🧹 Nitpick (assertive)
Action button config misuse
For the action button in MyMicroplanSearchConfig:
- You pass
isSearchable
,options
, andonOptionSelect
but also anonClick
no-op. Prefer removing redundantonClick
. - Guard download button using
EstimationsfileId
.
- isSearchable={false}
- title={t("MP_ACTIONS_FOR_MICROPLANS")}
- label={t("MP_ACTIONS_FOR_MICROPLANS")}
- isDisabled={!EstimationsfileId}
- onClick={() => { }}
+ isSearchable={false}
+ title={t("MP_ACTIONS_FOR_MICROPLANS")}
+ label={t("MP_ACTIONS_FOR_MICROPLANS")}
+ isDisabled={!EstimationsfileId}
Also applies to: 1194-1218
🤖 Prompt for AI Agents
In health/micro-ui/web/micro-ui-internals/example/src/UICustomizations.js around
lines 1108-1113 (and similarly at 1194-1218), the MyMicroplanSearchConfig action
button is being passed redundant props including a no-op onClick and the
download action is not properly guarded by the Estimations file id; remove the
unnecessary onClick prop so only isSearchable, options, and onOptionSelect are
passed, and add a guard that checks the Estimations file id (e.g.,
EstimationsfileId or the lookup for templateIdentifier "Estimations") before
rendering/enabling the download button so the button is hidden/disabled when
that id is missing.
import React, { useState } from "react"; | ||
import { useTranslation } from "react-i18next"; | ||
import { PopUp, Timeline, Loader, TextInput, Button } from '@egovernments/digit-ui-components'; | ||
import { useEffect } from "react"; | ||
import EditAttendanceManagementTable from "./EditAttendanceManagementTable"; | ||
import { useHistory } from "react-router-dom"; | ||
import AttendeeService from "../services/attendance/attendee_service/attendeeService"; | ||
|
||
import { useAttendanceSummary } from "../utils/update_attendance_summary"; | ||
|
||
import SearchUserPopUp from "./SearchUserPopUp"; | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🧹 Nitpick (assertive)
Remove unused imports and dead code
Timeline
, AttendeeService
, and useAttendanceSummary
are not used.
-import { PopUp, Timeline, Loader, TextInput, Button } from '@egovernments/digit-ui-components';
+import { PopUp, Loader, TextInput, Button } from '@egovernments/digit-ui-components';
...
-import AttendeeService from "../services/attendance/attendee_service/attendeeService";
-
-import { useAttendanceSummary } from "../utils/update_attendance_summary";
+// removed unused imports
Also applies to: 7-7, 9-10
🤖 Prompt for AI Agents
In
health/micro-ui/web/micro-ui-internals/packages/modules/health-payments/src/components/editAttendeesPopUp.js
around lines 1-12 (and specifically lines 7 and 9-10), remove the unused imports
Timeline, AttendeeService, and useAttendanceSummary from the import list and
delete any dead code or references related to them; ensure you only keep imports
that are actually used (e.g., PopUp, Loader, TextInput, Button,
EditAttendanceManagementTable, SearchUserPopUp, useTranslation, useState,
useEffect, useHistory), run the linter/TypeScript check to confirm no remaining
unused symbols, and adjust imports formatting if necessary.
const { isLoading: isAttendanceLoading, data: AttendanceData } = | ||
Digit.Hooks.useCustomAPIHook(AttendancereqCri); | ||
|
||
// Extract individualIds once AttendanceData is fetched | ||
useEffect(() => { | ||
if (AttendanceData?.attendanceRegister?.length > 0) { | ||
const ids = AttendanceData.attendanceRegister[0].attendees.map( | ||
(a) => a.individualId | ||
); | ||
setIndividualIds(ids); | ||
} | ||
}, [AttendanceData]); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
💡 Verification agent
❓ Verification inconclusive
Harden extraction when attendanceRegister or attendees are missing
Avoid runtime errors if API returns empty/malformed data.
- useEffect(() => {
- if (AttendanceData?.attendanceRegister?.length > 0) {
- const ids = AttendanceData.attendanceRegister[0].attendees.map(
- (a) => a.individualId
- );
- setIndividualIds(ids);
- }
- }, [AttendanceData]);
+ useEffect(() => {
+ const attendees = AttendanceData?.attendanceRegister?.[0]?.attendees || [];
+ if (Array.isArray(attendees) && attendees.length) {
+ setIndividualIds(attendees.map((a) => a.individualId).filter(Boolean));
+ } else {
+ setIndividualIds([]);
+ }
+ }, [AttendanceData]);
Consider adding an empty state in UI when no attendees exist.
Harden extraction of individualIds in useEffect
Use optional chaining and a safe default to avoid runtime errors when attendanceRegister or attendees is missing:
- useEffect(() => {
- if (AttendanceData?.attendanceRegister?.length > 0) {
- const ids = AttendanceData.attendanceRegister[0].attendees.map(
- (a) => a.individualId
- );
- setIndividualIds(ids);
- }
- }, [AttendanceData]);
+ useEffect(() => {
+ const attendees = AttendanceData?.attendanceRegister?.[0]?.attendees ?? [];
+ setIndividualIds(
+ Array.isArray(attendees)
+ ? attendees.map(a => a.individualId).filter(Boolean)
+ : []
+ );
+ }, [AttendanceData]);
Also render an empty-state UI when individualIds
is empty.
📝 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.
const { isLoading: isAttendanceLoading, data: AttendanceData } = | |
Digit.Hooks.useCustomAPIHook(AttendancereqCri); | |
// Extract individualIds once AttendanceData is fetched | |
useEffect(() => { | |
if (AttendanceData?.attendanceRegister?.length > 0) { | |
const ids = AttendanceData.attendanceRegister[0].attendees.map( | |
(a) => a.individualId | |
); | |
setIndividualIds(ids); | |
} | |
}, [AttendanceData]); | |
useEffect(() => { | |
const attendees = AttendanceData?.attendanceRegister?.[0]?.attendees ?? []; | |
setIndividualIds( | |
Array.isArray(attendees) | |
? attendees.map(a => a.individualId).filter(Boolean) | |
: [] | |
); | |
}, [AttendanceData]); |
🤖 Prompt for AI Agents
In
health/micro-ui/web/micro-ui-internals/packages/modules/health-payments/src/components/editAttendeesPopUp.js
around lines 55 to 66, the useEffect assumes
AttendanceData.attendanceRegister[0].attendees always exists which can throw if
attendanceRegister or attendees is missing; update the extraction to use
optional chaining and a safe default (e.g., const ids =
AttendanceData?.attendanceRegister?.[0]?.attendees?.map(a => a.individualId) ??
[]; then call setIndividualIds(ids)); additionally, add a simple empty-state
render path in the component UI when individualIds.length === 0 to show a
user-friendly message or placeholder.
...web/micro-ui-internals/packages/modules/health-payments/src/components/editAttendeesPopUp.js
Show resolved
Hide resolved
const { isLoading: childrenDataLoading, data: childrenData } = Digit.Hooks.payments.useAttendanceBoundarySearch(reqCriteriaResource); | ||
|
||
// Update the dropdown options and state when children data is fetched | ||
useEffect(() => { | ||
if (childrenData && childrenData.length > 0) { | ||
setValue((prevState) => ({ | ||
...prevState, | ||
[childrenData[0]?.boundary[0].boundaryType]: [childrenData[0]?.boundary[0]], | ||
})); | ||
|
||
const formattedData = createFormattedData(childrenData[0]?.boundary[0].boundaryType); | ||
setBoundaryData(formattedData); | ||
if (!initialValue) { | ||
|
||
handleButtonClick(childrenData[0]?.boundary[0]); | ||
} | ||
} | ||
}, [childrenData]); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Guard against empty boundary arrays in API response
childrenData[0]?.boundary[0]
can be undefined even when childrenData.length > 0
.
- useEffect(() => {
- if (childrenData && childrenData.length > 0) {
- setValue((prevState) => ({
- ...prevState,
- [childrenData[0]?.boundary[0].boundaryType]: [childrenData[0]?.boundary[0]],
- }));
- const formattedData = createFormattedData(childrenData[0]?.boundary[0].boundaryType);
- setBoundaryData(formattedData);
- if (!initialValue) {
- handleButtonClick(childrenData[0]?.boundary[0]);
- }
- }
- }, [childrenData]);
+ useEffect(() => {
+ const first = childrenData?.[0]?.boundary?.[0];
+ if (first?.boundaryType && first?.code) {
+ setValue((prevState) => ({
+ ...prevState,
+ [first.boundaryType]: [first],
+ }));
+ setBoundaryData(createFormattedData(first.boundaryType));
+ if (!initialValue) handleButtonClick(first);
+ }
+ }, [childrenData, initialValue]);
📝 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.
const { isLoading: childrenDataLoading, data: childrenData } = Digit.Hooks.payments.useAttendanceBoundarySearch(reqCriteriaResource); | |
// Update the dropdown options and state when children data is fetched | |
useEffect(() => { | |
if (childrenData && childrenData.length > 0) { | |
setValue((prevState) => ({ | |
...prevState, | |
[childrenData[0]?.boundary[0].boundaryType]: [childrenData[0]?.boundary[0]], | |
})); | |
const formattedData = createFormattedData(childrenData[0]?.boundary[0].boundaryType); | |
setBoundaryData(formattedData); | |
if (!initialValue) { | |
handleButtonClick(childrenData[0]?.boundary[0]); | |
} | |
} | |
}, [childrenData]); | |
const { isLoading: childrenDataLoading, data: childrenData } = Digit.Hooks.payments.useAttendanceBoundarySearch(reqCriteriaResource); | |
// Update the dropdown options and state when children data is fetched | |
useEffect(() => { | |
const first = childrenData?.[0]?.boundary?.[0]; | |
if (first?.boundaryType && first?.code) { | |
setValue((prevState) => ({ | |
...prevState, | |
[first.boundaryType]: [first], | |
})); | |
setBoundaryData(createFormattedData(first.boundaryType)); | |
if (!initialValue) handleButtonClick(first); | |
} | |
}, [childrenData, initialValue]); |
🤖 Prompt for AI Agents
In
health/micro-ui/web/micro-ui-internals/packages/modules/health-payments/src/components/SearchAttendeeBoundary.js
around lines 100 to 117, the code assumes childrenData[0].boundary[0] exists;
update the effect to guard against empty or missing boundary arrays by first
finding the first childrenData item that has a non-empty boundary (e.g., const
item = childrenData.find(c => Array.isArray(c.boundary) && c.boundary.length >
0)); only access item.boundary[0] after that null check; then use that safeItem
to setValue, compute formattedData and call handleButtonClick when initialValue
is falsy. Ensure all optional chaining is removed where necessary and return
early from the effect if no suitable item is found.
<span | ||
onClick={() => { | ||
setReset(true); | ||
}} | ||
style={{ border: "1px solid #e0e0e0", padding: "6px", marginBottom: "10px", cursor: "pointer" }} | ||
> | ||
<SVG.AutoRenew width={"24px"} height={"24px"} fill={"#c84c0e"} /> | ||
</span> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🧹 Nitpick (assertive)
🛠️ Refactor suggestion
Fix a11y: interactive span without keyboard support
Use a button with proper role/label and keyboard handling. Also resolves Biome a11y errors.
- <span
- onClick={() => {
- setReset(true);
- }}
- style={{ border: "1px solid #e0e0e0", padding: "6px", marginBottom: "10px", cursor: "pointer" }}
- >
- <SVG.AutoRenew width={"24px"} height={"24px"} fill={"#c84c0e"} />
- </span>
+ <button
+ type="button"
+ aria-label={t?.("RESET") || "Reset"}
+ onClick={() => setReset(true)}
+ style={{ border: "1px solid #e0e0e0", padding: "6px", marginBottom: "10px", cursor: "pointer", background: "transparent" }}
+ >
+ <SVG.AutoRenew width={"24px"} height={"24px"} fill={"#c84c0e"} />
+ </button>
I can also replace this inline style with a themed class if you share the design token.
📝 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.
<span | |
onClick={() => { | |
setReset(true); | |
}} | |
style={{ border: "1px solid #e0e0e0", padding: "6px", marginBottom: "10px", cursor: "pointer" }} | |
> | |
<SVG.AutoRenew width={"24px"} height={"24px"} fill={"#c84c0e"} /> | |
</span> | |
<button | |
type="button" | |
aria-label={t?.("RESET") || "Reset"} | |
onClick={() => setReset(true)} | |
style={{ | |
border: "1px solid #e0e0e0", | |
padding: "6px", | |
marginBottom: "10px", | |
cursor: "pointer", | |
background: "transparent" | |
}} | |
> | |
<SVG.AutoRenew width="24px" height="24px" fill="#c84c0e" /> | |
</button> |
🧰 Tools
🪛 Biome (2.1.2)
[error] 228-233: Static Elements should not be interactive.
To add interactivity such as a mouse or key event listener to a static element, give the element an appropriate role value.
(lint/a11y/noStaticElementInteractions)
[error] 228-233: Enforce to have the onClick mouse event with the onKeyUp, the onKeyDown, or the onKeyPress keyboard event.
Actions triggered using mouse events should have corresponding keyboard events to account for keyboard-only navigation.
(lint/a11y/useKeyWithClickEvents)
🤖 Prompt for AI Agents
In
health/micro-ui/web/micro-ui-internals/packages/modules/health-payments/src/components/SearchAttendeeBoundary.js
around lines 228-235, the interactive span lacks keyboard accessibility and
semantic meaning; replace the span with a <button type="button">, move the
inline styles to a themed CSS class (or keep styles but ensure focus styles are
visible), add an accessible label like aria-label="Reset" (or visually-hidden
text) and preserve the onClick handler as onClick={() => setReset(true)}; do not
add role attributes for a native button and ensure it remains focusable and
operable via keyboard.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 4
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
health/micro-ui/web/micro-ui-internals/example/src/UICustomizations.js (1)
54-60
: Epoch unit mismatch: comment says seconds, code returns milliseconds.Align docs or logic.
- // Convert the date to epoch time (seconds) - return Math.floor(date.getTime()); + // Convert the date to epoch time (milliseconds) + return Math.floor(date.getTime());If backend expects seconds, divide by 1000 instead and update all call sites accordingly.
♻️ Duplicate comments (10)
health/micro-ui/web/micro-ui-internals/packages/modules/health-payments/src/pages/employee/AttendeeSearchAssign.js (1)
1-2
: Remove unused imports (and unused React hook).Neither useState, HeaderComponent, Toast, nor Loader are used. Clean up imports to satisfy linters and reduce bundle size.
-import React, { useState } from "react"; -import { InboxSearchComposer, HeaderComponent, Toast, Loader } from "@egovernments/digit-ui-components"; +import React from "react"; +import { InboxSearchComposer } from "@egovernments/digit-ui-components";health/micro-ui/web/micro-ui-internals/packages/modules/health-payments/src/config/AttendeeInboxConfig.js (4)
132-134
: Avoid hard-coded tenantId. Use current tenant."dev" will break in other envs.
defaultValues: { @@ - tenantId: "dev", + tenantId: Digit.ULBService.getCurrentTenantId(), @@ requestParam: { @@ - tenantId: "dev", + tenantId: Digit.ULBService.getCurrentTenantId(),Also applies to: 203-205
171-174
: ASSIGNMENT column lacks jsonPath, will render empty.Provide the correct path or remove the column.
{ label: "ASSIGNMENT", - //jsonPath: "assignments[0]", + jsonPath: "assignments[0]", additionalCustomization: true, },
175-179
: Remove commented-out column block.Dead code.
- // { - // label: "HR_EMPLOYMENT_DEPARTMENT_LABEL", - // jsonPath: "assignments[0]", - // additionalCustomization: true, - // },
214-214
: Remove commented component reference.Not used.
- //component: BoundaryComponent,
health/micro-ui/web/micro-ui-internals/example/src/UICustomizations.js (5)
810-823
: Duplicate/overwritten fields in MicroplanSearchConfig.preProcess.name is set twice; status is overridden later by tab filter. Set each once.
- const { name, status } = data?.state?.searchForm || {}; + const { name, microplanName } = data?.state?.searchForm || {}; @@ - data.body.PlanConfigurationSearchCriteria.name = name; + if (microplanName) { + data.body.PlanConfigurationSearchCriteria.name = microplanName; + } else if (name) { + data.body.PlanConfigurationSearchCriteria.name = name; + } @@ - data.body.PlanConfigurationSearchCriteria.status = status?.status; - data.body.PlanConfigurationSearchCriteria.name = data?.state?.searchForm?.microplanName; + // status set via tab mapping below
839-882
: Invalid React Hook usage inside cell renderer (and switch-case scope leaks).useState and data hooks are called inside additionalCustomizations; violates Hook rules. Also consts declared directly in case without block.
- Extract ACTIONS cell into a React component and return it from the case.
- Wrap each case with { } to satisfy noSwitchDeclarations.
Minimal change to scope the case:
- case "ACTIONS": + case "ACTIONS": { @@ - return ( + return ( <> ... </> ); + }Recommended: move logic into a component:
// outside UICustomizations object function MicroplanActionsCell({ row, t }) { const [showToast, setShowToast] = React.useState(false); const tenantId = Digit.ULBService.getCurrentTenantId(); const microplanId = row?.id; const { data: rootEstimationApprover } = Digit.Hooks.microplanv1.usePlanSearchEmployeeWithTagging({/* as-is */}); const { data: rootPopulationApprover } = Digit.Hooks.microplanv1.usePlanSearchEmployeeWithTagging({/* as-is */}); const { data: rootFacilityMapper } = Digit.Hooks.microplanv1.usePlanSearchEmployeeWithTagging({/* as-is */}); // handlers unchanged... return (/* existing JSX */); }Then:
- case "ACTIONS": { /* long inline hook logic */ } + case "ACTIONS": { + return <MicroplanActionsCell row={row} t={t} />; + }Also applies to: 884-967
1194-1218
: Action button: remove no-op onClick; guard by file presence only.Keeps props minimal and avoids misleading handler.
- isSearchable={false} - title={t("MP_ACTIONS_FOR_MICROPLANS")} - label={t("MP_ACTIONS_FOR_MICROPLANS")} - isDisabled={!EstimationsfileId} - onClick={() => { }} + isSearchable={false} + title={t("MP_ACTIONS_FOR_MICROPLANS")} + label={t("MP_ACTIONS_FOR_MICROPLANS")} + isDisabled={!EstimationsfileId}
2621-2636
: Remove console logs and guard string trims in AttendeeSearchInboxConfig.preProcess.Prevent runtime errors when fields are absent and keep console clean.
- console.log(data) + // logs removed @@ - const { phone, names, codes } = data.state.searchForm; + const { phone, names, codes } = data.state.searchForm || {}; @@ - if (phone && phone.trim() !== "") { + if (typeof phone === "string" && phone.trim() !== "") { Individual.mobileNumber = [phone]; } @@ - if (names && names.trim() !== "") { + if (typeof names === "string" && names.trim() !== "") { Individual.name = { givenName: names }; } @@ - if (codes && codes.trim() !== "") { + if (typeof codes === "string" && codes.trim() !== "") { Individual.username = [codes]; } @@ - if (boundaryCode && boundaryCode.trim() !== "") { + if (typeof boundaryCode === "string" && boundaryCode.trim() !== "") { Individual.locality = { id: null, tenantId: null, code: boundaryCode, geometry: null, auditDetails: null, additionalDetails: null, }; } @@ - console.log("payload", data) + // logs removedAlso applies to: 2659-2694, 2707-2709
2767-2769
: Avoid window.history.back() after assignment.Post-success back navigation can be jarring. Prefer closing toast/modal and refreshing results.
📜 Review details
Configuration used: CodeRabbit UI
Review profile: ASSERTIVE
Plan: Pro
⛔ Files ignored due to path filters (1)
health/micro-ui/web/micro-ui-internals/packages/modules/health-payments/package.json
is excluded by!**/*.json
📒 Files selected for processing (3)
health/micro-ui/web/micro-ui-internals/example/src/UICustomizations.js
(24 hunks)health/micro-ui/web/micro-ui-internals/packages/modules/health-payments/src/config/AttendeeInboxConfig.js
(1 hunks)health/micro-ui/web/micro-ui-internals/packages/modules/health-payments/src/pages/employee/AttendeeSearchAssign.js
(1 hunks)
🧰 Additional context used
📓 Path-based instructions (1)
**/*.js
⚙️ CodeRabbit configuration file
check
Files:
health/micro-ui/web/micro-ui-internals/example/src/UICustomizations.js
health/micro-ui/web/micro-ui-internals/packages/modules/health-payments/src/pages/employee/AttendeeSearchAssign.js
health/micro-ui/web/micro-ui-internals/packages/modules/health-payments/src/config/AttendeeInboxConfig.js
🧠 Learnings (8)
📚 Learning: 2024-11-07T11:02:33.520Z
Learnt from: rachana-egov
PR: egovernments/DIGIT-Frontend#1770
File: health/micro-ui/web/micro-ui-internals/packages/modules/microplan/src/pages/employee/viewVillage.js:320-322
Timestamp: 2024-11-07T11:02:33.520Z
Learning: In `health/micro-ui/web/micro-ui-internals/packages/modules/microplan/src/pages/employee/viewVillage.js`, the `data?.additionalFields` object is guaranteed to be defined, so checking for its existence before accessing its keys is unnecessary.
Applied to files:
health/micro-ui/web/micro-ui-internals/example/src/UICustomizations.js
health/micro-ui/web/micro-ui-internals/packages/modules/health-payments/src/config/AttendeeInboxConfig.js
📚 Learning: 2024-10-26T15:11:49.938Z
Learnt from: nabeelmd-eGov
PR: egovernments/DIGIT-Frontend#1680
File: health/micro-ui/web/micro-ui-internals/example/src/UICustomizations.js:1032-1094
Timestamp: 2024-10-26T15:11:49.938Z
Learning: In the DIGIT-Frontend project, when reviewing the `UICustomizations.js` file, avoid suggesting refactoring of repetitive rendering logic in switch cases into helper functions, unless explicitly requested.
Applied to files:
health/micro-ui/web/micro-ui-internals/example/src/UICustomizations.js
health/micro-ui/web/micro-ui-internals/packages/modules/health-payments/src/pages/employee/AttendeeSearchAssign.js
📚 Learning: 2024-11-07T07:17:27.636Z
Learnt from: jagankumar-egov
PR: egovernments/DIGIT-Frontend#1763
File: health/micro-ui/web/micro-ui-internals/packages/modules/campaign-manager/src/pages/employee/MyCampaign.js:65-75
Timestamp: 2024-11-07T07:17:27.636Z
Learning: In `MyCampaign.js`, when suggesting code improvements for the `onClickRow` function, keep suggestions simple and avoid unnecessary complexity.
Applied to files:
health/micro-ui/web/micro-ui-internals/example/src/UICustomizations.js
📚 Learning: 2024-06-10T19:25:42.992Z
Learnt from: siddhant-nawale-egov
PR: egovernments/DIGIT-Frontend#698
File: micro-ui/web/micro-ui-internals/packages/modules/hcm-microplanning/src/components/MicroplanPreview.js:1-1
Timestamp: 2024-06-10T19:25:42.992Z
Learning: The imports in `MicroplanPreview.js` are from different libraries: `egovernments/digit-ui-components` and `egovernments/digit-ui-react-components`.
Applied to files:
health/micro-ui/web/micro-ui-internals/example/src/UICustomizations.js
health/micro-ui/web/micro-ui-internals/packages/modules/health-payments/src/pages/employee/AttendeeSearchAssign.js
📚 Learning: 2024-10-08T20:11:12.539Z
Learnt from: siddhant-nawale-egov
PR: egovernments/DIGIT-Frontend#691
File: micro-ui/web/micro-ui-internals/packages/modules/hcm-microplanning/src/components/Upload.js:16-17
Timestamp: 2024-10-08T20:11:12.539Z
Learning: The components `Loader`, `Toast`, and `Modal` are from different libraries in the DIGIT-Frontend project, as clarified by the user.
Applied to files:
health/micro-ui/web/micro-ui-internals/packages/modules/health-payments/src/pages/employee/AttendeeSearchAssign.js
📚 Learning: 2025-06-04T04:08:48.234Z
Learnt from: jagankumar-egov
PR: egovernments/DIGIT-Frontend#2488
File: micro-ui/web/micro-ui-internals/packages/modules/core/src/pages/employee/Login/login.js:152-152
Timestamp: 2025-06-04T04:08:48.234Z
Learning: In the employee login component (micro-ui/web/micro-ui-internals/packages/modules/core/src/pages/employee/Login/login.js), prefer using a `defaultTenant` variable to store `Digit.ULBService.getStateId()` instead of calling the function multiple times inline in the `defaultValue` object. This improves code readability and avoids function call duplication.
Applied to files:
health/micro-ui/web/micro-ui-internals/packages/modules/health-payments/src/config/AttendeeInboxConfig.js
📚 Learning: 2025-01-02T04:41:15.957Z
Learnt from: jagankumar-egov
PR: egovernments/DIGIT-Frontend#2089
File: micro-ui/web/micro-ui-internals/packages/modules/workbench/src/pages/employee/MDMSAddV2.js:111-111
Timestamp: 2025-01-02T04:41:15.957Z
Learning: In micro-ui/web/micro-ui-internals/packages/modules/workbench/src/pages/employee/MDMSAddV2.js, always use "mdms[0].uniqueIdentifier" for the jsonPath instead of differentiating between "SOR" and other masters.
Applied to files:
health/micro-ui/web/micro-ui-internals/packages/modules/health-payments/src/config/AttendeeInboxConfig.js
📚 Learning: 2025-07-15T04:58:30.634Z
Learnt from: Hari-egov
PR: egovernments/DIGIT-Frontend#2788
File: micro-ui/web/micro-ui-internals/packages/modules/hrms/src/components/pageComponents/jurisdiction.js:26-26
Timestamp: 2025-07-15T04:58:30.634Z
Learning: In the HRMS module (micro-ui/web/micro-ui-internals/packages/modules/hrms/src/components/pageComponents/jurisdiction.js), the team has moved away from using MDMS hooks for boundary data fetching and now uses direct API calls to the boundary service endpoint `/boundary-service/boundary-relationships/_search` instead of the `useHrmsMDMS` hook with "FetchBoundaries" parameter.
Applied to files:
health/micro-ui/web/micro-ui-internals/packages/modules/health-payments/src/config/AttendeeInboxConfig.js
🧬 Code graph analysis (1)
health/micro-ui/web/micro-ui-internals/packages/modules/health-payments/src/pages/employee/AttendeeSearchAssign.js (1)
micro-ui/web/micro-ui-internals/packages/react-components/src/hoc/InboxSearchComposer.js (1)
InboxSearchComposer
(19-322)
🪛 Biome (2.1.2)
health/micro-ui/web/micro-ui-internals/example/src/UICustomizations.js
[error] 887-887: Other switch clauses can erroneously access this declaration.
Wrap the declaration in a block to restrict its access to the switch clause.
The declaration is defined in this switch clause:
Safe fix: Wrap the declaration in a block.
(lint/correctness/noSwitchDeclarations)
[error] 888-888: Other switch clauses can erroneously access this declaration.
Wrap the declaration in a block to restrict its access to the switch clause.
The declaration is defined in this switch clause:
Safe fix: Wrap the declaration in a block.
(lint/correctness/noSwitchDeclarations)
[error] 889-889: Other switch clauses can erroneously access this declaration.
Wrap the declaration in a block to restrict its access to the switch clause.
The declaration is defined in this switch clause:
Safe fix: Wrap the declaration in a block.
(lint/correctness/noSwitchDeclarations)
[error] 890-890: Other switch clauses can erroneously access this declaration.
Wrap the declaration in a block to restrict its access to the switch clause.
The declaration is defined in this switch clause:
Safe fix: Wrap the declaration in a block.
(lint/correctness/noSwitchDeclarations)
[error] 902-916: Other switch clauses can erroneously access this declaration.
Wrap the declaration in a block to restrict its access to the switch clause.
The declaration is defined in this switch clause:
Safe fix: Wrap the declaration in a block.
(lint/correctness/noSwitchDeclarations)
[error] 918-962: Other switch clauses can erroneously access this declaration.
Wrap the declaration in a block to restrict its access to the switch clause.
The declaration is defined in this switch clause:
Safe fix: Wrap the declaration in a block.
(lint/correctness/noSwitchDeclarations)
[error] 964-966: Other switch clauses can erroneously access this declaration.
Wrap the declaration in a block to restrict its access to the switch clause.
The declaration is defined in this switch clause:
Safe fix: Wrap the declaration in a block.
(lint/correctness/noSwitchDeclarations)
⏰ Context from checks skipped due to timeout of 10000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
- GitHub Check: Analyze (javascript-typescript)
🔇 Additional comments (2)
health/micro-ui/web/micro-ui-internals/packages/modules/health-payments/src/config/AttendeeInboxConfig.js (1)
181-189
: Verify API response paths.Confirm resultsJsonPath ("Individual") and totalCountJsonPath ("TotalCount") match the /health-individual/v1/_search response.
Would you confirm the exact keys returned by that endpoint so we can align the jsonPaths?
Also applies to: 192-213
health/micro-ui/web/micro-ui-internals/example/src/UICustomizations.js (1)
1587-1594
: PGR preProcess cleanup looks good.Range extraction and normalization are handled defensively. No action.
Also applies to: 1595-1602, 1613-1630, 1631-1641
const tenantId = Digit.ULBService.getCurrentTenantId(); | ||
const {campaignId} = Digit.Hooks.useQueryParams(); | ||
const { campaignId } = Digit.Hooks.useQueryParams(); | ||
return { | ||
url: `/project-factory/v1/project-type/search`, | ||
params: { }, | ||
params: {}, | ||
body: { | ||
CampaignDetails: { | ||
"tenantId": tenantId, | ||
"ids": [ | ||
campaignId | ||
] | ||
} | ||
} | ||
}, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion
Avoid calling useQueryParams() inside utility getFacilitySearchRequest.
Treat it as a pure function: read campaignId from props or additionalDetails.
- const { campaignId } = Digit.Hooks.useQueryParams();
+ const { campaignId } = prop; // expect caller to pass campaignId
@@
- "ids": [
- campaignId
- ]
+ "ids": [campaignId]
Update callers to pass { campaignId }.
Committable suggestion skipped: line range outside the PR's diff.
🤖 Prompt for AI Agents
In health/micro-ui/web/micro-ui-internals/example/src/UICustomizations.js around
lines 1442-1454, getFacilitySearchRequest currently calls
Digit.Hooks.useQueryParams() to read campaignId inside the utility, which
violates purity; change the function to accept campaignId (e.g., via props or
additionalDetails) instead of calling useQueryParams(), remove the hook call
from the utility, and update every caller of getFacilitySearchRequest to pass {
campaignId } (or include it on additionalDetails) so the function remains a pure
utility that only builds and returns the request object.
{/* { <div | ||
// style={ | ||
// isMobile | ||
// ? { marginLeft: "-12px", fontFamily: "calibri", color: "#FF0000" } | ||
// : { marginLeft: "15px", fontFamily: "calibri", color: "#FF0000" } | ||
// } | ||
> | ||
{ | ||
// <HeaderComponent className="digit-inbox-search-composer-header" styles={{ marginBottom: "1.5rem" }}> | ||
// {t("HR_HOME_SEARCH_RESULTS_HEADING")} | ||
// </HeaderComponent> | ||
} | ||
{t("HR_HOME_SEARCH_RESULTS_HEADING")} | ||
</div>} */} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🧹 Nitpick (assertive)
Delete commented header block.
Dead comment noise. If you want a header, prefer passing headerLabel to InboxSearchComposer (see next comment).
- {/* { <div
- // style={
- // isMobile
- // ? { marginLeft: "-12px", fontFamily: "calibri", color: "#FF0000" }
- // : { marginLeft: "15px", fontFamily: "calibri", color: "#FF0000" }
- // }
- >
- {
- // <HeaderComponent className="digit-inbox-search-composer-header" styles={{ marginBottom: "1.5rem" }}>
- // {t("HR_HOME_SEARCH_RESULTS_HEADING")}
- // </HeaderComponent>
- }
-
- {t("HR_HOME_SEARCH_RESULTS_HEADING")}
- </div>} */}
+ {/* header intentionally omitted */}
📝 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.
{/* { <div | |
// style={ | |
// isMobile | |
// ? { marginLeft: "-12px", fontFamily: "calibri", color: "#FF0000" } | |
// : { marginLeft: "15px", fontFamily: "calibri", color: "#FF0000" } | |
// } | |
> | |
{ | |
// <HeaderComponent className="digit-inbox-search-composer-header" styles={{ marginBottom: "1.5rem" }}> | |
// {t("HR_HOME_SEARCH_RESULTS_HEADING")} | |
// </HeaderComponent> | |
} | |
{t("HR_HOME_SEARCH_RESULTS_HEADING")} | |
</div>} */} | |
{/* header intentionally omitted */} |
🤖 Prompt for AI Agents
In
health/micro-ui/web/micro-ui-internals/packages/modules/health-payments/src/pages/employee/AttendeeSearchAssign.js
around lines 35 to 49, remove the entire commented-out header block (the
JSX/HTML comment wrapping the unused div/HeaderComponent and style fragments) to
clean up dead comment noise; if a header is required later, pass headerLabel
into InboxSearchComposer instead of keeping this commented code.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 8
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (3)
health/micro-ui/web/micro-ui-internals/example/src/UICustomizations.js (3)
54-60
: Comment mismatch: returns milliseconds, not secondsEither rename or fix the comment to avoid confusion.
- // Convert the date to epoch time (seconds) + // Convert the date to epoch time (milliseconds)
118-121
: Hardcoded tenant in SearchDefaultConfig (Projects path)
tenantId: "mz"
is hardcoded. Consider usingDigit.ULBService.getCurrentTenantId()
unless this is intentional for a sandbox view.Also applies to: 652-654
171-177
: Remove hardcoded tenantIds and debug logs in example UICustomizations
- In health/micro-ui/web/micro-ui-internals/example/src/UICustomizations.js, line 534: replace
tenantId: "tenantId"
with dynamic retrieval.- In the same file, line 653: remove the hardcoded
"mz"
literal.- Remove all
console.log
calls at lines 1154, 2620, 2707 (and the commented debug on line 1502).
♻️ Duplicate comments (19)
health/micro-ui/web/micro-ui-internals/packages/modules/health-hrms/src/components/pageComponents/UserAssigment.js (9)
1-1
: Rename file to fix typo and align importsUse
UserAssignment.js
and update all imports (e.g., in Module.js).
2-12
: Prune unused imports
useTranslation
,HeaderComponent
,Card
,Button
,Toast
aren’t used.Apply:
-import { useTranslation } from "react-i18next"; -import { - Dropdown, - Loader, - HeaderComponent, - Card, - LabelFieldPair, - Button, - Toast, - CardLabel -} from "@egovernments/digit-ui-components"; +import { + Dropdown, + Loader, + LabelFieldPair, + CardLabel +} from "@egovernments/digit-ui-components";
22-22
: Use current tenant, not stateAlign with HRMS usage patterns.
- const tenantId = Digit.ULBService.getStateId(); + const tenantId = Digit.ULBService.getCurrentTenantId();
24-26
: Avoid hard-coded service path; honor INDIVIDUAL_CONTEXT_PATHKeep endpoints configurable.
- const reqCri = { - url: `/health-individual/v1/_search`, + const individualContextPath = window?.globalConfigs?.getConfig("INDIVIDUAL_CONTEXT_PATH") || "health-individual"; + const reqCri = { + url: `/${individualContextPath}/v1/_search`, + method: "POST",
45-51
: Guard fetch by boundary and remove debug log; harden selectorPrevent unnecessary calls and avoid PII logs.
config: { - enabled: true, - select: (data) => { - - console.log("data", data); - return data.Individual; - }, + enabled: Boolean(boundaryCode), + select: (data) => data?.Individual ?? [], },
56-56
: Remove PII-leaking debug logAvoid logging user data in production.
- console.log("assignTo", individualData); + // debug log removed
62-67
: Harden option mapping and avoid blank labelsFallback to username or a translated NA.
- const result = individualData.map(item => ({ - code: item.id, - name: item.name?.givenName || null - })); + const result = individualData.map((item) => ({ + code: item?.id, + name: item?.name?.givenName || item?.userDetails?.username || (t ? t("NA") : "NA"), + }));
80-85
: Don’t pass t to Dropdown for human names; remove fixed widthPassing
t
causes names to be run through i18n; also replace hard-coded width.- <Dropdown - style={{ width: "40rem" }} - t={t} + <Dropdown + className="w-100" option={options} optionKey={"name"} selected={selectedHierarchy}
76-79
: Avoid inline width on label; prefer CSS classInline
50.1%
is brittle; use a class for responsive layout.- <CardLabel style={{ width: "50.1%" }} className="digit-card-label-smaller"> + <CardLabel className="digit-card-label-smaller user-assignment__label">Add CSS:
.user-assignment__label { /* responsive width rules */ }
health/micro-ui/web/micro-ui-internals/packages/modules/health-payments/src/config/AttendeeInboxConfig.js (5)
171-174
: ASSIGNMENT column lacks jsonPathAdd the correct jsonPath or remove the column to avoid an empty cell.
{ label: "ASSIGNMENT", - //jsonPath: "assignments[0]", + jsonPath: "assignments[0]", // verify payload shape; adjust if needed additionalCustomization: true, },Would you like me to wire a renderer for this column similar to HRMS?
132-134
: Remove hardcoded tenantId ("dev") in defaultValuesUse the current tenant dynamically.
- tenantId: "dev", + tenantId: Digit.ULBService.getCurrentTenantId(),
175-179
: Remove stale commented blockClean up the commented HR_EMPLOYMENT_DEPARTMENT_LABEL column.
- // { - // label: "HR_EMPLOYMENT_DEPARTMENT_LABEL", - // jsonPath: "assignments[0]", - // additionalCustomization: true, - // },
203-205
: Remove hardcoded tenantId ("dev") in apiDetails.requestParamUse the runtime tenant.
- tenantId: "dev", + tenantId: Digit.ULBService.getCurrentTenantId(),
214-214
: Delete commented component entryDrop the dead line to reduce noise.
- //component: BoundaryComponent,
health/micro-ui/web/micro-ui-internals/example/src/UICustomizations.js (5)
1108-1218
: Action button: remove redundant onClick and guard downloadThe action button passes a no-op onClick and should rely on onOptionSelect; ensure disabled when no file.
- <ButtonNew - isSearchable={false} - title={t("MP_ACTIONS_FOR_MICROPLANS")} - label={t("MP_ACTIONS_FOR_MICROPLANS")} - isDisabled={!EstimationsfileId} - onClick={() => { }} + <ButtonNew + isSearchable={false} + title={t("MP_ACTIONS_FOR_MICROPLANS")} + label={t("MP_ACTIONS_FOR_MICROPLANS")} + isDisabled={!EstimationsfileId} variation="primary" onOptionSelect={(option) => onOptionSelect(option)} options={[ /* as-is */ ]} optionsKey="name" showBottom={true} style={{ width: "290px" }} type="actionButton" className="my-microplans-action-button" />
810-823
: Duplicate assignments and unclear precedence in MicroplanSearchConfig.preProcess
name
andstatus
are assigned twice; tab filter overrides form without explanation. Simplify and document precedence.- const { name, status } = data?.state?.searchForm || {}; + const { name } = data?.state?.searchForm || {}; @@ - data.body.PlanConfigurationSearchCriteria.name = name; + data.body.PlanConfigurationSearchCriteria.name = name; @@ - data.body.PlanConfigurationSearchCriteria.status = status?.status; - data.body.PlanConfigurationSearchCriteria.name = data?.state?.searchForm?.microplanName; + // If microplanName is provided, it takes precedence over 'name' + if (data?.state?.searchForm?.microplanName) { + data.body.PlanConfigurationSearchCriteria.name = data.state.searchForm.microplanName; + }Then tabId mapping below sets status once; keep only that.
1442-1454
: Avoid using hooks inside utility (getFacilitySearchRequest)
useQueryParams()
violates rules in a non-component. AcceptcampaignId
via args.- getFacilitySearchRequest: (prop) => { + getFacilitySearchRequest: (prop) => { const tenantId = Digit.ULBService.getCurrentTenantId(); - const { campaignId } = Digit.Hooks.useQueryParams(); + const { campaignId } = prop; // pass in from caller @@ - body: { + body: { CampaignDetails: { "tenantId": tenantId, "ids": [ campaignId ] } },Update callers accordingly.
2614-2709
: AttendeeSearchInboxConfig.preProcess: remove logs and guard trimsAvoid console noise;
.trim()
on non-strings can throw. BuildIndividual
defensively.- console.log(data) + // console.log removed @@ - const { phone, names, codes } = data.state.searchForm; + const { phone, names, codes } = data.state.searchForm || {}; @@ - const boundaryCode = data.state.filterForm.AttendeeBoundaryComponent - || Digit?.SessionStorage.get("selectedBoundary")?.code; + const boundaryCode = data?.state?.filterForm?.AttendeeBoundaryComponent + || Digit?.SessionStorage?.get("selectedBoundary")?.code; @@ - if (phone && phone.trim() !== "") { + if (typeof phone === "string" && phone.trim() !== "") { Individual.mobileNumber = [phone]; } @@ - if (names && names.trim() !== "") { + if (typeof names === "string" && names.trim() !== "") { Individual.name = { givenName: names }; } @@ - if (codes && codes.trim() !== "") { + if (typeof codes === "string" && codes.trim() !== "") { Individual.username = [codes]; } @@ - if (boundaryCode && boundaryCode.trim() !== "") { + if (typeof boundaryCode === "string" && boundaryCode.trim() !== "") { Individual.locality = { id: null, tenantId: null, code: boundaryCode, geometry: null, auditDetails: null, additionalDetails: null, }; } @@ - console.log("payload", data) + // console.log removed
839-906
: Invalid Hook usage inside cell renderer; heavy logic in switch; dummy file idHooks (
useState
, data hooks) are called insideadditionalCustomizations
, violating React rules; case-level consts also hit noSwitchDeclarations; remove hardcoded dummy file id.Minimal safe fix (wrap case in a block and drop dummy), or preferred refactor to a component:
Preferred (extract ACTIONS to component):
- additionalCustomizations: (row, key, column, value, t, searchResult) => { - const [showToast, setShowToast] = useState(false); - const tenantId = Digit.ULBService.getCurrentTenantId(); - const microplanId = row?.id; - const { data: rootEstimationApprover } = Digit.Hooks.microplanv1.usePlanSearchEmployeeWithTagging({ ... }); - const { data: rootPopulationApprover } = Digit.Hooks.microplanv1.usePlanSearchEmployeeWithTagging({ ... }); - const { data: rootFacilityMapper } = Digit.Hooks.microplanv1.usePlanSearchEmployeeWithTagging({ ... }); + additionalCustomizations: (row, key, column, value, t, searchResult) => { switch (key) { - case "ACTIONS": - // TODO : Replace dummy file id with real file id when API is ready - const dummyFile = "c22a7676-d5d7-49b6-bcdb-83e9519f58df" - const microplanFileId = row?.campaignDetails?.additionalDetails?.microplanFileId || dummyFile; - const EstimationsfileId = row?.files.find((item) => item.templateIdentifier === "Estimations")?.filestoreId; - let options = []; + case "ACTIONS": { + return <MicroplanActionsCell row={row} t={t} />; + } case "NAME_OF_MICROPLAN": ... } },Add component (outside the object):
function MicroplanActionsCell({ row, t }) { const [showToast, setShowToast] = React.useState(false); const tenantId = Digit.ULBService.getCurrentTenantId(); const microplanId = row?.id; const { data: rootEstimationApprover } = Digit.Hooks.microplanv1.usePlanSearchEmployeeWithTagging({ tenantId, body:{ PlanEmployeeAssignmentSearchCriteria:{ tenantId, planConfigurationId: microplanId, role:["ROOT_PLAN_ESTIMATION_APPROVER"], active:true } }, config:{ enabled:true }}); const { data: rootPopulationApprover } = Digit.Hooks.microplanv1.usePlanSearchEmployeeWithTagging({ tenantId, body:{ PlanEmployeeAssignmentSearchCriteria:{ tenantId, planConfigurationId: microplanId, role:["ROOT_POPULATION_DATA_APPROVER"], active:true } }, config:{ enabled:true }}); const { data: rootFacilityMapper } = Digit.Hooks.microplanv1.usePlanSearchEmployeeWithTagging({ tenantId, body:{ PlanEmployeeAssignmentSearchCriteria:{ tenantId, planConfigurationId: microplanId, role:["ROOT_FACILITY_CATCHMENT_MAPPER"], active:true } }, config:{ enabled:true }}); const EstimationsfileId = row?.files?.find((i) => i.templateIdentifier === "Estimations")?.filestoreId; const microplanFileId = row?.campaignDetails?.additionalDetails?.microplanFileId; const handleDownload = ({ type }) => { const template = type === "Estimations" ? "Estimations" : "DraftComplete"; const fileId = row?.files?.find((i) => i.templateIdentifier === template)?.filestoreId; if (!fileId) { setShowToast({ label: t("NO_DRAFT_FILE_FOUND") }); return; } const campaignName = row?.name || ""; const customName = type === "Estimations" ? campaignName : `${campaignName}_DRAFT`; Digit.Utils.campaign.downloadExcelWithCustomName({ fileStoreId: fileId, customName }); }; // ... keep onActionSelect / handleToast from current case, unchanged ... return ( <> {microplanFileId && row?.status === "RESOURCE_ESTIMATIONS_APPROVED" ? ( <ButtonNew style={{ width: "20rem" }} icon="DownloadIcon" onClick={() => handleDownload({ type: "Estimations" })} label={t("WBH_DOWNLOAD_MICROPLAN")} title={t("WBH_DOWNLOAD_MICROPLAN")} isDisabled={!EstimationsfileId} /> ) : ( <div className="action-button-open-microplan"> <ButtonNew type="actionButton" variation="secondary" label={t("MP_ACTIONS_FOR_MICROPLAN_SEARCH")} title={t("MP_ACTIONS_FOR_MICROPLAN_SEARCH")} options={[/* as-is from code */]} style={{ width: "20rem" }} optionsKey="name" showBottom isSearchable={false} onOptionSelect={(item) => onActionSelect(item, row)} /> </div> )} {showToast && <Toast type={showToast?.type || "warning"} label={showToast?.label} onClose={() => setShowToast(false)} />} </> ); }If you prefer not to extract, at least wrap the case in
{}
and delete the dummy id.Also applies to: 918-967, 968-997
📜 Review details
Configuration used: CodeRabbit UI
Review profile: ASSERTIVE
Plan: Pro
📒 Files selected for processing (3)
health/micro-ui/web/micro-ui-internals/example/src/UICustomizations.js
(24 hunks)health/micro-ui/web/micro-ui-internals/packages/modules/health-hrms/src/components/pageComponents/UserAssigment.js
(1 hunks)health/micro-ui/web/micro-ui-internals/packages/modules/health-payments/src/config/AttendeeInboxConfig.js
(1 hunks)
🧰 Additional context used
📓 Path-based instructions (1)
**/*.js
⚙️ CodeRabbit configuration file
check
Files:
health/micro-ui/web/micro-ui-internals/packages/modules/health-payments/src/config/AttendeeInboxConfig.js
health/micro-ui/web/micro-ui-internals/packages/modules/health-hrms/src/components/pageComponents/UserAssigment.js
health/micro-ui/web/micro-ui-internals/example/src/UICustomizations.js
🧠 Learnings (8)
📚 Learning: 2025-06-04T04:08:48.234Z
Learnt from: jagankumar-egov
PR: egovernments/DIGIT-Frontend#2488
File: micro-ui/web/micro-ui-internals/packages/modules/core/src/pages/employee/Login/login.js:152-152
Timestamp: 2025-06-04T04:08:48.234Z
Learning: In the employee login component (micro-ui/web/micro-ui-internals/packages/modules/core/src/pages/employee/Login/login.js), prefer using a `defaultTenant` variable to store `Digit.ULBService.getStateId()` instead of calling the function multiple times inline in the `defaultValue` object. This improves code readability and avoids function call duplication.
Applied to files:
health/micro-ui/web/micro-ui-internals/packages/modules/health-payments/src/config/AttendeeInboxConfig.js
health/micro-ui/web/micro-ui-internals/packages/modules/health-hrms/src/components/pageComponents/UserAssigment.js
📚 Learning: 2025-01-02T04:41:15.957Z
Learnt from: jagankumar-egov
PR: egovernments/DIGIT-Frontend#2089
File: micro-ui/web/micro-ui-internals/packages/modules/workbench/src/pages/employee/MDMSAddV2.js:111-111
Timestamp: 2025-01-02T04:41:15.957Z
Learning: In micro-ui/web/micro-ui-internals/packages/modules/workbench/src/pages/employee/MDMSAddV2.js, always use "mdms[0].uniqueIdentifier" for the jsonPath instead of differentiating between "SOR" and other masters.
Applied to files:
health/micro-ui/web/micro-ui-internals/packages/modules/health-payments/src/config/AttendeeInboxConfig.js
📚 Learning: 2024-11-07T11:02:33.520Z
Learnt from: rachana-egov
PR: egovernments/DIGIT-Frontend#1770
File: health/micro-ui/web/micro-ui-internals/packages/modules/microplan/src/pages/employee/viewVillage.js:320-322
Timestamp: 2024-11-07T11:02:33.520Z
Learning: In `health/micro-ui/web/micro-ui-internals/packages/modules/microplan/src/pages/employee/viewVillage.js`, the `data?.additionalFields` object is guaranteed to be defined, so checking for its existence before accessing its keys is unnecessary.
Applied to files:
health/micro-ui/web/micro-ui-internals/packages/modules/health-payments/src/config/AttendeeInboxConfig.js
health/micro-ui/web/micro-ui-internals/packages/modules/health-hrms/src/components/pageComponents/UserAssigment.js
health/micro-ui/web/micro-ui-internals/example/src/UICustomizations.js
📚 Learning: 2025-07-15T04:58:30.634Z
Learnt from: Hari-egov
PR: egovernments/DIGIT-Frontend#2788
File: micro-ui/web/micro-ui-internals/packages/modules/hrms/src/components/pageComponents/jurisdiction.js:26-26
Timestamp: 2025-07-15T04:58:30.634Z
Learning: In the HRMS module (micro-ui/web/micro-ui-internals/packages/modules/hrms/src/components/pageComponents/jurisdiction.js), the team has moved away from using MDMS hooks for boundary data fetching and now uses direct API calls to the boundary service endpoint `/boundary-service/boundary-relationships/_search` instead of the `useHrmsMDMS` hook with "FetchBoundaries" parameter.
Applied to files:
health/micro-ui/web/micro-ui-internals/packages/modules/health-payments/src/config/AttendeeInboxConfig.js
📚 Learning: 2024-06-10T19:25:42.992Z
Learnt from: siddhant-nawale-egov
PR: egovernments/DIGIT-Frontend#698
File: micro-ui/web/micro-ui-internals/packages/modules/hcm-microplanning/src/components/MicroplanPreview.js:1-1
Timestamp: 2024-06-10T19:25:42.992Z
Learning: The imports in `MicroplanPreview.js` are from different libraries: `egovernments/digit-ui-components` and `egovernments/digit-ui-react-components`.
Applied to files:
health/micro-ui/web/micro-ui-internals/packages/modules/health-hrms/src/components/pageComponents/UserAssigment.js
health/micro-ui/web/micro-ui-internals/example/src/UICustomizations.js
📚 Learning: 2024-10-26T15:11:49.938Z
Learnt from: nabeelmd-eGov
PR: egovernments/DIGIT-Frontend#1680
File: health/micro-ui/web/micro-ui-internals/example/src/UICustomizations.js:1032-1094
Timestamp: 2024-10-26T15:11:49.938Z
Learning: In the DIGIT-Frontend project, when reviewing the `UICustomizations.js` file, avoid suggesting refactoring of repetitive rendering logic in switch cases into helper functions, unless explicitly requested.
Applied to files:
health/micro-ui/web/micro-ui-internals/example/src/UICustomizations.js
📚 Learning: 2024-11-07T07:17:27.636Z
Learnt from: jagankumar-egov
PR: egovernments/DIGIT-Frontend#1763
File: health/micro-ui/web/micro-ui-internals/packages/modules/campaign-manager/src/pages/employee/MyCampaign.js:65-75
Timestamp: 2024-11-07T07:17:27.636Z
Learning: In `MyCampaign.js`, when suggesting code improvements for the `onClickRow` function, keep suggestions simple and avoid unnecessary complexity.
Applied to files:
health/micro-ui/web/micro-ui-internals/example/src/UICustomizations.js
📚 Learning: 2024-09-30T05:45:14.549Z
Learnt from: ashish-egov
PR: egovernments/DIGIT-Frontend#1441
File: health/micro-ui/web/micro-ui-internals/packages/modules/microplan/src/hooks/useGenerateIdCampaign.js:1-1
Timestamp: 2024-09-30T05:45:14.549Z
Learning: In the `useGenerateIdCampaign` function, auto assignment of default parameter values is needed in parameter destructuring.
Applied to files:
health/micro-ui/web/micro-ui-internals/example/src/UICustomizations.js
🧬 Code graph analysis (2)
health/micro-ui/web/micro-ui-internals/packages/modules/health-hrms/src/components/pageComponents/UserAssigment.js (2)
health/micro-ui/web/micro-ui-internals/example/src/UICustomizations.js (37)
options
(890-890)options
(1721-1724)boundaryCode
(2660-2661)Digit
(1443-1443)Digit
(2725-2725)tenantId
(391-391)tenantId
(757-757)tenantId
(840-840)tenantId
(1387-1387)tenantId
(1442-1442)tenantId
(1689-1689)tenantId
(1897-1897)tenantId
(2162-2162)tenantId
(2194-2194)tenantId
(2239-2239)tenantId
(2269-2269)tenantId
(2314-2314)tenantId
(2345-2345)tenantId
(2390-2390)tenantId
(2420-2420)tenantId
(2465-2465)data
(415-415)data
(517-517)data
(734-734)data
(794-794)data
(811-811)data
(1071-1071)data
(1333-1333)data
(1350-1350)data
(1351-1351)data
(1352-1352)data
(2164-2164)data
(2165-2165)data
(2241-2241)data
(2242-2242)data
(2316-2316)data
(2317-2317)micro-ui/web/micro-ui-internals/packages/react-components/src/atoms/Dropdown.js (1)
Dropdown
(94-281)
health/micro-ui/web/micro-ui-internals/example/src/UICustomizations.js (5)
health/micro-ui/web/micro-ui-internals/packages/modules/campaign-manager/src/pages/employee/NewCampaignCreate/CampaignDetails.js (3)
url
(156-156)data
(304-418)showToast
(152-152)health/micro-ui/web/micro-ui-internals/packages/modules/campaign-manager/src/pages/employee/NewCampaignCreate/AppModule.js (1)
url
(24-24)health/micro-ui/web/micro-ui-internals/packages/modules/campaign-manager/src/configs/UICustomizations.js (34)
url
(401-401)url
(593-593)url
(740-740)url
(935-935)url
(1031-1031)url
(1126-1126)data
(370-370)data
(371-371)data
(564-564)data
(565-565)data
(710-710)data
(711-711)data
(906-906)data
(907-907)data
(1002-1002)data
(1003-1003)data
(1098-1098)data
(1099-1099)showToast
(195-195)tenantId
(92-92)tenantId
(174-174)tenantId
(235-235)tenantId
(368-368)tenantId
(400-400)tenantId
(562-562)tenantId
(592-592)tenantId
(708-708)tenantId
(739-739)tenantId
(904-904)tenantId
(934-934)tenantId
(1000-1000)tenantId
(1030-1030)tenantId
(1096-1096)tenantId
(1125-1125)health/micro-ui/web/micro-ui-internals/packages/modules/health-payments/src/pages/employee/EditRegister.js (4)
data
(44-44)Digit
(32-32)showToast
(48-48)loading
(49-49)health/micro-ui/web/micro-ui-internals/packages/modules/health-payments/src/components/SearchUserPopUp.js (1)
createMapping
(15-15)
🪛 Biome (2.1.2)
health/micro-ui/web/micro-ui-internals/example/src/UICustomizations.js
[error] 887-887: Other switch clauses can erroneously access this declaration.
Wrap the declaration in a block to restrict its access to the switch clause.
The declaration is defined in this switch clause:
Safe fix: Wrap the declaration in a block.
(lint/correctness/noSwitchDeclarations)
[error] 888-888: Other switch clauses can erroneously access this declaration.
Wrap the declaration in a block to restrict its access to the switch clause.
The declaration is defined in this switch clause:
Safe fix: Wrap the declaration in a block.
(lint/correctness/noSwitchDeclarations)
[error] 889-889: Other switch clauses can erroneously access this declaration.
Wrap the declaration in a block to restrict its access to the switch clause.
The declaration is defined in this switch clause:
Safe fix: Wrap the declaration in a block.
(lint/correctness/noSwitchDeclarations)
[error] 890-890: Other switch clauses can erroneously access this declaration.
Wrap the declaration in a block to restrict its access to the switch clause.
The declaration is defined in this switch clause:
Safe fix: Wrap the declaration in a block.
(lint/correctness/noSwitchDeclarations)
[error] 902-916: Other switch clauses can erroneously access this declaration.
Wrap the declaration in a block to restrict its access to the switch clause.
The declaration is defined in this switch clause:
Safe fix: Wrap the declaration in a block.
(lint/correctness/noSwitchDeclarations)
[error] 918-962: Other switch clauses can erroneously access this declaration.
Wrap the declaration in a block to restrict its access to the switch clause.
The declaration is defined in this switch clause:
Safe fix: Wrap the declaration in a block.
(lint/correctness/noSwitchDeclarations)
[error] 964-966: Other switch clauses can erroneously access this declaration.
Wrap the declaration in a block to restrict its access to the switch clause.
The declaration is defined in this switch clause:
Safe fix: Wrap the declaration in a block.
(lint/correctness/noSwitchDeclarations)
[error] 2858-2858: Avoid passing children using a prop
The canonical way to pass children in React is to use JSX elements
(lint/correctness/noChildrenProp)
🔇 Additional comments (6)
health/micro-ui/web/micro-ui-internals/packages/modules/health-hrms/src/components/pageComponents/UserAssigment.js (2)
70-72
: Loading state handling looks good
86-89
: Confirm expected form value shape before persistingUpstream often expects an id/code rather than the whole object.
If only code is needed:
- setSelectedHierarchy(value) - onSelect(config.key, value); + setSelectedHierarchy(value); + onSelect(config.key, value?.code);If full object is required, keep as-is.
health/micro-ui/web/micro-ui-internals/example/src/UICustomizations.js (4)
37-44
: MDMS URL helper looks goodV1/V2 fallback is correct and consistent with other modules.
1587-1611
: PGR preProcess: logic looks correctDate range normalization and locality mapping are sound.
Also applies to: 1624-1640
1806-1828
: HRMSInbox preProcess: params enrichment is fineScoped updates via temporary object are clean.
263-270
: Inbox helpers generally look fineMapping for AttendanceInbox and postProcess status options is consistent.
Also applies to: 271-343
additionalCustomizations: (row, key, column, value, t, searchResult) => { | ||
|
||
const tenantId = Digit.ULBService.getCurrentTenantId(); | ||
|
||
const [openPopUp, setOpenPopUp] = useState(false); | ||
const [isTag, setIsTag] = useState(false); | ||
|
||
const [toast, setToast] = useState(null); | ||
const [modalOpen, setModalOpen] = useState(false); | ||
const [sessionFormData, setSessionFormData] = useState({}); | ||
const [refreshKey, setRefreshKey,] = useState(Date.now()); | ||
const [selectedId, setSelectedId] = useState(null); | ||
const [loading, setLoading] = useState(false); | ||
const { mutate: createMapping } = Digit.Hooks.payments.useCreateAttendeeFromRegister(tenantId); | ||
const { registerNumber, boundaryCode, registerId } = Digit.Hooks.useQueryParams(); | ||
|
||
const [tag, setTag] = useState(""); | ||
|
||
const handleToastClose = () => { | ||
setToast(null); | ||
}; | ||
|
||
const handleCreate = async (id) => { | ||
setSelectedId(id); | ||
setLoading(true); | ||
|
||
|
||
await createMapping({ | ||
"attendees": [ | ||
tag == "" ? | ||
{ | ||
registerId: registerId, | ||
individualId: row.id, | ||
enrollmentDate: new Date().getTime(), | ||
tenantId: row.tenantId, | ||
|
||
} : { | ||
registerId: registerId, | ||
individualId: row.id, | ||
enrollmentDate: new Date().getTime(), | ||
tenantId: row.tenantId, | ||
tag: tag | ||
}] | ||
}, | ||
{ | ||
onError: async (error) => { | ||
|
||
setLoading(false); | ||
setSelectedId(null); | ||
setTag(""); | ||
|
||
setIsTag(false); | ||
setOpenPopUp(false); | ||
|
||
|
||
const errorMessage = error?.response?.data?.Errors?.[0]?.message | ||
setToast( | ||
{ key: true, label: `${t(errorMessage)}`, type: "error" } | ||
|
||
); | ||
|
||
|
||
|
||
}, | ||
onSuccess: async (responseData) => { | ||
setTag(""); | ||
setLoading(false); | ||
setSelectedId(null); | ||
setIsTag(false); | ||
setOpenPopUp(false); | ||
|
||
|
||
setToast({ key: "success", label: `${t(`HCM_AM_NEW_EMPLOYEE`)} (${row.name.givenName || ""}) ${t(`HCM_AM_ENROLLED`)}`, transitionTime: 3000 }); | ||
|
||
setTimeout(() => { | ||
window.history.back(); | ||
}, 800); | ||
|
||
}, | ||
} | ||
); | ||
} | ||
|
||
switch (key) { | ||
case "HR_EMP_MOBILE_LABEL": | ||
return value ? `${value}` : t("ES_COMMON_NA"); | ||
|
||
case "HR_EMP_NAME_LABEL": | ||
return value ? `${value}` : t("ES_COMMON_NA"); | ||
|
||
case "HR_ROLE_NO_LABEL": | ||
return value?.length > 0 ? value?.length : t("ES_COMMON_NA"); | ||
|
||
case "HR_DESG_LABEL": | ||
return value ? t(`${value.designation}`) : t("ES_COMMON_NA"); | ||
|
||
case "HR_EMPLOYMENT_DEPARTMENT_LABEL": | ||
return value ? t(`${value.department}`) : t("ES_COMMON_NA"); | ||
|
||
case "HR_JURIDICTIONS_LABEL": | ||
return value ? t(value) : ( | ||
t("ES_COMMON_NA") | ||
); | ||
case "ASSIGNMENT": | ||
|
||
if (loading && (row.id === selectedId)) { | ||
return <Loader />; | ||
} | ||
|
||
return <> <Button | ||
key={refreshKey} | ||
variation={"primary"} | ||
label={t("ASSIGN")} | ||
style={{ minWidth: "10rem" }} | ||
onButtonClick={() => { | ||
|
||
// handleCreate(row.id); | ||
|
||
setOpenPopUp(true); | ||
return; | ||
|
||
|
||
}} | ||
/> | ||
{toast && ( | ||
<Toast | ||
error={toast.key} | ||
isDleteBtn={true} | ||
label={t(toast.label)} | ||
onClose={handleToastClose} | ||
type={toast.type} | ||
/> | ||
)} | ||
{ | ||
openPopUp && <PopUp | ||
style={{ minWidth: "500px" }} | ||
onClose={() => { | ||
setTag(""); | ||
setIsTag(false); | ||
setOpenPopUp(false); | ||
}} | ||
heading={t("Action Needed: Tag Code")} | ||
onOverlayClick={() => { | ||
setTag(""); | ||
setIsTag(false); | ||
setOpenPopUp(false); | ||
}} | ||
children={[ | ||
!isTag ? | ||
<div>Do you want to fill in the Tag Code? If yes, press Enter Tag. Otherwise, Assign it.</div> | ||
: <div> | ||
<span>Tag Code</span> | ||
<TextInput type="text" name="title" placeholder={t("Enter Tag Name")} value={tag} onChange={(e) => setTag(e.target.value)} /> | ||
</div> | ||
|
||
]} | ||
footerChildren={[ | ||
<ButtonNew | ||
type={"button"} | ||
size={"large"} | ||
variation={"primary"} | ||
label={t(isTag ? "HCM_AM_CLOSE_BT" : "HCM_AM_ENTER_TAG")} | ||
onClick={() => { | ||
if (isTag) { | ||
setTag(""); | ||
setOpenPopUp(false); | ||
setIsTag(false); | ||
} else { | ||
setIsTag(true); | ||
} | ||
return; | ||
}} | ||
/>, | ||
<ButtonNew | ||
type={"button"} | ||
size={"large"} | ||
variation={"primary"} | ||
label={t("Assign")} | ||
onClick={() => { | ||
handleCreate(row.id); | ||
return; | ||
}} | ||
/>, | ||
]} | ||
sortFooterChildren={true} | ||
/> | ||
} | ||
</> | ||
default: | ||
return t("ES_COMMON_NA"); | ||
} | ||
}, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion
AttendeeSearchInboxConfig.additionalCustomizations: Hooks in renderer; PopUp children prop misuse
- Hooks inside
additionalCustomizations
break React rules. - Pass JSX children instead of
children
prop to PopUp.
Refactor case to a component:
- switch (key) {
+ switch (key) {
case "HR_EMP_MOBILE_LABEL":
...
case "ASSIGNMENT":
- if (loading && (row.id === selectedId)) { return <Loader />; }
- return <> ... <PopUp children={[...]} footerChildren={[...]} ... /> </>
+ {
+ return <AttendeeAssignCell row={row} t={t} />;
+ }
default:
return t("ES_COMMON_NA");
}
And replace PopUp usage to JSX children (if you keep inline for now):
- openPopUp && <PopUp
- style={{ minWidth: "500px" }}
- onClose={...}
- heading={t("Action Needed: Tag Code")}
- onOverlayClick={...}
- children={[
- !isTag ? <div>...</div> : <div>...</div>
- ]}
- footerChildren={[
- <ButtonNew ... />,
- <ButtonNew ... />,
- ]}
- sortFooterChildren={true}
- />
+ openPopUp && (
+ <PopUp style={{ minWidth: "500px" }} onClose={...} heading={t("Action Needed: Tag Code")} onOverlayClick={...} sortFooterChildren>
+ {!isTag ? (
+ <div>Do you want to fill in the Tag Code? If yes, press Enter Tag. Otherwise, Assign it.</div>
+ ) : (
+ <div>
+ <span>Tag Code</span>
+ <TextInput type="text" name="title" placeholder={t("Enter Tag Name")} value={tag} onChange={(e) => setTag(e.target.value)} />
+ </div>
+ )}
+ {[
+ <ButtonNew ... key="enter" />,
+ <ButtonNew ... key="assign" />,
+ ]}
+ </PopUp>
+ )
Add extracted component (outside config):
function AttendeeAssignCell({ row, t }) {
const tenantId = Digit.ULBService.getCurrentTenantId();
const [toast, setToast] = React.useState(null);
const [openPopUp, setOpenPopUp] = React.useState(false);
const [isTag, setIsTag] = React.useState(false);
const [tag, setTag] = React.useState("");
const [loading, setLoading] = React.useState(false);
const [selectedId, setSelectedId] = React.useState(null);
const { registerId } = Digit.Hooks.useQueryParams();
const { mutate: createMapping } = Digit.Hooks.payments.useCreateAttendeeFromRegister(tenantId);
const handleCreate = async (id) => {
setSelectedId(id);
setLoading(true);
await createMapping(
{ attendees: [{ registerId, individualId: row.id, enrollmentDate: Date.now(), tenantId: row.tenantId, ...(tag ? { tag } : {}) }] },
{
onError: (error) => {
setLoading(false); setSelectedId(null); setTag(""); setIsTag(false); setOpenPopUp(false);
const msg = error?.response?.data?.Errors?.[0]?.message;
setToast({ key: true, label: t(msg), type: "error" });
},
onSuccess: () => {
setTag(""); setLoading(false); setSelectedId(null); setIsTag(false); setOpenPopUp(false);
setToast({ key: "success", label: `${t("HCM_AM_NEW_EMPLOYEE")} (${row.name.givenName || ""}) ${t("HCM_AM_ENROLLED")}`, transitionTime: 3000 });
setTimeout(() => window.history.back(), 800);
},
}
);
};
if (loading && row.id === selectedId) return <Loader />;
return (
<>
<Button key={row.id} variation="primary" label={t("ASSIGN")} style={{ minWidth: "10rem" }} onButtonClick={() => setOpenPopUp(true)} />
{toast && <Toast error={toast.key} isDleteBtn label={t(toast.label)} onClose={() => setToast(null)} type={toast.type} />}
{openPopUp && (
<PopUp style={{ minWidth: "500px" }} onClose={() => { setTag(""); setIsTag(false); setOpenPopUp(false); }} heading={t("Action Needed: Tag Code")} onOverlayClick={() => { setTag(""); setIsTag(false); setOpenPopUp(false); }} sortFooterChildren>
{!isTag ? (
<div>Do you want to fill in the Tag Code? If yes, press Enter Tag. Otherwise, Assign it.</div>
) : (
<div>
<span>Tag Code</span>
<TextInput type="text" name="title" placeholder={t("Enter Tag Name")} value={tag} onChange={(e) => setTag(e.target.value)} />
</div>
)}
{[
<ButtonNew key="enter" type="button" size="large" variation="primary" label={t(isTag ? "HCM_AM_CLOSE_BT" : "HCM_AM_ENTER_TAG")} onClick={() => (isTag ? (setTag(""), setOpenPopUp(false), setIsTag(false)) : setIsTag(true))} />,
<ButtonNew key="assign" type="button" size="large" variation="primary" label={t("Assign")} onClick={() => handleCreate(row.id)} />,
]}
</PopUp>
)}
</>
);
}
🧰 Tools
🪛 Biome (2.1.2)
[error] 2858-2858: Avoid passing children using a prop
The canonical way to pass children in React is to use JSX elements
(lint/correctness/noChildrenProp)
🤖 Prompt for AI Agents
In health/micro-ui/web/micro-ui-internals/example/src/UICustomizations.js around
lines 2711-2902: Hooks (useState/useQueryParams/useMutation) are used inside the
renderer function additionalCustomizations which violates React rules, and PopUp
is passed children via a prop instead of real JSX children. Summary: move
hookful UI into a separate React component and render that component from
additionalCustomizations. Fix by extracting the entire Assign/PopUp logic into a
new functional component (e.g., AttendeeAssignCell) defined outside this config
file scope that uses the hooks (useState, useQueryParams,
useCreateAttendeeFromRegister) and implements PopUp with JSX children and footer
buttons; then replace the case "ASSIGNMENT" body with a simple render of
<AttendeeAssignCell row={row} t={t} /> (or equivalent call) and ensure
loading/toast state and callbacks are managed inside the new component.
children={[ | ||
!isTag ? | ||
<div>Do you want to fill in the Tag Code? If yes, press Enter Tag. Otherwise, Assign it.</div> | ||
: <div> | ||
<span>Tag Code</span> | ||
<TextInput type="text" name="title" placeholder={t("Enter Tag Name")} value={tag} onChange={(e) => setTag(e.target.value)} /> | ||
</div> | ||
|
||
]} | ||
footerChildren={[ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion
Fix noChildrenProp: pass JSX children, not children
prop
See refactor above; this resolves the linter error.
🧰 Tools
🪛 Biome (2.1.2)
[error] 2858-2858: Avoid passing children using a prop
The canonical way to pass children in React is to use JSX elements
(lint/correctness/noChildrenProp)
🤖 Prompt for AI Agents
In health/micro-ui/web/micro-ui-internals/example/src/UICustomizations.js around
lines 2858 to 2867, the code is passing an array to a children prop (children=[
... ]) which triggers the noChildrenProp lint error; change the component usage
to supply the JSX as actual children (i.e., put the conditional JSX between the
component's opening and closing tags) instead of using a children prop, moving
the conditional fragment or the two <div> branches into the component body;
ensure proper parentheses/fragment wrapping and any required keys are preserved.
const [selectedHierarchy, setSelectedHierarchy] = useState(null); | ||
const [options, setOptions] = useState([]); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🧹 Nitpick (assertive)
Initialize selection from formData (edit flows)
Pre-populate selectedHierarchy
when editing.
- const [selectedHierarchy, setSelectedHierarchy] = useState(null);
+ const [selectedHierarchy, setSelectedHierarchy] = useState(formData?.[config?.key] ?? null);
@@
useEffect(() => {
- if (!individualData) return; // wait until data is available
+ if (!individualData) return;
Optionally, after options load, reconcile existing formData[config.key]
with fetched options.
Also applies to: 59-67
🤖 Prompt for AI Agents
In
health/micro-ui/web/micro-ui-internals/packages/modules/health-hrms/src/components/pageComponents/UserAssigment.js
around lines 17-18 (and also affecting lines 59-67), selectedHierarchy is always
initialized to null so edit flows don’t pre-populate the control; initialize
selectedHierarchy from formData[config.key] and, after options are loaded,
reconcile that value with the fetched options: when setting options (lines
~59-67) look up the matching option by id/value or label and call
setSelectedHierarchy(matchedOption) (or convert the stored primitive into an
option object), and add a useEffect that watches [formData, options] to set
selectedHierarchy when editing so the UI shows the existing selection. Ensure
you handle both primitive ids and full option objects and only run the
reconciliation after options are available.
...cro-ui-internals/packages/modules/health-hrms/src/components/pageComponents/UserAssigment.js
Outdated
Show resolved
Hide resolved
...cro-ui-internals/packages/modules/health-hrms/src/components/pageComponents/UserAssigment.js
Outdated
Show resolved
Hide resolved
label: "HCM_AM_COMMON_TABLE_COL_FILTER", | ||
isMandatory: false, | ||
key: "AttendeeBoundaryComponent", | ||
type: "component", | ||
disable: false, | ||
component: "AttendeeBoundaryComponent", | ||
|
||
populators: { | ||
name: "AttendeeBoundaryComponent", | ||
|
||
}, | ||
}, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🧹 Nitpick (assertive)
Boundary data source: confirm API usage (per learnings)
Ensure AttendeeBoundaryComponent fetches boundaries via /boundary-service/boundary-relationships/_search, not MDMS hooks (team standard).
I used your org’s prior learning here. If not aligned, I can generate the switch quickly.
primaryLabel: "Search", // Label for primary search button | ||
|
||
defaultValues: { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🧹 Nitpick (assertive)
Use i18n key for primary button label
Replace hardcoded "Search" with the standard i18n key.
- primaryLabel: "Search", // Label for primary search button
+ primaryLabel: "ES_COMMON_SEARCH", // Label for primary search button
📝 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.
primaryLabel: "Search", // Label for primary search button | |
defaultValues: { | |
primaryLabel: "ES_COMMON_SEARCH", // Label for primary search button | |
defaultValues: { |
🤖 Prompt for AI Agents
In
health/micro-ui/web/micro-ui-internals/packages/modules/health-payments/src/config/AttendeeInboxConfig.js
around lines 121 to 123, the primaryLabel is hardcoded as "Search"; replace that
literal with the standard i18n key (e.g. "common.search") so the label uses the
app's translation system, updating the config to reference the i18n key instead
of the hardcoded English word.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 24
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (3)
health/micro-ui/web/micro-ui-internals/example/src/UICustomizations.js (1)
54-60
: Fix epoch comment (ms vs seconds) and simplify returnThe function returns milliseconds, not seconds. Align the comment and remove the unnecessary Math.floor.
- // Convert the date to epoch time (seconds) - return Math.floor(date.getTime()); + // Convert the date to epoch time (milliseconds) + return date.getTime();health/micro-ui/web/micro-ui-internals/packages/modules/health-hrms/src/services/service.js (1)
132-138
: Update path omits reportingTo; edits won’t persist.Create payload sets reportingTo, but update mapping doesn’t. Editing the field in UI will be ignored server-side.
Add reportingTo to the assignment mapping during updates (illustrative patch):
requestdata.assignments = userExisting[0].assignments.map((j) => { const assigment = { ...j }; assigment.department = data?.SelectEmployeeDepartment?.code || j.department; assigment.designation = data?.SelectEmployeeDesignation?.code || j.designation; // NEW: persist reportingTo when provided assigment.reportingTo = data?.UserAssignment ?? assigment.reportingTo ?? null; return assigment; });health/micro-ui/web/micro-ui-internals/packages/modules/health-hrms/src/services/urls.js (1)
1-55
: Centralize endpoint constants into shared Urls service
Numerous modules still reference raw endpoint strings (e.g./boundary-service/...
,/health-attendance/...
,/health-individual/...
) instead of using the sharedUrls
object. Replace all hard-coded URLs (found in microplan/src/pages/employee/index.js:209; health-payments/src/services/attendance/attendanceService.js:33; health-hrms/src/services/hrms/SearchUser.js:33; etc.) with the corresponding entries inhealth-hrms/src/services/urls.js
(for example,Urls.attendee.search
,Urls.attendee.deenrollAttendee
,Urls.boundarySearchPath
) to enforce a single source of truth.
♻️ Duplicate comments (16)
health/micro-ui/web/micro-ui-internals/example/src/UICustomizations.js (9)
810-823
: Duplicate/overwritten fields in MicroplanSearchConfig.preProcessSet name once with clear precedence; don’t set status here if it’s overridden by the tab filter below.
- const { name, status } = data?.state?.searchForm || {}; + const { name, microplanName } = data?.state?.searchForm || {}; @@ - data.body.PlanConfigurationSearchCriteria.name = name; + if (microplanName) { + data.body.PlanConfigurationSearchCriteria.name = microplanName; + } else if (name) { + data.body.PlanConfigurationSearchCriteria.name = name; + } @@ - data.body.PlanConfigurationSearchCriteria.status = status?.status; - data.body.PlanConfigurationSearchCriteria.name = data?.state?.searchForm?.microplanName; + // status is set from tab filter below
839-856
: React Hooks inside cell renderer; and noSwitchDeclarationsHooks (
useState
, data hooks) are used insideadditionalCustomizations
and declarations leak across cases. Extract the ACTIONS cell into a component (as previously suggested) or, at minimum, wrap eachcase
in a block.Minimal scope-fix (does not solve hook-rule violation):
- case "ACTIONS": + case "ACTIONS": { // ... - return ( + return ( <> {/* ... */} </> ); + }Please adopt the earlier component extraction to resolve the Hook rule violation properly.
Also applies to: 884-966
886-889
: Remove hard-coded dummy filestore idDon’t fall back to a dummy file. Guard the UI on real availability.
- // TODO : Replace dummy file id with real file id when API is ready - const dummyFile = "c22a7676-d5d7-49b6-bcdb-83e9519f58df" - const microplanFileId = row?.campaignDetails?.additionalDetails?.microplanFileId || dummyFile; + const microplanFileId = row?.campaignDetails?.additionalDetails?.microplanFileId;
1189-1218
: Action button config: remove no-op onClick and rely on options+onOptionSelect- isSearchable={false} - title={t("MP_ACTIONS_FOR_MICROPLANS")} - label={t("MP_ACTIONS_FOR_MICROPLANS")} - isDisabled={!EstimationsfileId} - onClick={() => { }} + isSearchable={false} + title={t("MP_ACTIONS_FOR_MICROPLANS")} + label={t("MP_ACTIONS_FOR_MICROPLANS")} + isDisabled={!EstimationsfileId}
1442-1454
: Avoid hook inside utility: pass campaignId into getFacilitySearchRequestTreat the function as pure; accept
campaignId
viaprop
or caller.- const { campaignId } = Digit.Hooks.useQueryParams(); + const { campaignId } = prop; // expect caller to pass campaignIdAlso update callers to pass
{ campaignId }
.
2223-2224
: Remove empty additionalCustomizations stubs or add TODODrop these no-op functions to reduce bundle size, or replace with a shared noop and a brief TODO.
Also applies to: 2298-2299, 2374-2375, 2449-2450, 2524-2525, 2598-2599
2621-2621
: AttendeeSearch preProcess: remove console logs; guard .trim; verify payload schema
- Remove console logs.
- Guard
.trim()
calls.- Confirm BE expects arrays for
mobileNumber/username
andboundaryCode
at this path (vslocality
object).- console.log(data) + // debug log removed @@ - if (phone && phone.trim() !== "") { + if (typeof phone === "string" && phone.trim() !== "") { Individual.mobileNumber = [phone]; } @@ - if (names && names.trim() !== "") { + if (typeof names === "string" && names.trim() !== "") { Individual.name = { givenName: names }; } @@ - if (codes && codes.trim() !== "") { + if (typeof codes === "string" && codes.trim() !== "") { Individual.username = [codes]; } @@ - if (boundaryCode && boundaryCode.trim() !== "") { + if (typeof boundaryCode === "string" && boundaryCode.trim() !== "") { Individual.boundaryCode=boundaryCode } @@ - console.log("payload", data) + // debug log removedRun to verify the expected request shape:
#!/bin/bash # Look for attendee search payload contracts/usages rg -nC2 -e 'AttendeeSearch|useCreateAttendeeFromRegister|Individual(\\.|")' --type js --type ts --type tsxAlso applies to: 2666-2678, 2681-2691, 2708-2709
2716-2765
: Hooks inside renderer (rule-of-hooks)
useState
,useQueryParams
, and mutation hooks are used insideadditionalCustomizations
. Extract anAttendeeAssignCell
component and render it from the "ASSIGNMENT" case. This also avoids repeated re-creation per cell and improves performance.Also applies to: 2817-2844
2846-2897
: Fix noChildrenProp: pass JSX children to PopUpRender content between
<PopUp>...</PopUp>
instead of usingchildren
/footerChildren
arrays.- openPopUp && <PopUp + openPopUp && ( + <PopUp style={{ minWidth: "500px" }} onClose={() => { setTag(""); setIsTag(false); setOpenPopUp(false); }} heading={t("Action Needed: Tag Code")} onOverlayClick={() => { setTag(""); setIsTag(false); setOpenPopUp(false); }} - children={[ - !isTag ? - <div>Do you want to fill in the Tag Code? If yes, press Enter Tag. Otherwise, Assign it.</div> - : <div> - <span>Tag Code</span> - <TextInput type="text" name="title" placeholder={t("Enter Tag Name")} value={tag} onChange={(e) => setTag(e.target.value)} /> - </div> - ]} - footerChildren={[ - <ButtonNew ... />, - <ButtonNew ... />, - ]} - sortFooterChildren={true} - /> + sortFooterChildren={true} + > + {!isTag ? ( + <div>Do you want to fill in the Tag Code? If yes, press Enter Tag. Otherwise, Assign it.</div> + ) : ( + <div> + <span>Tag Code</span> + <TextInput type="text" name="title" placeholder={t("Enter Tag Name")} value={tag} onChange={(e) => setTag(e.target.value)} /> + </div> + )} + {[ + <ButtonNew key="enter" type="button" size="large" variation="primary" label={t(isTag ? "HCM_AM_CLOSE_BT" : "HCM_AM_ENTER_TAG")} onClick={() => { if (isTag) { setTag(""); setOpenPopUp(false); setIsTag(false); } else { setIsTag(true); } }} />, + <ButtonNew key="assign" type="button" size="large" variation="primary" label={t("Assign")} onClick={() => { handleCreate(row.id); }} />, + ]} + </PopUp> + )health/micro-ui/web/micro-ui-internals/packages/modules/health-hrms/src/services/service.js (1)
273-285
: Use stable keys and verify selectedProject shape (id vs code); avoid empty-string sentinel.Array index keys are fragile on reorder, and empty-string ids complicate truthy checks. Set selectedProject to null when absent.
- ? data?.map((ele, index) => ({ - key: index, + ? data?.map((ele, index) => ({ + key: ele?.projectId ?? ele?.id ?? `row-${index}`, fromDate: ele.startDate ? convertEpochToDate(ele.startDate) : "", toDate: ele.endDate ? convertEpochToDate(ele.endDate) : "", - selectedProject: { id: ele.projectId }, + selectedProject: ele?.projectId ? { id: ele.projectId } : null, })) : [ { - key: 0, + key: "row-0", fromDate: "", toDate: "", - selectedProject: { id: "" }, + selectedProject: null, }, ],If consumers expect a different shape (e.g., selectedProject: { code } or a plain id), align here accordingly.
health/micro-ui/web/micro-ui-internals/packages/modules/health-hrms/src/services/urls.js (3)
34-39
: Duplicatehrms
key; one will shadow the other.Keep a single
hrms
block to prevent accidental overrides. This was flagged earlier as well.Suggested change (outside this hunk): remove the duplicate at lines 34-39.
5-6
: Unused constants.
boundarySearchPath
andhierarchyType
are declared but unused; delete to reduce noise.
49-52
: Parameterize attendee/individual service paths (avoid hard-coded literals).Use globalConfigs like other services for portability. Also aligns with prior review.
Apply within this hunk:
attendee:{ - deenrollAttendee:`/health-attendance/attendee/v1/_delete`, - search: `/health-individual/v1/_search`, + deenrollAttendee:`/${attendanceContextPath}/attendee/v1/_delete`, + search: `/${individualContextPath}/v1/_search`, }Add (outside this hunk, near other context-path defs):
const attendanceContextPath = window?.globalConfigs?.getConfig("ATTENDANCE_CONTEXT_PATH") || "health-attendance"; const individualContextPath = window?.globalConfigs?.getConfig("INDIVIDUAL_CONTEXT_PATH") || "health-individual";health/micro-ui/web/micro-ui-internals/packages/modules/health-hrms/src/components/pageComponents/UserAssigment.js (3)
1-12
: Remove unused imports.
useTranslation
,HeaderComponent
,Card
,Button
,Toast
not used. This was flagged earlier.-import { useTranslation } from "react-i18next"; import { Dropdown, Loader, - HeaderComponent, - Card, LabelFieldPair, - Button, - Toast, CardLabel, TextInput, } from "@egovernments/digit-ui-components";
24-24
: UsegetCurrentTenantId()
instead ofgetStateId()
.Aligns with other HRMS calls. Previously suggested.
- const tenantId = Digit.ULBService.getStateId(); + const tenantId = Digit.ULBService.getCurrentTenantId();
1-1
: Filename typo: rename file.Rename
UserAssigment.js
→UserAssignment.js
and update imports/registry. Previously noted.
📜 Review details
Configuration used: CodeRabbit UI
Review profile: ASSERTIVE
Plan: Pro
📒 Files selected for processing (10)
health/micro-ui/web/micro-ui-internals/example/src/UICustomizations.js
(24 hunks)health/micro-ui/web/micro-ui-internals/packages/modules/health-hrms/src/Module.js
(2 hunks)health/micro-ui/web/micro-ui-internals/packages/modules/health-hrms/src/components/pageComponents/SearchUserToReport.js
(1 hunks)health/micro-ui/web/micro-ui-internals/packages/modules/health-hrms/src/components/pageComponents/SelectableList.js
(1 hunks)health/micro-ui/web/micro-ui-internals/packages/modules/health-hrms/src/components/pageComponents/UserAssigment.js
(1 hunks)health/micro-ui/web/micro-ui-internals/packages/modules/health-hrms/src/pages/employee/createEmployee.js
(6 hunks)health/micro-ui/web/micro-ui-internals/packages/modules/health-hrms/src/services/hrms/AttendeeService.js
(1 hunks)health/micro-ui/web/micro-ui-internals/packages/modules/health-hrms/src/services/hrms/SearchUser.js
(1 hunks)health/micro-ui/web/micro-ui-internals/packages/modules/health-hrms/src/services/service.js
(5 hunks)health/micro-ui/web/micro-ui-internals/packages/modules/health-hrms/src/services/urls.js
(1 hunks)
🧰 Additional context used
📓 Path-based instructions (1)
**/*.js
⚙️ CodeRabbit configuration file
check
Files:
health/micro-ui/web/micro-ui-internals/packages/modules/health-hrms/src/Module.js
health/micro-ui/web/micro-ui-internals/packages/modules/health-hrms/src/services/hrms/AttendeeService.js
health/micro-ui/web/micro-ui-internals/packages/modules/health-hrms/src/components/pageComponents/SearchUserToReport.js
health/micro-ui/web/micro-ui-internals/packages/modules/health-hrms/src/components/pageComponents/SelectableList.js
health/micro-ui/web/micro-ui-internals/packages/modules/health-hrms/src/services/service.js
health/micro-ui/web/micro-ui-internals/packages/modules/health-hrms/src/services/hrms/SearchUser.js
health/micro-ui/web/micro-ui-internals/packages/modules/health-hrms/src/pages/employee/createEmployee.js
health/micro-ui/web/micro-ui-internals/packages/modules/health-hrms/src/services/urls.js
health/micro-ui/web/micro-ui-internals/packages/modules/health-hrms/src/components/pageComponents/UserAssigment.js
health/micro-ui/web/micro-ui-internals/example/src/UICustomizations.js
🧠 Learnings (12)
📚 Learning: 2025-07-15T04:58:30.634Z
Learnt from: Hari-egov
PR: egovernments/DIGIT-Frontend#2788
File: micro-ui/web/micro-ui-internals/packages/modules/hrms/src/components/pageComponents/jurisdiction.js:26-26
Timestamp: 2025-07-15T04:58:30.634Z
Learning: In the HRMS module (micro-ui/web/micro-ui-internals/packages/modules/hrms/src/components/pageComponents/jurisdiction.js), the team has moved away from using MDMS hooks for boundary data fetching and now uses direct API calls to the boundary service endpoint `/boundary-service/boundary-relationships/_search` instead of the `useHrmsMDMS` hook with "FetchBoundaries" parameter.
Applied to files:
health/micro-ui/web/micro-ui-internals/packages/modules/health-hrms/src/Module.js
health/micro-ui/web/micro-ui-internals/packages/modules/health-hrms/src/services/hrms/SearchUser.js
📚 Learning: 2024-06-10T19:25:42.992Z
Learnt from: siddhant-nawale-egov
PR: egovernments/DIGIT-Frontend#606
File: micro-ui/web/micro-ui-internals/packages/modules/hcm-microplanning/src/utils/index.js:276-276
Timestamp: 2024-06-10T19:25:42.992Z
Learning: The `addResourcesToFilteredDataToShow` function in `micro-ui/web/micro-ui-internals/packages/modules/hcm-microplanning/src/utils/index.js` now includes checks for data integrity, such as validation of `previewData`, the common column, and `resources`, along with error logging for invalid data formats.
Applied to files:
health/micro-ui/web/micro-ui-internals/packages/modules/health-hrms/src/Module.js
📚 Learning: 2024-11-07T07:17:27.636Z
Learnt from: jagankumar-egov
PR: egovernments/DIGIT-Frontend#1763
File: health/micro-ui/web/micro-ui-internals/packages/modules/campaign-manager/src/pages/employee/MyCampaign.js:65-75
Timestamp: 2024-11-07T07:17:27.636Z
Learning: In `MyCampaign.js`, when suggesting code improvements for the `onClickRow` function, keep suggestions simple and avoid unnecessary complexity.
Applied to files:
health/micro-ui/web/micro-ui-internals/packages/modules/health-hrms/src/services/service.js
health/micro-ui/web/micro-ui-internals/example/src/UICustomizations.js
📚 Learning: 2024-11-07T11:02:33.520Z
Learnt from: rachana-egov
PR: egovernments/DIGIT-Frontend#1770
File: health/micro-ui/web/micro-ui-internals/packages/modules/microplan/src/pages/employee/viewVillage.js:320-322
Timestamp: 2024-11-07T11:02:33.520Z
Learning: In `health/micro-ui/web/micro-ui-internals/packages/modules/microplan/src/pages/employee/viewVillage.js`, the `data?.additionalFields` object is guaranteed to be defined, so checking for its existence before accessing its keys is unnecessary.
Applied to files:
health/micro-ui/web/micro-ui-internals/packages/modules/health-hrms/src/services/service.js
health/micro-ui/web/micro-ui-internals/packages/modules/health-hrms/src/pages/employee/createEmployee.js
health/micro-ui/web/micro-ui-internals/packages/modules/health-hrms/src/components/pageComponents/UserAssigment.js
health/micro-ui/web/micro-ui-internals/example/src/UICustomizations.js
📚 Learning: 2025-01-02T04:41:15.957Z
Learnt from: jagankumar-egov
PR: egovernments/DIGIT-Frontend#2089
File: micro-ui/web/micro-ui-internals/packages/modules/workbench/src/pages/employee/MDMSAddV2.js:111-111
Timestamp: 2025-01-02T04:41:15.957Z
Learning: In micro-ui/web/micro-ui-internals/packages/modules/workbench/src/pages/employee/MDMSAddV2.js, always use "mdms[0].uniqueIdentifier" for the jsonPath instead of differentiating between "SOR" and other masters.
Applied to files:
health/micro-ui/web/micro-ui-internals/packages/modules/health-hrms/src/pages/employee/createEmployee.js
📚 Learning: 2025-06-04T04:08:48.234Z
Learnt from: jagankumar-egov
PR: egovernments/DIGIT-Frontend#2488
File: micro-ui/web/micro-ui-internals/packages/modules/core/src/pages/employee/Login/login.js:152-152
Timestamp: 2025-06-04T04:08:48.234Z
Learning: In the employee login component (micro-ui/web/micro-ui-internals/packages/modules/core/src/pages/employee/Login/login.js), prefer using a `defaultTenant` variable to store `Digit.ULBService.getStateId()` instead of calling the function multiple times inline in the `defaultValue` object. This improves code readability and avoids function call duplication.
Applied to files:
health/micro-ui/web/micro-ui-internals/packages/modules/health-hrms/src/pages/employee/createEmployee.js
health/micro-ui/web/micro-ui-internals/packages/modules/health-hrms/src/components/pageComponents/UserAssigment.js
📚 Learning: 2025-02-05T10:01:29.668Z
Learnt from: Tulika-eGov
PR: egovernments/DIGIT-Frontend#2188
File: micro-ui/web/micro-ui-internals/packages/modules/core/src/pages/employee/Login/login.js:72-78
Timestamp: 2025-02-05T10:01:29.668Z
Learning: In the employee login form, defaultValues are dynamically generated from config[0].body based on populators.defaultValue, so spreading the entire defaultValues object is required rather than cherry-picking specific fields.
Applied to files:
health/micro-ui/web/micro-ui-internals/packages/modules/health-hrms/src/pages/employee/createEmployee.js
📚 Learning: 2024-06-10T19:25:42.992Z
Learnt from: siddhant-nawale-egov
PR: egovernments/DIGIT-Frontend#698
File: micro-ui/web/micro-ui-internals/packages/modules/hcm-microplanning/src/components/MicroplanPreview.js:1-1
Timestamp: 2024-06-10T19:25:42.992Z
Learning: The imports in `MicroplanPreview.js` are from different libraries: `egovernments/digit-ui-components` and `egovernments/digit-ui-react-components`.
Applied to files:
health/micro-ui/web/micro-ui-internals/packages/modules/health-hrms/src/components/pageComponents/UserAssigment.js
health/micro-ui/web/micro-ui-internals/example/src/UICustomizations.js
📚 Learning: 2024-06-10T19:25:42.992Z
Learnt from: nitish-egov
PR: egovernments/DIGIT-Frontend#0
File: :0-0
Timestamp: 2024-06-10T19:25:42.992Z
Learning: Validation for the presence of the `request` parameter in `autoGenerateBoundaryCodes` method of `dataManage.controller.ts` is handled at the entry level, making additional checks within the method unnecessary.
Applied to files:
health/micro-ui/web/micro-ui-internals/packages/modules/health-hrms/src/components/pageComponents/UserAssigment.js
📚 Learning: 2024-10-26T15:11:49.938Z
Learnt from: nabeelmd-eGov
PR: egovernments/DIGIT-Frontend#1680
File: health/micro-ui/web/micro-ui-internals/example/src/UICustomizations.js:1032-1094
Timestamp: 2024-10-26T15:11:49.938Z
Learning: In the DIGIT-Frontend project, when reviewing the `UICustomizations.js` file, avoid suggesting refactoring of repetitive rendering logic in switch cases into helper functions, unless explicitly requested.
Applied to files:
health/micro-ui/web/micro-ui-internals/example/src/UICustomizations.js
📚 Learning: 2024-09-30T05:45:14.549Z
Learnt from: ashish-egov
PR: egovernments/DIGIT-Frontend#1441
File: health/micro-ui/web/micro-ui-internals/packages/modules/microplan/src/hooks/useGenerateIdCampaign.js:1-1
Timestamp: 2024-09-30T05:45:14.549Z
Learning: In the `useGenerateIdCampaign` function, auto assignment of default parameter values is needed in parameter destructuring.
Applied to files:
health/micro-ui/web/micro-ui-internals/example/src/UICustomizations.js
📚 Learning: 2024-10-17T12:00:51.749Z
Learnt from: Ramkrishna-egov
PR: egovernments/DIGIT-Frontend#1545
File: health/micro-ui/web/micro-ui-internals/packages/modules/microplan/src/components/ActivityCard.js:30-35
Timestamp: 2024-10-17T12:00:51.749Z
Learning: In our codebase, the 'Card' component is commonly used by passing children via the 'children' prop.
Applied to files:
health/micro-ui/web/micro-ui-internals/example/src/UICustomizations.js
🧬 Code graph analysis (6)
health/micro-ui/web/micro-ui-internals/packages/modules/health-hrms/src/services/hrms/AttendeeService.js (2)
health/micro-ui/web/micro-ui-internals/example/src/UICustomizations.js (32)
tenantId
(391-391)tenantId
(757-757)tenantId
(840-840)tenantId
(1387-1387)tenantId
(1442-1442)tenantId
(1689-1689)tenantId
(1897-1897)tenantId
(2162-2162)tenantId
(2194-2194)tenantId
(2239-2239)tenantId
(2269-2269)tenantId
(2314-2314)tenantId
(2345-2345)tenantId
(2390-2390)tenantId
(2420-2420)tenantId
(2465-2465)data
(415-415)data
(517-517)data
(734-734)data
(794-794)data
(811-811)data
(1071-1071)data
(1333-1333)data
(1350-1350)data
(1351-1351)data
(1352-1352)data
(2164-2164)data
(2165-2165)data
(2241-2241)data
(2242-2242)data
(2316-2316)data
(2317-2317)health/micro-ui/web/micro-ui-internals/packages/modules/health-hrms/src/services/urls.js (1)
Urls
(9-53)
health/micro-ui/web/micro-ui-internals/packages/modules/health-hrms/src/components/pageComponents/SelectableList.js (1)
health/micro-ui/web/micro-ui-internals/packages/modules/health-hrms/src/components/pageComponents/SearchUserToReport.js (1)
onSelect
(70-74)
health/micro-ui/web/micro-ui-internals/packages/modules/health-hrms/src/services/service.js (2)
health/micro-ui/web/micro-ui-internals/packages/modules/health-hrms/src/constants/constants.js (2)
HRMS_CONSTANTS
(1-7)HRMS_CONSTANTS
(1-7)health/micro-ui/web/micro-ui-internals/packages/modules/health-hrms/src/components/Utils/index.js (2)
convertEpochToDate
(2-15)convertEpochToDate
(2-15)
health/micro-ui/web/micro-ui-internals/packages/modules/health-hrms/src/services/hrms/SearchUser.js (1)
health/micro-ui/web/micro-ui-internals/packages/modules/health-hrms/src/services/hrms/AttendeeService.js (1)
AttendeeService
(3-46)
health/micro-ui/web/micro-ui-internals/packages/modules/health-hrms/src/pages/employee/createEmployee.js (5)
health/micro-ui/web/micro-ui-internals/packages/modules/health-hrms/src/pages/employee/CampaignAssignmentInbox.js (1)
mdmsData
(14-20)health/micro-ui/web/micro-ui-internals/packages/modules/health-hrms/src/pages/employee/employeeDetails.js (2)
mdmsData
(29-40)Digit
(49-49)health/micro-ui/web/micro-ui-internals/packages/modules/health-hrms/src/pages/employee/Inbox.js (2)
mdmsData
(12-18)config
(26-26)health/micro-ui/web/micro-ui-internals/packages/modules/pgr/src/pages/employee/CreateComplaint/createComplaintForm.js (1)
validatePhoneNumber
(53-66)health/micro-ui/web/micro-ui-internals/packages/modules/health-hrms/src/components/config/createEmployeeConfig.js (2)
CreateEmployeeConfig
(6-321)CreateEmployeeConfig
(6-321)
health/micro-ui/web/micro-ui-internals/packages/modules/health-hrms/src/components/pageComponents/UserAssigment.js (2)
health/micro-ui/web/micro-ui-internals/example/src/UICustomizations.js (19)
boundaryCode
(2660-2661)Digit
(1443-1443)Digit
(2726-2726)tenantId
(391-391)tenantId
(757-757)tenantId
(840-840)tenantId
(1387-1387)tenantId
(1442-1442)tenantId
(1689-1689)tenantId
(1897-1897)tenantId
(2162-2162)tenantId
(2194-2194)tenantId
(2239-2239)tenantId
(2269-2269)tenantId
(2314-2314)tenantId
(2345-2345)tenantId
(2390-2390)tenantId
(2420-2420)tenantId
(2465-2465)health/micro-ui/web/micro-ui-internals/packages/modules/health-hrms/src/components/pageComponents/SearchUserToReport.js (3)
searchQuery
(31-31)onSelect
(70-74)SearchUserToReport
(11-132)
🪛 Biome (2.1.2)
health/micro-ui/web/micro-ui-internals/packages/modules/health-hrms/src/components/pageComponents/SearchUserToReport.js
[error] 99-99: Avoid passing children using a prop
The canonical way to pass children in React is to use JSX elements
(lint/correctness/noChildrenProp)
health/micro-ui/web/micro-ui-internals/packages/modules/health-hrms/src/components/pageComponents/SelectableList.js
[error] 20-31: Static Elements should not be interactive.
To add interactivity such as a mouse or key event listener to a static element, give the element an appropriate role value.
(lint/a11y/noStaticElementInteractions)
[error] 20-31: Enforce to have the onClick mouse event with the onKeyUp, the onKeyDown, or the onKeyPress keyboard event.
Actions triggered using mouse events should have corresponding keyboard events to account for keyboard-only navigation.
(lint/a11y/useKeyWithClickEvents)
health/micro-ui/web/micro-ui-internals/packages/modules/health-hrms/src/pages/employee/createEmployee.js
[error] 76-76: This is an unexpected use of the debugger statement.
Unsafe fix: Remove debugger statement
(lint/suspicious/noDebugger)
health/micro-ui/web/micro-ui-internals/packages/modules/health-hrms/src/components/pageComponents/UserAssigment.js
[error] 90-95: Static Elements should not be interactive.
To add interactivity such as a mouse or key event listener to a static element, give the element an appropriate role value.
(lint/a11y/noStaticElementInteractions)
[error] 90-95: Enforce to have the onClick mouse event with the onKeyUp, the onKeyDown, or the onKeyPress keyboard event.
Actions triggered using mouse events should have corresponding keyboard events to account for keyboard-only navigation.
(lint/a11y/useKeyWithClickEvents)
health/micro-ui/web/micro-ui-internals/example/src/UICustomizations.js
[error] 887-887: Other switch clauses can erroneously access this declaration.
Wrap the declaration in a block to restrict its access to the switch clause.
The declaration is defined in this switch clause:
Safe fix: Wrap the declaration in a block.
(lint/correctness/noSwitchDeclarations)
[error] 888-888: Other switch clauses can erroneously access this declaration.
Wrap the declaration in a block to restrict its access to the switch clause.
The declaration is defined in this switch clause:
Safe fix: Wrap the declaration in a block.
(lint/correctness/noSwitchDeclarations)
[error] 889-889: Other switch clauses can erroneously access this declaration.
Wrap the declaration in a block to restrict its access to the switch clause.
The declaration is defined in this switch clause:
Safe fix: Wrap the declaration in a block.
(lint/correctness/noSwitchDeclarations)
[error] 890-890: Other switch clauses can erroneously access this declaration.
Wrap the declaration in a block to restrict its access to the switch clause.
The declaration is defined in this switch clause:
Safe fix: Wrap the declaration in a block.
(lint/correctness/noSwitchDeclarations)
[error] 902-916: Other switch clauses can erroneously access this declaration.
Wrap the declaration in a block to restrict its access to the switch clause.
The declaration is defined in this switch clause:
Safe fix: Wrap the declaration in a block.
(lint/correctness/noSwitchDeclarations)
[error] 918-962: Other switch clauses can erroneously access this declaration.
Wrap the declaration in a block to restrict its access to the switch clause.
The declaration is defined in this switch clause:
Safe fix: Wrap the declaration in a block.
(lint/correctness/noSwitchDeclarations)
[error] 964-966: Other switch clauses can erroneously access this declaration.
Wrap the declaration in a block to restrict its access to the switch clause.
The declaration is defined in this switch clause:
Safe fix: Wrap the declaration in a block.
(lint/correctness/noSwitchDeclarations)
[error] 2859-2859: Avoid passing children using a prop
The canonical way to pass children in React is to use JSX elements
(lint/correctness/noChildrenProp)
⏰ Context from checks skipped due to timeout of 10000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
- GitHub Check: Analyze (javascript-typescript)
🔇 Additional comments (6)
health/micro-ui/web/micro-ui-internals/example/src/UICustomizations.js (1)
1587-1594
: LGTM: clearing range and normalizing date filtersDeleting the raw range object after extracting from/to dates is correct and avoids BE confusion.
health/micro-ui/web/micro-ui-internals/packages/modules/health-hrms/src/Module.js (1)
20-22
: Confirm registry keys match config usage and exports.Ensure CreateEmployeeConfig (or any MDMS config) references these exact component keys: "UserAssignment", "SearchUserToReport", "SelectableList", and that each file default-exports the component.
Also applies to: 84-86
health/micro-ui/web/micro-ui-internals/packages/modules/health-hrms/src/pages/employee/createEmployee.js (3)
322-324
: MDMS override: confirm intent to disable server-driven form config.Hard-wiring fConfig to CreateEmployeeConfig and keeping MDMS enable: false blocks runtime config updates. If this was temporary, revert to MDMS-first with static fallback.
Proposed pattern:
- const fConfig = CreateEmployeeConfig?.CreateEmployeeConfig?.[0]; - //const fConfig = mdmsData ? mdmsData : CreateEmployeeConfig?.CreateEmployeeConfig?.[0]; + const fConfig = mdmsData || CreateEmployeeConfig?.CreateEmployeeConfig?.[0];And enable the MDMS hook when ready.
333-339
: Verify updateDependent semantics for date fields.Confirm that preProcessMDMSConfig treats these values as defaultValue (not min/max). If the intent is to set max for DOB (18 years ago) and default for DOE (today), wire them to the correct keys expected by the form engine.
349-353
: Edit mode field filtering: confirm keys.Ensure the config uses field.key for "employeePassword", "employeeConfirmPassword", and "Jurisdictions". If any field relies on populators.name instead, it may slip through.
health/micro-ui/web/micro-ui-internals/packages/modules/health-hrms/src/components/pageComponents/SearchUserToReport.js (1)
50-54
: Remove debug logs (PII risk).Logs of user input can leak PII.
- if (/^\d+$/.test(name)) { - console.log("it is nummeric"); - } else { - console.log("it is not nummeric"); - } + // optionally branch on numeric vs text without logging PIILikely an incorrect or invalid review comment.
import { PopUp, Timeline, Loader, TextInput, Button } from '@egovernments/digit-ui-components'; | ||
import { useEffect } from "react"; | ||
import { useHistory } from "react-router-dom"; | ||
import AttendanceService from "../../services/hrms/SearchUser"; | ||
import SelectableList from "./SelectableList"; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🧹 Nitpick (assertive)
Prune unused imports.
Timeline
, Loader
, useEffect
, useHistory
, and context-path vars are unused.
-import { PopUp, Timeline, Loader, TextInput, Button } from '@egovernments/digit-ui-components';
-import { useEffect } from "react";
-import { useHistory } from "react-router-dom";
+import { PopUp, TextInput, Button } from '@egovernments/digit-ui-components';
Also remove unused attendanceContextPath
, individualContextPath
, labels
, labelWidth
.
📝 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.
import { PopUp, Timeline, Loader, TextInput, Button } from '@egovernments/digit-ui-components'; | |
import { useEffect } from "react"; | |
import { useHistory } from "react-router-dom"; | |
import AttendanceService from "../../services/hrms/SearchUser"; | |
import SelectableList from "./SelectableList"; | |
import { PopUp, TextInput, Button } from '@egovernments/digit-ui-components'; | |
import AttendanceService from "../../services/hrms/SearchUser"; | |
import SelectableList from "./SelectableList"; |
🤖 Prompt for AI Agents
In
health/micro-ui/web/micro-ui-internals/packages/modules/health-hrms/src/components/pageComponents/SearchUserToReport.js
around lines 3 to 7, several imports and local variables are unused: remove
Timeline, Loader, useEffect, useHistory from the import list (keep only PopUp,
TextInput, Button and any others actually referenced), and delete any unused
context-path vars (attendanceContextPath, individualContextPath) plus labels and
labelWidth declarations; ensure you also remove any dead references to these
identifiers elsewhere in the file so the component builds cleanly.
const searchUser = async (name) => { | ||
|
||
try { | ||
|
||
const locallity = Digit.SessionStorage.get("selectedBoundary")?.code || null; | ||
|
||
if (locallity === null) { | ||
setShowToast( | ||
{ key: "error", label: t(`Locality is not selected`), transitionTime: 3000 } | ||
); | ||
return; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🧹 Nitpick (assertive)
Typo: locallity
→ locality
(propagate to service signature).
Keeps naming consistent.
🤖 Prompt for AI Agents
In
health/micro-ui/web/micro-ui-internals/packages/modules/health-hrms/src/components/pageComponents/SearchUserToReport.js
around lines 37 to 47, the variable name "locallity" is a typo and should be
renamed to "locality" throughout this function and any service signatures or
calls that use it; update the variable declaration, all references in this file
(including setShowToast logic) and change the parameter name passed to
downstream services or helper functions to "locality" (and update those service
function signatures/implementations accordingly) to keep naming consistent and
avoid runtime mismatches.
if (locallity === null) { | ||
setShowToast( | ||
{ key: "error", label: t(`Locality is not selected`), transitionTime: 3000 } | ||
); | ||
return; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Runtime error: setShowToast
is undefined.
Either wire a Toast state or remove the call. Minimal safe fix: early-return without toast.
- if (locallity === null) {
- setShowToast(
- { key: "error", label: t(`Locality is not selected`), transitionTime: 3000 }
- );
- return;
- }
+ if (locallity === null) return;
Optionally, introduce a proper Toast via digit-ui-components.
📝 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.
if (locallity === null) { | |
setShowToast( | |
{ key: "error", label: t(`Locality is not selected`), transitionTime: 3000 } | |
); | |
return; | |
- if (locallity === null) { | |
- setShowToast( | |
- { key: "error", label: t(`Locality is not selected`), transitionTime: 3000 } | |
- ); | |
- return; | |
if (locallity === null) return; |
🤖 Prompt for AI Agents
In
health/micro-ui/web/micro-ui-internals/packages/modules/health-hrms/src/components/pageComponents/SearchUserToReport.js
around lines 43-47, the code calls setShowToast when locallity is null but
setShowToast is not defined, causing a runtime error; fix by removing the
setShowToast call and simply early-return when locallity is null (or
alternatively wire a proper Toast state/hook from digit-ui-components and call
that instead if toast feedback is required). Ensure no references to
setShowToast remain in this branch so the function exits cleanly.
onSubmit({ | ||
id: selectedUser?.userUuid, | ||
name: selectedUser?.name?.givenName | ||
}) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Wrong field: use id
, not userUuid
(downstream expects value.id
).
This breaks selection in UserAssignment.
- onSubmit({
- id: selectedUser?.userUuid,
- name: selectedUser?.name?.givenName
- })
+ onSubmit({
+ id: selectedUser?.id,
+ name: selectedUser?.name?.givenName
+ })
📝 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.
onSubmit({ | |
id: selectedUser?.userUuid, | |
name: selectedUser?.name?.givenName | |
}) | |
onSubmit({ | |
id: selectedUser?.id, | |
name: selectedUser?.name?.givenName | |
}) |
🤖 Prompt for AI Agents
In
health/micro-ui/web/micro-ui-internals/packages/modules/health-hrms/src/components/pageComponents/SearchUserToReport.js
around lines 81-84, the onSubmit payload uses selectedUser?.userUuid but
downstream expects value.id; change the payload to use id: selectedUser?.id
(keep name: selectedUser?.name?.givenName) so the submitted object matches
downstream shape (value.id). Ensure any related tests or callers rely on id
rather than userUuid.
...i-internals/packages/modules/health-hrms/src/components/pageComponents/SearchUserToReport.js
Show resolved
Hide resolved
url: "/health-attendance/attendee/v1/_delete", | ||
useCache: false, | ||
method: "POST", | ||
userService: true, | ||
body, | ||
params, | ||
}); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🧹 Nitpick (assertive)
Parameterize attendee delete path (or reuse AttendeeService.delete).
Dedup endpoints and centralize.
- url: "/health-attendance/attendee/v1/_delete",
+ url: `/${(window?.globalConfigs?.getConfig("ATTENDANCE_CONTEXT_PATH") || "health-attendance")}/attendee/v1/_delete`,
Or call AttendeeService.delete(...)
instead of duplicating this method.
📝 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.
url: "/health-attendance/attendee/v1/_delete", | |
useCache: false, | |
method: "POST", | |
userService: true, | |
body, | |
params, | |
}); | |
url: `/${(window?.globalConfigs?.getConfig("ATTENDANCE_CONTEXT_PATH") || "health-attendance")}/attendee/v1/_delete`, | |
useCache: false, | |
method: "POST", | |
userService: true, | |
body, | |
params, | |
}); |
🤖 Prompt for AI Agents
In
health/micro-ui/web/micro-ui-internals/packages/modules/health-hrms/src/services/hrms/SearchUser.js
around lines 56 to 62, the code directly calls the hardcoded attendee delete
endpoint ("/health-attendance/attendee/v1/_delete") which duplicates existing
functionality; replace this duplication by calling the central
AttendeeService.delete(...) or extract the attendee delete path into a shared
constant used by both services. Update import to include AttendeeService (or the
shared constant), remove the hardcoded URL, and delegate the delete operation to
AttendeeService.delete(body, params) (or call the request util with the shared
PATH constant) so endpoint definition is centralized and deduplicated.
searchIndividual: async ({ name, locallity, tenantId }) => { | ||
try { | ||
|
||
// if (data?.SelectEmployeePhoneNumber && data?.SelectEmployeePhoneNumber?.trim().length > 0) { | ||
const result = await AttendeeService.search(tenantId, null, { limit: 10, offset: 0 }, { | ||
|
||
"Individual": { | ||
|
||
"name": { | ||
"givenName": name | ||
// "givenName": "Ava Taylor" | ||
}, | ||
|
||
// "mobileNumber": null, | ||
|
||
"locality": { | ||
"id": null, | ||
"tenantId": null, | ||
"code": locallity, | ||
"geometry": null, | ||
"auditDetails": null, | ||
"additionalDetails": null | ||
} | ||
} | ||
|
||
}); | ||
|
||
return result.Individual; | ||
} catch (error) { | ||
throw error; // throw on error | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion
Normalize naming and slim payload.
- Fix typo
locallity
→locality
. - Send minimal
locality
object.
- searchIndividual: async ({ name, locallity, tenantId }) => {
+ searchIndividual: async ({ name, locality, tenantId }) => {
@@
- const result = await AttendeeService.search(tenantId, null, { limit: 10, offset: 0 }, {
+ const result = await AttendeeService.search(tenantId, {}, { limit: 10, offset: 0 }, {
@@
- "locality": {
- "id": null,
- "tenantId": null,
- "code": locallity,
- "geometry": null,
- "auditDetails": null,
- "additionalDetails": null
- }
+ "locality": { "code": locality }
📝 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.
searchIndividual: async ({ name, locallity, tenantId }) => { | |
try { | |
// if (data?.SelectEmployeePhoneNumber && data?.SelectEmployeePhoneNumber?.trim().length > 0) { | |
const result = await AttendeeService.search(tenantId, null, { limit: 10, offset: 0 }, { | |
"Individual": { | |
"name": { | |
"givenName": name | |
// "givenName": "Ava Taylor" | |
}, | |
// "mobileNumber": null, | |
"locality": { | |
"id": null, | |
"tenantId": null, | |
"code": locallity, | |
"geometry": null, | |
"auditDetails": null, | |
"additionalDetails": null | |
} | |
} | |
}); | |
return result.Individual; | |
} catch (error) { | |
throw error; // throw on error | |
} | |
searchIndividual: async ({ name, locality, tenantId }) => { | |
try { | |
// if (data?.SelectEmployeePhoneNumber && data?.SelectEmployeePhoneNumber?.trim().length > 0) { | |
const result = await AttendeeService.search(tenantId, {}, { limit: 10, offset: 0 }, { | |
"Individual": { | |
"name": { | |
"givenName": name | |
// "givenName": "Ava Taylor" | |
}, | |
"locality": { "code": locality } | |
} | |
}); | |
return result.Individual; | |
} catch (error) { | |
throw error; // throw on error | |
} |
🤖 Prompt for AI Agents
In
health/micro-ui/web/micro-ui-internals/packages/modules/health-hrms/src/services/hrms/SearchUser.js
around lines 75–105, fix the misspelled parameter and payload field `locallity`
→ `locality` (rename the function parameter and all uses) and reduce the
locality object sent to the API to a minimal shape (e.g., only include the
locality code: { code: locality }) instead of the large stubbed object; update
the request payload to reference the corrected variable name and remove
unused/null fields.
const result = await AttendeeService.search(tenantId, null, { limit: 10, offset: 0 }, { | ||
|
||
"Individual": { | ||
|
||
"name": { | ||
"givenName": name | ||
// "givenName": "Ava Taylor" | ||
}, | ||
|
||
// "mobileNumber": null, | ||
|
||
"locality": { | ||
"id": null, | ||
"tenantId": null, | ||
"code": locallity, | ||
"geometry": null, | ||
"auditDetails": null, | ||
"additionalDetails": null | ||
} | ||
} | ||
|
||
}); | ||
|
||
return result.Individual; | ||
} catch (error) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🧹 Nitpick (assertive)
Align with AttendeeService.search params fix.
Once filters
spread is guarded, passing {}
(not null
) avoids surprises.
🤖 Prompt for AI Agents
In
health/micro-ui/web/micro-ui-internals/packages/modules/health-hrms/src/services/hrms/SearchUser.js
around lines 79 to 103, the call to AttendeeService.search passes null for the
filters argument which will break when the callee guards a spread over filters;
change the second argument from null to an empty object ({}), ensuring filters
is an object so spreads/merges behave correctly and avoid surprises.
reportingTo: data?.UserAssignment || "undefined" | ||
}, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
💡 Verification agent
🧩 Analysis chain
Use null and confirm shape for reportingTo; avoid string literal "undefined".
Backends typically expect either a valid identifier or null. Persisting the string "undefined" risks data-quality issues and brittle filters.
- reportingTo: data?.UserAssignment || "undefined"
+ reportingTo: data?.UserAssignment ?? null
Also confirm whether reportingTo must be an id/uuid, code, or an object (and whether it belongs on assignment vs. user). I can align both create and update payloads once the contract is confirmed.
🏁 Script executed:
#!/bin/bash
# Locate the service.js file for the health-hrms module
file=$(find . -type f -path '*health-hrms/src/services/service.js')
echo "Service file located at: $file"
# Display the first 150 lines to inspect data assignment and context
sed -n '1,150p' "$file"
# Search the entire codebase for occurrences of 'UserAssignment' to find its origin or type definitions
rg -n 'UserAssignment'
Length of output: 7540
Replace string literal “undefined” with null in reportingTo
.
- reportingTo: data?.UserAssignment || "undefined"
+ reportingTo: data?.UserAssignment ?? null
Confirm whether reportingTo
should be an identifier (id/UUID/code) or an object and adjust the payload accordingly.
📝 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.
reportingTo: data?.UserAssignment || "undefined" | |
}, | |
reportingTo: data?.UserAssignment ?? null | |
}, |
🤖 Prompt for AI Agents
In
health/micro-ui/web/micro-ui-internals/packages/modules/health-hrms/src/services/service.js
around lines 75-76, the property reportingTo is being set to the literal string
"undefined" — replace that with null instead and avoid stringifying missing
values; also verify the intended shape of reportingTo (whether it should be an
identifier like id/UUID/code or a full object) and adjust the payload to send
either data?.UserAssignment?.id (or equivalent identifier field) when an id is
expected, or data?.UserAssignment (the object) when an object is expected,
defaulting to null when the value is absent.
mobileNumber: data?.SelectEmployeePhoneNumber?.startsWith(HRMS_CONSTANTS.INDIA_COUNTRY_CODE) | ||
? data?.SelectEmployeePhoneNumber?.substring(HRMS_CONSTANTS.INDIA_COUNTRY_CODE.length) | ||
: (data?.SelectEmployeePhoneNumber?.startsWith(HRMS_CONSTANTS.MOZ_COUNTRY_CODE) | ||
? data?.SelectEmployeePhoneNumber?.substring(HRMS_CONSTANTS.MOZ_COUNTRY_CODE.length) | ||
: data?.SelectEmployeePhoneNumber) || null, | ||
? data?.SelectEmployeePhoneNumber?.substring(HRMS_CONSTANTS.MOZ_COUNTRY_CODE.length) | ||
: data?.SelectEmployeePhoneNumber) || null, | ||
name: data?.SelectEmployeeName, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🧹 Nitpick (assertive)
Normalize phone consistently; collapse country-code logic.
The nested ternary is hard to read and misses whitespace/delimiter cases. Prefer a single normalizer to strip +91/+258 and non-digits.
Example:
const normalizeMobile = (v) => {
const s = String(v || "").replace(/\D+/g, ""); // keep digits
return s.startsWith("91") ? s.slice(2)
: s.startsWith("258") ? s.slice(3)
: s || null;
};
// usage
user: {
mobileNumber: normalizeMobile(data?.SelectEmployeePhoneNumber),
...
}
If you want a minimal inline change, we can replace the current ternary with a call to normalizeMobile at both create/update sites.
Also applies to: 147-152
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 4
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
health/micro-ui/web/micro-ui-internals/packages/modules/health-hrms/src/components/pageComponents/SearchUserToReport.js (1)
1-135
: Fix 'locallity' typo and import mismatch for AttendanceService
Replace all occurrences of "locallity" → "locality" in service signatures, callers and object keys. Affected files found:
- health/micro-ui/web/micro-ui-internals/packages/modules/health-hrms/src/services/hrms/SearchUser.js (searchIndividual param & usage)
- health/micro-ui/web/micro-ui-internals/packages/modules/health-payments/src/services/attendance/attendanceService.js (searchIndividual param & "code": locallity)
- health/micro-ui/web/micro-ui-internals/packages/modules/health-hrms/src/components/pageComponents/SearchUserToReport.js (const locallity = …; AttendanceService.searchIndividual({ name, locallity, tenantId }))
- health/micro-ui/web/micro-ui-internals/packages/modules/health-payments/src/components/SearchUserPopUp.js (AttendanceService.searchIndividual({ name, locallity, tenantId }))
SearchUser.js exports AttendanceService as a named export (
export const AttendanceService = { ... }
). Update callers to use a named import:
- change
import AttendanceService from ".../SearchUser"
→import { AttendanceService } from ".../SearchUser"
in callers (e.g., SearchUserToReport.js, SearchUserPopUp.js).After making the changes, run build/tests to verify no runtime import or parameter-name regressions.
♻️ Duplicate comments (15)
health/micro-ui/web/micro-ui-internals/packages/modules/health-hrms/src/components/pageComponents/SearchUserToReport.js (11)
3-5
: Prune unused imports.
Timeline
,Loader
,useEffect
, anduseHistory
aren’t used.-import { PopUp, Timeline, Loader, TextInput, Button } from '@egovernments/digit-ui-components'; -import { useEffect } from "react"; -import { useHistory } from "react-router-dom"; +import { PopUp, TextInput, Button } from '@egovernments/digit-ui-components';
15-23
: Remove unused vars (history, context paths).These constants are never referenced.
- const history = useHistory(); - // context path variables - const attendanceContextPath = - window?.globalConfigs?.getConfig("ATTENDANCE_CONTEXT_PATH") || - "health-attendance"; - const individualContextPath = - window?.globalConfigs?.getConfig("INDIVIDUAL_CONTEXT_PATH") || - "health-individual"; + // (removed unused history and context-path vars)
41-48
: Do not call undefinedsetShowToast
; early-return instead. Also fix “locality” spelling.Prevents a runtime error and aligns naming.
- const locallity = Digit.SessionStorage.get("selectedBoundary")?.code || null; - - if (locallity === null) { - setShowToast( - { key: "error", label: t(`Locality is not selected`), transitionTime: 3000 } - ); - return; - } + const locality = boundaryCode || Digit.SessionStorage.get("selectedBoundary")?.code || null; + if (!locality) return;
81-84
: Useid
, notuserUuid
, in submit payload.Downstream expects
value.id
.- onSubmit({ - id: selectedUser?.userUuid, - name: selectedUser?.name?.givenName - }) + onSubmit({ + id: selectedUser?.id, + name: selectedUser?.name?.givenName + })
94-120
: Render children as JSX, not viachildren
prop.Complies with Biome rule and React convention.
- <PopUp - style={{ width: "500px" }} - onClose={onClose} - heading={t("HCM_AM_SEARCH_USER")} - onOverlayClick={onClose} - children={[ - ( - <div style={{ - display: "flex", - flexDirection: "column", - gap: "16px", // same as Tailwind gap-4 - }} > - <TextInput type="search" name="title" placeholder={t("HCM_AM_VIEW_REGISTER_PLACE_HOLDER")} value={searchQuery} onChange={(e) => setSearchQuery(e.target.value)} onKeyPress={(e) => { - if (e.key === "Enter") { - e.preventDefault(); // prevent form submit if inside a form - searchUser(searchQuery); // call your API - } - }} /> - - {searchedIndividual.length > 0 && <SelectableList selectableList={searchedIndividual} onSelect={onSelect} />} - - </div> - ) - ]} - footerChildren={[ + <PopUp + style={{ width: "500px" }} + onClose={onClose} + heading={t("HCM_AM_SEARCH_USER")} + onOverlayClick={onClose} + > + <div style={{ display: "flex", flexDirection: "column", gap: "16px" }}> + <TextInput + type="search" + name="title" + placeholder={t("HCM_AM_VIEW_REGISTER_PLACE_HOLDER")} + value={searchQuery} + onChange={(e) => setSearchQuery(e.target.value)} + onKeyDown={(e) => { + if (e.key === "Enter") { + e.preventDefault(); + searchUser(searchQuery); + } + }} + /> + {searchedIndividual.length > 0 && ( + <SelectableList selectableList={searchedIndividual} onSelect={onSelect} /> + )} + </div> + </PopUp> + {/* Footer remains below */} + <PopUp + style={{ display: "none" }} + footerChildren={[ <Button type={"button"} size={"large"} variation={"primary"} label={t("HCM_AM_ASSIGN_BT")} onClick={handleEnrollAttendee} />, ]} sortFooterChildren={true} - /> + />If the PopUp supports JSX children and a footer simultaneously (likely), prefer a single PopUp element with both children and
footerChildren
instead of the placeholder second PopUp wrapper above.
106-111
: UseonKeyDown
instead of deprecatedonKeyPress
.- <TextInput ... onKeyPress={(e) => { + <TextInput ... onKeyDown={(e) => { if (e.key === "Enter") { e.preventDefault(); searchUser(searchQuery); } }} />
121-127
: Disable submit when no selection.Prevents accidental empty submits; keep guard in handler too.
<Button type={"button"} size={"large"} variation={"primary"} label={t("HCM_AM_ASSIGN_BT")} - onClick={handleEnrollAttendee} + onClick={handleEnrollAttendee} + isDisabled={!selectedUser} />,
27-30
: Remove unused label computations.
labels
,maxLabelLength
, andlabelWidth
are not used.- const labels = ["HCM_AM_ATTENDANCE_NOT_FIND_USER_LABEL", "HCM_AM_ATTENDANCE_USER_ASSIGN_REGISTER"]; - const maxLabelLength = Math.max(...labels.map(label => label.length)); - const labelWidth = `${maxLabelLength * 8}px`; + // (removed unused label computations)
77-90
: Defensively no-op when nothing is selected.Avoid submitting an empty payload.
const handleEnrollAttendee = async () => { - - // userUuid - - onSubmit({ - id: selectedUser?.userUuid, - name: selectedUser?.name?.givenName - }) - - onClose(); - return ; + if (!selectedUser) return; + onSubmit({ + id: selectedUser?.id, + name: selectedUser?.name?.givenName, + }); + onClose(); };
56-61
: Passlocality
(correctly spelled) to the service and trim query.Also guard against empty query.
- const result = await AttendanceService.searchIndividual( - { name, locallity, tenantId } - ); - - setSearchedIndividual(result) + const q = (name || "").trim(); + if (!q) return; + const result = await AttendanceService.searchIndividual({ name: q, locality, tenantId }); + setSearchedIndividual(Array.isArray(result) ? result : []);Follow-up: Update the service signature and usage to
locality
(notlocallity
) in:
- health-hrms/src/services/hrms/SearchUser.js →
searchIndividual({ name, locality, tenantId })
and the body"code": locality
.
If other call sites use the misspelling, update them too.
37-68
: Small UX hardening insearchUser
: trim query, prefer prop over session, consistent naming.Consolidated improvements without changing behavior.
- const searchUser = async (name) => { + const searchUser = async (name) => { try { - const locallity = Digit.SessionStorage.get("selectedBoundary")?.code || null; - if (locallity === null) { /* toast removed */ return; } + const locality = boundaryCode || Digit.SessionStorage.get("selectedBoundary")?.code || null; + if (!locality) return; - const result = await AttendanceService.searchIndividual( - { name, locallity, tenantId } - ); - setSearchedIndividual(result) + const q = (name || "").trim(); + if (!q) return; + const result = await AttendanceService.searchIndividual({ name: q, locality, tenantId }); + setSearchedIndividual(Array.isArray(result) ? result : []); } catch (error) { - /* swallow */ + // optional: Digit.UserService?.notify? or log } }health/micro-ui/web/micro-ui-internals/packages/modules/health-hrms/src/components/config/createEmployeeConfig.js (1)
294-305
: Remove leftover “testing” placeholder and commented block.This dead code adds noise and risks drift with the injected approach in CreateEmployee. Keep a single source of truth.
- // // INFO:: testing - - // { - // type: "component", - // isMandatory: true, - // component: "UserAssignment", - // key: "UserAssignment", - // withoutLabel: true, - // populators: { - // name: "UserAssignment", - // }, - // },health/micro-ui/web/micro-ui-internals/packages/modules/health-hrms/src/pages/employee/createEmployee.js (3)
331-339
: Verify component registration and filename spelling.Ensure the module registers
UserAssignment
and that the file is namedUserAssignment.js
(notUserAssigment.js
) everywhere.#!/bin/bash # Check registration and spelling rg -nP '(componentsToRegister|ComponentRegistryService).*UserAssignment|component:\s*"UserAssignment"' fd -t f -a 'UserAssigment.js' 2>/dev/null || true
75-77
: Removedebugger
.Breaks CI lint and can pause prod.
- debugger +
149-162
: Don’t traverse config on each change; memoize the phone field config.Precompute once and use it here to avoid null risks and repeated work.
- // Validate mobile number - const contactFieldConfig = updatedConfig?.form?.flatMap(section => section?.body || []) - .find(field => field?.populators?.name === "SelectEmployeePhoneNumber"); - - if (EmployeeContactNumber && !validatePhoneNumber(EmployeeContactNumber, contactFieldConfig)) { + // Validate mobile number + if (EmployeeContactNumber && contactFieldConfig && !validatePhoneNumber(EmployeeContactNumber, contactFieldConfig)) { if (!formState.errors.SelectEmployeePhoneNumber) { setError("SelectEmployeePhoneNumber", { type: "custom", message: t("CORE_COMMON_APPLICANT_MOBILE_NUMBER_INVALID") },); } } else if (formState.errors.SelectEmployeePhoneNumber) { clearErrors("SelectEmployeePhoneNumber"); }Add this near the updatedConfig declaration (outside the selected range):
const contactFieldConfig = useMemo( () => updatedConfig?.form ?.flatMap((s) => s?.body || []) ?.find((f) => f?.populators?.name === "SelectEmployeePhoneNumber"), [updatedConfig] );
📜 Review details
Configuration used: CodeRabbit UI
Review profile: ASSERTIVE
Plan: Pro
📒 Files selected for processing (3)
health/micro-ui/web/micro-ui-internals/packages/modules/health-hrms/src/components/config/createEmployeeConfig.js
(2 hunks)health/micro-ui/web/micro-ui-internals/packages/modules/health-hrms/src/components/pageComponents/SearchUserToReport.js
(1 hunks)health/micro-ui/web/micro-ui-internals/packages/modules/health-hrms/src/pages/employee/createEmployee.js
(6 hunks)
🧰 Additional context used
📓 Path-based instructions (1)
**/*.js
⚙️ CodeRabbit configuration file
check
Files:
health/micro-ui/web/micro-ui-internals/packages/modules/health-hrms/src/components/config/createEmployeeConfig.js
health/micro-ui/web/micro-ui-internals/packages/modules/health-hrms/src/components/pageComponents/SearchUserToReport.js
health/micro-ui/web/micro-ui-internals/packages/modules/health-hrms/src/pages/employee/createEmployee.js
🧠 Learnings (7)
📚 Learning: 2024-11-07T11:02:33.520Z
Learnt from: rachana-egov
PR: egovernments/DIGIT-Frontend#1770
File: health/micro-ui/web/micro-ui-internals/packages/modules/microplan/src/pages/employee/viewVillage.js:320-322
Timestamp: 2024-11-07T11:02:33.520Z
Learning: In `health/micro-ui/web/micro-ui-internals/packages/modules/microplan/src/pages/employee/viewVillage.js`, the `data?.additionalFields` object is guaranteed to be defined, so checking for its existence before accessing its keys is unnecessary.
Applied to files:
health/micro-ui/web/micro-ui-internals/packages/modules/health-hrms/src/components/config/createEmployeeConfig.js
health/micro-ui/web/micro-ui-internals/packages/modules/health-hrms/src/pages/employee/createEmployee.js
📚 Learning: 2024-06-10T19:25:42.992Z
Learnt from: siddhant-nawale-egov
PR: egovernments/DIGIT-Frontend#698
File: micro-ui/web/micro-ui-internals/packages/modules/hcm-microplanning/src/components/MicroplanPreview.js:1-1
Timestamp: 2024-06-10T19:25:42.992Z
Learning: The imports in `MicroplanPreview.js` are from different libraries: `egovernments/digit-ui-components` and `egovernments/digit-ui-react-components`.
Applied to files:
health/micro-ui/web/micro-ui-internals/packages/modules/health-hrms/src/components/pageComponents/SearchUserToReport.js
📚 Learning: 2025-01-02T04:41:15.957Z
Learnt from: jagankumar-egov
PR: egovernments/DIGIT-Frontend#2089
File: micro-ui/web/micro-ui-internals/packages/modules/workbench/src/pages/employee/MDMSAddV2.js:111-111
Timestamp: 2025-01-02T04:41:15.957Z
Learning: In micro-ui/web/micro-ui-internals/packages/modules/workbench/src/pages/employee/MDMSAddV2.js, always use "mdms[0].uniqueIdentifier" for the jsonPath instead of differentiating between "SOR" and other masters.
Applied to files:
health/micro-ui/web/micro-ui-internals/packages/modules/health-hrms/src/components/pageComponents/SearchUserToReport.js
📚 Learning: 2024-10-17T12:00:51.749Z
Learnt from: Ramkrishna-egov
PR: egovernments/DIGIT-Frontend#1545
File: health/micro-ui/web/micro-ui-internals/packages/modules/microplan/src/components/ActivityCard.js:30-35
Timestamp: 2024-10-17T12:00:51.749Z
Learning: In our codebase, the 'Card' component is commonly used by passing children via the 'children' prop.
Applied to files:
health/micro-ui/web/micro-ui-internals/packages/modules/health-hrms/src/components/pageComponents/SearchUserToReport.js
📚 Learning: 2024-06-10T19:25:42.992Z
Learnt from: siddhant-nawale-egov
PR: egovernments/DIGIT-Frontend#698
File: micro-ui/web/micro-ui-internals/packages/modules/hcm-microplanning/src/components/resourceMapping.js:74-74
Timestamp: 2024-06-10T19:25:42.992Z
Learning: `onKeyPress` is deprecated and should be replaced with `onKeyDown` or `onKeyUp` for handling keyboard interactions.
Applied to files:
health/micro-ui/web/micro-ui-internals/packages/modules/health-hrms/src/components/pageComponents/SearchUserToReport.js
📚 Learning: 2025-06-04T04:08:48.234Z
Learnt from: jagankumar-egov
PR: egovernments/DIGIT-Frontend#2488
File: micro-ui/web/micro-ui-internals/packages/modules/core/src/pages/employee/Login/login.js:152-152
Timestamp: 2025-06-04T04:08:48.234Z
Learning: In the employee login component (micro-ui/web/micro-ui-internals/packages/modules/core/src/pages/employee/Login/login.js), prefer using a `defaultTenant` variable to store `Digit.ULBService.getStateId()` instead of calling the function multiple times inline in the `defaultValue` object. This improves code readability and avoids function call duplication.
Applied to files:
health/micro-ui/web/micro-ui-internals/packages/modules/health-hrms/src/pages/employee/createEmployee.js
📚 Learning: 2025-02-05T10:01:29.668Z
Learnt from: Tulika-eGov
PR: egovernments/DIGIT-Frontend#2188
File: micro-ui/web/micro-ui-internals/packages/modules/core/src/pages/employee/Login/login.js:72-78
Timestamp: 2025-02-05T10:01:29.668Z
Learning: In the employee login form, defaultValues are dynamically generated from config[0].body based on populators.defaultValue, so spreading the entire defaultValues object is required rather than cherry-picking specific fields.
Applied to files:
health/micro-ui/web/micro-ui-internals/packages/modules/health-hrms/src/pages/employee/createEmployee.js
🧬 Code graph analysis (2)
health/micro-ui/web/micro-ui-internals/packages/modules/health-hrms/src/components/pageComponents/SearchUserToReport.js (2)
health/micro-ui/web/micro-ui-internals/packages/modules/health-hrms/src/services/hrms/SearchUser.js (3)
result
(79-100)AttendanceService
(4-108)AttendanceService
(4-108)health/micro-ui/web/micro-ui-internals/packages/modules/health-hrms/src/components/pageComponents/SelectableList.js (1)
SelectableList
(3-37)
health/micro-ui/web/micro-ui-internals/packages/modules/health-hrms/src/pages/employee/createEmployee.js (2)
health/micro-ui/web/micro-ui-internals/packages/modules/pgr/src/pages/employee/CreateComplaint/createComplaintForm.js (1)
validatePhoneNumber
(53-66)health/micro-ui/web/micro-ui-internals/packages/modules/health-hrms/src/components/config/createEmployeeConfig.js (2)
CreateEmployeeConfig
(6-322)CreateEmployeeConfig
(6-322)
🪛 Biome (2.1.2)
health/micro-ui/web/micro-ui-internals/packages/modules/health-hrms/src/components/pageComponents/SearchUserToReport.js
[error] 99-99: Avoid passing children using a prop
The canonical way to pass children in React is to use JSX elements
(lint/correctness/noChildrenProp)
health/micro-ui/web/micro-ui-internals/packages/modules/health-hrms/src/pages/employee/createEmployee.js
[error] 76-76: This is an unexpected use of the debugger statement.
Unsafe fix: Remove debugger statement
(lint/suspicious/noDebugger)
🔇 Additional comments (4)
health/micro-ui/web/micro-ui-internals/packages/modules/health-hrms/src/components/pageComponents/SearchUserToReport.js (1)
70-74
: Selection wiring looks fine.Parent receives the selected user object from
SelectableList
.health/micro-ui/web/micro-ui-internals/packages/modules/health-hrms/src/pages/employee/createEmployee.js (3)
322-324
: Delete commented-out assignments.
[ suggest_nitpick ]- //const fConfig = CreateEmployeeConfig?.CreateEmployeeConfig?.[0]; - //const fConfig = mdmsData ? mdmsData : CreateEmployeeConfig?.CreateEmployeeConfig?.[0]; -
372-378
: LGTM: dynamic max-date wiring.Sets DOB and appointment max dates via preProcess; aligns with config.
386-393
: Confirm edit-mode field removals.You filter out password fields and Jurisdictions in edit flows. Validate this matches UX rules and that UserAssignment remains visible when editing.
import { PopUp, Timeline, Loader, TextInput, Button } from '@egovernments/digit-ui-components'; | ||
import { useEffect } from "react"; | ||
import { useHistory } from "react-router-dom"; | ||
import AttendanceService from "../../services/hrms/SearchUser"; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fix incorrect import of AttendanceService (named export, not default).
SearchUser.js
exports AttendanceService
as a named export. Importing it as default will be undefined
at runtime.
-import AttendanceService from "../../services/hrms/SearchUser";
+import { AttendanceService } from "../../services/hrms/SearchUser";
📝 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.
import AttendanceService from "../../services/hrms/SearchUser"; | |
import { AttendanceService } from "../../services/hrms/SearchUser"; |
🤖 Prompt for AI Agents
In
health/micro-ui/web/micro-ui-internals/packages/modules/health-hrms/src/components/pageComponents/SearchUserToReport.js
around line 6, the file incorrectly imports AttendanceService as a default
export; since SearchUser.js exports AttendanceService as a named export the
import will be undefined at runtime — change the import to a named import (e.g.
import { AttendanceService } from "../../services/hrms/SearchUser";), keeping
the same path and ensuring any usages match the named binding.
if (/^\d+$/.test(name)) { | ||
console.log("it is nummeric"); | ||
} else { | ||
console.log("it is not nummeric"); | ||
} | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🧹 Nitpick (assertive)
Drop console noise.
Remove debug logs (“nummeric” typo) to keep console clean.
- if (/^\d+$/.test(name)) {
- console.log("it is nummeric");
- } else {
- console.log("it is not nummeric");
- }
+ // optional: handle numeric-only input if required by UX
📝 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.
if (/^\d+$/.test(name)) { | |
console.log("it is nummeric"); | |
} else { | |
console.log("it is not nummeric"); | |
} | |
// optional: handle numeric-only input if required by UX |
🤖 Prompt for AI Agents
In
health/micro-ui/web/micro-ui-internals/packages/modules/health-hrms/src/components/pageComponents/SearchUserToReport.js
around lines 50 to 55, remove the two console.log debug statements (which also
contain a typo "nummeric") to eliminate console noise; if logging is required
use the app's logger at an appropriate log level or return a boolean/result from
the function instead, and ensure any user-facing behavior relies on that return
value rather than console output.
const { data: mdmsData, isLoading: isHRMSConfigLoading } = Digit.Hooks.useCommonMDMS(Digit.ULBService.getStateId(), "egov-hrms", ["CreateEmployeeConfig"], { | ||
select: (data) => { | ||
return data?.["egov-hrms"]?.CreateEmployeeConfig?.[0]; | ||
}, | ||
retry: false, | ||
enable: false, | ||
}); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
💡 Verification agent
🧩 Analysis chain
Fix react-query option name: use enabled
, not enable
.
enable
is ignored; the query behavior becomes implicit. Use enabled
and set the intended value (likely true
since MDMS-driven config is being used).
- const { data: mdmsData, isLoading: isHRMSConfigLoading } = Digit.Hooks.useCommonMDMS(Digit.ULBService.getStateId(), "egov-hrms", ["CreateEmployeeConfig"], {
- select: (data) => {
- return data?.["egov-hrms"]?.CreateEmployeeConfig?.[0];
- },
- retry: false,
- enable: false,
- });
+ const { data: mdmsData, isLoading: isHRMSConfigLoading } = Digit.Hooks.useCommonMDMS(
+ Digit.ULBService.getStateId(),
+ "egov-hrms",
+ ["CreateEmployeeConfig"],
+ {
+ select: (data) => data?.["egov-hrms"]?.CreateEmployeeConfig?.[0],
+ retry: false,
+ enabled: true,
+ }
+ );
🏁 Script executed:
#!/bin/bash
# Verify convention across repo (should be `enabled`, not `enable`)
rg -nP 'useCommonMDMS\([^)]*\{\s*[^}]*enab\w*\s*:' -C2
Length of output: 0
🏁 Script executed:
#!/bin/bash
set -euo pipefail
printf "PWD: %s\n\n" "$(pwd)"
printf "Top-level files/directories:\n"
ls -la | sed -n '1,200p' || true
echo -e "\nSearching for files named createEmployee.js..."
rg -n --hidden -S "createEmployee\.js" -g '!**/node_modules/**' -C3 || true
echo -e "\nSearching for occurrences of 'useCommonMDMS'..."
rg -n --hidden -S "useCommonMDMS" -g '!**/node_modules/**' -C3 || true
echo -e "\nSearching for occurrences of 'Digit.Hooks.useCommonMDMS'..."
rg -n --hidden -S "Digit\.Hooks\.useCommonMDMS" -g '!**/node_modules/**' -C3 || true
echo -e "\nSearching repo-wide for 'enable:' in JS/TS files (excluding node_modules)..."
rg -n --hidden -S "\benable\s*:" -g '!**/node_modules/**' -t js -t ts -t jsx -t tsx -C2 || true
echo -e "\nSearching repo-wide for 'enabled:' in JS/TS files (excluding node_modules)..."
rg -n --hidden -S "\benabled\s*:" -g '!**/node_modules/**' -t js -t ts -t jsx -t tsx -C2 || true
TARGET="health/micro-ui/web/micro-ui-internals/packages/modules/health-hrms/src/pages/employee/createEmployee.js"
echo -e "\nChecking specific target file: $TARGET"
if [ -f "$TARGET" ]; then
echo "---- File content (first 240 lines) ----"
sed -n '1,240p' "$TARGET"
else
echo "Target file not found: $TARGET"
fi
Length of output: 10170
Use react-query's enabled
option (not enable
)
In health/micro-ui/web/micro-ui-internals/packages/modules/health-hrms/src/pages/employee/createEmployee.js (lines 50-56) replace enable: false
with enabled: true
— enable
is ignored by react-query.
🤖 Prompt for AI Agents
In
health/micro-ui/web/micro-ui-internals/packages/modules/health-hrms/src/pages/employee/createEmployee.js
around lines 50 to 56, the react-query option is misspelled as `enable: false`
(which is ignored); replace it with `enabled: true` so the hook actually runs
and returns data. Ensure you only change the option key from `enable` to
`enabled` and set it to `true`.
// Original config assignment | ||
const fConfig = mdmsData ? mdmsData : CreateEmployeeConfig?.CreateEmployeeConfig?.[0]; | ||
|
||
// Define your new component to be injected | ||
const userAssignmentComponent = { | ||
type: "component", | ||
isMandatory: true, | ||
component: "UserAssignment", | ||
key: "UserAssignment", | ||
withoutLabel: true, | ||
populators: { | ||
name: "UserAssignment", | ||
}, | ||
}; | ||
|
||
// Find the section where you want to insert (HR_NEW_EMPLOYEE_FORM_HEADER) | ||
const newEmployeeFormSection = fConfig?.form?.find( | ||
(section) => section.head === "HR_NEW_EMPLOYEE_FORM_HEADER" | ||
); | ||
|
||
if (newEmployeeFormSection) { | ||
const body = newEmployeeFormSection.body; | ||
|
||
// Check if UserAssignment already exists | ||
const alreadyExists = body.some((field) => field.key === "UserAssignment"); | ||
|
||
if (!alreadyExists) { | ||
// Find index of RolesAssigned field | ||
const index = body.findIndex((field) => field.key === "RolesAssigned"); | ||
|
||
if (index !== -1) { | ||
// Insert UserAssignment right after RolesAssigned | ||
body.splice(index + 1, 0, userAssignmentComponent); | ||
} | ||
} | ||
} | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion
Avoid mutating imported/MDMS config; clone and inject deterministically.
Current splice mutates fConfig
(which may be shared). Clone and compute via useMemo
for stability and idempotency.
-// Original config assignment
-const fConfig = mdmsData ? mdmsData : CreateEmployeeConfig?.CreateEmployeeConfig?.[0];
+// Base config (MDMS overrides static)
+const baseConfig = mdmsData ?? CreateEmployeeConfig?.CreateEmployeeConfig?.[0];
// Define your new component to be injected
const userAssignmentComponent = {
type: "component",
isMandatory: true,
component: "UserAssignment",
key: "UserAssignment",
withoutLabel: true,
populators: {
name: "UserAssignment",
},
};
-// Find the section where you want to insert (HR_NEW_EMPLOYEE_FORM_HEADER)
-const newEmployeeFormSection = fConfig?.form?.find(
- (section) => section.head === "HR_NEW_EMPLOYEE_FORM_HEADER"
-);
-
-if (newEmployeeFormSection) {
- const body = newEmployeeFormSection.body;
-
- // Check if UserAssignment already exists
- const alreadyExists = body.some((field) => field.key === "UserAssignment");
-
- if (!alreadyExists) {
- // Find index of RolesAssigned field
- const index = body.findIndex((field) => field.key === "RolesAssigned");
-
- if (index !== -1) {
- // Insert UserAssignment right after RolesAssigned
- body.splice(index + 1, 0, userAssignmentComponent);
- }
- }
-}
+// Compute fConfig without side effects
+const fConfig = useMemo(() => {
+ if (!baseConfig) return baseConfig;
+ const cfg = typeof structuredClone === "function"
+ ? structuredClone(baseConfig)
+ : JSON.parse(JSON.stringify(baseConfig));
+ const section = cfg?.form?.find((s) => s.head === "HR_NEW_EMPLOYEE_FORM_HEADER");
+ if (!section || !Array.isArray(section.body)) return cfg;
+ const alreadyExists = section.body.some((f) => f?.key === "UserAssignment");
+ if (!alreadyExists) {
+ const index = section.body.findIndex((f) => f?.key === "RolesAssigned");
+ if (index !== -1) section.body.splice(index + 1, 0, userAssignmentComponent);
+ }
+ return cfg;
+}, [baseConfig]);
📝 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.
// Original config assignment | |
const fConfig = mdmsData ? mdmsData : CreateEmployeeConfig?.CreateEmployeeConfig?.[0]; | |
// Define your new component to be injected | |
const userAssignmentComponent = { | |
type: "component", | |
isMandatory: true, | |
component: "UserAssignment", | |
key: "UserAssignment", | |
withoutLabel: true, | |
populators: { | |
name: "UserAssignment", | |
}, | |
}; | |
// Find the section where you want to insert (HR_NEW_EMPLOYEE_FORM_HEADER) | |
const newEmployeeFormSection = fConfig?.form?.find( | |
(section) => section.head === "HR_NEW_EMPLOYEE_FORM_HEADER" | |
); | |
if (newEmployeeFormSection) { | |
const body = newEmployeeFormSection.body; | |
// Check if UserAssignment already exists | |
const alreadyExists = body.some((field) => field.key === "UserAssignment"); | |
if (!alreadyExists) { | |
// Find index of RolesAssigned field | |
const index = body.findIndex((field) => field.key === "RolesAssigned"); | |
if (index !== -1) { | |
// Insert UserAssignment right after RolesAssigned | |
body.splice(index + 1, 0, userAssignmentComponent); | |
} | |
} | |
} | |
// Base config (MDMS overrides static) | |
const baseConfig = mdmsData ?? CreateEmployeeConfig?.CreateEmployeeConfig?.[0]; | |
// Define your new component to be injected | |
const userAssignmentComponent = { | |
type: "component", | |
isMandatory: true, | |
component: "UserAssignment", | |
key: "UserAssignment", | |
withoutLabel: true, | |
populators: { | |
name: "UserAssignment", | |
}, | |
}; | |
// Compute fConfig without side effects | |
const fConfig = useMemo(() => { | |
if (!baseConfig) return baseConfig; | |
const cfg = typeof structuredClone === "function" | |
? structuredClone(baseConfig) | |
: JSON.parse(JSON.stringify(baseConfig)); | |
const section = cfg?.form?.find((s) => s.head === "HR_NEW_EMPLOYEE_FORM_HEADER"); | |
if (!section || !Array.isArray(section.body)) return cfg; | |
const alreadyExists = section.body.some((f) => f?.key === "UserAssignment"); | |
if (!alreadyExists) { | |
const index = section.body.findIndex((f) => f?.key === "RolesAssigned"); | |
if (index !== -1) section.body.splice(index + 1, 0, userAssignmentComponent); | |
} | |
return cfg; | |
}, [baseConfig]); |
🤖 Prompt for AI Agents
In
health/micro-ui/web/micro-ui-internals/packages/modules/health-hrms/src/pages/employee/createEmployee.js
around lines 326-362, the code mutates the imported/MDMS config via splice which
can affect shared references; instead create an immutable cloned config (deep
clone the relevant fConfig object or its form array), perform the injection on
the clone, and memoize the result with useMemo so the operation is deterministic
and idempotent; ensure the code checks for existing UserAssignment before
inserting, inserts into the cloned body at the computed index, and then use the
cloned/memoized config for rendering so the original MDMS data is never
modified.
There was a problem hiding this 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
♻️ Duplicate comments (24)
health/micro-ui/web/micro-ui-internals/packages/modules/health-payments/src/components/EditAttendanceManagementTable.js (8)
10-10
: Remove unused import.The
AttendeeService
import is not being used anywhere in this component. The component uses the hookuseDeleteAttendeeFromRegister
instead.-import AttendeeService from "../services/attendance/attendee_service/attendeeService"; -
2-2
: Remove unused imports and variables.The
history
variable anduseHistory
import are not used in this component. Additionally,url
fromDigit.Hooks.useQueryParams()
is also unused.-import { useHistory } from "react-router-dom";
const { t } = useTranslation(); -const history = useHistory(); -const url = Digit.Hooks.useQueryParams();Also applies to: 34-35
41-41
: Remove unused state variable.The
toast
state variable is declared but never used. The component usesshowToast
instead.-const [toast, setToast] = useState({ show: false, label: "", type: "" }); -
121-152
: Clean up commented code.This large block of commented code should be removed to improve code readability. If this functionality is needed in the future, it can be retrieved from version control.
- // { - // name: t("HCM_AM_ACTION"), - // selector: (row) => { - // return ( - // <div className="ellipsis-cell" title={t(row?.[5] || "0")}> - // {row?.[5] == false ? <Tag label={t("HCM_AM_VIEW_REGISTER_DISABLED_TAG")} type="error" stroke={false} /> : - // <Button - // className="custom-class" - // icon="Edit" - // iconFill="" - // label={t(`HCM_AM_VIEW_REGISTER_DISABLE_USER`)} - // onClick={() => { - // setSelectedRowId(row?.[0]); - // setOpenAlertPopUp(true); - // // handleDaysWorkedChange(row?.[0]) - // }} - // options={[]} - // optionsKey="" - // size="" - // style={{}} - // title={t(`HCM_AM_VIEW_REGISTER_DISABLE_USER`)} - // variation="secondary" - // /> - // } - // </div> - // ); - // }, - // style: { - // justifyContent: "flex-end", - // }, - // },
161-161
: Use strict equality for boolean comparison.Use strict equality (
===
) instead of loose equality (==
) when comparing boolean values.- {row?.[5] == false ? <Tag label={t("HCM_AM_VIEW_REGISTER_DISABLED_TAG")} type="error" stroke={false} /> : + {row?.[5] === false ? <Tag label={t("HCM_AM_VIEW_REGISTER_DISABLED_TAG")} type="error" stroke={false} /> :
196-196
: Fix timestamp calculation logic.The denrollment date calculation seems incorrect. The current calculation
Date.now() - (1 * 60 * 1000 + 30 * 1000)
sets the date to 90 seconds ago, which doesn't seem meaningful for a denrollment date. Consider using the current time or a more appropriate business logic.- denrollmentDate: new Date(Date.now() - (1 * 60 * 1000 + 30 * 1000)).getTime(), + denrollmentDate: Date.now(),
201-212
: Remove console.log statements.Debug console.log statements should be removed before merging to production code.
onError: async (error) => { - - console.log("hello", error) setShowToast(onSuccess: async (responseData) => { - - console.log("responseData", responseData); - setShowToast({ key: "success", label: t(`HCM_AM_ATTENDEE_DE_ENROLL_SUCCESS_MESSAGE`), transitionTime: 3000 });
249-249
: Remove commented code.The commented
error
prop should be removed if it's not needed.type={showToast.key} - // error={showToast.key === "error"} transitionTime={showToast.transitionTime}
health/micro-ui/web/micro-ui-internals/packages/modules/health-payments/src/config/AttendeeInboxConfig.js (5)
132-133
: Remove hardcoded tenantId value.The tenantId is hardcoded to "dev" in both defaultValues and requestParam. This should be dynamically retrieved using
Digit.ULBService.getCurrentTenantId()
or passed as a parameter.defaultValues: { // Default search parameters codes: "", limit: 10, names: "", phone: "", roles: "", offset: 0, - tenantId: "dev", + tenantId: Digit.ULBService.getCurrentTenantId(), sortOrder: "DESC", },requestParam: { // Default request parameters for API call offset: 0, - tenantId: "dev", + tenantId: Digit.ULBService.getCurrentTenantId(), },Also applies to: 203-204
171-174
: Missing jsonPath for ASSIGNMENT column.The ASSIGNMENT column is defined without a
jsonPath
, which means it won't display any data. Either provide the correct jsonPath or remove this column if it's not needed.{ label: "HCM_ASSIGNMENT", - //jsonPath: "assignments[0]", + jsonPath: "assignments[0]", // or remove this column entirely additionalCustomization: true, },
175-179
: Remove commented code block.Clean up the commented code for the HR_EMPLOYMENT_DEPARTMENT_LABEL column.
- // { - // label: "HR_EMPLOYMENT_DEPARTMENT_LABEL", - // jsonPath: "assignments[0]", - // additionalCustomization: true, - // },
214-214
: Remove commented component declaration.The commented BoundaryComponent line should be removed.
}, - //component: BoundaryComponent, - persistFormData: true, // Keeps form data persisted between searches
121-123
: Use i18n key for primary button labelReplace hardcoded "Search" with the standard i18n key.
- primaryLabel: "Search", // Label for primary search button + primaryLabel: "ES_COMMON_SEARCH", // Label for primary search buttonhealth/micro-ui/web/micro-ui-internals/example/src/UICustomizations.js (6)
810-823
: Duplicate/overwritten fields in MicroplanSearchConfig.preProcess
name
is assigned twice;status
is first read from form and later overridden by tab filter. Simplify to avoid confusion.
1108-1218
: Remove redundant onClick prop in action button.The action button in MyMicroplanSearchConfig has both
onClick
(empty function) andonOptionSelect
handlers. The emptyonClick
prop is redundant and should be removed.isSearchable={false} title={t("MP_ACTIONS_FOR_MICROPLANS")} label={t("MP_ACTIONS_FOR_MICROPLANS")} isDisabled={!EstimationsfileId} - onClick={() => { }} variation="primary" onOptionSelect={(option) => onOptionSelect(option)}
2614-2709
: AttendeeSearchInboxConfig: Remove console logs and make boundary code handling defensive.Remove
console.log
statements and add defensive checks for boundaryCode operations.- console.log(data) if (data.state.filterForm && Object.keys(data.state.filterForm).length > 0) {
- if (boundaryCode && boundaryCode.trim() !== "") { + if (typeof boundaryCode === "string" && boundaryCode.trim() !== "") { Individual.boundaryCode=boundaryCode }- console.log("payload", data) return data;
2223-2224
: Remove empty additionalCustomizations stubs.Multiple configs have empty
additionalCustomizations
functions that serve no purpose. Consider removing them to reduce bundle size.- additionalCustomizations: (row, key, column, value, searchResult) => { },
Also applies to: 2298-2299, 2374-2375, 2449-2450, 2524-2525, 2598-2599
839-967
: Invalid Hook usage inside cell renderer and switch case declarations leak scope.Hooks (
useState
,useDeleteAttendeeFromRegister
,usePlanSearchEmployeeWithTagging
) are called directly insideadditionalCustomizations
and withinswitch
cases. This violates React Hook rules. Additionally, the switch case declarations can leak into other cases as indicated by Biome.You need to refactor this in two ways:
- Extract the cell rendering logic into separate React components
- Wrap switch cases in block scopes to fix the noSwitchDeclarations lint errors
Here's how to fix the switch case scoping issue first:
switch (key) { - case "ACTIONS": + case "ACTIONS": { const dummyFile = "c22a7676-d5d7-49b6-bcdb-83e9519f58df" const microplanFileId = row?.campaignDetails?.additionalDetails?.microplanFileId || dummyFile; // ... rest of the code return ( /* JSX */ ); + } - case "NAME_OF_MICROPLAN": + case "NAME_OF_MICROPLAN": { // ... code return ( /* JSX */ ); + } // Apply same pattern for other cases }For the hooks issue, create a separate component outside the config:
function MicroplanActionsCell({ row, t }) { const [showToast, setShowToast] = useState(false); const tenantId = Digit.ULBService.getCurrentTenantId(); const microplanId = row?.id; const { data: rootEstimationApprover } = Digit.Hooks.microplanv1.usePlanSearchEmployeeWithTagging({ /* params */ }); const { data: rootPopulationApprover } = Digit.Hooks.microplanv1.usePlanSearchEmployeeWithTagging({ /* params */ }); const { data: rootFacilityMapper } = Digit.Hooks.microplanv1.usePlanSearchEmployeeWithTagging({ /* params */ }); // Move all the handler functions and logic here return ( // Return the JSX from the original case ); }Then in the config:
additionalCustomizations: (row, key, column, value, t, searchResult) => { switch (key) { - case "ACTIONS": - // Remove all hooks and logic - return ( /* complex JSX */ ); + case "ACTIONS": { + return <MicroplanActionsCell row={row} t={t} />; + } } }
2859-2868
: Fix noChildrenProp: Pass JSX children instead of children prop.The PopUp component is receiving children as a prop instead of as JSX children, which violates React best practices.
- openPopUp && <PopUp - style={{ minWidth: "500px" }} - onClose={() => { /* ... */ }} - heading={t("Action Needed: Tag Code")} - onOverlayClick={() => { /* ... */ }} - children={[ - !isTag ? - <div>Do you want to fill in the Tag Code? If yes, press Enter Tag. Otherwise, Assign it.</div> - : <div> - <span>Tag Code</span> - <TextInput type="text" name="title" placeholder={t("Enter Tag Name")} value={tag} onChange={(e) => setTag(e.target.value)} /> - </div> - ]} + openPopUp && ( + <PopUp + style={{ minWidth: "500px" }} + onClose={() => { /* ... */ }} + heading={t("Action Needed: Tag Code")} + onOverlayClick={() => { /* ... */ }}> + {!isTag ? ( + <div>Do you want to fill in the Tag Code? If yes, press Enter Tag. Otherwise, Assign it.</div> + ) : ( + <div> + <span>Tag Code</span> + <TextInput type="text" name="title" placeholder={t("Enter Tag Name")} value={tag} onChange={(e) => setTag(e.target.value)} /> + </div> + )} + </PopUp> + )health/micro-ui/web/micro-ui-internals/packages/modules/health-payments/src/components/editAttendeesPopUp.js (5)
1-10
: Remove unused imports to reduce bundle sizeThe following imports are not used in the component and should be removed:
Timeline
from line 3AttendeeService
from line 7useAttendanceSummary
from line 9-import { PopUp, Timeline, Loader, TextInput, Button } from '@egovernments/digit-ui-components'; +import { PopUp, Loader, TextInput, Button } from '@egovernments/digit-ui-components';-import AttendeeService from "../services/attendance/attendee_service/attendeeService"; - -import { useAttendanceSummary } from "../utils/update_attendance_summary";
59-66
: Add defensive checks to prevent runtime errors when attendees data is missingThe current implementation assumes
attendanceRegister[0].attendees
always exists, which could cause runtime errors if the API returns empty or malformed data.useEffect(() => { - if (AttendanceData?.attendanceRegister?.length > 0) { - const ids = AttendanceData.attendanceRegister[0].attendees.map( - (a) => a.individualId - ); - setIndividualIds(ids); - } + const attendees = AttendanceData?.attendanceRegister?.[0]?.attendees ?? []; + setIndividualIds( + Array.isArray(attendees) + ? attendees.map(a => a?.individualId).filter(Boolean) + : [] + ); }, [AttendanceData]);
183-227
: Fix PopUp children prop usage and swapped registerId/registerNumber propsMultiple issues in the PopUp component usage:
- Children should be passed as JSX elements, not via the
children
prop (Biome warning)- The
registerId
andregisterNumber
props passed toEditAttendanceManagementTable
appear to be swapped based on the prop names<PopUp style={{ minWidth: "1000px" }} onClose={onClose} heading={t(heading)} onOverlayClick={onClose} - children={[ - isAttendanceLoading || isAllIndividualsLoading ? ( + footerChildren={[ + <Button + type={"button"} + size={"large"} + variation={"primary"} + label={t("HCM_AM_SAVE_AND_CLOSE")} + onClick={onClose} + />, + ]} + sortFooterChildren={true} +> + {isAttendanceLoading || isAllIndividualsLoading ? ( <Loader /> ) : ( <div style={{ display: "flex", flexDirection: "column", gap: "16px", }} > <TextInput type="search" name="title" placeholder={t("HCM_AM_VIEW_REGISTER_PLACE_HOLDER")} value={searchQuery} onChange={(e) => setSearchQuery(e.target.value)} /> <EditAttendanceManagementTable data={searchQuery != "" ? filteredData : attendanceSummary} setAttendanceSummary={setAttendanceSummary} disableUser={disableUser} - registerId={businessId} - registerNumber={registerId} + registerId={registerId} + registerNumber={businessId} editAction={true} /> <div style={{ display: "grid", gridTemplateColumns: `${labelWidth} auto`, rowGap: "10px", alignItems: "center" }}> <div>{t(labels[1])}</div> <Button label={t("HCM_AM_SEARCH_USER")} variation="link" onClick={() => { history.push(`/${window?.contextPath}/employee/payments/attendee-inbox?registerId=${registerId}&boundaryCode=${boundaryCode}`) }} /> </div> </div> - ) - ]} - footerChildren={[ - <Button - type={"button"} - size={"large"} - variation={"primary"} - label={t("HCM_AM_SAVE_AND_CLOSE")} - onClick={ onClose} - />, - ]} - sortFooterChildren={true} -/> + )} +</PopUp>
194-194
: Use strict inequality check for consistency-data={searchQuery != "" ? filteredData : attendanceSummary} +data={searchQuery !== "" ? filteredData : attendanceSummary}
94-123
: Add error handling for missing attendanceRegister dataThe
getUserAttendanceSummary
function assumesattendanceData.attendanceRegister[0]
exists without checking, which could cause a runtime error.function getUserAttendanceSummary(attendanceData, individualsData, t) { + if (!attendanceData?.attendanceRegister?.[0]?.attendees) { + return []; + } const attendanceLogData = attendanceData.attendanceRegister[0].attendees.map((individualEntry) => {
📜 Review details
Configuration used: CodeRabbit UI
Review profile: ASSERTIVE
Plan: Pro
📒 Files selected for processing (4)
health/micro-ui/web/micro-ui-internals/example/src/UICustomizations.js
(24 hunks)health/micro-ui/web/micro-ui-internals/packages/modules/health-payments/src/components/EditAttendanceManagementTable.js
(1 hunks)health/micro-ui/web/micro-ui-internals/packages/modules/health-payments/src/components/editAttendeesPopUp.js
(1 hunks)health/micro-ui/web/micro-ui-internals/packages/modules/health-payments/src/config/AttendeeInboxConfig.js
(1 hunks)
🧰 Additional context used
📓 Path-based instructions (1)
**/*.js
⚙️ CodeRabbit configuration file
check
Files:
health/micro-ui/web/micro-ui-internals/packages/modules/health-payments/src/config/AttendeeInboxConfig.js
health/micro-ui/web/micro-ui-internals/packages/modules/health-payments/src/components/EditAttendanceManagementTable.js
health/micro-ui/web/micro-ui-internals/packages/modules/health-payments/src/components/editAttendeesPopUp.js
health/micro-ui/web/micro-ui-internals/example/src/UICustomizations.js
🧠 Learnings (9)
📚 Learning: 2025-06-04T04:08:48.234Z
Learnt from: jagankumar-egov
PR: egovernments/DIGIT-Frontend#2488
File: micro-ui/web/micro-ui-internals/packages/modules/core/src/pages/employee/Login/login.js:152-152
Timestamp: 2025-06-04T04:08:48.234Z
Learning: In the employee login component (micro-ui/web/micro-ui-internals/packages/modules/core/src/pages/employee/Login/login.js), prefer using a `defaultTenant` variable to store `Digit.ULBService.getStateId()` instead of calling the function multiple times inline in the `defaultValue` object. This improves code readability and avoids function call duplication.
Applied to files:
health/micro-ui/web/micro-ui-internals/packages/modules/health-payments/src/config/AttendeeInboxConfig.js
📚 Learning: 2025-01-02T04:41:15.957Z
Learnt from: jagankumar-egov
PR: egovernments/DIGIT-Frontend#2089
File: micro-ui/web/micro-ui-internals/packages/modules/workbench/src/pages/employee/MDMSAddV2.js:111-111
Timestamp: 2025-01-02T04:41:15.957Z
Learning: In micro-ui/web/micro-ui-internals/packages/modules/workbench/src/pages/employee/MDMSAddV2.js, always use "mdms[0].uniqueIdentifier" for the jsonPath instead of differentiating between "SOR" and other masters.
Applied to files:
health/micro-ui/web/micro-ui-internals/packages/modules/health-payments/src/config/AttendeeInboxConfig.js
📚 Learning: 2024-11-07T11:02:33.520Z
Learnt from: rachana-egov
PR: egovernments/DIGIT-Frontend#1770
File: health/micro-ui/web/micro-ui-internals/packages/modules/microplan/src/pages/employee/viewVillage.js:320-322
Timestamp: 2024-11-07T11:02:33.520Z
Learning: In `health/micro-ui/web/micro-ui-internals/packages/modules/microplan/src/pages/employee/viewVillage.js`, the `data?.additionalFields` object is guaranteed to be defined, so checking for its existence before accessing its keys is unnecessary.
Applied to files:
health/micro-ui/web/micro-ui-internals/packages/modules/health-payments/src/config/AttendeeInboxConfig.js
health/micro-ui/web/micro-ui-internals/packages/modules/health-payments/src/components/EditAttendanceManagementTable.js
health/micro-ui/web/micro-ui-internals/example/src/UICustomizations.js
📚 Learning: 2025-07-15T04:58:30.634Z
Learnt from: Hari-egov
PR: egovernments/DIGIT-Frontend#2788
File: micro-ui/web/micro-ui-internals/packages/modules/hrms/src/components/pageComponents/jurisdiction.js:26-26
Timestamp: 2025-07-15T04:58:30.634Z
Learning: In the HRMS module (micro-ui/web/micro-ui-internals/packages/modules/hrms/src/components/pageComponents/jurisdiction.js), the team has moved away from using MDMS hooks for boundary data fetching and now uses direct API calls to the boundary service endpoint `/boundary-service/boundary-relationships/_search` instead of the `useHrmsMDMS` hook with "FetchBoundaries" parameter.
Applied to files:
health/micro-ui/web/micro-ui-internals/packages/modules/health-payments/src/config/AttendeeInboxConfig.js
📚 Learning: 2024-11-07T07:17:27.636Z
Learnt from: jagankumar-egov
PR: egovernments/DIGIT-Frontend#1763
File: health/micro-ui/web/micro-ui-internals/packages/modules/campaign-manager/src/pages/employee/MyCampaign.js:65-75
Timestamp: 2024-11-07T07:17:27.636Z
Learning: In `MyCampaign.js`, when suggesting code improvements for the `onClickRow` function, keep suggestions simple and avoid unnecessary complexity.
Applied to files:
health/micro-ui/web/micro-ui-internals/packages/modules/health-payments/src/components/EditAttendanceManagementTable.js
health/micro-ui/web/micro-ui-internals/example/src/UICustomizations.js
📚 Learning: 2024-10-26T15:11:49.938Z
Learnt from: nabeelmd-eGov
PR: egovernments/DIGIT-Frontend#1680
File: health/micro-ui/web/micro-ui-internals/example/src/UICustomizations.js:1032-1094
Timestamp: 2024-10-26T15:11:49.938Z
Learning: In the DIGIT-Frontend project, when reviewing the `UICustomizations.js` file, avoid suggesting refactoring of repetitive rendering logic in switch cases into helper functions, unless explicitly requested.
Applied to files:
health/micro-ui/web/micro-ui-internals/example/src/UICustomizations.js
📚 Learning: 2024-09-30T05:45:14.549Z
Learnt from: ashish-egov
PR: egovernments/DIGIT-Frontend#1441
File: health/micro-ui/web/micro-ui-internals/packages/modules/microplan/src/hooks/useGenerateIdCampaign.js:1-1
Timestamp: 2024-09-30T05:45:14.549Z
Learning: In the `useGenerateIdCampaign` function, auto assignment of default parameter values is needed in parameter destructuring.
Applied to files:
health/micro-ui/web/micro-ui-internals/example/src/UICustomizations.js
📚 Learning: 2024-10-17T12:00:51.749Z
Learnt from: Ramkrishna-egov
PR: egovernments/DIGIT-Frontend#1545
File: health/micro-ui/web/micro-ui-internals/packages/modules/microplan/src/components/ActivityCard.js:30-35
Timestamp: 2024-10-17T12:00:51.749Z
Learning: In our codebase, the 'Card' component is commonly used by passing children via the 'children' prop.
Applied to files:
health/micro-ui/web/micro-ui-internals/example/src/UICustomizations.js
📚 Learning: 2024-06-10T19:25:42.992Z
Learnt from: siddhant-nawale-egov
PR: egovernments/DIGIT-Frontend#698
File: micro-ui/web/micro-ui-internals/packages/modules/hcm-microplanning/src/components/MicroplanPreview.js:1-1
Timestamp: 2024-06-10T19:25:42.992Z
Learning: The imports in `MicroplanPreview.js` are from different libraries: `egovernments/digit-ui-components` and `egovernments/digit-ui-react-components`.
Applied to files:
health/micro-ui/web/micro-ui-internals/example/src/UICustomizations.js
🧬 Code graph analysis (3)
health/micro-ui/web/micro-ui-internals/packages/modules/health-payments/src/components/EditAttendanceManagementTable.js (3)
health/micro-ui/web/micro-ui-internals/packages/modules/health-payments/src/utils/constants.js (4)
defaultRowsPerPageForEditAttendee
(19-19)defaultRowsPerPageForEditAttendee
(19-19)defaultPaginationValuesForEditAttendee
(22-22)defaultPaginationValuesForEditAttendee
(22-22)health/micro-ui/web/micro-ui-internals/packages/modules/health-payments/src/components/table_inbox_custom_style.js (2)
editAttendeetableCustomStyle
(227-334)editAttendeetableCustomStyle
(227-334)health/micro-ui/web/micro-ui-internals/packages/modules/health-payments/src/components/alertPopUp.js (1)
AlertPopUp
(19-57)
health/micro-ui/web/micro-ui-internals/packages/modules/health-payments/src/components/editAttendeesPopUp.js (3)
health/micro-ui/web/micro-ui-internals/packages/modules/health-payments/src/components/EditAttendanceManagementTable.js (4)
history
(34-34)useTranslation
(33-33)tenantId
(40-40)EditAttendanceManagementTable
(31-272)health/micro-ui/web/micro-ui-internals/packages/modules/health-payments/src/components/SearchUserPopUp.js (10)
history
(16-16)attendanceContextPath
(18-20)individualContextPath
(21-23)useTranslation
(25-25)tenantId
(14-14)labels
(28-28)maxLabelLength
(29-29)labelWidth
(30-30)searchQuery
(32-32)SearchUserPopUp
(12-176)health/micro-ui/web/micro-ui-internals/packages/modules/health-payments/src/utils/update_attendance_summary.js (7)
attendanceContextPath
(4-6)individualContextPath
(7-9)attendanceSummary
(12-12)individualIds
(11-11)isAttendanceLoading
(27-28)allIndividualReqCriteria
(41-58)isAllIndividualsLoading
(60-61)
health/micro-ui/web/micro-ui-internals/example/src/UICustomizations.js (7)
health/micro-ui/web/micro-ui-internals/packages/modules/microplan/src/configs/UICustomizations.js (11)
url
(72-72)url
(334-334)data
(52-52)data
(308-308)Digit
(680-680)dic
(65-71)dic
(322-333)tabId
(74-74)tabId
(336-336)showToast
(80-80)microplanId
(82-82)health/micro-ui/web/micro-ui-internals/packages/modules/microplan/src/pages/employee/PopInbox.js (4)
url
(21-21)showToast
(40-40)microplanId
(22-22)config
(16-16)health/micro-ui/web/micro-ui-internals/packages/modules/health-payments/src/pages/employee/EditRegister.js (4)
data
(44-44)Digit
(32-32)showToast
(48-48)loading
(49-49)health/micro-ui/web/micro-ui-internals/packages/modules/health-payments/src/services/attendance/attendanceService.js (3)
response
(9-16)response
(32-39)response
(55-62)health/micro-ui/web/micro-ui-internals/packages/modules/campaign-manager/src/hooks/useUpdateAppConfig.js (1)
response
(7-33)health/micro-ui/web/micro-ui-internals/packages/modules/hcm-microplanning/src/components/Modal.js (1)
Modal
(6-75)health/micro-ui/web/micro-ui-internals/packages/modules/health-payments/src/components/SearchUserPopUp.js (1)
createMapping
(15-15)
🪛 Biome (2.1.2)
health/micro-ui/web/micro-ui-internals/packages/modules/health-payments/src/components/editAttendeesPopUp.js
[error] 183-183: Avoid passing children using a prop
The canonical way to pass children in React is to use JSX elements
(lint/correctness/noChildrenProp)
health/micro-ui/web/micro-ui-internals/example/src/UICustomizations.js
[error] 887-887: Other switch clauses can erroneously access this declaration.
Wrap the declaration in a block to restrict its access to the switch clause.
The declaration is defined in this switch clause:
Safe fix: Wrap the declaration in a block.
(lint/correctness/noSwitchDeclarations)
[error] 888-888: Other switch clauses can erroneously access this declaration.
Wrap the declaration in a block to restrict its access to the switch clause.
The declaration is defined in this switch clause:
Safe fix: Wrap the declaration in a block.
(lint/correctness/noSwitchDeclarations)
[error] 889-889: Other switch clauses can erroneously access this declaration.
Wrap the declaration in a block to restrict its access to the switch clause.
The declaration is defined in this switch clause:
Safe fix: Wrap the declaration in a block.
(lint/correctness/noSwitchDeclarations)
[error] 890-890: Other switch clauses can erroneously access this declaration.
Wrap the declaration in a block to restrict its access to the switch clause.
The declaration is defined in this switch clause:
Safe fix: Wrap the declaration in a block.
(lint/correctness/noSwitchDeclarations)
[error] 902-916: Other switch clauses can erroneously access this declaration.
Wrap the declaration in a block to restrict its access to the switch clause.
The declaration is defined in this switch clause:
Safe fix: Wrap the declaration in a block.
(lint/correctness/noSwitchDeclarations)
[error] 918-962: Other switch clauses can erroneously access this declaration.
Wrap the declaration in a block to restrict its access to the switch clause.
The declaration is defined in this switch clause:
Safe fix: Wrap the declaration in a block.
(lint/correctness/noSwitchDeclarations)
[error] 964-966: Other switch clauses can erroneously access this declaration.
Wrap the declaration in a block to restrict its access to the switch clause.
The declaration is defined in this switch clause:
Safe fix: Wrap the declaration in a block.
(lint/correctness/noSwitchDeclarations)
[error] 2859-2859: Avoid passing children using a prop
The canonical way to pass children in React is to use JSX elements
(lint/correctness/noChildrenProp)
⏰ Context from checks skipped due to timeout of 10000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (3)
- GitHub Check: Build application amd64
- GitHub Check: Build application arm64
- GitHub Check: Analyze (javascript-typescript)
additionalCustomizations: (row, key, column, value, t, searchResult) => { | ||
|
||
const tenantId = Digit.ULBService.getCurrentTenantId(); | ||
|
||
const [openPopUp, setOpenPopUp] = useState(false); | ||
const [isTag, setIsTag] = useState(false); | ||
|
||
const [toast, setToast] = useState(null); | ||
const [modalOpen, setModalOpen] = useState(false); | ||
const [sessionFormData, setSessionFormData] = useState({}); | ||
const [refreshKey, setRefreshKey,] = useState(Date.now()); | ||
const [selectedId, setSelectedId] = useState(null); | ||
const [loading, setLoading] = useState(false); | ||
const { mutate: createMapping } = Digit.Hooks.payments.useCreateAttendeeFromRegister(tenantId); | ||
const { registerNumber, boundaryCode, registerId } = Digit.Hooks.useQueryParams(); | ||
|
||
const [tag, setTag] = useState(""); | ||
|
||
const handleToastClose = () => { | ||
setToast(null); | ||
}; | ||
|
||
const handleCreate = async (id) => { | ||
setSelectedId(id); | ||
setLoading(true); | ||
|
||
|
||
await createMapping({ | ||
"attendees": [ | ||
tag == "" ? | ||
{ | ||
registerId: registerId, | ||
individualId: row.id, | ||
enrollmentDate: new Date().getTime(), | ||
tenantId: row.tenantId, | ||
|
||
} : { | ||
registerId: registerId, | ||
individualId: row.id, | ||
enrollmentDate: new Date().getTime(), | ||
tenantId: row.tenantId, | ||
tag: tag | ||
}] | ||
}, | ||
{ | ||
onError: async (error) => { | ||
|
||
setLoading(false); | ||
setSelectedId(null); | ||
setTag(""); | ||
|
||
setIsTag(false); | ||
setOpenPopUp(false); | ||
|
||
|
||
const errorMessage = error?.response?.data?.Errors?.[0]?.message | ||
setToast( | ||
{ key: true, label: `${t(errorMessage)}`, type: "error" } | ||
|
||
); | ||
|
||
|
||
|
||
}, | ||
onSuccess: async (responseData) => { | ||
setTag(""); | ||
setLoading(false); | ||
setSelectedId(null); | ||
setIsTag(false); | ||
setOpenPopUp(false); | ||
|
||
|
||
setToast({ key: "success", label: `${t(`HCM_AM_NEW_EMPLOYEE`)} (${row.name.givenName || ""}) ${t(`HCM_AM_ENROLLED`)}`, transitionTime: 3000 }); | ||
|
||
setTimeout(() => { | ||
window.history.back(); | ||
}, 800); | ||
|
||
}, | ||
} | ||
); | ||
} | ||
|
||
switch (key) { | ||
case "HCM_HR_EMP_MOBILE_LABEL": | ||
return value ? `${value}` : t("ES_COMMON_NA"); | ||
|
||
case "HCM_HR_EMP_NAME_LABEL": | ||
return value ? `${value}` : t("ES_COMMON_NA"); | ||
|
||
case "HCM_HR_ROLE_NO_LABEL": | ||
return value?.length > 0 ? value?.length : t("ES_COMMON_NA"); | ||
|
||
case "HR_DESG_LABEL": | ||
return value ? t(`${value.designation}`) : t("ES_COMMON_NA"); | ||
|
||
case "HR_EMPLOYMENT_DEPARTMENT_LABEL": | ||
return value ? t(`${value.department}`) : t("ES_COMMON_NA"); | ||
|
||
case "HCM_HR_JURIDICTIONS_LABEL": | ||
return value ? t(value) : ( | ||
t("ES_COMMON_NA") | ||
); | ||
case "HCM_ASSIGNMENT": | ||
|
||
if (loading && (row.id === selectedId)) { | ||
return <Loader />; | ||
} | ||
|
||
return <> <Button | ||
key={refreshKey} | ||
variation={"primary"} | ||
label={t("ASSIGN")} | ||
style={{ minWidth: "10rem" }} | ||
onButtonClick={() => { | ||
|
||
// handleCreate(row.id); | ||
|
||
setOpenPopUp(true); | ||
return; | ||
|
||
|
||
}} | ||
/> | ||
{toast && ( | ||
<Toast | ||
error={toast.key} | ||
isDleteBtn={true} | ||
label={t(toast.label)} | ||
onClose={handleToastClose} | ||
type={toast.type} | ||
/> | ||
)} | ||
{ | ||
openPopUp && <PopUp | ||
style={{ minWidth: "500px" }} | ||
onClose={() => { | ||
setTag(""); | ||
setIsTag(false); | ||
setOpenPopUp(false); | ||
}} | ||
heading={t("Action Needed: Tag Code")} | ||
onOverlayClick={() => { | ||
setTag(""); | ||
setIsTag(false); | ||
setOpenPopUp(false); | ||
}} | ||
children={[ | ||
!isTag ? | ||
<div>Do you want to fill in the Tag Code? If yes, press Enter Tag. Otherwise, Assign it.</div> | ||
: <div> | ||
<span>Tag Code</span> | ||
<TextInput type="text" name="title" placeholder={t("Enter Tag Name")} value={tag} onChange={(e) => setTag(e.target.value)} /> | ||
</div> | ||
|
||
]} | ||
footerChildren={[ | ||
<ButtonNew | ||
type={"button"} | ||
size={"large"} | ||
variation={"primary"} | ||
label={t(isTag ? "HCM_AM_CLOSE_BT" : "HCM_AM_ENTER_TAG")} | ||
onClick={() => { | ||
if (isTag) { | ||
setTag(""); | ||
setOpenPopUp(false); | ||
setIsTag(false); | ||
} else { | ||
setIsTag(true); | ||
} | ||
return; | ||
}} | ||
/>, | ||
<ButtonNew | ||
type={"button"} | ||
size={"large"} | ||
variation={"primary"} | ||
label={t("Assign")} | ||
onClick={() => { | ||
handleCreate(row.id); | ||
return; | ||
}} | ||
/>, | ||
]} | ||
sortFooterChildren={true} | ||
/> | ||
} | ||
</> | ||
default: | ||
return t("ES_COMMON_NA"); | ||
} | ||
}, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Invalid React Hook usage inside AttendeeSearchInboxConfig cell renderer.
Hooks are called directly inside additionalCustomizations
function which violates React Hook rules. This needs to be extracted into a separate component.
Extract the attendee assignment logic into a separate React component:
function AttendeeAssignCell({ row, t }) {
const tenantId = Digit.ULBService.getCurrentTenantId();
const [openPopUp, setOpenPopUp] = useState(false);
const [isTag, setIsTag] = useState(false);
const [toast, setToast] = useState(null);
const [tag, setTag] = useState("");
const [loading, setLoading] = useState(false);
const [selectedId, setSelectedId] = useState(null);
const { registerId } = Digit.Hooks.useQueryParams();
const { mutate: createMapping } = Digit.Hooks.payments.useCreateAttendeeFromRegister(tenantId);
const handleCreate = async (id) => {
// Move the existing handleCreate logic here
};
// Return the existing JSX
return (
<>
{/* Button, Toast, and PopUp JSX */}
</>
);
}
Then update the config:
additionalCustomizations: (row, key, column, value, t, searchResult) => {
switch (key) {
- case "HCM_ASSIGNMENT":
- // Remove all hooks and state
- return <> ... </>;
+ case "HCM_ASSIGNMENT": {
+ return <AttendeeAssignCell row={row} t={t} />;
+ }
}
}
🧰 Tools
🪛 Biome (2.1.2)
[error] 2859-2859: Avoid passing children using a prop
The canonical way to pass children in React is to use JSX elements
(lint/correctness/noChildrenProp)
🤖 Prompt for AI Agents
In health/micro-ui/web/micro-ui-internals/example/src/UICustomizations.js around
lines 2712 to 2903, React Hooks (useState, custom hooks) are being called inside
the additionalCustomizations function which violates the Rules of Hooks; extract
the entire attendee-assignment UI and logic into a separate React component
(e.g., AttendeeAssignCell) that lives outside additionalCustomizations, move all
useState and Digit.Hooks.* calls and the handleCreate handler into that
component, accept props (row, t) plus any needed ids, return the existing
Button/Toast/PopUp JSX from the component, and then replace the case
"HCM_ASSIGNMENT" body in additionalCustomizations with a simple JSX return that
renders <AttendeeAssignCell row={row} t={t} /> (ensure React is imported and the
new component is exported/available in the same file or imported accordingly and
remove all hook usage from additionalCustomizations).
...web/micro-ui-internals/packages/modules/health-payments/src/components/editAttendeesPopUp.js
Show resolved
Hide resolved
const filteredData = searchQuery.length >= 3 ? | ||
attendanceSummary.filter( | ||
(row) => | ||
row[1].toLowerCase().includes(searchQuery.toLowerCase()) || // Name | ||
row[2].toLowerCase().includes(searchQuery.toLowerCase()) // ID | ||
) : attendanceSummary; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🧹 Nitpick (assertive)
Simplify search filtering logic
The current filter applies only when the search query has 3+ characters, otherwise shows all data. This creates an inconsistent UX where typing 1-2 characters shows everything.
-const filteredData = searchQuery.length >= 3 ?
- attendanceSummary.filter(
- (row) =>
- row[1].toLowerCase().includes(searchQuery.toLowerCase()) || // Name
- row[2].toLowerCase().includes(searchQuery.toLowerCase()) // ID
- ) : attendanceSummary;
+const filteredData = searchQuery.trim()
+ ? attendanceSummary.filter(
+ (row) =>
+ row[1]?.toLowerCase().includes(searchQuery.toLowerCase()) || // Name
+ row[2]?.toLowerCase().includes(searchQuery.toLowerCase()) // ID
+ )
+ : attendanceSummary;
Committable suggestion skipped: line range outside the PR's diff.
🤖 Prompt for AI Agents
In
health/micro-ui/web/micro-ui-internals/packages/modules/health-payments/src/components/editAttendeesPopUp.js
around lines 155 to 160, remove the conditional that only applies filtering when
searchQuery.length >= 3 and instead always apply the filter: if searchQuery is
empty return attendanceSummary, otherwise filter attendanceSummary by checking
row[1] and row[2] against searchQuery (both lowercased) so typing 1-2 characters
will filter results consistently.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 16
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (9)
health/micro-ui/web/micro-ui-internals/packages/modules/campaign-manager/src/pages/employee/appConfigurationRedesign/AppLocalisationWrapper.js (2)
13-37
: Reducer default is incorrect; switch will return undefined on unknown actionsUse the
default:
branch (notcase "default"
). Without it, unknown actions break the reducer.Apply this diff:
- switch (action.type) { + switch (action.type) { case "SET_LOC": return action.payload.localisationData; - case "default": - return state; + default: + return state;
94-99
: React Query key mismatch; cache might not be clearedYou fetch with queryKey "FOR_APP_LOCALISATION", but remove "SEARCH_APP_LOCALISATION". Align the keys.
Suggested fix:
- queryClient.removeQueries(["SEARCH_APP_LOCALISATION", tenantId, localeModule]); + queryClient.removeQueries(["FOR_APP_LOCALISATION", tenantId, localeModule]);Alternatively, remove by predicate if the internal hook composes a different key:
- queryClient.removeQueries(["SEARCH_APP_LOCALISATION", tenantId, localeModule]); + queryClient.removeQueries({ + predicate: (q) => Array.isArray(q.queryKey) && String(q.queryKey[0]).includes("LOCALISATION"), + });health/micro-ui/web/micro-ui-internals/packages/modules/campaign-manager/src/pages/employee/appConfigurationRedesign/RenderConditionalField.js (1)
8-18
: Undefined identifiers in dependencyFieldWrapper; component will crashparentState, screenConfig, selectedField, and handleExpressionChange are not in props; handleExpressionChange is not defined at all.
Apply these diffs:
- Accept the props with a safe default for onExpressionChange:
-export const RenderConditionalField = ({ +export const RenderConditionalField = ({ cField, cIndex, cArray, setDrawerState, updateLocalization, state, drawerState, AppScreenLocalisationConfig, - disabled, + disabled, + parentState, + screenConfig, + selectedField, + onExpressionChange = () => {}, }) => {
- Pass the correct variable to DependentFieldsWrapper:
- onExpressionChange={handleExpressionChange} + onExpressionChange={onExpressionChange}Also ensure the caller provides these props when rendering this component (see DrawerFieldComposer).
Also applies to: 221-229
health/micro-ui/web/micro-ui-internals/packages/modules/campaign-manager/src/pages/employee/appConfigurationRedesign/DrawerFieldComposer.js (3)
122-219
: Hooks used inside switch cases; violates React Hooks rulesuseRef/useState inside case "toggle"/"text"/"DetailsCard" are conditional. This breaks hook ordering and can cause runtime errors.
Refactor each case into its own component so hooks are at the top-level of that component. Example:
function ToggleField({ t, drawerState, panelItem, setDrawerState, resourceData }) { const switchRef = useRef(null); const [showTooltip, setShowTooltip] = useState(false); const isDisabled = disableFieldForMandatory(drawerState, panelItem, resourceData); ... return (...); }Then in RenderField’s switch return <ToggleField ... /> etc. Repeat for TextField and DetailsTable cases. This keeps hooks unconditionally ordered.
Additionally, pass required props to RenderConditionalField (see next comment). Also applies to: 288-378 --- `159-171`: **Pass required props to RenderConditionalField to support dependencyFieldWrapper** Currently missing parentState/screenConfig/selectedField/onExpressionChange. Apply this diff: ```diff <RenderConditionalField key={cIndex} cField={cField} cIndex={cIndex} cArray={shouldShow} setDrawerState={setDrawerState} updateLocalization={updateLocalization} state={state} drawerState={drawerState} AppScreenLocalisationConfig={AppScreenLocalisationConfig} disabled={drawerState?.hidden} + parentState={parentState} + screenConfig={state?.screenConfig?.[0]} + selectedField={state?.drawerField} + onExpressionChange={() => {}} />
Also update DrawerFieldComposer to accept and receive parentState (see AppConfigurationWrapper change).
469-483
: Add a key to items returned from mapThe wrapper div lacks a React key; add one to prevent reconciliation issues.
- {currentDrawerState?.map((panelItem, index) => { + {currentDrawerState?.map((panelItem, index) => { if (isFieldVisible(panelItem)) { return ( - <div className="drawer-toggle-field-container"> + <div className="drawer-toggle-field-container" key={panelItem?.label || index}> <RenderFieldhealth/micro-ui/web/micro-ui-internals/packages/modules/campaign-manager/src/pages/employee/appConfigurationRedesign/AppFieldScreenWrapper.js (1)
54-85
: Add keys to mapped fragmentsThe map over currentCard.cards returns fragments without keys, causing React warnings.
- return ( - <> + return ( + <React.Fragment key={index}> <div className="app-config-drawer-subheader"> <div>{t("APPCONFIG_HEAD_FIELDS")}</div> <ConsoleTooltip className="app-config-tooltip" toolTipContent={t("TIP_APPCONFIG_HEAD_FIELDS")} /> </div> <Divider /> {headerFields?.map(({ type, label, active, required, value }, indx, cx) => ( <AppFieldComposer ... /> ))} <Divider /> ... - </> + </React.Fragment> );health/micro-ui/web/micro-ui-internals/packages/modules/campaign-manager/src/pages/employee/appConfigurationRedesign/AppConfigurationParentLayer.js (1)
90-103
: MDMS v2 flag appears omitted; may call the wrong endpointSimilar hooks elsewhere pass the mdmsv2 boolean. Add the final
true
arg to ensure v2.- const { isLoading: isLoadingAppConfigMdmsData, data: AppConfigMdmsData } = Digit.Hooks.useCustomMDMS( + const { isLoading: isLoadingAppConfigMdmsData, data: AppConfigMdmsData } = Digit.Hooks.useCustomMDMS( Digit.ULBService.getCurrentTenantId(), MODULE_CONSTANTS, [{ name: fieldTypeMaster, limit: 1000 }], { cacheTime: Infinity, staleTime: Infinity, select: (data) => { return data?.[MODULE_CONSTANTS]; }, }, - { schemaCode: "BASE_APP_MASTER_DATA3" } //mdmsv2 + { schemaCode: "BASE_APP_MASTER_DATA3" }, // mdmsv2 + true );health/micro-ui/web/micro-ui-internals/packages/modules/campaign-manager/src/utils/template_components/RegistrationComponents.js (1)
127-148
: Replace clickable div with button in TextButtonUse a semantic button for accessibility.
- <div - style={{ display: "inline-flex", alignItems: "center", justifyContent: "center", gap: "8px", padding: "8px 16px", background: "#FFFFFF", color: "rgba(244, 119, 56, 1)", borderRadius: "4px", cursor: "pointer", fontWeight: 400, fontSize: "16px", lineHeight: "100%", border: "none" }} - className="digit-search-action" - onClick={props.onClick} - > + <button + type="button" + style={{ display: "inline-flex", alignItems: "center", justifyContent: "center", gap: "8px", padding: "8px 16px", background: "#FFFFFF", color: "rgba(244, 119, 56, 1)", borderRadius: "4px", cursor: "pointer", fontWeight: 400, fontSize: "16px", lineHeight: "100%", border: "1px solid transparent" }} + className="digit-search-action" + onClick={props.onClick} + > {props.addMember ? <CustomSVG.AddFilled width={"16px"} height={"16px"} fill={"#F47738"} /> : <EditIcon />} <span className="digit-search-text">{props?.label || "EDIT_LABEL"}</span> - </div> + </button>
📜 Review details
Configuration used: CodeRabbit UI
Review profile: ASSERTIVE
Plan: Pro
📒 Files selected for processing (13)
health/micro-ui/web/micro-ui-internals/packages/modules/campaign-manager/src/components/AppPreview.js
(2 hunks)health/micro-ui/web/micro-ui-internals/packages/modules/campaign-manager/src/pages/employee/appConfigurationRedesign/AppConfigurationParentLayer.js
(11 hunks)health/micro-ui/web/micro-ui-internals/packages/modules/campaign-manager/src/pages/employee/appConfigurationRedesign/AppConfigurationWrapper.js
(5 hunks)health/micro-ui/web/micro-ui-internals/packages/modules/campaign-manager/src/pages/employee/appConfigurationRedesign/AppFieldScreenWrapper.js
(6 hunks)health/micro-ui/web/micro-ui-internals/packages/modules/campaign-manager/src/pages/employee/appConfigurationRedesign/AppLocalisationWrapper.js
(2 hunks)health/micro-ui/web/micro-ui-internals/packages/modules/campaign-manager/src/pages/employee/appConfigurationRedesign/DependentFieldsWrapper.js
(1 hunks)health/micro-ui/web/micro-ui-internals/packages/modules/campaign-manager/src/pages/employee/appConfigurationRedesign/DrawerFieldComposer.js
(3 hunks)health/micro-ui/web/micro-ui-internals/packages/modules/campaign-manager/src/pages/employee/appConfigurationRedesign/ImpelComponentWrapper.js
(2 hunks)health/micro-ui/web/micro-ui-internals/packages/modules/campaign-manager/src/pages/employee/appConfigurationRedesign/NavigationLogicWrapper.js
(1 hunks)health/micro-ui/web/micro-ui-internals/packages/modules/campaign-manager/src/pages/employee/appConfigurationRedesign/RenderConditionalField.js
(5 hunks)health/micro-ui/web/micro-ui-internals/packages/modules/campaign-manager/src/pages/employee/appConfigurationRedesign/useCustomT.js
(1 hunks)health/micro-ui/web/micro-ui-internals/packages/modules/campaign-manager/src/utils/appConfigHelpers.js
(7 hunks)health/micro-ui/web/micro-ui-internals/packages/modules/campaign-manager/src/utils/template_components/RegistrationComponents.js
(14 hunks)
🧰 Additional context used
📓 Path-based instructions (1)
**/*.js
⚙️ CodeRabbit configuration file
check
Files:
health/micro-ui/web/micro-ui-internals/packages/modules/campaign-manager/src/utils/appConfigHelpers.js
health/micro-ui/web/micro-ui-internals/packages/modules/campaign-manager/src/pages/employee/appConfigurationRedesign/RenderConditionalField.js
health/micro-ui/web/micro-ui-internals/packages/modules/campaign-manager/src/pages/employee/appConfigurationRedesign/useCustomT.js
health/micro-ui/web/micro-ui-internals/packages/modules/campaign-manager/src/pages/employee/appConfigurationRedesign/AppLocalisationWrapper.js
health/micro-ui/web/micro-ui-internals/packages/modules/campaign-manager/src/pages/employee/appConfigurationRedesign/DrawerFieldComposer.js
health/micro-ui/web/micro-ui-internals/packages/modules/campaign-manager/src/components/AppPreview.js
health/micro-ui/web/micro-ui-internals/packages/modules/campaign-manager/src/pages/employee/appConfigurationRedesign/AppConfigurationParentLayer.js
health/micro-ui/web/micro-ui-internals/packages/modules/campaign-manager/src/pages/employee/appConfigurationRedesign/DependentFieldsWrapper.js
health/micro-ui/web/micro-ui-internals/packages/modules/campaign-manager/src/pages/employee/appConfigurationRedesign/ImpelComponentWrapper.js
health/micro-ui/web/micro-ui-internals/packages/modules/campaign-manager/src/pages/employee/appConfigurationRedesign/AppFieldScreenWrapper.js
health/micro-ui/web/micro-ui-internals/packages/modules/campaign-manager/src/pages/employee/appConfigurationRedesign/NavigationLogicWrapper.js
health/micro-ui/web/micro-ui-internals/packages/modules/campaign-manager/src/pages/employee/appConfigurationRedesign/AppConfigurationWrapper.js
health/micro-ui/web/micro-ui-internals/packages/modules/campaign-manager/src/utils/template_components/RegistrationComponents.js
🧠 Learnings (2)
📚 Learning: 2025-02-05T10:18:29.947Z
Learnt from: Tulika-eGov
PR: egovernments/DIGIT-Frontend#2188
File: micro-ui/web/micro-ui-internals/packages/modules/pgr/src/pages/employee/new-inbox.js:34-47
Timestamp: 2025-02-05T10:18:29.947Z
Learning: In the DIGIT-Frontend codebase, translations within FormComposer are handled internally by the component itself, so the translation function 't' does not need to be added to useMemo dependency arrays even when used within the memoized function that generates form configurations.
Applied to files:
health/micro-ui/web/micro-ui-internals/packages/modules/campaign-manager/src/pages/employee/appConfigurationRedesign/useCustomT.js
📚 Learning: 2025-06-26T10:38:13.794Z
Learnt from: Hari-egov
PR: egovernments/DIGIT-Frontend#2644
File: micro-ui/web/micro-ui-internals/packages/modules/sandbox/src/pages/employee/ProductDetails/ProductDetailsComponentUpdated.js:326-345
Timestamp: 2025-06-26T10:38:13.794Z
Learning: In the DIGIT Frontend sandbox module, configuration data comes from MDMS (Master Data Management System) which provides reliable, well-structured data for UI components, reducing the likelihood of malformed configuration data that would require extensive error handling.
Applied to files:
health/micro-ui/web/micro-ui-internals/packages/modules/campaign-manager/src/pages/employee/appConfigurationRedesign/AppConfigurationParentLayer.js
🧬 Code graph analysis (11)
health/micro-ui/web/micro-ui-internals/packages/modules/campaign-manager/src/pages/employee/appConfigurationRedesign/RenderConditionalField.js (2)
health/micro-ui/web/micro-ui-internals/packages/modules/campaign-manager/src/pages/employee/appConfigurationRedesign/DependentFieldsWrapper.js (1)
useT
(73-73)health/micro-ui/web/micro-ui-internals/packages/modules/campaign-manager/src/pages/employee/appConfigurationRedesign/useCustomT.js (2)
useCustomT
(12-40)useCustomT
(12-40)
health/micro-ui/web/micro-ui-internals/packages/modules/campaign-manager/src/pages/employee/appConfigurationRedesign/useCustomT.js (2)
health/micro-ui/web/micro-ui-internals/packages/modules/campaign-manager/src/pages/employee/appConfigurationRedesign/AppConfigurationWrapper.js (2)
useAppLocalisationContext
(317-317)currentLocale
(321-321)health/micro-ui/web/micro-ui-internals/packages/modules/campaign-manager/src/pages/employee/appConfigurationRedesign/AppLocalisationWrapper.js (2)
locState
(46-46)addMissingKey
(53-55)
health/micro-ui/web/micro-ui-internals/packages/modules/campaign-manager/src/pages/employee/appConfigurationRedesign/AppLocalisationWrapper.js (1)
health/micro-ui/web/micro-ui-internals/packages/modules/campaign-manager/src/pages/employee/appConfigurationRedesign/AppConfigurationParentLayer.js (2)
localeModule
(66-66)parentState
(60-60)
health/micro-ui/web/micro-ui-internals/packages/modules/campaign-manager/src/pages/employee/appConfigurationRedesign/DrawerFieldComposer.js (1)
health/micro-ui/web/micro-ui-internals/packages/modules/campaign-manager/src/pages/employee/appConfigurationRedesign/useCustomT.js (2)
useCustomT
(12-40)useCustomT
(12-40)
health/micro-ui/web/micro-ui-internals/packages/modules/campaign-manager/src/pages/employee/appConfigurationRedesign/AppConfigurationParentLayer.js (2)
health/micro-ui/web/micro-ui-internals/packages/modules/campaign-manager/src/pages/employee/NewCampaignCreate/AppFeatures.js (4)
isCacheLoading
(117-117)Digit
(75-75)Digit
(421-421)reqCriteriaForm
(97-115)health/micro-ui/web/micro-ui-internals/packages/modules/campaign-manager/src/pages/employee/appConfigurationRedesign/AppConfigurationTabLayer.js (1)
numberTabs
(111-111)
health/micro-ui/web/micro-ui-internals/packages/modules/campaign-manager/src/pages/employee/appConfigurationRedesign/DependentFieldsWrapper.js (2)
health/micro-ui/web/micro-ui-internals/packages/modules/campaign-manager/src/pages/employee/appConfigurationRedesign/NavigationLogicWrapper.js (5)
tenantId
(17-17)module
(18-18)list
(20-31)options
(33-36)selectedOption
(38-42)micro-ui/web/micro-ui-internals/packages/react-components/src/atoms/Dropdown.js (1)
Dropdown
(94-281)
health/micro-ui/web/micro-ui-internals/packages/modules/campaign-manager/src/pages/employee/appConfigurationRedesign/ImpelComponentWrapper.js (1)
health/micro-ui/web/micro-ui-internals/packages/modules/campaign-manager/src/pages/employee/appConfigurationRedesign/AppConfigurationParentLayer.js (3)
back
(530-541)localeModule
(66-66)parentState
(60-60)
health/micro-ui/web/micro-ui-internals/packages/modules/campaign-manager/src/pages/employee/appConfigurationRedesign/AppFieldScreenWrapper.js (5)
health/micro-ui/web/micro-ui-internals/packages/modules/campaign-manager/src/pages/employee/appConfigurationRedesign/AppConfigurationWrapper.js (4)
useAppLocalisationContext
(317-317)searchParams
(328-328)useTranslation
(320-320)useT
(315-315)health/micro-ui/web/micro-ui-internals/packages/modules/campaign-manager/src/pages/employee/appConfigurationRedesign/AppLocalisationWrapper.js (3)
useAppLocalisationContext
(9-11)useAppLocalisationContext
(9-11)searchParams
(47-47)health/micro-ui/web/micro-ui-internals/packages/modules/campaign-manager/src/pages/employee/appConfigurationRedesign/useCustomT.js (3)
useAppLocalisationContext
(13-13)useCustomT
(12-40)useCustomT
(12-40)health/micro-ui/web/micro-ui-internals/packages/modules/campaign-manager/src/pages/employee/appConfigurationRedesign/AppConfigurationParentLayer.js (3)
searchParams
(53-53)useTranslation
(49-49)parentState
(60-60)health/micro-ui/web/micro-ui-internals/packages/modules/campaign-manager/src/components/ConsoleToolTip.js (1)
ConsoleTooltip
(34-69)
health/micro-ui/web/micro-ui-internals/packages/modules/campaign-manager/src/pages/employee/appConfigurationRedesign/NavigationLogicWrapper.js (1)
micro-ui/web/micro-ui-internals/packages/react-components/src/atoms/Dropdown.js (1)
Dropdown
(94-281)
health/micro-ui/web/micro-ui-internals/packages/modules/campaign-manager/src/pages/employee/appConfigurationRedesign/AppConfigurationWrapper.js (3)
health/micro-ui/web/micro-ui-internals/packages/modules/campaign-manager/src/pages/employee/appConfigurationRedesign/AppConfigurationParentLayer.js (1)
parentState
(60-60)health/micro-ui/web/micro-ui-internals/packages/modules/campaign-manager/src/pages/employee/appConfigurationRedesign/useCustomT.js (2)
useCustomT
(12-40)useCustomT
(12-40)health/micro-ui/web/micro-ui-internals/packages/modules/campaign-manager/src/components/AppPreview.js (1)
AppPreview
(172-281)
health/micro-ui/web/micro-ui-internals/packages/modules/campaign-manager/src/utils/template_components/RegistrationComponents.js (1)
health/micro-ui/web/micro-ui-internals/packages/modules/campaign-manager/src/components/RenderSelectionField.js (1)
RenderSelectionField
(4-46)
🪛 Biome (2.1.2)
health/micro-ui/web/micro-ui-internals/packages/modules/campaign-manager/src/pages/employee/appConfigurationRedesign/RenderConditionalField.js
[error] 38-38: This hook is being called conditionally, but all hooks must be called in the exact same order in every component render.
For React to preserve state between calls, hooks needs to be called unconditionally and always in the same order.
See https://reactjs.org/docs/hooks-rules.html#only-call-hooks-at-the-top-level
(lint/correctness/useHookAtTopLevel)
[error] 90-90: This hook is being called from a nested function, but all hooks must be called unconditionally from the top-level component.
For React to preserve state between calls, hooks needs to be called unconditionally and always in the same order.
See https://reactjs.org/docs/hooks-rules.html#only-call-hooks-at-the-top-level
(lint/correctness/useHookAtTopLevel)
health/micro-ui/web/micro-ui-internals/packages/modules/campaign-manager/src/pages/employee/appConfigurationRedesign/DrawerFieldComposer.js
[error] 196-196: This hook is being called conditionally, but all hooks must be called in the exact same order in every component render.
For React to preserve state between calls, hooks needs to be called unconditionally and always in the same order.
See https://reactjs.org/docs/hooks-rules.html#only-call-hooks-at-the-top-level
(lint/correctness/useHookAtTopLevel)
[error] 355-355: This hook is being called from a nested function, but all hooks must be called unconditionally from the top-level component.
For React to preserve state between calls, hooks needs to be called unconditionally and always in the same order.
See https://reactjs.org/docs/hooks-rules.html#only-call-hooks-at-the-top-level
(lint/correctness/useHookAtTopLevel)
health/micro-ui/web/micro-ui-internals/packages/modules/campaign-manager/src/pages/employee/appConfigurationRedesign/DependentFieldsWrapper.js
[error] 514-515: The elements with this role can be changed to the following elements:
For examples and more information, see WAI-ARIA Roles
(lint/a11y/useSemanticElements)
[error] 513-520: The HTML element with the interactive role "button" is not focusable.
A non-interactive HTML element that is not focusable may not be reachable for users that rely on keyboard navigation, even with an added role like "button".
Add a tabIndex attribute to make this element focusable.
(lint/a11y/useFocusableInteractive)
[error] 513-520: Enforce to have the onClick mouse event with the onKeyUp, the onKeyDown, or the onKeyPress keyboard event.
Actions triggered using mouse events should have corresponding keyboard events to account for keyboard-only navigation.
(lint/a11y/useKeyWithClickEvents)
[error] 528-529: The elements with this role can be changed to the following elements:
For examples and more information, see WAI-ARIA Roles
(lint/a11y/useSemanticElements)
[error] 527-534: Enforce to have the onClick mouse event with the onKeyUp, the onKeyDown, or the onKeyPress keyboard event.
Actions triggered using mouse events should have corresponding keyboard events to account for keyboard-only navigation.
(lint/a11y/useKeyWithClickEvents)
[error] 527-534: The HTML element with the interactive role "button" is not focusable.
A non-interactive HTML element that is not focusable may not be reachable for users that rely on keyboard navigation, even with an added role like "button".
Add a tabIndex attribute to make this element focusable.
(lint/a11y/useFocusableInteractive)
[error] 917-924: Static Elements should not be interactive.
To add interactivity such as a mouse or key event listener to a static element, give the element an appropriate role value.
(lint/a11y/noStaticElementInteractions)
[error] 917-924: Enforce to have the onClick mouse event with the onKeyUp, the onKeyDown, or the onKeyPress keyboard event.
Actions triggered using mouse events should have corresponding keyboard events to account for keyboard-only navigation.
(lint/a11y/useKeyWithClickEvents)
[error] 598-598: Avoid passing children using a prop
The canonical way to pass children in React is to use JSX elements
(lint/correctness/noChildrenProp)
health/micro-ui/web/micro-ui-internals/packages/modules/campaign-manager/src/pages/employee/appConfigurationRedesign/AppFieldScreenWrapper.js
[error] 68-68: This hook is being called from a nested function, but all hooks must be called unconditionally from the top-level component.
For React to preserve state between calls, hooks needs to be called unconditionally and always in the same order.
See https://reactjs.org/docs/hooks-rules.html#only-call-hooks-at-the-top-level
(lint/correctness/useHookAtTopLevel)
[error] 94-94: This hook is being called from a nested function, but all hooks must be called unconditionally from the top-level component.
For React to preserve state between calls, hooks needs to be called unconditionally and always in the same order.
See https://reactjs.org/docs/hooks-rules.html#only-call-hooks-at-the-top-level
(lint/correctness/useHookAtTopLevel)
[error] 134-134: This hook is being called from a nested function, but all hooks must be called unconditionally from the top-level component.
For React to preserve state between calls, hooks needs to be called unconditionally and always in the same order.
See https://reactjs.org/docs/hooks-rules.html#only-call-hooks-at-the-top-level
(lint/correctness/useHookAtTopLevel)
[error] 135-135: This hook is being called from a nested function, but all hooks must be called unconditionally from the top-level component.
For React to preserve state between calls, hooks needs to be called unconditionally and always in the same order.
See https://reactjs.org/docs/hooks-rules.html#only-call-hooks-at-the-top-level
(lint/correctness/useHookAtTopLevel)
[error] 136-136: This hook is being called from a nested function, but all hooks must be called unconditionally from the top-level component.
For React to preserve state between calls, hooks needs to be called unconditionally and always in the same order.
See https://reactjs.org/docs/hooks-rules.html#only-call-hooks-at-the-top-level
(lint/correctness/useHookAtTopLevel)
[error] 229-229: This hook is being called conditionally, but all hooks must be called in the exact same order in every component render.
For React to preserve state between calls, hooks needs to be called unconditionally and always in the same order.
See https://reactjs.org/docs/hooks-rules.html#only-call-hooks-at-the-top-level
(lint/correctness/useHookAtTopLevel)
health/micro-ui/web/micro-ui-internals/packages/modules/campaign-manager/src/pages/employee/appConfigurationRedesign/NavigationLogicWrapper.js
[error] 619-619: The elements with this role can be changed to the following elements:
For examples and more information, see WAI-ARIA Roles
(lint/a11y/useSemanticElements)
[error] 618-624: The HTML element with the interactive role "button" is not focusable.
A non-interactive HTML element that is not focusable may not be reachable for users that rely on keyboard navigation, even with an added role like "button".
Add a tabIndex attribute to make this element focusable.
(lint/a11y/useFocusableInteractive)
[error] 618-624: Enforce to have the onClick mouse event with the onKeyUp, the onKeyDown, or the onKeyPress keyboard event.
Actions triggered using mouse events should have corresponding keyboard events to account for keyboard-only navigation.
(lint/a11y/useKeyWithClickEvents)
[error] 633-633: The elements with this role can be changed to the following elements:
For examples and more information, see WAI-ARIA Roles
(lint/a11y/useSemanticElements)
[error] 632-638: Enforce to have the onClick mouse event with the onKeyUp, the onKeyDown, or the onKeyPress keyboard event.
Actions triggered using mouse events should have corresponding keyboard events to account for keyboard-only navigation.
(lint/a11y/useKeyWithClickEvents)
[error] 632-638: The HTML element with the interactive role "button" is not focusable.
A non-interactive HTML element that is not focusable may not be reachable for users that rely on keyboard navigation, even with an added role like "button".
Add a tabIndex attribute to make this element focusable.
(lint/a11y/useFocusableInteractive)
[error] 949-961: Enforce to have the onClick mouse event with the onKeyUp, the onKeyDown, or the onKeyPress keyboard event.
Actions triggered using mouse events should have corresponding keyboard events to account for keyboard-only navigation.
(lint/a11y/useKeyWithClickEvents)
[error] 960-960: The elements with this role can be changed to the following elements:
For examples and more information, see WAI-ARIA Roles
(lint/a11y/useSemanticElements)
[error] 949-961: The HTML element with the interactive role "button" is not focusable.
A non-interactive HTML element that is not focusable may not be reachable for users that rely on keyboard navigation, even with an added role like "button".
Add a tabIndex attribute to make this element focusable.
(lint/a11y/useFocusableInteractive)
[error] 689-689: Avoid passing children using a prop
The canonical way to pass children in React is to use JSX elements
(lint/correctness/noChildrenProp)
health/micro-ui/web/micro-ui-internals/packages/modules/campaign-manager/src/pages/employee/appConfigurationRedesign/AppConfigurationWrapper.js
[error] 326-326: This hook is being called conditionally, but all hooks must be called in the exact same order in every component render.
For React to preserve state between calls, hooks needs to be called unconditionally and always in the same order.
See https://reactjs.org/docs/hooks-rules.html#only-call-hooks-at-the-top-level
(lint/correctness/useHookAtTopLevel)
[error] 755-755: This hook is being called conditionally, but all hooks must be called in the exact same order in every component render.
For React to preserve state between calls, hooks needs to be called unconditionally and always in the same order.
See https://reactjs.org/docs/hooks-rules.html#only-call-hooks-at-the-top-level
(lint/correctness/useHookAtTopLevel)
health/micro-ui/web/micro-ui-internals/packages/modules/campaign-manager/src/utils/template_components/RegistrationComponents.js
[error] 39-39: Alternative text title element cannot be empty
For accessibility purposes, SVGs should have an alternative text, provided via title element. If the svg element has role="img", you should add the aria-label or aria-labelledby attribute.
(lint/a11y/noSvgWithoutTitle)
[error] 39-39: Enforce to have the onClick mouse event with the onKeyUp, the onKeyDown, or the onKeyPress keyboard event.
Actions triggered using mouse events should have corresponding keyboard events to account for keyboard-only navigation.
(lint/a11y/useKeyWithClickEvents)
⏰ Context from checks skipped due to timeout of 10000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
- GitHub Check: Analyze (javascript-typescript)
🔇 Additional comments (8)
health/micro-ui/web/micro-ui-internals/packages/modules/campaign-manager/src/pages/employee/appConfigurationRedesign/AppLocalisationWrapper.js (1)
41-41
: parentState propagation LGTMNew prop accepted and forwarded correctly.
Also applies to: 132-133
health/micro-ui/web/micro-ui-internals/packages/modules/campaign-manager/src/pages/employee/appConfigurationRedesign/AppFieldScreenWrapper.js (1)
33-34
: LGTM on translation alias and navigation logic blockuseT adoption and NavigationLogicWrapper wiring look correct.
Also applies to: 194-214
health/micro-ui/web/micro-ui-internals/packages/modules/campaign-manager/src/pages/employee/appConfigurationRedesign/ImpelComponentWrapper.js (1)
9-10
: parentState propagation LGTMSignature now accepts parentState and forwards it properly.
health/micro-ui/web/micro-ui-internals/packages/modules/campaign-manager/src/pages/employee/appConfigurationRedesign/AppConfigurationWrapper.js (2)
582-583
: AppPreview now consumes useT; good changePassing the translator function aligns with the new localization flow.
661-666
: Pass parentState to DrawerFieldComposer (needed for dependencyFieldWrapper flow)Currently not provided.
- <DrawerFieldComposer /> + <DrawerFieldComposer parentState={parentState} />Also ensure DrawerFieldComposer accepts this prop.
health/micro-ui/web/micro-ui-internals/packages/modules/campaign-manager/src/utils/appConfigHelpers.js (1)
135-164
: Restructure/reverseRestructure extensions look consistentFlattening helpers and added properties (schemaCode/prefixText/suffixText/autoFillCondition/conditionalNavigateTo) are correctly propagated.
Also applies to: 179-264, 294-340
health/micro-ui/web/micro-ui-internals/packages/modules/campaign-manager/src/pages/employee/appConfigurationRedesign/useCustomT.js (1)
12-40
: Approve translator hook; no direct calls detected
useCustomT
returns a stable translate function; scanning the codebase found no legacy direct calls. Continue usingconst t = useCustomT(); t('KEY')
to avoid React Hooks rule violations.health/micro-ui/web/micro-ui-internals/packages/modules/campaign-manager/src/pages/employee/appConfigurationRedesign/AppConfigurationParentLayer.js (1)
530-541
: Confirm previous-tab back-nav target
When on a tab’s first page, you dispatch PREVIOUS_TAB but resetcurrentStep
to the global first step. Should back-nav instead compute and land on the previous tab’s last page (vs its first page)?
case "textArea": | ||
return "textarea"; | ||
case "time": |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Restore lowercase textarea
mapping in getFieldType
.
Changing the case label to "textArea"
drops support for the existing "textarea"
value. Any config row still sending "textarea"
now falls through to the default and renders as a button, breaking those fields. Please keep the lowercase mapping (and optionally add the camel-case alias if needed).
- case "textArea":
- return "textarea";
+ case "textarea":
+ case "textArea":
+ return "textarea";
📝 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.
case "textArea": | |
return "textarea"; | |
case "time": | |
case "textarea": | |
case "textArea": | |
return "textarea"; | |
case "time": |
🤖 Prompt for AI Agents
In
health/micro-ui/web/micro-ui-internals/packages/modules/campaign-manager/src/components/AppPreview.js
around lines 140 to 142, the switch in getFieldType removed the lowercase
"textarea" case which causes existing configs sending "textarea" to fall through
to default; restore the lowercase mapping by adding a case "textarea": return
"textarea"; (you may also keep or add the camelCase alias case "textArea":
return "textarea"; so both values are supported).
const { isLoading: isCacheLoading, data: cacheData, refetch: refetchCache, revalidate } = Digit.Hooks.useCustomAPIHook(reqCriteriaForm); | ||
const { isLoading: isCacheLoading, data: cacheData, refetch: refetchCache } = Digit.Hooks.useCustomAPIHook(reqCriteriaForm); | ||
|
||
const { mutate: updateMutate } = Digit.Hooks.campaign.useUpdateAppConfig(tenantId); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion | 🟠 Major
🧩 Analysis chain
Verify mutation API; avoid “await mutate” if not promise-based
If useUpdateAppConfig
exposes mutate
(callback), await
won’t work and try/catch won’t catch. Prefer mutateAsync
.
If mutateAsync
exists, refactor:
-const { mutate: updateMutate } = Digit.Hooks.campaign.useUpdateAppConfig(tenantId);
+const { mutateAsync: updateAppConfig } = Digit.Hooks.campaign.useUpdateAppConfig(tenantId);
…and replace await updateMutate(...)
with await updateAppConfig(...)
across this file.
🏁 Script executed:
#!/bin/bash
# Inspect hook definition and exports to confirm whether mutateAsync is available
rg -nP 'useUpdateAppConfig\s*\(' -C3
rg -nP 'useMutation\(|mutateAsync|mutate\s*:\s*' -C3
Length of output: 104508
🏁 Script executed:
#!/bin/bash
rg -nP 'updateMutate\s*\(' -n health/micro-ui/web/micro-ui-internals/packages/modules/campaign-manager/src/pages/employee/appConfigurationRedesign/AppConfigurationParentLayer.js
Length of output: 159
Switch to mutateAsync for useUpdateAppConfig
Refactor the hook and calls:
- const { mutate: updateMutate } = Digit.Hooks.campaign.useUpdateAppConfig(tenantId);
+ const { mutateAsync: updateAppConfig } = Digit.Hooks.campaign.useUpdateAppConfig(tenantId);
Replace all await updateMutate(...)
calls (lines 364, 386, 440, 463, 498) with await updateAppConfig(...)
.
📝 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.
const { mutate: updateMutate } = Digit.Hooks.campaign.useUpdateAppConfig(tenantId); | |
const { mutateAsync: updateAppConfig } = Digit.Hooks.campaign.useUpdateAppConfig(tenantId); |
🤖 Prompt for AI Agents
In
health/micro-ui/web/micro-ui-internals/packages/modules/campaign-manager/src/pages/employee/appConfigurationRedesign/AppConfigurationParentLayer.js
around line 131, the hook currently destructures mutate as updateMutate; change
it to destructure mutateAsync and name it updateAppConfig, and then replace all
awaited calls to updateMutate(...) (at lines ~364, 386, 440, 463, 498) with
awaited calls to updateAppConfig(...). Ensure the hook line reads to extract
mutateAsync as updateAppConfig and update every call site to use
updateAppConfig(...) with the same arguments.
useEffect(() => { | ||
const last = currentTabPages.length | ||
? Number(currentTabPages[currentTabPages.length - 1].order) | ||
: null; | ||
|
||
const isLast = last != null && Math.abs(Number(currentStep) - last) < 1e-6; | ||
|
||
// Check if there's only one page in the current tab - if so, disable Next | ||
const isSinglePage = currentTabPages.length === 1; | ||
|
||
// Dispatch immediately - this runs synchronously | ||
window.dispatchEvent(new CustomEvent("lastButtonDisabled", { | ||
detail: isLast || isSinglePage | ||
})); | ||
}, [currentStep, currentTabPages]); | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🧹 Nitpick | 🔵 Trivial
Duplicate event dispatch for lastButtonDisabled
Both effects dispatch the same event; this can cause double-fires. Merge into one effect.
-useEffect(() => {
- const last = currentTabPages.length
- ? Number(currentTabPages[currentTabPages.length - 1].order)
- : null;
- const isLast = last != null && Math.abs(Number(currentStep) - last) < 1e-6;
- const isSinglePage = currentTabPages.length === 1;
- window.dispatchEvent(new CustomEvent("lastButtonDisabled", {
- detail: isLast || isSinglePage
- }));
-}, [currentStep, currentTabPages]);
-
-// ALSO ADD: Dispatch the event immediately when currentTabPages changes
-// Add this new useEffect right after the above one:
-useEffect(() => {
- // This ensures the button state is set immediately when pages load
- if (currentTabPages.length > 0) {
- const last = Number(currentTabPages[currentTabPages.length - 1].order);
- const isLast = Math.abs(Number(currentStep) - last) < 1e-6;
- const isSinglePage = currentTabPages.length === 1;
- window.dispatchEvent(new CustomEvent("lastButtonDisabled", {
- detail: isLast || isSinglePage
- }));
- }
-}, [currentTabPages]); // Only dep
+useEffect(() => {
+ if (!currentTabPages.length) return;
+ const last = Number(currentTabPages[currentTabPages.length - 1]?.order);
+ const isLast = Number.isFinite(last) && Math.abs(Number(currentStep) - last) < 1e-6;
+ const isSinglePage = currentTabPages.length === 1;
+ window.dispatchEvent(new CustomEvent("lastButtonDisabled", { detail: isLast || isSinglePage }));
+}, [currentStep, currentTabPages]);
Also applies to: 208-220
🤖 Prompt for AI Agents
In
health/micro-ui/web/micro-ui-internals/packages/modules/campaign-manager/src/pages/employee/appConfigurationRedesign/AppConfigurationParentLayer.js
around lines 188-203 (and also 208-220), there are two useEffect blocks both
dispatching the same "lastButtonDisabled" CustomEvent which can cause duplicate
event firing; consolidate the logic into a single useEffect that computes last,
isLast and isSinglePage from currentStep and currentTabPages and then dispatches
the CustomEvent once, remove the duplicate effect, and keep the dependency array
[currentStep, currentTabPages] so the event is emitted synchronously when those
values change.
// Build the ordered list of valid steps once. | ||
// 👉 Replace p.step / p.order / p.name with whatever your source-of-truth field is. | ||
const availableSteps = React.useMemo(() => { | ||
const raw = (parentState?.steps | ||
|| parentState?.stepOrder | ||
|| (parentState?.currentTemplate || []).map((p) => p?.step || p?.order || p?.name) | ||
); | ||
|
||
return (raw || []) | ||
.map((x) => parseFloat(String(x))) | ||
.filter((n) => Number.isFinite(n)) | ||
.sort((a, b) => a - b); | ||
}, [parentState]); | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🧹 Nitpick | 🔵 Trivial
Scope availableSteps to active tab (optional)
availableSteps
is global. If navigation should be within the active tab, derive from currentTabPages
instead.
-const availableSteps = React.useMemo(() => {
- const raw = (parentState?.steps
- || parentState?.stepOrder
- || (parentState?.currentTemplate || []).map((p) => p?.step || p?.order || p?.name)
- );
+const availableSteps = React.useMemo(() => {
+ const raw =
+ parentState?.steps ||
+ parentState?.stepOrder ||
+ currentTabPages.map((p) => p?.step || p?.order || p?.name);
return (raw || [])
.map((x) => parseFloat(String(x)))
.filter((n) => Number.isFinite(n))
.sort((a, b) => a - b);
-}, [parentState]);
+}, [currentTabPages, parentState?.steps, parentState?.stepOrder]);
📝 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.
// Build the ordered list of valid steps once. | |
// 👉 Replace p.step / p.order / p.name with whatever your source-of-truth field is. | |
const availableSteps = React.useMemo(() => { | |
const raw = (parentState?.steps | |
|| parentState?.stepOrder | |
|| (parentState?.currentTemplate || []).map((p) => p?.step || p?.order || p?.name) | |
); | |
return (raw || []) | |
.map((x) => parseFloat(String(x))) | |
.filter((n) => Number.isFinite(n)) | |
.sort((a, b) => a - b); | |
}, [parentState]); | |
// Build the ordered list of valid steps once. | |
// 👉 Replace p.step / p.order / p.name with whatever your source-of-truth field is. | |
const availableSteps = React.useMemo(() => { | |
const raw = | |
parentState?.steps || | |
parentState?.stepOrder || | |
currentTabPages.map((p) => p?.step || p?.order || p?.name); | |
return (raw || []) | |
.map((x) => parseFloat(String(x))) | |
.filter((n) => Number.isFinite(n)) | |
.sort((a, b) => a - b); | |
}, [currentTabPages, parentState?.steps, parentState?.stepOrder]); |
🤖 Prompt for AI Agents
In
health/micro-ui/web/micro-ui-internals/packages/modules/campaign-manager/src/pages/employee/appConfigurationRedesign/AppConfigurationParentLayer.js
around lines 222 to 235, availableSteps is currently derived from the global
parentState steps/stepOrder/currentTemplate and thus applies across all tabs;
scope it to the active tab by deriving raw from parentState.currentTabPages (or
the existing currentTabPages variable) for the currently selected tab (falling
back to parentState.steps/stepOrder/currentTemplate if not present), extract the
step/order/name from that tab's pages, and update the useMemo dependency list to
include the active tab/currentTabPages so availableSteps only reflects the
active tab’s pages.
case "PATCH_PAGE_CONDITIONAL_NAV": { | ||
const { pageName, data } = action; // data is the array from onConditionalNavigateChange | ||
|
||
const patchArray = (arr) => { | ||
if (!Array.isArray(arr) || arr.length === 0) return arr; | ||
|
||
// If pageName is provided, try to patch by name | ||
if (pageName) { | ||
const idx = arr.findIndex((p) => p?.name === pageName); | ||
if (idx !== -1) { | ||
return arr.map((p, i) => (i === idx ? { ...p, conditionalNavigateTo: data } : p)); | ||
} | ||
} | ||
|
||
// Fallback: patch the first page (your “current page is first” invariant) | ||
return arr; | ||
}; | ||
|
||
return { | ||
...state, | ||
screenConfig: patchArray(state.screenConfig), | ||
screenData: patchArray(state.screenData), | ||
}; | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
PATCH_PAGE_CONDITIONAL_NAV fallback does nothing; implement first-page patch as commented
Currently returns arr unchanged. Apply actual fallback to avoid silent no-op.
- const patchArray = (arr) => {
+ const patchArray = (arr) => {
if (!Array.isArray(arr) || arr.length === 0) return arr;
-
- // If pageName is provided, try to patch by name
+ // If pageName is provided, try to patch by name
if (pageName) {
const idx = arr.findIndex((p) => p?.name === pageName);
if (idx !== -1) {
return arr.map((p, i) => (i === idx ? { ...p, conditionalNavigateTo: data } : p));
}
}
-
- // Fallback: patch the first page (your “current page is first” invariant)
- return arr;
+ // Fallback: patch the first page
+ return arr.map((p, i) => (i === 0 ? { ...p, conditionalNavigateTo: data } : p));
};
📝 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.
case "PATCH_PAGE_CONDITIONAL_NAV": { | |
const { pageName, data } = action; // data is the array from onConditionalNavigateChange | |
const patchArray = (arr) => { | |
if (!Array.isArray(arr) || arr.length === 0) return arr; | |
// If pageName is provided, try to patch by name | |
if (pageName) { | |
const idx = arr.findIndex((p) => p?.name === pageName); | |
if (idx !== -1) { | |
return arr.map((p, i) => (i === idx ? { ...p, conditionalNavigateTo: data } : p)); | |
} | |
} | |
// Fallback: patch the first page (your “current page is first” invariant) | |
return arr; | |
}; | |
return { | |
...state, | |
screenConfig: patchArray(state.screenConfig), | |
screenData: patchArray(state.screenData), | |
}; | |
} | |
case "PATCH_PAGE_CONDITIONAL_NAV": { | |
const { pageName, data } = action; // data is the array from onConditionalNavigateChange | |
const patchArray = (arr) => { | |
if (!Array.isArray(arr) || arr.length === 0) return arr; | |
// If pageName is provided, try to patch by name | |
if (pageName) { | |
const idx = arr.findIndex((p) => p?.name === pageName); | |
if (idx !== -1) { | |
return arr.map((p, i) => | |
i === idx ? { ...p, conditionalNavigateTo: data } : p | |
); | |
} | |
} | |
// Fallback: patch the first page | |
return arr.map((p, i) => | |
i === 0 ? { ...p, conditionalNavigateTo: data } : p | |
); | |
}; | |
return { | |
...state, | |
screenConfig: patchArray(state.screenConfig), | |
screenData: patchArray(state.screenData), | |
}; | |
} |
🤖 Prompt for AI Agents
In
health/micro-ui/web/micro-ui-internals/packages/modules/campaign-manager/src/pages/employee/appConfigurationRedesign/AppConfigurationWrapper.js
around lines 283 to 306, the PATCH_PAGE_CONDITIONAL_NAV case defines a
patchArray that, on fallback when pageName is not found, currently returns the
array unchanged — implement the commented fallback by returning a new array
where the first element (if any) is immutably replaced with a copy that sets
conditionalNavigateTo to data; ensure you still handle non-array / empty cases
by returning the original arr, and preserve immutability for screenConfig and
screenData updates so both get the patched-first-page object when pageName
lookup fails.
{showPopUp && editorIndex !== null && rules[editorIndex] && ( | ||
<BodyPortal> | ||
<div className="popup-portal-overlay"> | ||
<PopUp | ||
className="digit-popup--fullscreen" | ||
type={"default"} | ||
heading={editLabel} | ||
children={[ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🧹 Nitpick | 🔵 Trivial
Prefer JSX children over the children prop for PopUp
Replace children={[...]}
with nested JSX.
-<PopUp
- className="digit-popup--fullscreen"
- type={"default"}
- heading={editLabel}
- children={[
- <div key="single-rule-editor" style={{ display: "grid", gap: "1rem" }}>
- {(() => { /* ... */ })()}
- </div>,
- ]}
- onOverlayClick={discardAndCloseEditor}
- onClose={discardAndCloseEditor}
- equalWidthButtons={false}
- footerChildren={[ /* ... */ ]}
-/>
+<PopUp
+ className="digit-popup--fullscreen"
+ type="default"
+ heading={editLabel}
+ onOverlayClick={discardAndCloseEditor}
+ onClose={discardAndCloseEditor}
+ equalWidthButtons={false}
+ footerChildren={[ /* ... */ ]}
+>
+ <div style={{ display: "grid", gap: "1rem" }}>
+ {(() => { /* ... */ })()}
+ </div>
+</PopUp>
📝 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.
{showPopUp && editorIndex !== null && rules[editorIndex] && ( | |
<BodyPortal> | |
<div className="popup-portal-overlay"> | |
<PopUp | |
className="digit-popup--fullscreen" | |
type={"default"} | |
heading={editLabel} | |
children={[ | |
{showPopUp && editorIndex !== null && rules[editorIndex] && ( | |
<BodyPortal> | |
<div className="popup-portal-overlay"> | |
<PopUp | |
className="digit-popup--fullscreen" | |
type="default" | |
heading={editLabel} | |
onOverlayClick={discardAndCloseEditor} | |
onClose={discardAndCloseEditor} | |
equalWidthButtons={false} | |
footerChildren={[ /* ... */ ]} | |
> | |
<div style={{ display: "grid", gap: "1rem" }}> | |
{(() => { /* ... */ })()} | |
</div> | |
</PopUp> | |
</div> | |
</BodyPortal> | |
)} |
🧰 Tools
🪛 Biome (2.1.2)
[error] 689-689: Avoid passing children using a prop
The canonical way to pass children in React is to use JSX elements
(lint/correctness/noChildrenProp)
🤖 Prompt for AI Agents
In
health/micro-ui/web/micro-ui-internals/packages/modules/campaign-manager/src/pages/employee/appConfigurationRedesign/NavigationLogicWrapper.js
around lines 682-689, the PopUp is being passed content via the children prop
(children={[ ... ]}); change this to use JSX children instead: remove the
children={...} prop and place the array/JSX elements directly between the
<PopUp>...</PopUp> tags, preserving the same elements, keys and props, and
ensure proper indentation and closing tag.
{/* Remove condition */} | ||
<div | ||
style={{ | ||
marginLeft: "auto", | ||
display: "flex", | ||
alignItems: "center", | ||
gap: "0.25rem", | ||
cursor: "pointer", | ||
}} | ||
onClick={() => removeCondition(editorIndex, idx)} | ||
title={removeConditionLabel} | ||
aria-label={removeConditionLabel} | ||
role="button" | ||
> | ||
<SVG.Delete fill={"#C84C0E"} width={"1.25rem"} height={"1.25rem"} /> | ||
<span style={{ color: "#C84C0E", fontSize: "0.875rem", fontWeight: 500 }}> | ||
{removeConditionLabel} | ||
</span> | ||
</div> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Make “Remove condition” control accessible
Use a button with keyboard handlers.
-<div
- style={{ marginLeft: "auto", display: "flex", alignItems: "center", gap: "0.25rem", cursor: "pointer" }}
- onClick={() => removeCondition(editorIndex, idx)}
- title={removeConditionLabel}
- aria-label={removeConditionLabel}
- role="button"
->
- <SVG.Delete fill={"#C84C0E"} width={"1.25rem"} height={"1.25rem"} />
- <span style={{ color: "#C84C0E", fontSize: "0.875rem", fontWeight: 500 }}>{removeConditionLabel}</span>
-</div>
+<button
+ type="button"
+ style={{ marginLeft: "auto", display: "flex", alignItems: "center", gap: "0.25rem", cursor: "pointer", background: "none", border: "none", padding: 0 }}
+ onClick={() => removeCondition(editorIndex, idx)}
+ onKeyDown={(e) => (e.key === "Enter" || e.key === " ") && removeCondition(editorIndex, idx)}
+ title={removeConditionLabel}
+ aria-label={removeConditionLabel}
+>
+ <SVG.Delete fill={"#C84C0E"} width={"1.25rem"} height={"1.25rem"} />
+ <span style={{ color: "#C84C0E", fontSize: "0.875rem", fontWeight: 500 }}>{removeConditionLabel}</span>
+ <span className="sr-only">{removeConditionLabel}</span>
+</button>
📝 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.
{/* Remove condition */} | |
<div | |
style={{ | |
marginLeft: "auto", | |
display: "flex", | |
alignItems: "center", | |
gap: "0.25rem", | |
cursor: "pointer", | |
}} | |
onClick={() => removeCondition(editorIndex, idx)} | |
title={removeConditionLabel} | |
aria-label={removeConditionLabel} | |
role="button" | |
> | |
<SVG.Delete fill={"#C84C0E"} width={"1.25rem"} height={"1.25rem"} /> | |
<span style={{ color: "#C84C0E", fontSize: "0.875rem", fontWeight: 500 }}> | |
{removeConditionLabel} | |
</span> | |
</div> | |
{/* Remove condition */} | |
- <div | |
- style={{ | |
- marginLeft: "auto", | |
- display: "flex", | |
- alignItems: "center", | |
- gap: "0.25rem", | |
- cursor: "pointer", | |
- }} | |
- onClick={() => removeCondition(editorIndex, idx)} | |
- title={removeConditionLabel} | |
- aria-label={removeConditionLabel} | |
- role="button" | |
- > | |
- <SVG.Delete fill={"#C84C0E"} width={"1.25rem"} height={"1.25rem"} /> | |
- <span style={{ color: "#C84C0E", fontSize: "0.875rem", fontWeight: 500 }}> | |
- {removeConditionLabel} | |
- </span> | |
<button | |
type="button" | |
style={{ | |
marginLeft: "auto", | |
display: "flex", | |
alignItems: "center", | |
gap: "0.25rem", | |
cursor: "pointer", | |
background: "none", | |
border: "none", | |
padding: 0, | |
}} | |
onClick={() => removeCondition(editorIndex, idx)} | |
onKeyDown={e => (e.key === "Enter" || e.key === " ") && removeCondition(editorIndex, idx)} | |
title={removeConditionLabel} | |
aria-label={removeConditionLabel} | |
> | |
<SVG.Delete fill={"#C84C0E"} width={"1.25rem"} height={"1.25rem"} /> | |
<span style={{ color: "#C84C0E", fontSize: "0.875rem", fontWeight: 500 }}> | |
{removeConditionLabel} | |
</span> | |
<span className="sr-only">{removeConditionLabel}</span> | |
</button> |
🧰 Tools
🪛 Biome (2.1.2)
[error] 949-961: Enforce to have the onClick mouse event with the onKeyUp, the onKeyDown, or the onKeyPress keyboard event.
Actions triggered using mouse events should have corresponding keyboard events to account for keyboard-only navigation.
(lint/a11y/useKeyWithClickEvents)
[error] 960-960: The elements with this role can be changed to the following elements:
For examples and more information, see WAI-ARIA Roles
(lint/a11y/useSemanticElements)
[error] 949-961: The HTML element with the interactive role "button" is not focusable.
A non-interactive HTML element that is not focusable may not be reachable for users that rely on keyboard navigation, even with an added role like "button".
Add a tabIndex attribute to make this element focusable.
(lint/a11y/useFocusableInteractive)
🤖 Prompt for AI Agents
In
health/micro-ui/web/micro-ui-internals/packages/modules/campaign-manager/src/pages/employee/appConfigurationRedesign/NavigationLogicWrapper.js
around lines 948 to 966, the "Remove condition" element is a clickable div which
is not keyboard-accessible; replace the div with a semantic <button
type="button"> (remove role="button"), keep the onClick handler, ensure
aria-label is preserved, include the SVG and label inside the button, and ensure
button has visible focus styles and prevents unintended form submission; if any
custom key handling is required, add onKeyDown to handle Enter/Space, otherwise
rely on native button behavior for keyboard accessibility.
const FilterIcon = (props) => ( | ||
<svg onClick={props?.onClick} width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg"> | ||
<path | ||
d="M0.250666 1.61C2.27067 4.2 6.00067 9 6.00067 9V15C6.00067 15.55 6.45067 16 7.00067 16H9.00067C9.55067 16 10.0007 15.55 10.0007 15V9C10.0007 9 13.7207 4.2 15.7407 1.61C16.2507 0.95 15.7807 0 14.9507 0H1.04067C0.210666 0 -0.259334 0.95 0.250666 1.61Z" | ||
fill="#C84C0E" | ||
/> | ||
</svg> | ||
|
||
); | ||
const Filter = (props) => ( | ||
<div className="digit-search-action"> | ||
{/* <RoundedLabel count={props.filterCount}></RoundedLabel> */} | ||
<FilterIcon /> <span className="digit-search-text">{props.t(props.field.label) || "LABEL"}</span> | ||
</div> | ||
); | ||
|
||
|
||
const Toggle = (props) => ( | ||
<Switch | ||
label={props.t(props.field?.label) || "LABEL"} | ||
onToggle={null} | ||
isCheckedInitially={true} | ||
shapeOnOff | ||
/> | ||
); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
SVG used as control; add semantics and keyboard support
Wrap in a button, provide accessible name.
-const FilterIcon = (props) => (
- <svg onClick={props?.onClick} width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
- <path d="M0.250666 1.61C2.27067 4.2 6.00067 9 6.00067 9V15C6.00067 15.55 6.45067 16 7.00067 16H9.00067C9.55067 16 10.0007 15.55 10.0007 15V9C10.0007 9 13.7207 4.2 15.7407 1.61C16.2507 0.95 15.7807 0 14.9507 0H1.04067C0.210666 0 -0.259334 0.95 0.250666 1.61Z" fill="#C84C0E"/>
- </svg>
-);
+const FilterIcon = ({ onClick }) => (
+ <button type="button" aria-label="Filter" onClick={onClick} style={{ background: "none", border: "none", padding: 0, cursor: "pointer" }}>
+ <svg width="16" height="16" viewBox="0 0 16 16" role="img" aria-hidden="true" xmlns="http://www.w3.org/2000/svg">
+ <title>Filter</title>
+ <path d="M0.250666 1.61C2.27067 4.2 6.00067 9 6.00067 9V15C6.00067 15.55 6.45067 16 7.00067 16H9.00067C9.55067 16 10.0007 15.55 10.0007 15V9C10.0007 9 13.7207 4.2 15.7407 1.61C16.2507 0.95 15.7807 0 14.9507 0H1.04067C0.210666 0 -0.259334 0.95 0.250666 1.61Z" fill="#C84C0E"/>
+ </svg>
+ </button>
+);
📝 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.
const FilterIcon = (props) => ( | |
<svg onClick={props?.onClick} width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg"> | |
<path | |
d="M0.250666 1.61C2.27067 4.2 6.00067 9 6.00067 9V15C6.00067 15.55 6.45067 16 7.00067 16H9.00067C9.55067 16 10.0007 15.55 10.0007 15V9C10.0007 9 13.7207 4.2 15.7407 1.61C16.2507 0.95 15.7807 0 14.9507 0H1.04067C0.210666 0 -0.259334 0.95 0.250666 1.61Z" | |
fill="#C84C0E" | |
/> | |
</svg> | |
); | |
const Filter = (props) => ( | |
<div className="digit-search-action"> | |
{/* <RoundedLabel count={props.filterCount}></RoundedLabel> */} | |
<FilterIcon /> <span className="digit-search-text">{props.t(props.field.label) || "LABEL"}</span> | |
</div> | |
); | |
const Toggle = (props) => ( | |
<Switch | |
label={props.t(props.field?.label) || "LABEL"} | |
onToggle={null} | |
isCheckedInitially={true} | |
shapeOnOff | |
/> | |
); | |
const FilterIcon = ({ onClick }) => ( | |
<button | |
type="button" | |
aria-label="Filter" | |
onClick={onClick} | |
style={{ background: "none", border: "none", padding: 0, cursor: "pointer" }} | |
> | |
<svg | |
width="16" | |
height="16" | |
viewBox="0 0 16 16" | |
role="img" | |
aria-hidden="true" | |
xmlns="http://www.w3.org/2000/svg" | |
> | |
<title>Filter</title> | |
<path | |
d="M0.250666 1.61C2.27067 4.2 6.00067 9 6.00067 9V15C6.00067 15.55 6.45067 16 7.00067 16H9.00067C9.55067 16 10.0007 15.55 10.0007 15V9C10.0007 9 13.7207 4.2 15.7407 1.61C16.2507 0.95 15.7807 0 14.9507 0H1.04067C0.210666 0 -0.259334 0.95 0.250666 1.61Z" | |
fill="#C84C0E" | |
/> | |
</svg> | |
</button> | |
); |
🧰 Tools
🪛 Biome (2.1.2)
[error] 39-39: Alternative text title element cannot be empty
For accessibility purposes, SVGs should have an alternative text, provided via title element. If the svg element has role="img", you should add the aria-label or aria-labelledby attribute.
(lint/a11y/noSvgWithoutTitle)
[error] 39-39: Enforce to have the onClick mouse event with the onKeyUp, the onKeyDown, or the onKeyPress keyboard event.
Actions triggered using mouse events should have corresponding keyboard events to account for keyboard-only navigation.
(lint/a11y/useKeyWithClickEvents)
🤖 Prompt for AI Agents
In
health/micro-ui/web/micro-ui-internals/packages/modules/campaign-manager/src/utils/template_components/RegistrationComponents.js
around lines 38-45, the SVG is used as an interactive control without semantics
or keyboard support; replace it with a focusable <button type="button"> wrapper
(move onClick from the svg to the button), accept and pass an accessible name
via aria-label (or aria-labelledby) from props, ensure keyboard activation is
provided by the native button, remove onClick from the svg, and forward any
className/other props to the button so styling and event handling remain
consistent.
const Toggle = (props) => <Switch label={props.t(props.field?.label) || "LABEL"} onToggle={null} isCheckedInitially={true} shapeOnOff />; | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Provide a no-op handler for Toggle
Avoid passing null; supply a stable function.
-const Toggle = (props) => <Switch label={props.t(props.field?.label) || "LABEL"} onToggle={null} isCheckedInitially={true} shapeOnOff />;
+const Toggle = (props) => <Switch label={props.t(props.field?.label) || "LABEL"} onToggle={() => {}} isCheckedInitially={true} shapeOnOff />;
📝 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.
const Toggle = (props) => <Switch label={props.t(props.field?.label) || "LABEL"} onToggle={null} isCheckedInitially={true} shapeOnOff />; | |
const Toggle = (props) => <Switch label={props.t(props.field?.label) || "LABEL"} onToggle={() => {}} isCheckedInitially={true} shapeOnOff />; |
🤖 Prompt for AI Agents
In
health/micro-ui/web/micro-ui-internals/packages/modules/campaign-manager/src/utils/template_components/RegistrationComponents.js
around lines 87-88, the Toggle component currently passes onToggle={null};
replace that with a stable no-op handler instead of null (e.g., a module-level
or memoized no-op function such as a useCallback(() => {}) or a shared const
noop = () => {}) so the prop always receives a callable function and avoids
passing null.
const householdDetails = props.beneficiaryDetails | ||
? props.beneficiaryDetails | ||
: [ | ||
//TODO: Need this to be moved to config @Pitabsh, @ram | ||
// { label: "HOUSEHOLD_HEAD", value: "Value" }, | ||
// { label: "ADMINSTRATIVE_AREA", value: "value" }, | ||
// { label: "MEMBER_COUNT", value: 5 }, | ||
|
||
{ label: "HouseHold Head", value: "Rohit" }, | ||
{ label: "Adminstrative Area", value: "Boundary A" }, | ||
{ label: "Member Count", value: 5 }, | ||
]; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🧹 Nitpick | 🔵 Trivial
Avoid hardcoded placeholder PII in defaults
The fallback shows real-looking names/areas. Remove or gate behind config; default to translated placeholders.
- const householdDetails = props.beneficiaryDetails
- ? props.beneficiaryDetails
- : [
- { label: "HouseHold Head", value: "Rohit" },
- { label: "Adminstrative Area", value: "Boundary A" },
- { label: "Member Count", value: 5 },
- ];
+ const householdDetails = Array.isArray(props.beneficiaryDetails)
+ ? props.beneficiaryDetails
+ : [];
If placeholders are required for design, prefer keys like "N/A" via t(..).
📝 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.
const householdDetails = props.beneficiaryDetails | |
? props.beneficiaryDetails | |
: [ | |
//TODO: Need this to be moved to config @Pitabsh, @ram | |
// { label: "HOUSEHOLD_HEAD", value: "Value" }, | |
// { label: "ADMINSTRATIVE_AREA", value: "value" }, | |
// { label: "MEMBER_COUNT", value: 5 }, | |
{ label: "HouseHold Head", value: "Rohit" }, | |
{ label: "Adminstrative Area", value: "Boundary A" }, | |
{ label: "Member Count", value: 5 }, | |
]; | |
const householdDetails = Array.isArray(props.beneficiaryDetails) | |
? props.beneficiaryDetails | |
: []; |
🤖 Prompt for AI Agents
In
health/micro-ui/web/micro-ui-internals/packages/modules/campaign-manager/src/utils/template_components/RegistrationComponents.js
around lines 156 to 167, replace the hardcoded PII-like fallback data with
non-identifiable, translatable placeholders or configurable defaults: remove
real-looking name/area values and instead use either values from configuration
(if provided) or neutral placeholders such as t('N/A') /
t('placeholder.householdHead') / t('placeholder.administrativeArea') and numeric
defaults like 0 or null; ensure the fallback branch checks a config flag or env
to permit demo placeholders and document where to supply real defaults via props
or config.
There was a problem hiding this 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 (3)
health/micro-ui/web/micro-ui-internals/packages/modules/health-payments/src/components/attendance_inbox/table_inbox.js (3)
87-117
: Fix misleading comments and simplify condition.The comments at lines 99 and 104 are incorrect:
- Line 99 says "Allowed → Navigate" but this branch executes when
currentDate > endDate
, meaning the project has expired (not "allowed" in the sense of active).- Line 104 says "Expired → handle case" but this branch executes when
currentDate <= endDate
, meaning the project is still active (not expired).Additionally, the condition
!(currentDate <= endDate)
is confusing with its double negative.Apply this diff to fix the comments and simplify the condition:
- if (!(currentDate <= endDate)) { - // Allowed → Navigate + if (currentDate > endDate) { + // Expired project → Navigate to view-only mode history.push( `/${window?.contextPath}/employee/payments/view-attendance?registerNumber=${row?.id}&boundaryCode=${row?.boundary}` ); } else { - // Expired → handle case + // Active project → Navigate to edit mode history.push( `/${window?.contextPath}/employee/payments/edit-register?registerNumber=${row?.id}&boundaryCode=${row?.boundary}®isterId=${row?.registerId}` ); }
Note: This code segment also has the following issues previously flagged in earlier reviews that remain unaddressed:
- Potential ms/sec date bug:
Date.now()
returns milliseconds, butendDate
may be in seconds. Normalize before comparison.- Missing stopPropagation: The click handler doesn't stop event propagation, which can cause double navigation when combined with
handleRowClick
.- Session storage preference: Prefer the
selectedProject
prop over session storage to avoid stale data.- Console.warn vs user feedback: Replace
console.warn
with a user-visible toast notification.
242-252
: Fix loader container height for proper centering.The loader container uses
height: "1vh"
(very small) combined withpaddingTop: "2rem"
andmarginTop: "2rem"
, which prevents proper vertical centering. This issue was previously flagged and remains unaddressed.For consistency, the loader container should use a similar height to the
NoResultsFound
component.Apply this diff:
{isLoading ? <div style={{ display: "flex", justifyContent: "center", alignItems: "center", - height: "1vh", - paddingTop: "2rem", - marginTop:"2rem" + height: "50vh" }}> <Loader /> </div>
261-262
: Remove redundant progressPending prop.The
progressPending={isLoading}
prop is alwaysfalse
when theDataTable
renders, since this code path only executes whenisLoading
isfalse
(line 242 ternary). This was previously flagged and remains unaddressed.- progressPending={isLoading} - progressComponent={<Loader />}
📜 Review details
Configuration used: CodeRabbit UI
Review profile: ASSERTIVE
Plan: Pro
📒 Files selected for processing (3)
health/micro-ui/web/micro-ui-internals/packages/modules/health-payments/src/components/attendance_inbox/attendance_inbox.js
(2 hunks)health/micro-ui/web/micro-ui-internals/packages/modules/health-payments/src/components/attendance_inbox/table_inbox.js
(2 hunks)health/micro-ui/web/micro-ui-internals/packages/modules/health-payments/src/pages/employee/attendance_inbox.js
(1 hunks)
🧰 Additional context used
📓 Path-based instructions (1)
**/*.js
⚙️ CodeRabbit configuration file
check
Files:
health/micro-ui/web/micro-ui-internals/packages/modules/health-payments/src/components/attendance_inbox/attendance_inbox.js
health/micro-ui/web/micro-ui-internals/packages/modules/health-payments/src/components/attendance_inbox/table_inbox.js
health/micro-ui/web/micro-ui-internals/packages/modules/health-payments/src/pages/employee/attendance_inbox.js
🧬 Code graph analysis (3)
health/micro-ui/web/micro-ui-internals/packages/modules/health-payments/src/components/attendance_inbox/attendance_inbox.js (2)
health/micro-ui/web/micro-ui-internals/packages/modules/health-payments/src/components/bill_inbox/BillInbox.js (1)
selectedProject
(37-37)health/micro-ui/web/micro-ui-internals/packages/modules/health-payments/src/components/SearchResultsPlaceholder.js (1)
SearchResultsPlaceholder
(17-31)
health/micro-ui/web/micro-ui-internals/packages/modules/health-payments/src/components/attendance_inbox/table_inbox.js (3)
health/micro-ui/web/micro-ui-internals/packages/modules/health-payments/src/pages/employee/EditRegister.js (2)
Digit
(34-34)history
(27-27)health/micro-ui/web/micro-ui-internals/packages/modules/health-payments/src/pages/employee/ViewAttendance.js (2)
Digit
(32-32)history
(24-24)health/micro-ui/web/micro-ui-internals/packages/modules/health-payments/src/components/bill_inbox/billInboxTable.js (3)
history
(23-23)columns
(70-140)handleRowClick
(159-163)
health/micro-ui/web/micro-ui-internals/packages/modules/health-payments/src/pages/employee/attendance_inbox.js (1)
health/micro-ui/web/micro-ui-internals/packages/modules/health-payments/src/components/attendance_inbox/attendance_inbox.js (1)
AttendanceInboxComponent
(14-244)
⏰ Context from checks skipped due to timeout of 10000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (2)
- GitHub Check: Build application amd64
- GitHub Check: Build application arm64
🔇 Additional comments (4)
health/micro-ui/web/micro-ui-internals/packages/modules/health-payments/src/components/attendance_inbox/table_inbox.js (1)
255-255
: LGTM: NoResultsFound height adjustment.The height change from the original value to
40vh
appears intentional and aligns with the new layout design.health/micro-ui/web/micro-ui-internals/packages/modules/health-payments/src/pages/employee/attendance_inbox.js (1)
43-50
: LGTM: Minor styling adjustments.The fontSize reduction to
28px
and the wrapper height adjustment to160px
appear to be intentional layout refinements. The explicit JSX braces around the wrapper are redundant but harmless.health/micro-ui/web/micro-ui-internals/packages/modules/health-payments/src/components/attendance_inbox/attendance_inbox.js (2)
200-200
: LGTM: Consistent height styling.Adding explicit
height: "60vh"
to the filter and table sections improves layout consistency and prevents content overflow.Also applies to: 210-210
214-214
: LGTM: JSX braces are redundant but harmless.Wrapping
<SearchResultsPlaceholder />
in explicit braces ({<SearchResultsPlaceholder />}
) is unnecessary since JSX elements don't require wrapping, but it doesn't affect functionality.Optionally, simplify to:
- {<SearchResultsPlaceholder placeholderText={"HCM_AM_FILTER_AND_CHOOSE_BOUNDARY_PLACEHOLDER_TEXT"} />} + <SearchResultsPlaceholder placeholderText={"HCM_AM_FILTER_AND_CHOOSE_BOUNDARY_PLACEHOLDER_TEXT"} />
<div className="custom-register-inbox-screen" style={{ | ||
// "minHeight":"20%", | ||
// "maxHeight":"30%" | ||
}}> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🧹 Nitpick | 🔵 Trivial
Remove commented-out code.
Lines 195-196 contain commented-out minHeight
and maxHeight
styles. Remove commented code to keep the codebase clean.
<div className="custom-register-inbox-screen" style={{
- // "minHeight":"20%",
- // "maxHeight":"30%"
}}>
If these styles are needed, uncomment and apply them; otherwise, remove them entirely.
🤖 Prompt for AI Agents
In
health/micro-ui/web/micro-ui-internals/packages/modules/health-payments/src/components/attendance_inbox/attendance_inbox.js
around lines 194 to 197, remove the commented-out inline style lines for
"minHeight" and "maxHeight" (lines 195-196) so the JSX contains only the active
style object; if those height constraints are actually required, instead of
leaving them commented, uncomment them and set appropriate numeric/string values
in the style object.
There was a problem hiding this 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 (2)
health/micro-ui/web/micro-ui-internals/packages/modules/health-hrms/src/pages/employee/HierarchySelection.js (2)
96-101
: Redundant session write persists.The session storage write on line 98 is redundant since
onHierarchySelect
(line 69) already persistsHIERARCHY_TYPE_SELECTED
. Remove the duplicate write from this else block.Apply this diff:
else { - - Digit.SessionStorage.set("HIERARCHY_TYPE_SELECTED", selectedHierarchy); - onHierarchyChosen(selectedHierarchy); }
121-134
: Unnecessary braces around Loader.The centered loader improves UX consistency, but line 132 has unnecessary braces around the component.
Remove the braces:
- {<Loader />} + <Loader />
📜 Review details
Configuration used: CodeRabbit UI
Review profile: ASSERTIVE
Plan: Pro
📒 Files selected for processing (1)
health/micro-ui/web/micro-ui-internals/packages/modules/health-hrms/src/pages/employee/HierarchySelection.js
(4 hunks)
🧰 Additional context used
📓 Path-based instructions (1)
**/*.js
⚙️ CodeRabbit configuration file
check
Files:
health/micro-ui/web/micro-ui-internals/packages/modules/health-hrms/src/pages/employee/HierarchySelection.js
🧬 Code graph analysis (1)
health/micro-ui/web/micro-ui-internals/packages/modules/health-hrms/src/pages/employee/HierarchySelection.js (4)
health/micro-ui/web/micro-ui-internals/packages/modules/pgr/src/components/HierarchySelection.js (3)
HierarchySelection
(15-167)selectedHierarchy
(24-26)isStoreLoading
(45-51)health/micro-ui/web/micro-ui-internals/packages/modules/health-hrms/src/hooks/boundaries/useFetchAllHierarchies.js (1)
Digit
(21-30)health/micro-ui/web/micro-ui-internals/packages/modules/pgr/src/hooks/boundary/useFetchAllHierarchies.js (1)
Digit
(21-30)health/micro-ui/web/micro-ui-internals/packages/modules/health-hrms/src/components/pageComponents/Jurisdictions.js (1)
selectedHierarchy
(8-8)
<p className="description-type">{t(`HCM_HIERARCHY_TYPE_DESCRIPTION`)}</p> | ||
<LabelFieldPair> | ||
<div className="campaign-type"> | ||
<div className=""> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🧩 Analysis chain
Verify layout impact of removed className.
The className
was changed from "campaign-type"
to an empty string. If CSS rules target .campaign-type
, this change may affect the label/field layout or spacing.
Run this script to check for CSS dependencies:
🏁 Script executed:
#!/bin/bash
# Description: Check if campaign-type class is defined in CSS/styling files
# Search for campaign-type class definitions in CSS/SCSS/styled files
rg -n --type-add 'style:*.{css,scss,styled.js,styles.js}' --type style 'campaign-type' -C 2
# Also check if it's used elsewhere in the codebase
rg -n 'className.*campaign-type' -C 1
Length of output: 25365
Re-add className="campaign-type"
to the wrapper <div>
– this class applies crucial margin styles defined in packages/css/src/pages/employee/campaign.scss
(line 24) for correct layout spacing.
🤖 Prompt for AI Agents
In
health/micro-ui/web/micro-ui-internals/packages/modules/health-hrms/src/pages/employee/HierarchySelection.js
around line 144, the wrapper <div> lost its className="campaign-type" which
provides essential margin styles from
packages/css/src/pages/employee/campaign.scss (line 24); restore
className="campaign-type" on that <div> so the component regains the intended
layout spacing.
There was a problem hiding this 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
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
health/micro-ui/web/micro-ui-internals/packages/modules/health-payments/src/pages/employee/my_bills.js (1)
63-67
: Fix offset calculation to use new rows per page value.The offset calculation on line 66 uses the stale
rowsPerPage
variable instead of the newcurrentRowsPerPage
parameter. This will produce an incorrect offset when the user changes the rows per page setting.Apply this diff to fix the calculation:
const handlePerRowsChange = (currentRowsPerPage, currentPage) => { setRowsPerPage(currentRowsPerPage); setCurrentPage(1); - setLimitAndOffset({ limit: currentRowsPerPage, offset: (currentPage - 1) * rowsPerPage }); + setLimitAndOffset({ limit: currentRowsPerPage, offset: 0 }); }Note: Since you're resetting to page 1 (line 65), the offset should be 0, not calculated from currentPage.
📜 Review details
Configuration used: CodeRabbit UI
Review profile: ASSERTIVE
Plan: Pro
📒 Files selected for processing (1)
health/micro-ui/web/micro-ui-internals/packages/modules/health-payments/src/pages/employee/my_bills.js
(2 hunks)
🧰 Additional context used
📓 Path-based instructions (1)
**/*.js
⚙️ CodeRabbit configuration file
check
Files:
health/micro-ui/web/micro-ui-internals/packages/modules/health-payments/src/pages/employee/my_bills.js
🧬 Code graph analysis (1)
health/micro-ui/web/micro-ui-internals/packages/modules/health-payments/src/pages/employee/my_bills.js (3)
health/micro-ui/web/micro-ui-internals/packages/modules/health-payments/src/components/MyBillsSearch.js (1)
MyBillsSearch
(13-88)health/micro-ui/web/micro-ui-internals/packages/modules/health-dss/src/hooks/useInboxSearch.js (1)
isFetching
(74-74)health/micro-ui/web/micro-ui-internals/packages/modules/health-payments/src/components/MyBillsTable.js (1)
MyBillsTable
(21-227)
⏰ Context from checks skipped due to timeout of 10000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (2)
- GitHub Check: Build application arm64
- GitHub Check: Build application amd64
import React, { useMemo, useState, useEffect } from "react"; | ||
import { useTranslation } from "react-i18next"; | ||
import { Header, InboxSearchComposer, Loader } from "@egovernments/digit-ui-react-components"; | ||
import { Header, InboxSearchComposer } from "@egovernments/digit-ui-react-components"; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Remove unused import.
InboxSearchComposer
is imported but not used anywhere in this file.
Apply this diff to remove the unused import:
-import { Header, InboxSearchComposer } from "@egovernments/digit-ui-react-components";
+import { Header } from "@egovernments/digit-ui-react-components";
📝 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.
import { Header, InboxSearchComposer } from "@egovernments/digit-ui-react-components"; | |
import { Header } from "@egovernments/digit-ui-react-components"; |
🤖 Prompt for AI Agents
In
health/micro-ui/web/micro-ui-internals/packages/modules/health-payments/src/pages/employee/my_bills.js
around line 3, the imported symbol InboxSearchComposer is unused; remove it from
the import statement (leave Header) so the line only imports the used components
and save the file to clear the unused-import lint error.
return <div style={{ | ||
display: "flex", | ||
justifyContent: "center", | ||
alignItems: "center", | ||
height: "100vh" // full screen height | ||
}}> | ||
<Loader /> | ||
</div> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🧹 Nitpick | 🔵 Trivial
Consider extracting the full-page loader pattern.
The full-page centered loader implementation is correct, but according to the PR context, this pattern is duplicated across multiple HRMS-related components (HierarchySelection.js, Inbox.js, etc.).
Consider creating a reusable FullPageLoader
component to reduce duplication:
// In a shared components file
const FullPageLoader = () => (
<div style={{
display: "flex",
justifyContent: "center",
alignItems: "center",
height: "100vh"
}}>
<Loader />
</div>
);
Then use it here:
if (isBillLoading) {
- return <div style={{
- display: "flex",
- justifyContent: "center",
- alignItems: "center",
- height: "100vh" // full screen height
- }}>
- <Loader />
- </div>
+ return <FullPageLoader />
}
Note: Using 100vh
can cause issues on mobile browsers where the viewport height changes as address bars show/hide. Consider using 100dvh
(dynamic viewport height) for better mobile support if targeting modern browsers.
🤖 Prompt for AI Agents
In
health/micro-ui/web/micro-ui-internals/packages/modules/health-payments/src/pages/employee/my_bills.js
around lines 92-99, the full-page centered loader markup is duplicated across
multiple HRMS components; extract this into a reusable FullPageLoader component
in a shared components folder (e.g.,
packages/shared/components/FullPageLoader.js or similar), implement it to render
a centered Loader and prefer using height: "100dvh" for better mobile viewport
behavior, export it, and replace the inline div/Loader here with the imported
FullPageLoader component to remove duplication.
{<Header styles={{ fontSize: "32px" }}> | ||
{t("HCM_AM_MY_BILLS")} | ||
</Header> | ||
</Header>} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🧹 Nitpick | 🔵 Trivial
Remove unnecessary braces around JSX elements.
The Header
(lines 104-106) and Card
(lines 111-114) elements are wrapped in unnecessary braces. Since these are direct JSX elements without any conditional logic or expression evaluation, the braces add no value and reduce readability.
Apply this diff to simplify the JSX:
- {<Header styles={{ fontSize: "32px" }}>
+ <Header styles={{ fontSize: "32px" }}>
{t("HCM_AM_MY_BILLS")}
- </Header>}
+ </Header>
<MyBillsSearch onSubmit={onSubmit} onClear={onClear} />
- {<Card>
+ <Card>
{isFetching ? <Loader /> : tableData.length === 0 ? <NoResultsFound text={t(`HCM_AM_NO_DATA_FOUND_FOR_BILLS`)} /> : <MyBillsTable data={tableData} totalCount={totalCount} rowsPerPage={rowsPerPage} currentPage={currentPage} handlePageChange={handlePageChange}
handlePerRowsChange={handlePerRowsChange} />}
- </Card>}
+ </Card>
Also applies to: 111-114
🤖 Prompt for AI Agents
In
health/micro-ui/web/micro-ui-internals/packages/modules/health-payments/src/pages/employee/my_bills.js
around lines 104-106 and 111-114, there are unnecessary surrounding braces
wrapping JSX elements (Header and Card). Remove the extra { ... } tokens so the
JSX elements are rendered directly (e.g., replace `{<Header ...>...</Header>}`
with `<Header ...>...</Header>` and similarly for Card), preserving props,
children, and indentation; run a quick lint/format to ensure valid JSX after
removal.
There was a problem hiding this 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 (5)
health/micro-ui/web/micro-ui-internals/packages/modules/health-payments/src/components/editAttendeesPopUp.js (3)
212-268
: Fix PopUp children API & missing keys (still failing lint).Biome’s
noChildrenProp
/useJsxKeyInIterable
errors persist because the popup still passeschildren
/footerChildren
arrays without keys—the build will continue to fail. Move the JSX inside<PopUp>
as proper children and render the footer via a footer slot (or add stable keys if you must keep arrays).- <PopUp - style={{ minWidth: popupWidth, height: "650px" }} - onClose={onClose} - heading={t(heading)} - onOverlayClick={onClose} - children={[ - isAttendanceLoading || isAllIndividualsLoading ? ( - <div style={{ - display: "flex", - justifyContent: "center", - alignItems: "center", - height: "100vh" // full screen height - }}> - <Loader /> - </div> - ) : ( - <div style={{ - display: "flex", - flexDirection: "column", - gap: "16px", // same as Tailwind gap-4 - }} > - <TextInput type="search" name="title" placeholder={t("HCM_AM_VIEW_REGISTER_PLACE_HOLDER")} value={searchQuery} onChange={(e) => setSearchQuery(e.target.value)} /> - <EditAttendanceManagementTable - height="320px" - data={searchQuery != "" ? filteredData : attendanceSummary} - setAttendanceSummary={setAttendanceSummary} - disableUser={disableUser} - registerId={businessId} - registerNumber={registerId} - editAction={true} - /> - <div style={{ display: "grid", gridTemplateColumns: `${labelWidth} auto`, rowGap: "5px", alignItems: "center" }}> - - - <div>{t(labels[1])}</div> - <Button label={t("HCM_AM_SEARCH_USER")} variation="link" onClick={() => { - - - - history.push(`/${window?.contextPath}/employee/payments/attendee-inbox?registerId=${registerId}&boundaryCode=${boundaryCode}`) - }} /> - </div> - - </div> - ) - ]} - footerChildren={[ - <Button - type={"button"} - size={"large"} - variation={"primary"} - label={t("HCM_AM_SAVE_AND_CLOSE")} - onClick={onClose} - />, - ]} - sortFooterChildren={true} - /> + <PopUp + style={{ minWidth: popupWidth, height: "650px" }} + onClose={onClose} + heading={t(heading)} + onOverlayClick={onClose} + > + {isAttendanceLoading || isAllIndividualsLoading ? ( + <div + style={{ + display: "flex", + justifyContent: "center", + alignItems: "center", + height: "100vh", + }} + > + <Loader /> + </div> + ) : ( + <div + style={{ + display: "flex", + flexDirection: "column", + gap: "16px", + }} + > + <TextInput + type="search" + name="title" + placeholder={t("HCM_AM_VIEW_REGISTER_PLACE_HOLDER")} + value={searchQuery} + onChange={(e) => setSearchQuery(e.target.value)} + /> + <EditAttendanceManagementTable + height="320px" + data={searchQuery !== "" ? filteredData : attendanceSummary} + setAttendanceSummary={setAttendanceSummary} + disableUser={disableUser} + registerId={businessId} + registerNumber={registerId} + editAction={true} + /> + <div + style={{ + display: "grid", + gridTemplateColumns: `${labelWidth} auto`, + rowGap: "5px", + alignItems: "center", + }} + > + <div>{t(labels[1])}</div> + <Button + label={t("HCM_AM_SEARCH_USER")} + variation="link" + onClick={() => + history.push( + `/${window?.contextPath}/employee/payments/attendee-inbox?registerId=${registerId}&boundaryCode=${boundaryCode}` + ) + } + /> + </div> + </div> + )} + <div slot="footer"> + <Button + type="button" + size="large" + variation="primary" + label={t("HCM_AM_SAVE_AND_CLOSE")} + onClick={onClose} + /> + </div> + </PopUp>
94-101
: Guard against missing attendees before mapping.
AttendanceData.attendanceRegister[0].attendees
is assumed to exist; when the API omits or nullsattendees
, this effect throws and bricks the popup. Please default to an empty array (and filter falsy IDs) before mapping.- useEffect(() => { - if (AttendanceData?.attendanceRegister?.length > 0) { - const ids = AttendanceData.attendanceRegister[0].attendees.map( - (a) => a.individualId - ); - setIndividualIds(ids); - } - }, [AttendanceData]); + useEffect(() => { + const attendees = AttendanceData?.attendanceRegister?.[0]?.attendees ?? []; + setIndividualIds( + Array.isArray(attendees) + ? attendees.map((a) => a?.individualId).filter(Boolean) + : [] + ); + }, [AttendanceData]);
127-164
: HardengetUserAttendanceSummary
before accessing register data.This helper still indexes
attendanceData.attendanceRegister[0].attendees
unconditionally. If the register array or its attendees payload is missing/empty, the popup crashes. Guard the access and short-circuit to[]
.- function getUserAttendanceSummary(attendanceData, individualsData, t) { - const attendanceLogData = - attendanceData.attendanceRegister[0].attendees.map((individualEntry) => { + function getUserAttendanceSummary(attendanceData, individualsData, t) { + const attendees = attendanceData?.attendanceRegister?.[0]?.attendees; + if (!Array.isArray(attendees) || attendees.length === 0) return []; + + const attendanceLogData = attendees.map((individualEntry) => {health/micro-ui/web/micro-ui-internals/packages/modules/health-payments/src/pages/employee/EditRegister.js (2)
34-51
: Fix destructuring fallback forlocation.state
.
const { fromCampaignSupervisor } = location.state || false;
will throw whenever the page is opened without navigation state (it tries to destructure fromfalse
). Default to an object before destructuring.- const { fromCampaignSupervisor } = location.state || false; + const { fromCampaignSupervisor = false } = location?.state || {};
145-167
:getUserAttendanceSummary
must handle missing attendees safely.The helper still dereferences
attendanceData.attendanceRegister[0].attendees
without checks. If the register is empty, the whole page crashes. Guard the register lookup and bail out with[]
when attendees are absent.function getUserAttendanceSummary(attendanceData, individualsData, t) { - - const attendanceLogData = attendanceData.attendanceRegister[0].attendees.map((individualEntry) => { + const attendees = attendanceData?.attendanceRegister?.[0]?.attendees; + if (!Array.isArray(attendees) || attendees.length === 0) return []; + + const attendanceLogData = attendees.map((individualEntry) => {
📜 Review details
Configuration used: CodeRabbit UI
Review profile: ASSERTIVE
Plan: Pro
📒 Files selected for processing (3)
health/micro-ui/web/micro-ui-internals/packages/modules/health-payments/src/components/EditAttendanceManagementTable.js
(1 hunks)health/micro-ui/web/micro-ui-internals/packages/modules/health-payments/src/components/editAttendeesPopUp.js
(1 hunks)health/micro-ui/web/micro-ui-internals/packages/modules/health-payments/src/pages/employee/EditRegister.js
(1 hunks)
🧰 Additional context used
📓 Path-based instructions (1)
**/*.js
⚙️ CodeRabbit configuration file
check
Files:
health/micro-ui/web/micro-ui-internals/packages/modules/health-payments/src/components/editAttendeesPopUp.js
health/micro-ui/web/micro-ui-internals/packages/modules/health-payments/src/components/EditAttendanceManagementTable.js
health/micro-ui/web/micro-ui-internals/packages/modules/health-payments/src/pages/employee/EditRegister.js
🧠 Learnings (2)
📚 Learning: 2024-11-07T07:17:27.636Z
Learnt from: jagankumar-egov
PR: egovernments/DIGIT-Frontend#1763
File: health/micro-ui/web/micro-ui-internals/packages/modules/campaign-manager/src/pages/employee/MyCampaign.js:65-75
Timestamp: 2024-11-07T07:17:27.636Z
Learning: In `MyCampaign.js`, when suggesting code improvements for the `onClickRow` function, keep suggestions simple and avoid unnecessary complexity.
Applied to files:
health/micro-ui/web/micro-ui-internals/packages/modules/health-payments/src/components/EditAttendanceManagementTable.js
📚 Learning: 2024-11-07T11:02:33.520Z
Learnt from: rachana-egov
PR: egovernments/DIGIT-Frontend#1770
File: health/micro-ui/web/micro-ui-internals/packages/modules/microplan/src/pages/employee/viewVillage.js:320-322
Timestamp: 2024-11-07T11:02:33.520Z
Learning: In `health/micro-ui/web/micro-ui-internals/packages/modules/microplan/src/pages/employee/viewVillage.js`, the `data?.additionalFields` object is guaranteed to be defined, so checking for its existence before accessing its keys is unnecessary.
Applied to files:
health/micro-ui/web/micro-ui-internals/packages/modules/health-payments/src/pages/employee/EditRegister.js
🧬 Code graph analysis (3)
health/micro-ui/web/micro-ui-internals/packages/modules/health-payments/src/components/editAttendeesPopUp.js (3)
health/micro-ui/web/micro-ui-internals/packages/modules/health-payments/src/components/EditAttendanceManagementTable.js (4)
history
(34-34)useTranslation
(33-33)tenantId
(40-40)EditAttendanceManagementTable
(31-274)health/micro-ui/web/micro-ui-internals/packages/modules/health-payments/src/components/SearchUserPopUp.js (10)
history
(16-16)attendanceContextPath
(18-20)individualContextPath
(21-23)useTranslation
(25-25)tenantId
(14-14)labels
(28-28)maxLabelLength
(29-29)labelWidth
(30-30)searchQuery
(32-32)SearchUserPopUp
(12-176)health/micro-ui/web/micro-ui-internals/packages/modules/health-payments/src/utils/update_attendance_summary.js (7)
attendanceContextPath
(4-6)individualContextPath
(7-9)attendanceSummary
(12-12)individualIds
(11-11)isAttendanceLoading
(27-28)allIndividualReqCriteria
(41-58)isAllIndividualsLoading
(60-61)
health/micro-ui/web/micro-ui-internals/packages/modules/health-payments/src/components/EditAttendanceManagementTable.js (3)
health/micro-ui/web/micro-ui-internals/packages/modules/health-payments/src/utils/constants.js (4)
defaultRowsPerPageForEditAttendee
(19-19)defaultRowsPerPageForEditAttendee
(19-19)defaultPaginationValuesForEditAttendee
(22-22)defaultPaginationValuesForEditAttendee
(22-22)health/micro-ui/web/micro-ui-internals/packages/modules/health-payments/src/components/table_inbox_custom_style.js (2)
editAttendeetableCustomStyle
(227-334)editAttendeetableCustomStyle
(227-334)health/micro-ui/web/micro-ui-internals/packages/modules/health-payments/src/components/alertPopUp.js (1)
AlertPopUp
(19-57)
health/micro-ui/web/micro-ui-internals/packages/modules/health-payments/src/pages/employee/EditRegister.js (3)
health/micro-ui/web/micro-ui-internals/packages/modules/health-payments/src/pages/employee/ViewAttendance.js (28)
useTranslation
(23-23)attendanceContextPath
(27-27)individualContextPath
(29-29)Digit
(32-32)attendanceDuration
(35-35)attendanceSummary
(36-36)initialAttendanceSummary
(37-37)isSubmitEnabled
(38-38)disabledAction
(40-40)individualIds
(48-48)triggerEstimate
(49-49)comment
(50-50)showToast
(51-51)loading
(52-52)showLogs
(53-53)showCommentLogPopup
(54-54)showDeEnrollPopup
(57-57)project
(59-59)AttendancereqCri
(62-74)isAttendanceLoading
(76-76)allIndividualReqCriteria
(312-331)isAllIndividualsLoading
(333-333)individualReqCriteria
(335-357)isIndividualsLoading
(359-359)closeActionBarPopUp
(428-430)handleDeEnrollClick
(441-443)onDeEnrollClose
(445-447)renderLabelPair
(450-455)health/micro-ui/web/micro-ui-internals/packages/modules/health-payments/src/components/EditAttendanceManagementTable.js (4)
useTranslation
(33-33)tenantId
(40-40)showToast
(36-36)EditAttendanceManagementTable
(31-274)health/micro-ui/web/micro-ui-internals/packages/modules/health-payments/src/components/editAttendeesPopUp.js (12)
useTranslation
(24-24)attendanceContextPath
(17-19)individualContextPath
(20-22)tenantId
(25-25)attendanceSummary
(32-32)individualIds
(33-33)AttendancereqCri
(77-88)isAttendanceLoading
(90-91)allIndividualReqCriteria
(104-121)isAllIndividualsLoading
(123-124)closeActionBarPopUp
(206-208)EditAttendeePopUp
(14-282)
🪛 Biome (2.1.2)
health/micro-ui/web/micro-ui-internals/packages/modules/health-payments/src/components/editAttendeesPopUp.js
[error] 218-218: Avoid passing children using a prop
The canonical way to pass children in React is to use JSX elements
(lint/correctness/noChildrenProp)
[error] 220-226: Missing key property for this element in iterable.
The order of the items may change, and having a key can help React identify which item was moved.
Check the React documentation.
(lint/correctness/useJsxKeyInIterable)
[error] 229-234: Missing key property for this element in iterable.
The order of the items may change, and having a key can help React identify which item was moved.
Check the React documentation.
(lint/correctness/useJsxKeyInIterable)
[error] 260-267: Missing key property for this element in iterable.
The order of the items may change, and having a key can help React identify which item was moved.
Check the React documentation.
(lint/correctness/useJsxKeyInIterable)
health/micro-ui/web/micro-ui-internals/packages/modules/health-payments/src/pages/employee/EditRegister.js
[error] 327-328: Provide screen reader accessible content when using heading elements.
All headings on a page should have content that is accessible to screen readers.
(lint/a11y/useHeadingContent)
if (AttendanceData) { | ||
setAttendanceDuration( | ||
Math.ceil((AttendanceData?.attendanceRegister[0]?.endDate - AttendanceData?.attendanceRegister[0]?.startDate) / (24 * 60 * 60 * 1000)) | ||
); | ||
|
||
} | ||
}, [AttendanceData]) | ||
|
||
useEffect(() => { | ||
if (AttendanceData?.attendanceRegister?.length > 0) { | ||
const ids = AttendanceData.attendanceRegister[0].attendees.map( | ||
(a) => a.individualId | ||
); | ||
setIndividualIds(ids); | ||
} | ||
}, [AttendanceData]); | ||
|
||
|
||
const allIndividualReqCriteria = { | ||
url: `/${individualContextPath}/v1/_search`, | ||
params: { | ||
tenantId: tenantId, | ||
limit: individualIds.length, | ||
offset: 0, | ||
}, | ||
body: { | ||
Individual: { | ||
id: individualIds, | ||
}, | ||
}, | ||
config: { | ||
enabled: individualIds.length > 0, // ✅ only fire when we have IDs | ||
select: (datap) => datap, | ||
}, | ||
changeQueryName: "allIndividuals", | ||
}; | ||
|
||
const { isLoading: isAllIndividualsLoading, data: AllIndividualsData } = Digit.Hooks.useCustomAPIHook(allIndividualReqCriteria); | ||
|
||
const individualReqCriteria = { | ||
url: `/${individualContextPath}/v1/_search`, | ||
params: { | ||
tenantId: tenantId, | ||
limit: 100, | ||
offset: 0, | ||
}, | ||
body: { | ||
Individual: { | ||
id: [AttendanceData?.attendanceRegister[0]?.staff?.find( | ||
(staff) => staff?.staffType?.includes("OWNER") | ||
)?.userId] | ||
} | ||
}, | ||
config: { | ||
enabled: AttendanceData?.attendanceRegister.length === 1 && AttendanceData?.attendanceRegister[0]?.staff?.find( | ||
(staff) => staff?.staffType?.includes("OWNER") | ||
)?.userId ? true : false, | ||
select: (data) => { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Optional-chain attendanceRegister
and guard attendees
everywhere.
Several spots still assume attendanceRegister[0]
and its attendees
exist. When the API returns an empty register (or the property is missing), the page crashes:
- Line 82:
AttendanceData?.attendanceRegister[0]?.endDate
should beAttendanceData?.attendanceRegister?.[0]?.endDate
. - Lines 89‑94:
AttendanceData.attendanceRegister[0].attendees.map(...)
will throw ifattendees
is absent. - Lines 127‑136: both the request body and
enabled
flag indexattendanceRegister[0]
and.length
without guardingattendanceRegister
.
Please optional-chain attendanceRegister
(?.[0]
) in all these expressions and default attendees
to []
before mapping.
- setAttendanceDuration(
- Math.ceil((AttendanceData?.attendanceRegister[0]?.endDate - AttendanceData?.attendanceRegister[0]?.startDate) / (24 * 60 * 60 * 1000))
- );
+ const register = AttendanceData?.attendanceRegister?.[0];
+ if (register?.endDate && register?.startDate) {
+ setAttendanceDuration(
+ Math.ceil((register.endDate - register.startDate) / (24 * 60 * 60 * 1000))
+ );
+ } else {
+ setAttendanceDuration(null);
+ }
@@
- if (AttendanceData?.attendanceRegister?.length > 0) {
- const ids = AttendanceData.attendanceRegister[0].attendees.map(
- (a) => a.individualId
- );
- setIndividualIds(ids);
- }
+ const attendees = AttendanceData?.attendanceRegister?.[0]?.attendees ?? [];
+ setIndividualIds(
+ Array.isArray(attendees)
+ ? attendees.map((a) => a?.individualId).filter(Boolean)
+ : []
+ );
@@
- Individual: {
- id: [AttendanceData?.attendanceRegister[0]?.staff?.find(
- (staff) => staff?.staffType?.includes("OWNER")
- )?.userId]
- }
+ Individual: {
+ id: [
+ AttendanceData?.attendanceRegister?.[0]?.staff?.find((staff) =>
+ staff?.staffType?.includes("OWNER")
+ )?.userId,
+ ].filter(Boolean),
+ }
@@
- enabled: AttendanceData?.attendanceRegister.length === 1 && AttendanceData?.attendanceRegister[0]?.staff?.find(
- (staff) => staff?.staffType?.includes("OWNER")
- )?.userId ? true : false,
+ enabled: Boolean(
+ AttendanceData?.attendanceRegister?.[0]?.staff?.find((staff) =>
+ staff?.staffType?.includes("OWNER")
+ )?.userId
+ ),
📝 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.
if (AttendanceData) { | |
setAttendanceDuration( | |
Math.ceil((AttendanceData?.attendanceRegister[0]?.endDate - AttendanceData?.attendanceRegister[0]?.startDate) / (24 * 60 * 60 * 1000)) | |
); | |
} | |
}, [AttendanceData]) | |
useEffect(() => { | |
if (AttendanceData?.attendanceRegister?.length > 0) { | |
const ids = AttendanceData.attendanceRegister[0].attendees.map( | |
(a) => a.individualId | |
); | |
setIndividualIds(ids); | |
} | |
}, [AttendanceData]); | |
const allIndividualReqCriteria = { | |
url: `/${individualContextPath}/v1/_search`, | |
params: { | |
tenantId: tenantId, | |
limit: individualIds.length, | |
offset: 0, | |
}, | |
body: { | |
Individual: { | |
id: individualIds, | |
}, | |
}, | |
config: { | |
enabled: individualIds.length > 0, // ✅ only fire when we have IDs | |
select: (datap) => datap, | |
}, | |
changeQueryName: "allIndividuals", | |
}; | |
const { isLoading: isAllIndividualsLoading, data: AllIndividualsData } = Digit.Hooks.useCustomAPIHook(allIndividualReqCriteria); | |
const individualReqCriteria = { | |
url: `/${individualContextPath}/v1/_search`, | |
params: { | |
tenantId: tenantId, | |
limit: 100, | |
offset: 0, | |
}, | |
body: { | |
Individual: { | |
id: [AttendanceData?.attendanceRegister[0]?.staff?.find( | |
(staff) => staff?.staffType?.includes("OWNER") | |
)?.userId] | |
} | |
}, | |
config: { | |
enabled: AttendanceData?.attendanceRegister.length === 1 && AttendanceData?.attendanceRegister[0]?.staff?.find( | |
(staff) => staff?.staffType?.includes("OWNER") | |
)?.userId ? true : false, | |
select: (data) => { | |
useEffect(() => { | |
if (AttendanceData) { | |
const register = AttendanceData?.attendanceRegister?.[0]; | |
if (register?.endDate && register?.startDate) { | |
setAttendanceDuration( | |
Math.ceil((register.endDate - register.startDate) / (24 * 60 * 60 * 1000)) | |
); | |
} else { | |
setAttendanceDuration(null); | |
} | |
} | |
}, [AttendanceData]); | |
useEffect(() => { | |
const attendees = AttendanceData?.attendanceRegister?.[0]?.attendees ?? []; | |
setIndividualIds( | |
Array.isArray(attendees) | |
? attendees.map((a) => a?.individualId).filter(Boolean) | |
: [] | |
); | |
}, [AttendanceData]); | |
// … (allIndividualReqCriteria and its hook stay unchanged) | |
const individualReqCriteria = { | |
url: `/${individualContextPath}/v1/_search`, | |
params: { | |
tenantId: tenantId, | |
limit: 100, | |
offset: 0, | |
}, | |
body: { | |
Individual: { | |
id: [ | |
AttendanceData?.attendanceRegister?.[0]?.staff?.find((staff) => | |
staff?.staffType?.includes("OWNER") | |
)?.userId, | |
].filter(Boolean), | |
}, | |
}, | |
config: { | |
enabled: Boolean( | |
AttendanceData?.attendanceRegister?.[0]?.staff?.find((staff) => | |
staff?.staffType?.includes("OWNER") | |
)?.userId | |
), | |
select: (data) => { | |
// … | |
}, | |
}, | |
}; |
🤖 Prompt for AI Agents
In
health/micro-ui/web/micro-ui-internals/packages/modules/health-payments/src/pages/employee/EditRegister.js
around lines 80 to 137, several expressions assume attendanceRegister[0] and its
attendees exist; change all occurrences to use optional chaining on the array
element (attendanceRegister?.[0]) and guard attendees by defaulting to an empty
array before mapping (e.g., (AttendanceData?.attendanceRegister?.[0]?.attendees
|| []) ). Also update checks that inspect length or access staff/userId to first
ensure attendanceRegister exists (e.g.,
AttendanceData?.attendanceRegister?.length and
AttendanceData?.attendanceRegister?.[0]?.staff) so the request body and enabled
flag only index [0] when attendanceRegister is present.
There was a problem hiding this 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 (11)
health/micro-ui/web/micro-ui-internals/packages/modules/health-hrms/src/components/pageComponents/SearchUserToReport.js (11)
3-5
: Remove unused imports.
Timeline
,useEffect
, anduseHistory
are imported but never used in this component.Apply this diff:
-import { PopUp, Timeline, Loader, TextInput, Button, NoResultsFound } from '@egovernments/digit-ui-components'; -import { useEffect } from "react"; -import { useHistory } from "react-router-dom"; +import { PopUp, Loader, TextInput, Button, NoResultsFound } from '@egovernments/digit-ui-components';Also remove the unused
history
declaration on line 18.
6-6
: Critical: Fix incorrect import causing runtime undefined.
AttendanceService
is exported as a named export fromSearchUser.js
, not as default. Importing it as default will result inundefined
at runtime, causing all search operations to fail.Apply this diff:
-import AttendanceService from "../../services/hrms/SearchUser"; +import { AttendanceService } from "../../services/hrms/SearchUser";
17-18
: Remove commented-out code.Dead code should be removed to keep the codebase clean.
Apply this diff:
const tenantId = Digit.ULBService.getCurrentTenantId(); - // const { mutate: createMapping } = Digit.Hooks.payments.useCreateAttendeeFromRegister(tenantId); - const history = useHistory();
20-32
: Remove unused variable declarations.
attendanceContextPath
,individualContextPath
,labels
,maxLabelLength
, andlabelWidth
are declared but never used.Apply this diff:
- const attendanceContextPath = - window?.globalConfigs?.getConfig("ATTENDANCE_CONTEXT_PATH") || - "health-attendance"; - const individualContextPath = - window?.globalConfigs?.getConfig("INDIVIDUAL_CONTEXT_PATH") || - "health-individual"; - const { t } = useTranslation(); - - - const labels = ["HCM_AM_ATTENDANCE_NOT_FIND_USER_LABEL", "HCM_AM_ATTENDANCE_USER_ASSIGN_REGISTER"]; - const maxLabelLength = Math.max(...labels.map(label => label.length)); - const labelWidth = `${maxLabelLength * 8}px`;
57-57
: Fix typo:locallity
→locality
.The typo should be corrected throughout the file and in the service call to maintain consistency. Note that the service signature in
SearchUser.js
also uses the misspelling, which should be corrected there as well.- const locallity = Digit.SessionStorage.get("selectedBoundary")?.code || null; + const locality = Digit.SessionStorage.get("selectedBoundary")?.code || null;Update all references in lines 59, 74 accordingly, and update the service signature.
59-65
: Critical: Remove undefinedsetShowToast
call.
setShowToast
is not defined in this component, causing a runtimeReferenceError
when locality validation fails. This completely breaks the search flow when no locality is selected.Apply this diff to prevent the crash:
if (locallity === null) { - setShowToast( - { key: "error", label: t(`HCM_AM_LOCALITY_NOT_SELECTED`), transitionTime: 3000 } - ); setLoading(false); return; }To properly display the error to users, consider wiring a Toast component from
@egovernments/digit-ui-components
.
67-71
: Remove debug console statements.Console logs with a typo ("nummeric") serve no functional purpose and pollute the console.
Apply this diff:
- if (/^\d+$/.test(name)) { - console.log("it is nummeric"); - } else { - console.log("it is not nummeric"); - } -
101-104
: Critical: Useid
field, notuserUuid
.The downstream consumer (likely UserAssignment) expects
value.id
in the submission payload. UsinguserUuid
will break the assignment flow.Apply this diff:
onSubmit({ - id: selectedUser?.userUuid, + id: selectedUser?.id, name: selectedUser?.name?.givenName })
119-210
: Major: Fix PopUp children rendering and missing keys.Three issues with the PopUp component:
- Passing content via
children
prop violates React conventions and triggers Biome'snoChildrenProp
lint error- The child element in the
children
array lacks akey
prop- The footer button in
footerChildren
array also lacks akey
propApply this diff to move JSX content to be direct children and add keys:
<PopUp style={{ width: "800px", minHeight: "430px" }} onClose={onClose} heading={t("HCM_AM_SEARCH_USER")} onOverlayClick={onClose} - children={[ - ( - <div style={{ + footerChildren={[ + <Button + key="assign-user" + isDisabled={!selectedUser} + type={"button"} + size={"large"} + variation={"primary"} + label={t("HCM_AM_ASSIGN_BT")} + onClick={handleEnrollAttendee} + />, + ]} + sortFooterChildren={true} + > + <div style={{ display: "flex", flexDirection: "column", gap: "16px", }} > {/* ...existing content... */} - </div> - ) - ]} - footerChildren={[ - <Button - isDisabled={selectedUser ? false : true} - type={"button"} - size={"large"} - variation={"primary"} - label={t("HCM_AM_ASSIGN_BT")} - onClick={handleEnrollAttendee} - />, - ]} - sortFooterChildren={true} - /> + </div> + </PopUp>
142-149
: Replace deprecatedonKeyPress
withonKeyDown
.React has deprecated
onKeyPress
. Switch toonKeyDown
to align with current APIs and avoid future breaking changes. Based on learnings.Apply this diff:
- }} onKeyPress={(e) => { + }} onKeyDown={(e) => { if (e.key === "Enter") { e.preventDefault(); searchUser(searchQuery, 0, rowsPerPage); } }} />
213-213
: Simplify boolean expression.The ternary
selectedUser ? false : true
can be simplified to!selectedUser
.Apply this diff:
- isDisabled={selectedUser ? false : true} + isDisabled={!selectedUser}
📜 Review details
Configuration used: CodeRabbit UI
Review profile: ASSERTIVE
Plan: Pro
📒 Files selected for processing (1)
health/micro-ui/web/micro-ui-internals/packages/modules/health-hrms/src/components/pageComponents/SearchUserToReport.js
(1 hunks)
🧰 Additional context used
📓 Path-based instructions (1)
**/*.js
⚙️ CodeRabbit configuration file
check
Files:
health/micro-ui/web/micro-ui-internals/packages/modules/health-hrms/src/components/pageComponents/SearchUserToReport.js
🧠 Learnings (1)
📚 Learning: 2024-06-10T19:25:42.992Z
Learnt from: siddhant-nawale-egov
PR: egovernments/DIGIT-Frontend#698
File: micro-ui/web/micro-ui-internals/packages/modules/hcm-microplanning/src/components/resourceMapping.js:74-74
Timestamp: 2024-06-10T19:25:42.992Z
Learning: `onKeyPress` is deprecated and should be replaced with `onKeyDown` or `onKeyUp` for handling keyboard interactions.
Applied to files:
health/micro-ui/web/micro-ui-internals/packages/modules/health-hrms/src/components/pageComponents/SearchUserToReport.js
🧬 Code graph analysis (1)
health/micro-ui/web/micro-ui-internals/packages/modules/health-hrms/src/components/pageComponents/SearchUserToReport.js (2)
health/micro-ui/web/micro-ui-internals/packages/modules/health-hrms/src/components/pageComponents/ReportingUserSearchTable.js (2)
useTranslation
(14-14)ReportingUserSearchTable
(5-109)health/micro-ui/web/micro-ui-internals/packages/modules/health-hrms/src/services/hrms/SearchUser.js (3)
result
(79-103)AttendanceService
(4-111)AttendanceService
(4-111)
🪛 Biome (2.1.2)
health/micro-ui/web/micro-ui-internals/packages/modules/health-hrms/src/components/pageComponents/SearchUserToReport.js
[error] 119-119: Avoid passing children using a prop
The canonical way to pass children in React is to use JSX elements
(lint/correctness/noChildrenProp)
[error] 121-126: Missing key property for this element in iterable.
The order of the items may change, and having a key can help React identify which item was moved.
Check the React documentation.
(lint/correctness/useJsxKeyInIterable)
[error] 212-219: Missing key property for this element in iterable.
The order of the items may change, and having a key can help React identify which item was moved.
Check the React documentation.
(lint/correctness/useJsxKeyInIterable)
⏰ Context from checks skipped due to timeout of 10000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (2)
- GitHub Check: Build application amd64
- GitHub Check: Build application arm64
} | ||
|
||
|
||
{!loading && searchQuery != "" && searchedIndividual.length === 0 && apiCall ==true && ( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Use strict equality operator.
Use ===
instead of ==
for comparison to avoid type coercion issues.
Apply this diff:
- {!loading && searchQuery != "" && searchedIndividual.length === 0 && apiCall ==true && (
+ {!loading && searchQuery !== "" && searchedIndividual.length === 0 && apiCall === true && (
📝 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.
{!loading && searchQuery != "" && searchedIndividual.length === 0 && apiCall ==true && ( | |
{!loading && searchQuery !== "" && searchedIndividual.length === 0 && apiCall === true && ( |
🤖 Prompt for AI Agents
In
health/micro-ui/web/micro-ui-internals/packages/modules/health-hrms/src/components/pageComponents/SearchUserToReport.js
around line 183, the conditional uses a loose equality check `apiCall == true`;
replace it with the strict equality operator (`apiCall === true`) so the
condition avoids type coercion and correctly checks the boolean value.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 10
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (2)
health/micro-ui/web/micro-ui-internals/packages/modules/health-payments/src/components/attendance_inbox/attendance_inbox.js (2)
54-54
: Use strict equality operators.Multiple locations use loose equality (
==
) instead of strict equality (===
):
- Line 54:
totalNext == undefined
- Lines 58-60:
filterData?.code == undefined
,filterData?.code == null
,filterCriteria?.code == undefined
,filterCriteria?.code == null
- Line 63:
status == undefined
- Line 171:
status.code == StatusEnum.PENDING_FOR_APPROVAL
Use
===
and!==
for type-safe comparisons and to follow JavaScript best practices.Example for line 54:
- offset: totalNext == undefined ? (currentPage - 1) * rowsPerPage : (totalNext - 1) * totalRows, + offset: totalNext === undefined ? (currentPage - 1) * rowsPerPage : (totalNext - 1) * totalRows,Apply similar changes to other locations with loose equality.
Also applies to: 58-60, 63-63, 171-171
58-62
: Simplify nested ternary forlocalityCode
.The nested ternary expression for determining
localityCode
is difficult to read and maintain.Consider extracting this logic into a helper function:
+const getLocalityCode = (filterData, filterCriteria) => { + if (filterData?.code != null) return filterData.code; + if (filterCriteria?.code != null) return filterCriteria.code; + return Digit.SessionStorage.get("paymentInbox").code; +}; + const triggerAttendanceSearch = (filterData, status, totalRows, totalNext, selectedProject) => { try { setChildrenDataLoading(true); fetchRegisters.mutateAsync( { params: { tenantId: Digit.ULBService.getStateId(), limit: totalRows || rowsPerPage, offset: totalNext === undefined ? (currentPage - 1) * rowsPerPage : (totalNext - 1) * totalRows, referenceId: selectedProject?.id === undefined ? Digit.SessionStorage.get("paymentInbox").selectedProject?.id : selectedProject?.id, staffId: Digit.SessionStorage.get("UserIndividual")?.[0]?.id, - localityCode: - filterData?.code == undefined || filterData?.code == null - ? filterCriteria?.code == undefined || filterCriteria?.code == null - ? Digit.SessionStorage.get("paymentInbox").code - : filterCriteria?.code - : filterData?.code, + localityCode: getLocalityCode(filterData, filterCriteria), reviewStatus: status === undefined ? selectedStatus : status, isChildrenRequired: true, }, },
♻️ Duplicate comments (14)
health/micro-ui/web/micro-ui-internals/packages/modules/health-payments/src/components/attendance_inbox/attendance_inbox.js (1)
195-196
: Remove commented-out code.Lines 195-196 contain commented-out
minHeight
andmaxHeight
styles. This was previously flagged. Remove commented code to keep the codebase clean.Apply this diff to remove the commented lines:
<div className="custom-register-inbox-screen" style={{ - // "minHeight":"20%", - // "maxHeight":"30%" }}>If these styles are needed, uncomment and apply proper values; otherwise, remove them entirely.
health/micro-ui/web/micro-ui-internals/packages/modules/health-payments/src/components/EditAttendanceManagementTable.js (1)
6-6
: Remove unused type import.
TableProps
is imported but never used. This appears to be a TypeScript type import in a JavaScript file.Note: This is similar to the already-flagged unused imports. Based on past review comments,
AttendeeService
(line 10),useHistory
(line 2), and variableshistory
andurl
(lines 34-35) should also be removed.health/micro-ui/web/micro-ui-internals/packages/modules/health-payments/src/components/attendance_inbox/table_inbox.js (1)
253-254
: Remove redundant progressPending prop.The
progressPending={isLoading}
prop is alwaysfalse
when the DataTable renders, since this code path only executes whenisLoading
isfalse
(line 235 ternary condition).Apply this diff:
<DataTable columns={columns} className="search-component-table" data={tableData} - progressPending={isLoading} - progressComponent={<Loader />} pagination paginationServerhealth/micro-ui/web/micro-ui-internals/packages/modules/health-hrms/src/components/pageComponents/SearchUserToReport.js (11)
184-184
: Use strict equality operator.Replace loose equality (
==
) with strict equality (===
) to avoid type coercion issues.Apply this diff:
- {!loading && searchQuery != "" && searchedIndividual.length === 0 && apiCall ==true && ( + {!loading && searchQuery !== "" && searchedIndividual.length === 0 && apiCall === true && ( <div>
214-214
: Simplify boolean ternary.The ternary expression can be simplified for better readability.
Apply this diff:
- isDisabled={selectedUser ? false : true} + isDisabled={!selectedUser}
6-6
: Critical: Fix incorrect import of AttendanceService (named export, not default).
AttendanceService
is exported as a named export inSearchUser.js
, but imported as default here. This will beundefined
at runtime and crash whensearchIndividual
is called.Apply this diff:
-import AttendanceService from "../../services/hrms/SearchUser"; +import { AttendanceService } from "../../services/hrms/SearchUser";
142-150
: UseonKeyDown
instead of deprecatedonKeyPress
.React has deprecated
onKeyPress
. Switch toonKeyDown
to align with current APIs. Based on learnings.Apply this diff:
- }} onKeyPress={(e) => { + }} onKeyDown={(e) => { if (e.key === "Enter") { e.preventDefault(); // prevent form submit if inside a form setApiCall(true); searchUser(searchQuery, 0, rowsPerPage); // call your API
17-17
: Remove commented-out code.This dead code serves no purpose and should be removed to keep the codebase clean.
Apply this diff:
const tenantId = Digit.ULBService.getCurrentTenantId(); - // const { mutate: createMapping } = Digit.Hooks.payments.useCreateAttendeeFromRegister(tenantId); - const history = useHistory();
57-57
: Typo:locallity
→locality
(propagate to service signature).The variable name contains a typo. Rename throughout this function and update the service call parameter to maintain consistency.
Apply this diff:
- const locallity = Digit.SessionStorage.get("selectedBoundary")?.code || null; + const locality = Digit.SessionStorage.get("selectedBoundary")?.code || null; - if (locallity === null) { + if (locality === null) { setLoading(false); return; } const result = await AttendanceService.searchIndividual( - { name, locallity, tenantId, offset: currentoffset, limit } + { name, locality, tenantId, offset: currentoffset, limit } );
57-65
: Critical: Remove undefinedsetShowToast
call to avoid runtime crash.
setShowToast
is not defined in this component. Whenlocallity
is null, the code will throw a ReferenceError and crash the modal.Apply this diff:
const locallity = Digit.SessionStorage.get("selectedBoundary")?.code || null; if (locallity === null) { - setShowToast( - { key: "error", label: t(`HCM_AM_LOCALITY_NOT_SELECTED`), transitionTime: 3000 } - ); setLoading(false); return; }If toast feedback is required, wire a proper Toast state/hook from
@egovernments/digit-ui-components
.
3-5
: Prune unused imports.
Timeline
,Loader
,useEffect
, anduseHistory
are imported but never used in this component.Apply this diff:
-import { PopUp, Timeline, Loader, TextInput, Button, NoResultsFound } from '@egovernments/digit-ui-components'; -import { useEffect } from "react"; -import { useHistory } from "react-router-dom"; +import { PopUp, TextInput, Button, NoResultsFound } from '@egovernments/digit-ui-components';
67-71
: Drop console noise.These debug logs (with typo "nummeric") only spam the console and should be removed.
Apply this diff:
- if (/^\d+$/.test(name)) { - console.log("it is nummeric"); - } else { - console.log("it is not nummeric"); - } - const result = await AttendanceService.searchIndividual(
18-32
: Remove unused variables.The variables
history
,attendanceContextPath
,individualContextPath
,labels
, andlabelWidth
are declared but never used.Apply this diff:
const tenantId = Digit.ULBService.getCurrentTenantId(); - const history = useHistory(); - // context path variables - const attendanceContextPath = - window?.globalConfigs?.getConfig("ATTENDANCE_CONTEXT_PATH") || - "health-attendance"; - const individualContextPath = - window?.globalConfigs?.getConfig("INDIVIDUAL_CONTEXT_PATH") || - "health-individual"; const { t } = useTranslation(); - - const labels = ["HCM_AM_ATTENDANCE_NOT_FIND_USER_LABEL", "HCM_AM_ATTENDANCE_USER_ASSIGN_REGISTER"]; - const maxLabelLength = Math.max(...labels.map(label => label.length)); - const labelWidth = `${maxLabelLength * 8}px`; - const [searchQuery, setSearchQuery] = useState("");
119-211
: Fix PopUp children pattern to satisfy Biome and React correctness.Passing content through the
children
prop array triggers Biome'snoChildrenProp
error and also lacks akey
for the array element. Move the JSX inside the PopUp tags as normal children.Apply this diff:
<PopUp style={{ width: "800px", minHeight: "430px" }} onClose={onClose} heading={t("HCM_AM_SEARCH_USER")} onOverlayClick={onClose} - children={[ - ( - <div style={{ + footerChildren={[ + <Button + key="assign-user" + isDisabled={!selectedUser} + type={"button"} + size={"large"} + variation={"primary"} + label={t("HCM_AM_ASSIGN_BT")} + onClick={handleEnrollAttendee} + />, + ]} + sortFooterChildren={true} + > + <div style={{ display: "flex", flexDirection: "column", gap: "16px", // same as Tailwind gap-4 - }} > + }} > <div style={{ display: "flex", flexDirection: "column", gap: "2px" }}> @@ -205,21 +205,8 @@ - </div> - ) - ]} - footerChildren={[ - <Button - isDisabled={selectedUser ? false : true} - type={"button"} - size={"large"} - variation={"primary"} - label={t("HCM_AM_ASSIGN_BT")} - onClick={handleEnrollAttendee} - />, - ]} - sortFooterChildren={true} - /> + </div> + </PopUp>
📜 Review details
Configuration used: CodeRabbit UI
Review profile: ASSERTIVE
Plan: Pro
📒 Files selected for processing (5)
health/micro-ui/web/micro-ui-internals/packages/modules/health-hrms/src/components/pageComponents/SearchUserToReport.js
(1 hunks)health/micro-ui/web/micro-ui-internals/packages/modules/health-payments/src/components/EditAttendanceManagementTable.js
(1 hunks)health/micro-ui/web/micro-ui-internals/packages/modules/health-payments/src/components/attendance_inbox/attendance_inbox.js
(3 hunks)health/micro-ui/web/micro-ui-internals/packages/modules/health-payments/src/components/attendance_inbox/table_inbox.js
(5 hunks)health/micro-ui/web/micro-ui-internals/packages/modules/health-payments/src/pages/employee/attendance_inbox.js
(1 hunks)
🧰 Additional context used
📓 Path-based instructions (1)
**/*.js
⚙️ CodeRabbit configuration file
check
Files:
health/micro-ui/web/micro-ui-internals/packages/modules/health-payments/src/components/attendance_inbox/attendance_inbox.js
health/micro-ui/web/micro-ui-internals/packages/modules/health-payments/src/pages/employee/attendance_inbox.js
health/micro-ui/web/micro-ui-internals/packages/modules/health-hrms/src/components/pageComponents/SearchUserToReport.js
health/micro-ui/web/micro-ui-internals/packages/modules/health-payments/src/components/attendance_inbox/table_inbox.js
health/micro-ui/web/micro-ui-internals/packages/modules/health-payments/src/components/EditAttendanceManagementTable.js
🧠 Learnings (2)
📚 Learning: 2024-06-10T19:25:42.992Z
Learnt from: siddhant-nawale-egov
PR: egovernments/DIGIT-Frontend#698
File: micro-ui/web/micro-ui-internals/packages/modules/hcm-microplanning/src/components/resourceMapping.js:74-74
Timestamp: 2024-06-10T19:25:42.992Z
Learning: `onKeyPress` is deprecated and should be replaced with `onKeyDown` or `onKeyUp` for handling keyboard interactions.
Applied to files:
health/micro-ui/web/micro-ui-internals/packages/modules/health-hrms/src/components/pageComponents/SearchUserToReport.js
📚 Learning: 2024-11-07T07:17:27.636Z
Learnt from: jagankumar-egov
PR: egovernments/DIGIT-Frontend#1763
File: health/micro-ui/web/micro-ui-internals/packages/modules/campaign-manager/src/pages/employee/MyCampaign.js:65-75
Timestamp: 2024-11-07T07:17:27.636Z
Learning: In `MyCampaign.js`, when suggesting code improvements for the `onClickRow` function, keep suggestions simple and avoid unnecessary complexity.
Applied to files:
health/micro-ui/web/micro-ui-internals/packages/modules/health-payments/src/components/EditAttendanceManagementTable.js
🧬 Code graph analysis (5)
health/micro-ui/web/micro-ui-internals/packages/modules/health-payments/src/components/attendance_inbox/attendance_inbox.js (1)
health/micro-ui/web/micro-ui-internals/packages/modules/health-payments/src/components/SearchResultsPlaceholder.js (1)
SearchResultsPlaceholder
(17-31)
health/micro-ui/web/micro-ui-internals/packages/modules/health-payments/src/pages/employee/attendance_inbox.js (1)
health/micro-ui/web/micro-ui-internals/packages/modules/health-payments/src/components/attendance_inbox/attendance_inbox.js (1)
AttendanceInboxComponent
(14-244)
health/micro-ui/web/micro-ui-internals/packages/modules/health-hrms/src/components/pageComponents/SearchUserToReport.js (2)
health/micro-ui/web/micro-ui-internals/packages/modules/health-hrms/src/components/pageComponents/ReportingUserSearchTable.js (2)
useTranslation
(14-14)ReportingUserSearchTable
(5-109)health/micro-ui/web/micro-ui-internals/packages/modules/health-hrms/src/services/hrms/SearchUser.js (3)
result
(79-103)AttendanceService
(4-111)AttendanceService
(4-111)
health/micro-ui/web/micro-ui-internals/packages/modules/health-payments/src/components/attendance_inbox/table_inbox.js (3)
health/micro-ui/web/micro-ui-internals/packages/modules/health-payments/src/pages/employee/EditRegister.js (1)
Digit
(34-34)health/micro-ui/web/micro-ui-internals/packages/modules/health-payments/src/pages/employee/ViewAttendance.js (1)
Digit
(32-32)health/micro-ui/web/micro-ui-internals/packages/modules/health-payments/src/components/bill_inbox/billInboxTable.js (1)
triggerMusterRollSearch
(35-56)
health/micro-ui/web/micro-ui-internals/packages/modules/health-payments/src/components/EditAttendanceManagementTable.js (3)
health/micro-ui/web/micro-ui-internals/packages/modules/health-payments/src/utils/constants.js (4)
defaultRowsPerPageForEditAttendee
(19-19)defaultRowsPerPageForEditAttendee
(19-19)defaultPaginationValuesForEditAttendee
(22-22)defaultPaginationValuesForEditAttendee
(22-22)health/micro-ui/web/micro-ui-internals/packages/modules/health-payments/src/components/table_inbox_custom_style.js (2)
editAttendeetableCustomStyle
(227-334)editAttendeetableCustomStyle
(227-334)health/micro-ui/web/micro-ui-internals/packages/modules/health-payments/src/components/alertPopUp.js (1)
AlertPopUp
(19-57)
🪛 Biome (2.1.2)
health/micro-ui/web/micro-ui-internals/packages/modules/health-hrms/src/components/pageComponents/SearchUserToReport.js
[error] 119-119: Avoid passing children using a prop
The canonical way to pass children in React is to use JSX elements
(lint/correctness/noChildrenProp)
[error] 121-126: Missing key property for this element in iterable.
The order of the items may change, and having a key can help React identify which item was moved.
Check the React documentation.
(lint/correctness/useJsxKeyInIterable)
[error] 213-220: Missing key property for this element in iterable.
The order of the items may change, and having a key can help React identify which item was moved.
Check the React documentation.
(lint/correctness/useJsxKeyInIterable)
⏰ Context from checks skipped due to timeout of 10000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (3)
- GitHub Check: Build application arm64
- GitHub Check: Build application amd64
- GitHub Check: Analyze (javascript-typescript)
🔇 Additional comments (6)
health/micro-ui/web/micro-ui-internals/packages/modules/health-payments/src/pages/employee/attendance_inbox.js (1)
43-43
: LGTM: Header font size adjustment.The reduction from 32px to 28px improves visual hierarchy consistency.
health/micro-ui/web/micro-ui-internals/packages/modules/health-payments/src/components/attendance_inbox/attendance_inbox.js (1)
200-200
: Verify height changes work across screen sizes.The height was reduced from
80vh
to60vh
in both the filter section (line 200) and table section (line 210). Ensure this change doesn't cause layout issues on smaller screens or when content overflows.Consider testing the UI with:
- Different viewport heights (mobile, tablet, desktop)
- Maximum filter options expanded
- Large datasets in the table
Also applies to: 210-210
health/micro-ui/web/micro-ui-internals/packages/modules/health-payments/src/components/attendance_inbox/table_inbox.js (3)
235-245
: LGTM! Loader container properly centered.The loader container now uses
height: "100%"
within the flex layout, which properly centers the loader within the available vertical space. This addresses the past review concern about inadequate height.
114-132
: LGTM! Conditional column rendering is well-structured.The column definition correctly handles the different display requirements for pending vs approved states, with proper fallbacks to "NA" when data is unavailable.
186-272
: LGTM! Well-structured layout with proper loading states.The component properly separates concerns with:
- Sticky tab section for navigation
- Scrollable table section with appropriate overflow handling
- Clear conditional rendering for loading, empty, and data states
The flexbox layout and sticky positioning are implemented correctly for a good user experience.
health/micro-ui/web/micro-ui-internals/packages/modules/health-hrms/src/components/pageComponents/SearchUserToReport.js (1)
101-104
: RetainuserUuid
asid
in onSubmit payload
seletctedValue
handler expectsvalue.id
, and you’re correctly mappingselectedUser.userUuid
toid
;selectedUser.id
doesn’t exist.Likely an incorrect or invalid review comment.
<Card className="card-overide"> | ||
<div className="summary-sub-heading">{t(selectedProject?.name)}</div> | ||
<SearchResultsPlaceholder placeholderText={"HCM_AM_FILTER_AND_CHOOSE_BOUNDARY_PLACEHOLDER_TEXT"} /> | ||
{<SearchResultsPlaceholder placeholderText={"HCM_AM_FILTER_AND_CHOOSE_BOUNDARY_PLACEHOLDER_TEXT"} />} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🧹 Nitpick | 🔵 Trivial
Remove unnecessary JSX expression wrapping.
The SearchResultsPlaceholder
component is wrapped in an unnecessary JSX expression ({<SearchResultsPlaceholder ... />}
). Direct JSX is cleaner and more idiomatic.
Apply this diff:
- {<SearchResultsPlaceholder placeholderText={"HCM_AM_FILTER_AND_CHOOSE_BOUNDARY_PLACEHOLDER_TEXT"} />}
+ <SearchResultsPlaceholder placeholderText={"HCM_AM_FILTER_AND_CHOOSE_BOUNDARY_PLACEHOLDER_TEXT"} />
📝 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.
{<SearchResultsPlaceholder placeholderText={"HCM_AM_FILTER_AND_CHOOSE_BOUNDARY_PLACEHOLDER_TEXT"} />} | |
<SearchResultsPlaceholder placeholderText={"HCM_AM_FILTER_AND_CHOOSE_BOUNDARY_PLACEHOLDER_TEXT"} /> |
🤖 Prompt for AI Agents
In
health/micro-ui/web/micro-ui-internals/packages/modules/health-payments/src/components/attendance_inbox/attendance_inbox.js
around line 214, remove the unnecessary JSX expression wrapping the component;
replace the wrapped form {<SearchResultsPlaceholder
placeholderText={"HCM_AM_FILTER_AND_CHOOSE_BOUNDARY_PLACEHOLDER_TEXT"} />} with
the direct JSX <SearchResultsPlaceholder
placeholderText={"HCM_AM_FILTER_AND_CHOOSE_BOUNDARY_PLACEHOLDER_TEXT"} /> so the
component is rendered directly without the extra {} expression.
onClick={() => { | ||
const existingPaymentInbox = Digit.SessionStorage.get("paymentInbox"); | ||
const endDate = existingPaymentInbox?.selectedProject?.endDate; | ||
|
||
if (endDate) { | ||
const currentDate = Date.now(); | ||
if (!(currentDate <= endDate)) { | ||
history.push( | ||
`/${window?.contextPath}/employee/payments/view-attendance?registerNumber=${row?.id}&boundaryCode=${row?.boundary}` | ||
); | ||
} else { | ||
history.push( | ||
`/${window?.contextPath}/employee/payments/edit-register?registerNumber=${row?.id}&boundaryCode=${row?.boundary}®isterId=${row?.registerId}` | ||
); | ||
} | ||
} else { | ||
console.warn("No endDate found in session storage"); | ||
history.push( | ||
`/${window?.contextPath}/employee/payments/view-attendance?registerNumber=${row?.id}&boundaryCode=${row?.boundary}` | ||
) | ||
); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fix navigation logic: prevent double navigation, prefer prop over session storage, and handle date units correctly.
The click handler has multiple issues that need to be addressed:
- Double navigation risk: The button click does not stop event propagation, so both this handler and the row click handler (line 258) will fire, causing two navigations.
- Stale session data: Reading
endDate
from session storage (line 82-83) instead of theselectedProject
prop can use outdated data if the prop has been updated. - Date unit mismatch:
Date.now()
returns milliseconds, butendDate
format is unknown. IfendDate
is in seconds (common in some APIs), the comparison will fail. - Silent fallback: The
console.warn
(line 97) provides no user feedback whenendDate
is missing.
Apply this diff to fix all issues:
<Button
label={t(`${row.id}`)}
- onClick={() => {
- const existingPaymentInbox = Digit.SessionStorage.get("paymentInbox");
- const endDate = existingPaymentInbox?.selectedProject?.endDate;
+ onClick={(e) => {
+ e.stopPropagation();
+
+ const endDate = selectedProject?.endDate ?? Digit.SessionStorage.get("paymentInbox")?.selectedProject?.endDate;
if (endDate) {
+ // Normalize endDate to milliseconds (some APIs return seconds)
+ const endDateMs = endDate < 1e12 ? endDate * 1000 : endDate;
const currentDate = Date.now();
- if (!(currentDate <= endDate)) {
+
+ if (currentDate > endDateMs) {
+ // Project expired: read-only view
history.push(
`/${window?.contextPath}/employee/payments/view-attendance?registerNumber=${row?.id}&boundaryCode=${row?.boundary}`
);
} else {
+ // Project active: allow editing
history.push(
`/${window?.contextPath}/employee/payments/edit-register?registerNumber=${row?.id}&boundaryCode=${row?.boundary}®isterId=${row?.registerId}`
);
}
} else {
- console.warn("No endDate found in session storage");
+ setShowToast({
+ key: "warning",
+ label: t("HCM_AM_END_DATE_MISSING_VIEW_ONLY"),
+ transitionTime: 3000
+ });
history.push(
`/${window?.contextPath}/employee/payments/view-attendance?registerNumber=${row?.id}&boundaryCode=${row?.boundary}`
);
}
}}
Note: You'll need to add the translation key HCM_AM_END_DATE_MISSING_VIEW_ONLY
with a message like "End date missing - opened in view-only mode".
Committable suggestion skipped: line range outside the PR's diff.
🤖 Prompt for AI Agents
In health/micro-ui/.../table_inbox.js around lines 81-101, the click handler
must be updated to (1) stop event propagation and prevent default to avoid
double navigation from the row click, (2) prefer the selectedProject prop over
session storage and only fall back to SessionStorage when the prop is absent,
(3) normalize endDate units before comparing to Date.now() (detect if endDate
looks like seconds and multiply by 1000, otherwise assume milliseconds), (4)
show a user-facing notification using the new translation key
HCM_AM_END_DATE_MISSING_VIEW_ONLY instead of console.warn when endDate is
missing, and (5) ensure navigation happens once and the handler returns
immediately after calling history.push.
let columns = [ | ||
{ | ||
name: ( | ||
<div style={{ borderRight: "2px solid #787878", width: "100%", textAlign: "start" }}> | ||
{t(`HCM_AM_FRONTLINE_WORKER`)} | ||
</div> | ||
), | ||
selector: (row) => { | ||
return ( | ||
<span className="ellipsis-cell"> | ||
{String(row?.[1] ? row?.[1] : t("ES_COMMON_NA"))} | ||
</span> | ||
); | ||
}, | ||
}, | ||
|
||
{ | ||
name: ( | ||
<div style={{ borderRight: "2px solid #787878", width: "100%", textAlign: "start" }}> | ||
{t("HCM_AM_WORKER_ID")} | ||
</div> | ||
), | ||
selector: (row) => { | ||
return ( | ||
<div className="ellipsis-cell" title={row?.[2] || t("NA")}> | ||
{row?.[2] || t("NA")} | ||
</div> | ||
); | ||
}, | ||
}, | ||
{ | ||
name: ( | ||
<div style={{ borderRight: "2px solid #787878", width: "100%", textAlign: "start" }}> | ||
{t("HCM_AM_ROLE")} | ||
</div> | ||
), | ||
selector: (row) => { | ||
return ( | ||
<div className="ellipsis-cell" title={t(row?.[3]) || t("NA")}> | ||
{t(row?.[3]) || t("NA")} | ||
</div> | ||
); | ||
}, | ||
}, | ||
|
||
{ | ||
name: ( | ||
<div style={{ borderRight: "2px solid #787878", width: "100%", textAlign: "start" }}> | ||
{t("HCM_AM_TAG_LABEL")} | ||
</div> | ||
), | ||
selector: (row) => { | ||
return ( | ||
<div className="ellipsis-cell" title={t(row?.[4]) || t("NA")}> | ||
{t(row?.[4]) || t("NA")} | ||
</div> | ||
); | ||
}, | ||
}, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🧹 Nitpick | 🔵 Trivial
Consider using named properties instead of array indices.
The column selectors rely on array indices (row?.[1]
, row?.[2]
, etc.), which are fragile and make the code harder to understand. If the data structure permits, consider mapping the input data to objects with named properties for better maintainability and type safety.
Example:
selector: (row) => {
return (
<span className="ellipsis-cell">
- {String(row?.[1] ? row?.[1] : t("ES_COMMON_NA"))}
+ {String(row?.workerName ? row.workerName : t("ES_COMMON_NA"))}
</span>
);
},
Committable suggestion skipped: line range outside the PR's diff.
🤖 Prompt for AI Agents
In
health/micro-ui/web/micro-ui-internals/packages/modules/health-payments/src/components/EditAttendanceManagementTable.js
around lines 61-119, the column selectors use fragile array indices (row?.[1],
row?.[2], etc.); replace this by converting the incoming row arrays into objects
with named fields (e.g., { name, workerId, role, tag }) before building the
columns or by updating the data source to provide objects, then update each
selector to read row.name, row.workerId, row.role, row.tag (and use the same
t(...) and fallbacks) so the code is self-descriptive and resistant to
index-shift bugs.
<Button | ||
className="custom-class" | ||
icon="Edit" | ||
iconFill="" | ||
label={t(`HCM_AM_VIEW_REGISTER_DISABLE_USER`)} | ||
onClick={() => { | ||
setSelectedRowId(row?.[0]); | ||
setOpenAlertPopUp(true); | ||
// handleDaysWorkedChange(row?.[0]) | ||
}} | ||
options={[]} | ||
optionsKey="" | ||
size="" | ||
style={{}} | ||
title={t(`HCM_AM_VIEW_REGISTER_DISABLE_USER`)} | ||
variation="secondary" | ||
/> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🧹 Nitpick | 🔵 Trivial
Remove commented code and clean up Button props.
Two issues:
- Line 170 contains a commented line that should be removed
- The Button component has several empty/default props that add noise
Apply this diff:
onClick={() => {
setSelectedRowId(row?.[0]);
setOpenAlertPopUp(true);
- // handleDaysWorkedChange(row?.[0])
}}
- options={[]}
- optionsKey=""
- size=""
- style={{}}
📝 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.
<Button | |
className="custom-class" | |
icon="Edit" | |
iconFill="" | |
label={t(`HCM_AM_VIEW_REGISTER_DISABLE_USER`)} | |
onClick={() => { | |
setSelectedRowId(row?.[0]); | |
setOpenAlertPopUp(true); | |
// handleDaysWorkedChange(row?.[0]) | |
}} | |
options={[]} | |
optionsKey="" | |
size="" | |
style={{}} | |
title={t(`HCM_AM_VIEW_REGISTER_DISABLE_USER`)} | |
variation="secondary" | |
/> | |
<Button | |
className="custom-class" | |
icon="Edit" | |
iconFill="" | |
label={t(`HCM_AM_VIEW_REGISTER_DISABLE_USER`)} | |
onClick={() => { | |
setSelectedRowId(row?.[0]); | |
setOpenAlertPopUp(true); | |
}} | |
title={t(`HCM_AM_VIEW_REGISTER_DISABLE_USER`)} | |
variation="secondary" | |
/> |
🤖 Prompt for AI Agents
In
health/micro-ui/web/micro-ui-internals/packages/modules/health-payments/src/components/EditAttendanceManagementTable.js
around lines 162 to 178, remove the commented out
handleDaysWorkedChange(row?.[0]) on line 170 and clean up the Button props by
removing empty or default-valued props (iconFill, options, optionsKey, size,
style) and any redundant attributes so the Button keeps only meaningful props
(e.g., className, icon, label, onClick, variation and title if intentionally
used).
const handleDaysWorkedChange = async (value) => { | ||
|
||
const attendee = { | ||
registerId: props.registerNumber, | ||
individualId: value, | ||
enrollmentDate: null, | ||
denrollmentDate: new Date(Date.now() - (1 * 60 * 1000 + 30 * 1000)).getTime(), | ||
tenantId: String(tenantId) | ||
}; | ||
await updateMapping({ "attendees": [attendee] }, | ||
{ | ||
onError: async (error) => { | ||
|
||
|
||
setShowToast( | ||
{ key: "error", label: t(`HCM_AM_ERROR_MESSAGE`), transitionTime: 3000 } | ||
); | ||
|
||
|
||
}, | ||
onSuccess: async (responseData) => { | ||
|
||
setShowToast({ key: "success", label: t(`HCM_AM_ATTENDEE_DE_ENROLL_SUCCESS_MESSAGE`), transitionTime: 3000 }); | ||
props.disableUser(""); | ||
}, | ||
} | ||
) | ||
|
||
|
||
}; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Handle mutation loading state.
The component doesn't display loading feedback while the de-enrollment mutation is in progress. Users may click the button multiple times or see no indication that their action is being processed.
Consider destructuring the mutation's isLoading
state and disabling UI or showing a loader:
-const { mutate: updateMapping } = Digit.Hooks.payments.useDeleteAttendeeFromRegister(tenantId);
+const { mutate: updateMapping, isLoading: isDeletingAttendee } = Digit.Hooks.payments.useDeleteAttendeeFromRegister(tenantId);
Then conditionally render a loader or disable buttons during the operation.
📝 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.
const handleDaysWorkedChange = async (value) => { | |
const attendee = { | |
registerId: props.registerNumber, | |
individualId: value, | |
enrollmentDate: null, | |
denrollmentDate: new Date(Date.now() - (1 * 60 * 1000 + 30 * 1000)).getTime(), | |
tenantId: String(tenantId) | |
}; | |
await updateMapping({ "attendees": [attendee] }, | |
{ | |
onError: async (error) => { | |
setShowToast( | |
{ key: "error", label: t(`HCM_AM_ERROR_MESSAGE`), transitionTime: 3000 } | |
); | |
}, | |
onSuccess: async (responseData) => { | |
setShowToast({ key: "success", label: t(`HCM_AM_ATTENDEE_DE_ENROLL_SUCCESS_MESSAGE`), transitionTime: 3000 }); | |
props.disableUser(""); | |
}, | |
} | |
) | |
}; | |
// Destructure loading state from the mutation hook: | |
const { mutate: updateMapping, isLoading: isDeletingAttendee } = Digit.Hooks.payments.useDeleteAttendeeFromRegister(tenantId); | |
// ... later in the component, you can use `isDeletingAttendee` to disable buttons | |
// or render a spinner while the de-enrollment is in progress. |
🤖 Prompt for AI Agents
In
health/micro-ui/web/micro-ui-internals/packages/modules/health-payments/src/components/EditAttendanceManagementTable.js
around lines 190 to 219, the de-enrollment mutation call doesn't surface a
loading state so users can re-click or get no feedback; destructure the mutation
result to read isLoading (e.g. const [updateMapping, { isLoading }]) and use
that boolean to disable the de-enroll control and/or render a spinner while the
mutation is in progress, keep current onSuccess/onError handlers, and ensure the
button click early-returns when isLoading is true to prevent duplicate requests.
🛠️ Refactor suggestion | 🟠 Major
Rename function to match its actual purpose.
The function name handleDaysWorkedChange
is misleading—it actually handles attendee de-enrollment. Consider renaming to handleAttendeeDeEnrollment
or handleDisableUser
for clarity.
Apply this diff:
-const handleDaysWorkedChange = async (value) => {
+const handleAttendeeDeEnrollment = async (value) => {
And update the call site on line 268:
- handleDaysWorkedChange(selectedRowId);
+ handleAttendeeDeEnrollment(selectedRowId);
📝 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.
const handleDaysWorkedChange = async (value) => { | |
const attendee = { | |
registerId: props.registerNumber, | |
individualId: value, | |
enrollmentDate: null, | |
denrollmentDate: new Date(Date.now() - (1 * 60 * 1000 + 30 * 1000)).getTime(), | |
tenantId: String(tenantId) | |
}; | |
await updateMapping({ "attendees": [attendee] }, | |
{ | |
onError: async (error) => { | |
setShowToast( | |
{ key: "error", label: t(`HCM_AM_ERROR_MESSAGE`), transitionTime: 3000 } | |
); | |
}, | |
onSuccess: async (responseData) => { | |
setShowToast({ key: "success", label: t(`HCM_AM_ATTENDEE_DE_ENROLL_SUCCESS_MESSAGE`), transitionTime: 3000 }); | |
props.disableUser(""); | |
}, | |
} | |
) | |
}; | |
const handleAttendeeDeEnrollment = async (value) => { | |
const attendee = { | |
registerId: props.registerNumber, | |
individualId: value, | |
enrollmentDate: null, | |
denrollmentDate: new Date(Date.now() - (1 * 60 * 1000 + 30 * 1000)).getTime(), | |
tenantId: String(tenantId) | |
}; | |
await updateMapping( | |
{ attendees: [attendee] }, | |
{ | |
onError: async (error) => { | |
setShowToast( | |
{ key: "error", label: t(`HCM_AM_ERROR_MESSAGE`), transitionTime: 3000 } | |
); | |
}, | |
onSuccess: async (responseData) => { | |
setShowToast( | |
{ key: "success", label: t(`HCM_AM_ATTENDEE_DE_ENROLL_SUCCESS_MESSAGE`), transitionTime: 3000 } | |
); | |
props.disableUser(""); | |
}, | |
} | |
); | |
}; |
const handleDaysWorkedChange = async (value) => { | |
const attendee = { | |
registerId: props.registerNumber, | |
individualId: value, | |
enrollmentDate: null, | |
denrollmentDate: new Date(Date.now() - (1 * 60 * 1000 + 30 * 1000)).getTime(), | |
tenantId: String(tenantId) | |
}; | |
await updateMapping({ "attendees": [attendee] }, | |
{ | |
onError: async (error) => { | |
setShowToast( | |
{ key: "error", label: t(`HCM_AM_ERROR_MESSAGE`), transitionTime: 3000 } | |
); | |
}, | |
onSuccess: async (responseData) => { | |
setShowToast({ key: "success", label: t(`HCM_AM_ATTENDEE_DE_ENROLL_SUCCESS_MESSAGE`), transitionTime: 3000 }); | |
props.disableUser(""); | |
}, | |
} | |
) | |
}; | |
handleAttendeeDeEnrollment(selectedRowId); |
🤖 Prompt for AI Agents
In
health/micro-ui/web/micro-ui-internals/packages/modules/health-payments/src/components/EditAttendanceManagementTable.js
around lines 190 to 219, the function currently named handleDaysWorkedChange
actually performs attendee de-enrollment; rename the function to
handleAttendeeDeEnrollment (or handleDisableUser) and update its declaration and
any export or references accordingly, and also update the call site on line 268
to use the new name; ensure parameter and behavior remain unchanged and run
tests/lint to catch any missed references.
onSuccess: async (responseData) => { | ||
|
||
setShowToast({ key: "success", label: t(`HCM_AM_ATTENDEE_DE_ENROLL_SUCCESS_MESSAGE`), transitionTime: 3000 }); | ||
props.disableUser(""); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Validate props.disableUser before calling.
Line 213 calls props.disableUser("")
without checking if it exists or is a function, which could cause a runtime error.
Add a guard:
- props.disableUser("");
+ props?.disableUser?.("");
Or validate in PropTypes/at component entry.
📝 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.
props.disableUser(""); | |
props?.disableUser?.(""); |
🤖 Prompt for AI Agents
In
health/micro-ui/web/micro-ui-internals/packages/modules/health-payments/src/components/EditAttendanceManagementTable.js
around line 213, props.disableUser("") is invoked without validation; update the
code to guard the call by checking that props.disableUser is defined and is a
function before calling it (or set a safe default in defaultProps and/or declare
it in PropTypes as a function), and only call props.disableUser("") when that
check passes so you avoid potential runtime errors.
<DataTable | ||
className="search-component-table" | ||
columns={columns} | ||
data={paginatedData} | ||
progressPending={false} | ||
progressComponent={<Loader />} | ||
pagination | ||
paginationServer | ||
customStyles={editAttendeetableCustomStyle(false)} | ||
paginationDefaultPage={currentPage} | ||
onChangePage={handlePageChange} | ||
onChangeRowsPerPage={handlePerRowsChange} | ||
paginationTotalRows={props?.data.length} | ||
paginationPerPage={defaultRowsPerPageForEditAttendee} | ||
sortIcon={<CustomSVG.SortUp width={"16px"} height={"16px"} fill={"#0b4b66"} />} | ||
paginationRowsPerPageOptions={defaultPaginationValuesForEditAttendee} | ||
fixedHeader={true} | ||
fixedHeaderScrollHeight={props.height ? props.height : "70vh"} | ||
paginationComponentOptions={getCustomPaginationOptions(t)} | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fix pagination configuration mismatch.
The DataTable is configured with paginationServer={true}
(line 232), but the data is sliced client-side (line 50: props.data.slice(...)
). This is a configuration inconsistency.
For client-side pagination, set paginationServer={false}
and remove the manual slicing since DataTable will handle it:
-const paginatedData = props.data.slice((currentPage - 1) * rowsPerPage, currentPage * rowsPerPage);
+// Remove manual slicing for client-side pagination
<DataTable
className="search-component-table"
columns={columns}
- data={paginatedData}
+ data={props.data}
progressPending={false}
progressComponent={<Loader />}
pagination
- paginationServer
+ paginationServer={false}
Alternatively, if server-side pagination is intended, implement proper server-side data fetching and remove the client-side slice.
📝 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.
<DataTable | |
className="search-component-table" | |
columns={columns} | |
data={paginatedData} | |
progressPending={false} | |
progressComponent={<Loader />} | |
pagination | |
paginationServer | |
customStyles={editAttendeetableCustomStyle(false)} | |
paginationDefaultPage={currentPage} | |
onChangePage={handlePageChange} | |
onChangeRowsPerPage={handlePerRowsChange} | |
paginationTotalRows={props?.data.length} | |
paginationPerPage={defaultRowsPerPageForEditAttendee} | |
sortIcon={<CustomSVG.SortUp width={"16px"} height={"16px"} fill={"#0b4b66"} />} | |
paginationRowsPerPageOptions={defaultPaginationValuesForEditAttendee} | |
fixedHeader={true} | |
fixedHeaderScrollHeight={props.height ? props.height : "70vh"} | |
paginationComponentOptions={getCustomPaginationOptions(t)} | |
// Removed manual slicing for client-side pagination | |
// const paginatedData = props.data.slice((currentPage - 1) * rowsPerPage, currentPage * rowsPerPage); | |
<DataTable | |
className="search-component-table" | |
columns={columns} | |
data={props.data} | |
progressPending={false} | |
progressComponent={<Loader />} | |
pagination | |
paginationServer={false} | |
customStyles={editAttendeetableCustomStyle(false)} | |
paginationDefaultPage={currentPage} | |
onChangePage={handlePageChange} | |
onChangeRowsPerPage={handlePerRowsChange} | |
paginationTotalRows={props?.data.length} | |
paginationPerPage={defaultRowsPerPageForEditAttendee} | |
sortIcon={<CustomSVG.SortUp width={"16px"} height={"16px"} fill={"#0b4b66"} />} | |
paginationRowsPerPageOptions={defaultPaginationValuesForEditAttendee} | |
fixedHeader={true} | |
fixedHeaderScrollHeight={props.height ? props.height : "70vh"} | |
paginationComponentOptions={getCustomPaginationOptions(t)} | |
/> |
🤖 Prompt for AI Agents
health/micro-ui/web/micro-ui-internals/packages/modules/health-payments/src/components/EditAttendanceManagementTable.js
lines 225-244: paginationServer is set true while the component slices
props.data client-side, causing a mismatch; either set paginationServer={false}
and remove the manual props.data.slice logic so the DataTable handles pagination
client-side, or keep paginationServer={true} and remove client-side slicing and
instead wire up server-side data fetching/requests (update
onChangePage/onChangeRowsPerPage to fetch the correct page and set paginatedData
from the server). Ensure only one pagination approach remains and keep
paginationTotalRows, paginationPerPage, and paginationComponentOptions
consistent with the chosen approach.
{<div className="inbox-search-wrapper" style={{ | ||
height:"160px" | ||
}}> | ||
<AttendanceInboxComponent></AttendanceInboxComponent> | ||
</div> | ||
</React.Fragment> | ||
</div>} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🧹 Nitpick | 🔵 Trivial
Remove unnecessary JSX braces and fix formatting.
The div element is wrapped in unnecessary JSX expression braces ({...}
), and the inline style has inconsistent spacing.
Apply this diff:
- {<div className="inbox-search-wrapper" style={{
- height:"160px"
- }}>
+ <div className="inbox-search-wrapper" style={{ height: "160px" }}>
<AttendanceInboxComponent></AttendanceInboxComponent>
- </div>}
+ </div>
📝 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.
{<div className="inbox-search-wrapper" style={{ | |
height:"160px" | |
}}> | |
<AttendanceInboxComponent></AttendanceInboxComponent> | |
</div> | |
</React.Fragment> | |
</div>} | |
<div className="inbox-search-wrapper" style={{ height: "160px" }}> | |
<AttendanceInboxComponent></AttendanceInboxComponent> | |
</div> |
🤖 Prompt for AI Agents
In
health/micro-ui/web/micro-ui-internals/packages/modules/health-payments/src/pages/employee/attendance_inbox.js
around lines 46 to 50, remove the unnecessary JSX expression braces surrounding
the div (drop the outer { ... }) and normalize the inline style spacing (e.g.,
use consistent spacing around keys/values like height: "160px"); also tidy the
JSX formatting for readability (remove extra blank lines and ensure proper
indentation, and optionally convert
<AttendanceInboxComponent></AttendanceInboxComponent> to a concise self-closing
tag if preferred).
{<div className="inbox-search-wrapper" style={{ | ||
height:"160px" | ||
}}> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🧩 Analysis chain
Verify the 160px height constraint.
The wrapper sets a fixed height: "160px"
, but the AttendanceInboxComponent
contains sections with height: "60vh"
(approximately 600px on a standard 1080p display). This constraint may cause overflow or clipping.
Run the following script to examine the inner component's height requirements:
🏁 Script executed:
#!/bin/bash
# Check height styles in AttendanceInboxComponent and related components
rg -n --type=js -C3 'height.*vh|height.*px' health/micro-ui/web/micro-ui-internals/packages/modules/health-payments/src/components/attendance_inbox/
Length of output: 8255
🏁 Script executed:
#!/bin/bash
sed -n '1,100p' health/micro-ui/web/micro-ui-internals/packages/modules/health-payments/src/pages/employee/attendance_inbox.js
Length of output: 2166
Remove fixed height: "160px"
on .inbox-search-wrapper
.
This wrapper encloses the entire AttendanceInboxComponent
, whose inner sections use vh
heights (60vh–80vh), causing overflow or clipping.
File: health/micro-ui/web/micro-ui-internals/packages/modules/health-payments/src/pages/employee/attendance_inbox.js Lines: 46–48
🤖 Prompt for AI Agents
health/micro-ui/web/micro-ui-internals/packages/modules/health-payments/src/pages/employee/attendance_inbox.js
lines 46-48: the .inbox-search-wrapper currently has a fixed height: "160px"
which conflicts with inner sections using vh units and causes overflow/clipping;
remove the fixed height (or replace it with responsive CSS such as auto,
min-height, or use padding/margins) so the wrapper can grow/shrink with its
children and avoid clipping, and ensure layout consistency by testing with the
inner 60vh–80vh sections.
There was a problem hiding this 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
📜 Review details
Configuration used: CodeRabbit UI
Review profile: ASSERTIVE
Plan: Pro
📒 Files selected for processing (1)
health/micro-ui/web/micro-ui-internals/packages/modules/health-payments/src/components/bill_inbox/BillInbox.js
(2 hunks)
🧰 Additional context used
📓 Path-based instructions (1)
**/*.js
⚙️ CodeRabbit configuration file
check
Files:
health/micro-ui/web/micro-ui-internals/packages/modules/health-payments/src/components/bill_inbox/BillInbox.js
🧠 Learnings (2)
📚 Learning: 2024-06-10T19:25:42.992Z
Learnt from: siddhant-nawale-egov
PR: egovernments/DIGIT-Frontend#698
File: micro-ui/web/micro-ui-internals/packages/modules/hcm-microplanning/src/components/MicroplanPreview.js:1-1
Timestamp: 2024-06-10T19:25:42.992Z
Learning: The imports in `MicroplanPreview.js` are from different libraries: `egovernments/digit-ui-components` and `egovernments/digit-ui-react-components`.
Applied to files:
health/micro-ui/web/micro-ui-internals/packages/modules/health-payments/src/components/bill_inbox/BillInbox.js
📚 Learning: 2024-06-10T19:25:42.992Z
Learnt from: siddhant-nawale-egov
PR: egovernments/DIGIT-Frontend#0
File: :0-0
Timestamp: 2024-06-10T19:25:42.992Z
Learning: The Button component from `egovernments/digit-ui-components` has compatibility issues with the ActionBar, leading to the preference for using the Button from `egovernments/digit-ui-react-components` in certain scenarios.
Applied to files:
health/micro-ui/web/micro-ui-internals/packages/modules/health-payments/src/components/bill_inbox/BillInbox.js
⏰ Context from checks skipped due to timeout of 10000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (3)
- GitHub Check: Build application arm64
- GitHub Check: Build application amd64
- GitHub Check: Analyze (javascript-typescript)
🔇 Additional comments (1)
health/micro-ui/web/micro-ui-internals/packages/modules/health-payments/src/components/bill_inbox/BillInbox.js (1)
5-5
: Verify AlertCard alias and props usage: Ensure theAlertCard
imported asInfoCard
inBillInbox.js
(lines 305–307) supports thepopulators
,variant
,style
,label
, andtext
props according to the@egovernments/digit-ui-components
API.
import { useTranslation } from "react-i18next"; | ||
const { fromViewScreen } = location.state || false; | ||
import { ActionBar, Button, Card, InfoCard, Loader, Tab, Toast } from "@egovernments/digit-ui-components"; | ||
import { ActionBar, Button, Card,AlertCard as InfoCard, Loader, Tab, Toast } from "@egovernments/digit-ui-components"; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🧹 Nitpick | 🔵 Trivial
Minor formatting: Add space after comma in import statement.
The import statement is missing a space after the comma between Card
and AlertCard
.
Apply this diff to fix the formatting:
-import { ActionBar, Button, Card,AlertCard as InfoCard, Loader, Tab, Toast } from "@egovernments/digit-ui-components";
+import { ActionBar, Button, Card, AlertCard as InfoCard, Loader, Tab, Toast } from "@egovernments/digit-ui-components";
📝 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.
import { ActionBar, Button, Card,AlertCard as InfoCard, Loader, Tab, Toast } from "@egovernments/digit-ui-components"; | |
import { ActionBar, Button, Card, AlertCard as InfoCard, Loader, Tab, Toast } from "@egovernments/digit-ui-components"; |
🤖 Prompt for AI Agents
In
health/micro-ui/web/micro-ui-internals/packages/modules/health-payments/src/components/bill_inbox/BillInbox.js
around line 5, the import list lacks a space after the comma between Card and
AlertCard; update the import statement to insert a space after the comma so it
reads "... Card, AlertCard as InfoCard, Loader ..." to correct formatting.
There was a problem hiding this 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
♻️ Duplicate comments (1)
health/micro-ui/web/micro-ui-internals/packages/modules/campaign-manager/src/pages/employee/appConfigurationRedesign/AppConfigurationWrapper.js (1)
283-306
: Implement the fallback logic for PATCH_PAGE_CONDITIONAL_NAV.The fallback when
pageName
is not found currently returns the array unchanged (line 298). This creates a silent no-op when the page isn't found.As flagged in previous review comments, apply this diff:
const patchArray = (arr) => { if (!Array.isArray(arr) || arr.length === 0) return arr; // If pageName is provided, try to patch by name if (pageName) { const idx = arr.findIndex((p) => p?.name === pageName); if (idx !== -1) { return arr.map((p, i) => (i === idx ? { ...p, conditionalNavigateTo: data } : p)); } } // Fallback: patch the first page - return arr; + return arr.map((p, i) => (i === 0 ? { ...p, conditionalNavigateTo: data } : p)); };
📜 Review details
Configuration used: CodeRabbit UI
Review profile: ASSERTIVE
Plan: Pro
📒 Files selected for processing (4)
health/micro-ui/web/micro-ui-internals/packages/modules/campaign-manager/src/pages/employee/appConfigurationRedesign/AppConfigurationWrapper.js
(5 hunks)health/micro-ui/web/micro-ui-internals/packages/modules/campaign-manager/src/pages/employee/appConfigurationRedesign/DependentFieldsWrapper.js
(1 hunks)health/micro-ui/web/micro-ui-internals/packages/modules/campaign-manager/src/pages/employee/appConfigurationRedesign/DrawerFieldComposer.js
(8 hunks)health/micro-ui/web/micro-ui-internals/packages/modules/campaign-manager/src/pages/employee/appConfigurationRedesign/RenderConditionalField.js
(5 hunks)
🧰 Additional context used
📓 Path-based instructions (1)
**/*.js
⚙️ CodeRabbit configuration file
check
Files:
health/micro-ui/web/micro-ui-internals/packages/modules/campaign-manager/src/pages/employee/appConfigurationRedesign/DependentFieldsWrapper.js
health/micro-ui/web/micro-ui-internals/packages/modules/campaign-manager/src/pages/employee/appConfigurationRedesign/RenderConditionalField.js
health/micro-ui/web/micro-ui-internals/packages/modules/campaign-manager/src/pages/employee/appConfigurationRedesign/DrawerFieldComposer.js
health/micro-ui/web/micro-ui-internals/packages/modules/campaign-manager/src/pages/employee/appConfigurationRedesign/AppConfigurationWrapper.js
🧠 Learnings (1)
📚 Learning: 2024-10-17T12:00:51.749Z
Learnt from: Ramkrishna-egov
PR: egovernments/DIGIT-Frontend#1545
File: health/micro-ui/web/micro-ui-internals/packages/modules/microplan/src/components/ActivityCard.js:30-35
Timestamp: 2024-10-17T12:00:51.749Z
Learning: In our codebase, the 'Card' component is commonly used by passing children via the 'children' prop.
Applied to files:
health/micro-ui/web/micro-ui-internals/packages/modules/campaign-manager/src/pages/employee/appConfigurationRedesign/DependentFieldsWrapper.js
🧬 Code graph analysis (4)
health/micro-ui/web/micro-ui-internals/packages/modules/campaign-manager/src/pages/employee/appConfigurationRedesign/DependentFieldsWrapper.js (1)
micro-ui/web/micro-ui-internals/packages/react-components/src/atoms/Dropdown.js (1)
Dropdown
(94-281)
health/micro-ui/web/micro-ui-internals/packages/modules/campaign-manager/src/pages/employee/appConfigurationRedesign/RenderConditionalField.js (4)
health/micro-ui/web/micro-ui-internals/packages/modules/campaign-manager/src/pages/employee/appConfigurationRedesign/DrawerFieldComposer.js (6)
useTranslation
(80-80)useTranslation
(391-391)useT
(89-89)isLocalisable
(81-83)drawerState
(396-398)handleExpressionChange
(413-423)health/micro-ui/web/micro-ui-internals/packages/modules/campaign-manager/src/pages/employee/appConfigurationRedesign/DependentFieldsWrapper.js (1)
useT
(73-73)health/micro-ui/web/micro-ui-internals/packages/modules/campaign-manager/src/pages/employee/appConfigurationRedesign/useCustomT.js (2)
useCustomT
(12-40)useCustomT
(12-40)health/micro-ui/web/micro-ui-internals/packages/modules/campaign-manager/src/pages/employee/appConfigurationRedesign/AppConfigurationParentLayer.js (1)
parentState
(60-60)
health/micro-ui/web/micro-ui-internals/packages/modules/campaign-manager/src/pages/employee/appConfigurationRedesign/DrawerFieldComposer.js (3)
health/micro-ui/web/micro-ui-internals/packages/modules/campaign-manager/src/pages/employee/appConfigurationRedesign/useCustomT.js (2)
useCustomT
(12-40)useCustomT
(12-40)health/micro-ui/web/micro-ui-internals/packages/modules/campaign-manager/src/pages/employee/appConfigurationRedesign/AppConfigurationParentLayer.js (1)
parentState
(60-60)health/micro-ui/web/micro-ui-internals/packages/modules/campaign-manager/src/pages/employee/appConfigurationRedesign/AppLocalisationWrapper.js (1)
updateLocalization
(56-62)
health/micro-ui/web/micro-ui-internals/packages/modules/campaign-manager/src/pages/employee/appConfigurationRedesign/AppConfigurationWrapper.js (3)
health/micro-ui/web/micro-ui-internals/packages/modules/campaign-manager/src/pages/employee/appConfigurationRedesign/AppConfigurationParentLayer.js (1)
parentState
(60-60)health/micro-ui/web/micro-ui-internals/packages/modules/campaign-manager/src/pages/employee/appConfigurationRedesign/useCustomT.js (2)
useCustomT
(12-40)useCustomT
(12-40)health/micro-ui/web/micro-ui-internals/packages/modules/campaign-manager/src/components/AppPreview.js (1)
AppPreview
(172-281)
🪛 Biome (2.1.2)
health/micro-ui/web/micro-ui-internals/packages/modules/campaign-manager/src/pages/employee/appConfigurationRedesign/DependentFieldsWrapper.js
[error] 514-515: The elements with this role can be changed to the following elements:
For examples and more information, see WAI-ARIA Roles
(lint/a11y/useSemanticElements)
[error] 513-520: The HTML element with the interactive role "button" is not focusable.
A non-interactive HTML element that is not focusable may not be reachable for users that rely on keyboard navigation, even with an added role like "button".
Add a tabIndex attribute to make this element focusable.
(lint/a11y/useFocusableInteractive)
[error] 513-520: Enforce to have the onClick mouse event with the onKeyUp, the onKeyDown, or the onKeyPress keyboard event.
Actions triggered using mouse events should have corresponding keyboard events to account for keyboard-only navigation.
(lint/a11y/useKeyWithClickEvents)
[error] 528-529: The elements with this role can be changed to the following elements:
For examples and more information, see WAI-ARIA Roles
(lint/a11y/useSemanticElements)
[error] 527-534: Enforce to have the onClick mouse event with the onKeyUp, the onKeyDown, or the onKeyPress keyboard event.
Actions triggered using mouse events should have corresponding keyboard events to account for keyboard-only navigation.
(lint/a11y/useKeyWithClickEvents)
[error] 527-534: The HTML element with the interactive role "button" is not focusable.
A non-interactive HTML element that is not focusable may not be reachable for users that rely on keyboard navigation, even with an added role like "button".
Add a tabIndex attribute to make this element focusable.
(lint/a11y/useFocusableInteractive)
[error] 917-924: Static Elements should not be interactive.
To add interactivity such as a mouse or key event listener to a static element, give the element an appropriate role value.
(lint/a11y/noStaticElementInteractions)
[error] 917-924: Enforce to have the onClick mouse event with the onKeyUp, the onKeyDown, or the onKeyPress keyboard event.
Actions triggered using mouse events should have corresponding keyboard events to account for keyboard-only navigation.
(lint/a11y/useKeyWithClickEvents)
[error] 598-598: Avoid passing children using a prop
The canonical way to pass children in React is to use JSX elements
(lint/correctness/noChildrenProp)
health/micro-ui/web/micro-ui-internals/packages/modules/campaign-manager/src/pages/employee/appConfigurationRedesign/RenderConditionalField.js
[error] 42-42: This hook is being called conditionally, but all hooks must be called in the exact same order in every component render.
For React to preserve state between calls, hooks needs to be called unconditionally and always in the same order.
See https://reactjs.org/docs/hooks-rules.html#only-call-hooks-at-the-top-level
(lint/correctness/useHookAtTopLevel)
[error] 94-94: This hook is being called from a nested function, but all hooks must be called unconditionally from the top-level component.
For React to preserve state between calls, hooks needs to be called unconditionally and always in the same order.
See https://reactjs.org/docs/hooks-rules.html#only-call-hooks-at-the-top-level
(lint/correctness/useHookAtTopLevel)
health/micro-ui/web/micro-ui-internals/packages/modules/campaign-manager/src/pages/employee/appConfigurationRedesign/DrawerFieldComposer.js
[error] 201-201: This hook is being called conditionally, but all hooks must be called in the exact same order in every component render.
For React to preserve state between calls, hooks needs to be called unconditionally and always in the same order.
See https://reactjs.org/docs/hooks-rules.html#only-call-hooks-at-the-top-level
(lint/correctness/useHookAtTopLevel)
[error] 360-360: This hook is being called from a nested function, but all hooks must be called unconditionally from the top-level component.
For React to preserve state between calls, hooks needs to be called unconditionally and always in the same order.
See https://reactjs.org/docs/hooks-rules.html#only-call-hooks-at-the-top-level
(lint/correctness/useHookAtTopLevel)
health/micro-ui/web/micro-ui-internals/packages/modules/campaign-manager/src/pages/employee/appConfigurationRedesign/AppConfigurationWrapper.js
[error] 326-326: This hook is being called conditionally, but all hooks must be called in the exact same order in every component render.
For React to preserve state between calls, hooks needs to be called unconditionally and always in the same order.
See https://reactjs.org/docs/hooks-rules.html#only-call-hooks-at-the-top-level
(lint/correctness/useHookAtTopLevel)
[error] 755-755: This hook is being called conditionally, but all hooks must be called in the exact same order in every component render.
For React to preserve state between calls, hooks needs to be called unconditionally and always in the same order.
See https://reactjs.org/docs/hooks-rules.html#only-call-hooks-at-the-top-level
(lint/correctness/useHookAtTopLevel)
⏰ Context from checks skipped due to timeout of 10000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
- GitHub Check: Analyze (javascript-typescript)
🔇 Additional comments (6)
health/micro-ui/web/micro-ui-internals/packages/modules/campaign-manager/src/pages/employee/appConfigurationRedesign/RenderConditionalField.js (1)
223-233
: LGTM! Dependency field wrapper integration.The new "dependencyFieldWrapper" case correctly passes all required props to DependentFieldsWrapper, enabling conditional display logic configuration.
health/micro-ui/web/micro-ui-internals/packages/modules/campaign-manager/src/pages/employee/appConfigurationRedesign/DependentFieldsWrapper.js (1)
1-964
: LGTM! Well-structured conditional navigation editor.The component implements a comprehensive rule-based conditional navigation/display system with:
- Proper state management for rules list
- Tokenization and parsing of conditional expressions
- Field type-aware operator options and value inputs
- Clear UI for adding/editing/deleting rules
The implementation correctly handles different field types (DOB, dates, checkboxes, dropdowns, numeric fields) and provides appropriate input controls for each.
Note: Accessibility improvements for interactive divs (lines 513-520, 527-534, 891-927) and children prop usage (line 598) have been flagged in previous review comments.
health/micro-ui/web/micro-ui-internals/packages/modules/campaign-manager/src/pages/employee/appConfigurationRedesign/AppConfigurationWrapper.js (2)
314-314
: LGTM! Proper prop threading for parentState and translation hook.The new
parentState
prop is correctly:
- Accepted in the function signature (line 314)
- Passed to child components (lines 661, 665)
The
useT
translation hook is properly initialized and passed to AppPreview (line 582).Also applies to: 582-582, 661-661, 665-665
315-315
: Critical: useT invoked conditionally in useMemo.
useT
(a hook returned fromuseCustomT()
) is being called insideuseMemo
callbacks (lines 326, 755), which are conditionally executed based on dependencies. This violates React's Rules of Hooks.Move the translation calls outside of useMemo:
function AppConfigurationWrapper({ screenConfig, localeModule, pageTag, parentState }) { const useT = useCustomT(); const queryClient = useQueryClient(); const { locState, addMissingKey, updateLocalization, onSubmit, back, showBack, parentDispatch } = useAppLocalisationContext(); // ... other hooks - const addFieldDataLabel = useMemo(() => { - return addFieldData?.label ? useT(addFieldData?.label) : null; - }, [addFieldData]); + // Simply compute the label directly - useT is already stable from useCustomT + const addFieldDataLabel = addFieldData?.label ? useT(addFieldData?.label) : null; // ... rest of component {popupData && ( <PopUp> <FieldV1 required={true} type={"text"} label={`${t("ADD_FIELD_LABEL")}`} - value={addFieldData?.label ? useT(addFieldData?.label) : ""} + value={addFieldDataLabel || ""} // ... rest unchanged /> </PopUp> )} }The
useT
function returned byuseCustomT()
is already memoized internally, so you don't need additional useMemo wrapping.Also applies to: 326-326, 755-755
⛔ Skipped due to learnings
Learnt from: Tulika-eGov PR: egovernments/DIGIT-Frontend#2188 File: micro-ui/web/micro-ui-internals/packages/modules/pgr/src/pages/employee/new-inbox.js:34-47 Timestamp: 2025-02-05T10:18:29.947Z Learning: In the DIGIT-Frontend codebase, translations within FormComposer are handled internally by the component itself, so the translation function 't' does not need to be added to useMemo dependency arrays even when used within the memoized function that generates form configurations.
Learnt from: Tulika-eGov PR: egovernments/DIGIT-Frontend#2188 File: micro-ui/web/micro-ui-internals/packages/libraries/src/hooks/pgr/useComplaintSubType.js:14-14 Timestamp: 2025-02-05T10:05:37.433Z Learning: In PGR's useComplaintSubType hook, the translation function 't' must be included in the useEffect dependency array to ensure complaint types are updated when the language changes.
health/micro-ui/web/micro-ui-internals/packages/modules/campaign-manager/src/pages/employee/appConfigurationRedesign/DrawerFieldComposer.js (2)
413-423
: LGTM! handleExpressionChange implementation.The function correctly updates the
visibilityCondition.expression
indrawerState
with proper immutability and guards against redundant updates.
78-79
: LGTM! Proper prop threading for new conditional navigation features.The new props (
parentState
,screenConfig
,selectedField
,handleExpressionChange
) are correctly:
- Added to RenderField signature (lines 78-79)
- Passed to RenderConditionalField (lines 168-172)
- Added to DrawerFieldComposer signature (line 390)
- Passed to RenderField (lines 493-499)
This enables the DependentFieldsWrapper to access parent state and update conditional navigation logic.
Also applies to: 168-172, 390-390, 493-499
const tenantId = searchParams.get("tenantId"); | ||
const shouldShow = whenToShow(panelItem, drawerState); | ||
const flowName = useMemo(() => state?.screenConfig?.[0]?.parent, [state?.screenConfig?.[0]]); | ||
const useT = useCustomT(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Critical: useT called conditionally inside switch and nested functions.
useT
is a hook and must be called at the component's top level. Currently it's invoked inside:
- Line 201: Inside switch case "text" (conditionally based on
panelItem?.fieldType
) - Line 360: Inside a
.map()
callback (nested function)
This violates React's Rules of Hooks and will corrupt state.
Refactor to call useT unconditionally:
const RenderField = ({ state, panelItem, parentState, screenConfig, selectedField, drawerState, setDrawerState, updateLocalization, handleExpressionChange, AppScreenLocalisationConfig }) => {
const { t } = useTranslation();
+ const useT = useCustomT();
+
+ // Pre-compute localized values at top level
+ const localizedFieldValue = isLocalisable ? useT(drawerState?.[panelItem?.bindTo]) : null;
+
const isLocalisable = AppScreenLocalisationConfig?.fields
?.find((i) => i.fieldType === drawerState?.appType)
?.localisableProperties?.includes(panelItem?.label);
const searchParams = new URLSearchParams(location.search);
const projectType = searchParams.get("projectType");
const tenantId = searchParams.get("tenantId");
const shouldShow = whenToShow(panelItem, drawerState);
const flowName = useMemo(() => state?.screenConfig?.[0]?.parent, [state?.screenConfig?.[0]]);
- const useT = useCustomT();
// ... rest of the logic
switch (panelItem?.fieldType) {
case "text": {
return (
<div>
<FieldV1
type={panelItem?.fieldType}
label={t(Digit.Utils.locale.getTransformedLocale(`FIELD_DRAWER_LABEL_${panelItem?.label}`))}
value={
- isLocalisable
- ? useT(drawerState?.[panelItem?.bindTo])
- : drawerState?.[panelItem?.bindTo] === true
- ? ""
- : drawerState?.[panelItem?.bindTo]
+ localizedFieldValue !== null
+ ? localizedFieldValue
+ : drawerState?.[panelItem?.bindTo] === true
+ ? ""
+ : drawerState?.[panelItem?.bindTo]
}
// ... rest unchanged
/>
</div>
);
}
case "DetailsCard":
case "Table": {
const selectedOptions = drawerState?.[panelItem?.bindTo] || [];
+ // Pre-compute all localized option codes at the top level
+ const localizedOptions = selectedOptions
+ .filter((opt) => opt && typeof opt.code === "string" && opt.code.includes("."))
+ .map((opt) => ({
+ ...opt,
+ localizedValue: useT(opt.code)
+ }));
return (
<>
{/* ... MultiSelectDropdown unchanged ... */}
- {Array.isArray(selectedOptions) &&
- selectedOptions
- .filter((opt) => opt && typeof opt.code === "string" && opt.code.includes("."))
- .map((option) => {
+ {localizedOptions.map((option) => {
const [entity, fieldKey] = option.code.split(".");
return (
<div key={option.code} style={{ marginTop: "16px" }}>
<FieldV1
label={`${t(entity)} - ${t(fieldKey)}`}
- value={useT(option.code)}
+ value={option.localizedValue}
type="text"
// ... rest unchanged
/>
</div>
);
})}
</>
);
}
}
};
Also applies to: 201-201, 360-360
disabled, | ||
}) => { | ||
const { t } = useTranslation(); | ||
const useT = useCustomT(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Critical: Move useT to component top level.
useT
is a hook and must be called unconditionally at the component's top level. Currently it's being invoked inside switch branches (lines 42, 94), which violates React's Rules of Hooks and will cause state to corrupt when the component re-renders with different cField.type
values.
Apply this diff to fix:
export const RenderConditionalField = ({
cField,
cIndex,
cArray,
setDrawerState,
updateLocalization,
state,
parentState,
drawerState,
screenConfig,
AppScreenLocalisationConfig,
handleExpressionChange,
selectedField,
disabled,
}) => {
const { t } = useTranslation();
const useT = useCustomT();
+
+ // Pre-compute localized values at the top level
+ const localizedFieldValue = isLocalisable ? useT(drawerState?.[cField?.bindTo]) : null;
+
const isLocalisable = AppScreenLocalisationConfig?.fields
?.find((i) => i.fieldType === (drawerState?.appType || drawerState?.type))
?.localisableProperties?.includes(cField?.bindTo?.split(".")?.at(-1));
const searchParams = new URLSearchParams(location.search);
const projectType = searchParams.get("prefix");
switch (cField?.type) {
case "text":
case "number":
case "date":
case "time":
return (
<FieldV1
type={cField?.type}
label={cField?.label}
withoutLabel={Boolean(!cField?.label)}
value={
- isLocalisable ? useT(drawerState?.[cField?.bindTo]) : drawerState?.[cField?.bindTo] === true ? "" : drawerState?.[cField?.bindTo]
+ localizedFieldValue !== null ? localizedFieldValue : drawerState?.[cField?.bindTo] === true ? "" : drawerState?.[cField?.bindTo]
}
// ... rest unchanged
/>
);
case "options":
return (
<div
style={{ padding: "1.5rem", border: "1px solid #c84c0e", borderRadius: "1rem", display: "flex", flexDirection: "column", gap: "1.5rem" }}
>
{(drawerState?.[cField?.bindTo] || []).map((item, index) => {
+ const localizedItemName = useT(item?.name);
return (
<div style={{ display: "flex", gap: "1rem" }} key={item.code || index}>
<TextInput
isRequired={true}
className=""
type={"text"}
name="title"
- value={useT(item?.name)}
+ value={localizedItemName}
onChange={(event) => {
// ... rest unchanged
}}
placeholder={""}
disabled={disabled}
/>
// ... rest unchanged
</div>
);
})}
// ... rest unchanged
</div>
);
// ... other cases unchanged
}
};
Note: For the "options" case (line 94), since it's inside a .map()
, you'll need to either:
- Pre-compute all localized names before the map
- Or use a custom child component that can safely call useT at its own top level
Also applies to: 42-42, 94-94
🤖 Prompt for AI Agents
In
health/micro-ui/web/micro-ui-internals/packages/modules/campaign-manager/src/pages/employee/appConfigurationRedesign/RenderConditionalField.js
(lines 24, 42, 94), the hook useCustomT is being called conditionally inside
switch branches which breaks the Rules of Hooks; move the hook call to the top
of the component (declare const t = useCustomT() immediately after the component
starts, before any switch/map/conditional) and replace in-branch calls with that
top-level t; for the "options" case where localization currently happens inside
a .map(), pre-compute an array of localized option labels using the top-level t
before mapping (or extract the option rendering into a small child component
that itself calls useCustomT at its own top level) so no hook is invoked
conditionally inside the map.
There was a problem hiding this 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 (5)
health/micro-ui/web/micro-ui-internals/packages/modules/health-payments/src/components/attendance_inbox/table_inbox.js (1)
76-107
: Fix navigation helper: stop bubbling, use latest endDate, and compare millis correctlyClicking the ID link currently fires both the button handler and the row handler, so we push two different URLs. On top of that,
Date.now()
(ms) is compared to anendDate
that the APIs return in seconds, so every register looks expired and forces the read-only route. Finally, we keep ignoring theselectedProject
prop and fall back to potentially stale session-state.Combine these into a single helper that (a) calls
event?.stopPropagation()
, (b) prefersselectedProject?.endDate
with session storage only as fallback, and (c) normalizes seconds ➝ milliseconds before comparing.@@ - <span className="link"> - <Button - label={t(`${row.id}`)} - onClick={() => { - const existingPaymentInbox = Digit.SessionStorage.get("paymentInbox"); - const endDate = existingPaymentInbox?.selectedProject?.endDate; - - if (endDate) { - const currentDate = Date.now(); - if (!(currentDate <= endDate)) { - history.push( - `/${window?.contextPath}/employee/payments/view-attendance?registerNumber=${row?.id}&boundaryCode=${row?.boundary}` - ); - } else { - history.push( - `/${window?.contextPath}/employee/payments/edit-register?registerNumber=${row?.id}&boundaryCode=${row?.boundary}®isterId=${row?.registerId}` - ); - } - } else { - console.warn("No endDate found in session storage"); - history.push( - `/${window?.contextPath}/employee/payments/view-attendance?registerNumber=${row?.id}&boundaryCode=${row?.boundary}` - ); - } - }} + <span className="link"> + <Button + label={t(`${row.id}`)} + onClick={(event) => navigateForRow(row, event)} @@ - const handleRowClick = (row) => { - - const existingPaymentInbox = Digit.SessionStorage.get("paymentInbox"); - const endDate = existingPaymentInbox?.selectedProject?.endDate; - - if (endDate) { - const currentDate = Date.now(); - if (!(currentDate <= endDate)) { - history.push( - `/${window?.contextPath}/employee/payments/view-attendance?registerNumber=${row?.id}&boundaryCode=${row?.boundary}` - ); - } else { - history.push( - `/${window?.contextPath}/employee/payments/edit-register?registerNumber=${row?.id}&boundaryCode=${row?.boundary}®isterId=${row?.registerId}` - ); - } - } else { - console.warn("No endDate found in session storage"); - history.push( - `/${window?.contextPath}/employee/payments/view-attendance?registerNumber=${row?.id}&boundaryCode=${row?.boundary}` - ); - } - - // history.push( - // `/${window?.contextPath}/employee/payments/view-attendance?registerNumber=${row?.id}&boundaryCode=${row?.boundary}` - // ); - }; + const navigateForRow = (row, event) => { + event?.stopPropagation(); + + const sessionProject = Digit.SessionStorage.get("paymentInbox")?.selectedProject; + const rawEndDate = selectedProject?.endDate ?? sessionProject?.endDate; + + if (rawEndDate) { + const endDateMs = rawEndDate < 1e12 ? rawEndDate * 1000 : rawEndDate; + const isExpired = Date.now() > endDateMs; + + history.push( + isExpired + ? `/${window?.contextPath}/employee/payments/view-attendance?registerNumber=${row?.id}&boundaryCode=${row?.boundary}` + : `/${window?.contextPath}/employee/payments/edit-register?registerNumber=${row?.id}&boundaryCode=${row?.boundary}®isterId=${row?.registerId}` + ); + return; + } + + setShowToast({ + key: "warning", + label: t("HCM_AM_END_DATE_MISSING_VIEW_ONLY"), + transitionTime: 3000, + }); + history.push( + `/${window?.contextPath}/employee/payments/view-attendance?registerNumber=${row?.id}&boundaryCode=${row?.boundary}` + ); + };Then wire the table with
onRowClicked={(row) => navigateForRow(row)}
. This keeps navigation consistent, avoids double pushes, and respects real expiry dates. TranslationHCM_AM_END_DATE_MISSING_VIEW_ONLY
needs to be added.Also applies to: 169-191
health/micro-ui/web/micro-ui-internals/packages/modules/health-payments/src/pages/employee/EditRegister.js (4)
35-35
: Guard against missinglocation.state
before destructuring.When
location.state
isundefined
, destructuring fromfalse
throws at render. Please default to an object and give the property its own fallback.- const { fromCampaignSupervisor } = location.state || false; + const { fromCampaignSupervisor = false } = location?.state || {};
82-95
: Protect everyattendanceRegister[0]
access.If
/v1/_search
returns no register rows, each direct[0]
index or.length
dereference will throw before the guard runs. Optional-chain the array element and default the attendee list before mapping, and reuse the derived owner id for the secondary search.- if (AttendanceData) { - setAttendanceDuration( - Math.ceil((AttendanceData?.attendanceRegister[0]?.endDate - AttendanceData?.attendanceRegister[0]?.startDate) / (24 * 60 * 60 * 1000)) - ); - } + const register = AttendanceData?.attendanceRegister?.[0]; + if (register?.endDate && register?.startDate) { + setAttendanceDuration( + Math.ceil((register.endDate - register.startDate) / (24 * 60 * 60 * 1000)) + ); + } else { + setAttendanceDuration(null); + } @@ - if (AttendanceData?.attendanceRegister?.length > 0) { - const ids = AttendanceData.attendanceRegister[0].attendees.map( - (a) => a.individualId - ); - setIndividualIds(ids); - } + const attendees = AttendanceData?.attendanceRegister?.[0]?.attendees ?? []; + setIndividualIds( + Array.isArray(attendees) + ? attendees.map((a) => a?.individualId).filter(Boolean) + : [] + ); @@ - Individual: { - id: [AttendanceData?.attendanceRegister[0]?.staff?.find( - (staff) => staff?.staffType?.includes("OWNER") - )?.userId] - } + Individual: { + id: ownerUserId ? [ownerUserId] : [] + } @@ - enabled: AttendanceData?.attendanceRegister.length === 1 && AttendanceData?.attendanceRegister[0]?.staff?.find( - (staff) => staff?.staffType?.includes("OWNER") - )?.userId ? true : false, + enabled: Boolean(ownerUserId),and define just before
individualReqCriteria
:+ const ownerUserId = AttendanceData?.attendanceRegister?.[0]?.staff?.find((staff) => + staff?.staffType?.includes("OWNER") + )?.userId;Also applies to: 128-135
145-176
: Null-guard attendee mapping insidegetUserAttendanceSummary
.
attendanceData.attendanceRegister[0]
explodes when the register array is empty or missing. Please short-circuit before touching[0]
, and reuse the guarded attendees array in the map.- if (attendanceData.attendanceRegister[0].attendees == null || attendanceData.attendanceRegister[0].attendees.length == 0) { + const register = attendanceData?.attendanceRegister?.[0]; + const attendees = Array.isArray(register?.attendees) ? register.attendees : []; + + if (attendees.length === 0) { return []; } - else { - const attendanceLogData = attendanceData.attendanceRegister[0].attendees.map((individualEntry) => { + else { + const attendanceLogData = attendees.map((individualEntry) => {
335-336
: Remove empty<h2>
to fix the a11y lint error.Biome reports
useHeadingContent
here; an empty heading confuses screen readers. Either supply meaningful text or drop the heading altogether.- <h2 className="card-heading-title"></h2> + {/* Removed empty heading; add meaningful title if required */}
📜 Review details
Configuration used: CodeRabbit UI
Review profile: ASSERTIVE
Plan: Pro
📒 Files selected for processing (2)
health/micro-ui/web/micro-ui-internals/packages/modules/health-payments/src/components/attendance_inbox/table_inbox.js
(5 hunks)health/micro-ui/web/micro-ui-internals/packages/modules/health-payments/src/pages/employee/EditRegister.js
(1 hunks)
🧰 Additional context used
📓 Path-based instructions (1)
**/*.js
⚙️ CodeRabbit configuration file
check
Files:
health/micro-ui/web/micro-ui-internals/packages/modules/health-payments/src/components/attendance_inbox/table_inbox.js
health/micro-ui/web/micro-ui-internals/packages/modules/health-payments/src/pages/employee/EditRegister.js
🧠 Learnings (1)
📚 Learning: 2024-11-07T11:02:33.520Z
Learnt from: rachana-egov
PR: egovernments/DIGIT-Frontend#1770
File: health/micro-ui/web/micro-ui-internals/packages/modules/microplan/src/pages/employee/viewVillage.js:320-322
Timestamp: 2024-11-07T11:02:33.520Z
Learning: In `health/micro-ui/web/micro-ui-internals/packages/modules/microplan/src/pages/employee/viewVillage.js`, the `data?.additionalFields` object is guaranteed to be defined, so checking for its existence before accessing its keys is unnecessary.
Applied to files:
health/micro-ui/web/micro-ui-internals/packages/modules/health-payments/src/pages/employee/EditRegister.js
🧬 Code graph analysis (2)
health/micro-ui/web/micro-ui-internals/packages/modules/health-payments/src/components/attendance_inbox/table_inbox.js (5)
health/micro-ui/web/micro-ui-internals/packages/modules/health-payments/src/pages/employee/EditRegister.js (2)
Digit
(34-34)history
(27-27)health/micro-ui/web/micro-ui-internals/packages/modules/health-payments/src/pages/employee/ViewAttendance.js (2)
Digit
(32-32)history
(24-24)health/micro-ui/web/micro-ui-internals/packages/modules/health-payments/src/components/bill_inbox/billInboxTable.js (4)
history
(23-23)columns
(70-140)triggerMusterRollSearch
(35-56)handleRowClick
(159-163)health/micro-ui/web/micro-ui-internals/packages/modules/health-payments/src/components/attendance_inbox/attendance_inbox.js (4)
selectedProject
(23-23)handlePaginationChange
(160-164)handleRowsPerPageChange
(165-169)rowsPerPage
(25-25)health/micro-ui/web/micro-ui-internals/packages/modules/health-payments/src/components/table_inbox_custom_style.js (2)
tableCustomStyle
(1-108)tableCustomStyle
(1-108)
health/micro-ui/web/micro-ui-internals/packages/modules/health-payments/src/pages/employee/EditRegister.js (4)
health/micro-ui/web/micro-ui-internals/packages/modules/health-payments/src/pages/employee/project_selection.js (5)
location
(15-15)useTranslation
(16-16)history
(17-17)showToast
(27-27)project
(23-23)health/micro-ui/web/micro-ui-internals/packages/modules/health-payments/src/pages/employee/ViewAttendance.js (28)
location
(22-22)location
(33-33)useTranslation
(23-23)history
(24-24)Digit
(32-32)attendanceDuration
(35-35)attendanceSummary
(36-36)initialAttendanceSummary
(37-37)isSubmitEnabled
(38-38)disabledAction
(40-40)individualIds
(48-48)triggerEstimate
(49-49)comment
(50-50)showToast
(51-51)loading
(52-52)showLogs
(53-53)showCommentLogPopup
(54-54)showDeEnrollPopup
(57-57)project
(59-59)AttendancereqCri
(62-74)isAttendanceLoading
(76-76)allIndividualReqCriteria
(312-331)isAllIndividualsLoading
(333-333)individualReqCriteria
(335-357)closeActionBarPopUp
(428-430)handleDeEnrollClick
(441-443)onDeEnrollClose
(445-447)renderLabelPair
(450-455)health/micro-ui/web/micro-ui-internals/packages/modules/health-payments/src/components/EditAttendanceManagementTable.js (5)
useTranslation
(33-33)history
(34-34)tenantId
(40-40)showToast
(36-36)EditAttendanceManagementTable
(31-274)health/micro-ui/web/micro-ui-internals/packages/modules/health-payments/src/components/editAttendeesPopUp.js (11)
useTranslation
(24-24)history
(15-15)tenantId
(25-25)attendanceSummary
(32-32)individualIds
(33-33)AttendancereqCri
(77-88)isAttendanceLoading
(90-91)allIndividualReqCriteria
(104-121)isAllIndividualsLoading
(123-124)closeActionBarPopUp
(206-208)EditAttendeePopUp
(14-282)
🪛 Biome (2.1.2)
health/micro-ui/web/micro-ui-internals/packages/modules/health-payments/src/pages/employee/EditRegister.js
[error] 335-336: Provide screen reader accessible content when using heading elements.
All headings on a page should have content that is accessible to screen readers.
(lint/a11y/useHeadingContent)
⏰ Context from checks skipped due to timeout of 10000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
- GitHub Check: Analyze (javascript-typescript)
<Fragment> | ||
{renderLabelPair('HCM_AM_ATTENDANCE_OFFICER', individualsData?.Individual?.[0]?.name?.givenName)} | ||
{renderLabelPair('HCM_AM_ATTENDANCE_OFFICER_CONTACT_NUMBER', individualsData?.Individual?.[0]?.mobileNumber)} | ||
{renderLabelPair('HCM_AM_NO_OF_ATTENDEE', AttendanceData?.attendanceRegister[0]?.attendees?.length || 0)} | ||
{renderLabelPair('HCM_AM_CAMPAIGN_START_DATE', formatTimestampToDate(project?.[0]?.startDate))} | ||
{renderLabelPair('HCM_AM_CAMPAIGN_END_DATE', formatTimestampToDate(project?.[0]?.endDate))} | ||
{renderLabelPair('HCM_AM_EVENT_DURATION', attendanceDuration || 0)} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Render path still crashes when attendanceRegister
is empty.
AttendanceData?.attendanceRegister[0]?.attendees
will dereference [0]
on undefined
. Please optional-chain the element before reading attendees and length.
- {renderLabelPair('HCM_AM_NO_OF_ATTENDEE', AttendanceData?.attendanceRegister[0]?.attendees?.length || 0)}
+ {renderLabelPair(
+ 'HCM_AM_NO_OF_ATTENDEE',
+ AttendanceData?.attendanceRegister?.[0]?.attendees?.length ?? 0
+ )}
🤖 Prompt for AI Agents
In
health/micro-ui/web/micro-ui-internals/packages/modules/health-payments/src/pages/employee/EditRegister.js
around lines 288 to 294, the expression
AttendanceData?.attendanceRegister[0]?.attendees?.length || 0 can throw when
attendanceRegister is undefined; update it to safely optional-chain the array
before indexing (e.g. AttendanceData?.attendanceRegister?.[0]?.attendees?.length
|| 0) so you never attempt to access [0] on undefined and the render path won't
crash.
Choose the appropriate template for your PR:
Feature/Bugfix Request
JIRA ID
Module
Description
Summary by CodeRabbit
New Features
Enhancements
Integration
Style