From 4bbf7166340ede38af53b4a1747c6de21c6acabc Mon Sep 17 00:00:00 2001 From: pitabash-eGov Date: Mon, 18 Aug 2025 14:02:33 +0530 Subject: [PATCH 01/74] edit compoent is designed --- .../micro-ui-internals/example/package.json | 1 + .../micro-ui-internals/example/src/index.js | 2 + .../EditAttendanceManagementTable.js | 201 ++++++++++++++++++ .../src/components/PaymentsCard.js | 1 + .../src/components/editAttendeesPopUp.js | 192 +++++++++++++++++ .../components/table_inbox_custom_style.js | 113 ++++++++++ .../src/pages/employee/ViewAttendance.js | 41 ++++ 7 files changed, 551 insertions(+) create mode 100644 health/micro-ui/web/micro-ui-internals/packages/modules/health-payments/src/components/EditAttendanceManagementTable.js create mode 100644 health/micro-ui/web/micro-ui-internals/packages/modules/health-payments/src/components/editAttendeesPopUp.js diff --git a/health/micro-ui/web/micro-ui-internals/example/package.json b/health/micro-ui/web/micro-ui-internals/example/package.json index 67be73932d3..e9400112ca1 100644 --- a/health/micro-ui/web/micro-ui-internals/example/package.json +++ b/health/micro-ui/web/micro-ui-internals/example/package.json @@ -9,6 +9,7 @@ "start": "react-scripts start" }, "devDependencies": { + "@egovernments/digit-ui-module-health-payments": "0.1.0", "@egovernments/digit-ui-module-health-hrms":"0.0.1", "@egovernments/digit-ui-libraries": "1.8.17", "@egovernments/digit-ui-module-workbench": "1.0.23", diff --git a/health/micro-ui/web/micro-ui-internals/example/src/index.js b/health/micro-ui/web/micro-ui-internals/example/src/index.js index 9226e46fc23..ba7dc0c3311 100644 --- a/health/micro-ui/web/micro-ui-internals/example/src/index.js +++ b/health/micro-ui/web/micro-ui-internals/example/src/index.js @@ -14,6 +14,7 @@ import { initWorkbenchHCMComponents } from "@egovernments/digit-ui-module-hcmwor import { initMicroplanComponents } from "@egovernments/digit-ui-module-microplan"; import { initHRMSComponents } from "@egovernments/digit-ui-module-health-hrms"; import { initPGRComponents } from "@egovernments/digit-ui-module-health-pgr"; +import { initPaymentComponents } from "@egovernments/digit-ui-module-health-payments"; var Digit = window.Digit || {}; @@ -81,6 +82,7 @@ const initDigitUI = () => { initMicroplanComponents(); initHRMSComponents(); initPGRComponents(); + initPaymentComponents(); const moduleReducers = (initData) => initData; diff --git a/health/micro-ui/web/micro-ui-internals/packages/modules/health-payments/src/components/EditAttendanceManagementTable.js b/health/micro-ui/web/micro-ui-internals/packages/modules/health-payments/src/components/EditAttendanceManagementTable.js new file mode 100644 index 00000000000..140a1a6b726 --- /dev/null +++ b/health/micro-ui/web/micro-ui-internals/packages/modules/health-payments/src/components/EditAttendanceManagementTable.js @@ -0,0 +1,201 @@ +import React, { Fragment, useState, } from "react"; +import { useHistory } from "react-router-dom"; +import { useTranslation } from "react-i18next"; +import { Loader, Button, TextInput, Toast, Tag } from "@egovernments/digit-ui-components"; +import { CustomSVG } from "@egovernments/digit-ui-components"; +import DataTable, { TableProps } from "react-data-table-component"; +import { tableCustomStyle, editAttendeetableCustomStyle } from "./table_inbox_custom_style"; +import { defaultPaginationValues, defaultRowsPerPage } from "../utils/constants"; +import { getCustomPaginationOptions } from "../utils"; + + +/** + * A React component for displaying a paginated table of frontline workers + * with editable columns for days worked and their roles. + * + * @param {object} props The props object contains the data to be displayed, + * the onEditAttendanceChange function to be called when the user updates + * the attendance records, the editAttendance boolean to indicate whether + * the table should be editable or not, and the duration of the event to validate max date. + * + * @returns {ReactElement} The JSX element for the table. + */ + + + + + +const EditAttendanceManagementTable = ({ ...props }) => { + const { t } = useTranslation(); + const history = useHistory(); + const url = Digit.Hooks.useQueryParams(); + const [showToast, setShowToast] = useState(null); + // Local state for pagination + const [currentPage, setCurrentPage] = useState(1); + const [rowsPerPage, setRowsPerPage] = useState(defaultRowsPerPage); + + // Sliced data based on pagination + const paginatedData = props.data.slice((currentPage - 1) * rowsPerPage, currentPage * rowsPerPage); + + const handlePageChange = (page, totalRows) => { + setCurrentPage(page); + }; + + const handlePerRowsChange = (currentRowsPerPage, currentPage) => { + setRowsPerPage(currentRowsPerPage); + setCurrentPage(1); + } + + const columns = [ + { + name: ( +
+ {t(`HCM_AM_FRONTLINE_WORKER`)} +
+ ), + selector: (row) => { + return ( + + {String(row?.[1] ? row?.[1] : t("ES_COMMON_NA"))} + + ); + }, + }, + + { + name: ( +
+ {t("HCM_AM_WORKER_ID")} +
+ ), + selector: (row) => { + return ( +
+ {row?.[2] || t("NA")} +
+ ); + }, + }, + { + name: ( +
+ {t("HCM_AM_ROLE")} +
+ ), + selector: (row) => { + return ( +
+ {t(row?.[3]) || t("NA")} +
+ ); + }, + }, + + { + name: t("Action"), + selector: (row) => { + return ( +
+ {row?.[4] == false ? : +
+ ); + }, + style: { + justifyContent: "flex-end", + }, + }, + ]; + + // const handleDaysWorkedChange = (workerId, value) => { + + // if (value?.target) { + // value = value?.target?.value; + // } + + // // Remove leading zeros from the value + // value = value === 0 ? value : String(value).replace(/^0+/, ""); + + // // Find the worker whose attendance is being updated + // const worker = props.data.find((worker) => worker[2] === workerId); + + // if (!worker) return; // If worker is not found, exit early + + // const previousValue = worker[4]; // Previous value for daysWorked + + + // // Check if both current value and previous value are 0 + // if (value === 0 && previousValue === 0) { + // setShowToast({ key: "error", label: t("HCM_AM_ATTENDANCE_CAN_NOT_BE_LESS_THAN_ZERO"), transitionTime: 3000 }); + // return; + // } + + // if (value > props.duration) { + // setShowToast({ key: "error", label: t("HCM_AM_ATTENDANCE_CAN_NOT_EXCEED_EVENT_DURATION_ERROR"), transitionTime: 3000 }); + // return; + // } + + // // Clear the toast if the input is valid + // setShowToast(null); + + // // Update the data directly using the parent's setState + // const updatedData = props.data.map((worker) => { + // if (worker[2] === workerId) { + // return [worker[0], worker[1], worker[2], worker[3], value || 0]; // Update the daysWorked value + // } + // return worker; // Keep other rows unchanged + // }); + // props.setAttendanceSummary(updatedData); + // }; + + return ( + <> + } + pagination + paginationServer + customStyles={editAttendeetableCustomStyle(false)} + paginationDefaultPage={currentPage} + onChangePage={handlePageChange} + onChangeRowsPerPage={handlePerRowsChange} + paginationTotalRows={props?.data.length} + paginationPerPage={rowsPerPage} + sortIcon={} + paginationRowsPerPageOptions={defaultPaginationValues} + fixedHeader={true} + fixedHeaderScrollHeight={"70vh"} + paginationComponentOptions={getCustomPaginationOptions(t)} + + /> + {showToast && ( + setShowToast(null)} + /> + )} + + ); +}; + +export default EditAttendanceManagementTable; diff --git a/health/micro-ui/web/micro-ui-internals/packages/modules/health-payments/src/components/PaymentsCard.js b/health/micro-ui/web/micro-ui-internals/packages/modules/health-payments/src/components/PaymentsCard.js index f4aaafe7fa3..5d4dd7e3719 100644 --- a/health/micro-ui/web/micro-ui-internals/packages/modules/health-payments/src/components/PaymentsCard.js +++ b/health/micro-ui/web/micro-ui-internals/packages/modules/health-payments/src/components/PaymentsCard.js @@ -9,6 +9,7 @@ const ROLES = { const PaymentsCard = () => { + // Reset session storage useEffect(() => { Digit.SessionStorage.del("paymentInbox"); diff --git a/health/micro-ui/web/micro-ui-internals/packages/modules/health-payments/src/components/editAttendeesPopUp.js b/health/micro-ui/web/micro-ui-internals/packages/modules/health-payments/src/components/editAttendeesPopUp.js new file mode 100644 index 00000000000..e23b69a4cf6 --- /dev/null +++ b/health/micro-ui/web/micro-ui-internals/packages/modules/health-payments/src/components/editAttendeesPopUp.js @@ -0,0 +1,192 @@ +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"; + + +const EditAttendeePopUp = ({ onClose, businessId, heading }) => { + // 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 tenantId = Digit.ULBService.getCurrentTenantId(); + + const [attendanceSummary, setAttendanceSummary] = useState([]); + const [individualIds, setIndividualIds] = useState([]); + + const [searchQuery, setSearchQuery] = useState(""); + + // -------- 1. Attendance Register API -------- + const AttendancereqCri = { + url: `/${attendanceContextPath}/v1/_search`, + params: { + tenantId: tenantId, + registerNumber: businessId, + }, + config: { + enabled: !!businessId, + select: (data) => data, + }, + }; + + 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]); + + // -------- 2. Individual API (depends on IDs) -------- + 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); + + // -------- 3. Build Attendance Summary -------- + function getUserAttendanceSummary(attendanceData, individualsData, t) { + 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]; + } else { + return [ + "N/A", + "Unknown", + "N/A", + "Unassigned", + individualEntry?.denrollmentDate == null ? true : false, + ]; + } + }); + + // sort alphabetically by user name + return [...attendanceLogData].sort((a, b) => + a[1].toLowerCase().localeCompare(b[1].toLowerCase()) + ); + } + + useEffect(() => { + if ( + AttendanceData?.attendanceRegister?.length > 0 && + AllIndividualsData?.Individual?.length > 0 + ) { + const summary = getUserAttendanceSummary( + AttendanceData, + AllIndividualsData, + t + ); + setAttendanceSummary(summary); + } + }, [AllIndividualsData, AttendanceData, t]); + + + // ✅ Filter attendanceSummary based on search query + const filteredData = searchQuery.length >= 3 ? + attendanceSummary.filter( + (row) => + row[1].toLowerCase().includes(searchQuery.toLowerCase()) || // Name + row[2].toLowerCase().includes(searchQuery.toLowerCase()) // ID + ) : attendanceSummary; + + // -------- Render -------- + return ( + + ) : ( +
+ setSearchQuery(e.target.value)} /> + +
+
+ Not finding the user? +
+
+ + +
+ ), + ]} + footerChildren={[ +