diff --git a/health/micro-ui/web/health-payments/App.js b/health/micro-ui/web/health-payments/App.js index ea57d736912..5053df25440 100644 --- a/health/micro-ui/web/health-payments/App.js +++ b/health/micro-ui/web/health-payments/App.js @@ -5,6 +5,7 @@ import { DigitUI } from "@egovernments/digit-ui-module-core"; import { UICustomizations } from "./Customisations/UICustomizations"; import { initPaymentComponents } from "@egovernments/digit-ui-module-health-payments"; +import { initHRMSComponents } from "@egovernments/digit-ui-module-hrms"; const enabledModules = [ @@ -24,7 +25,7 @@ const moduleReducers = (initData) => ({ const initDigitUI = () => { window.Digit.ComponentRegistryService.setupRegistry({ }); - + initHRMSComponents(); initPaymentComponents(); window.Digit.Customizations = { 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 2e9f1616e8d..b6d071ed93a 100644 --- a/health/micro-ui/web/micro-ui-internals/example/package.json +++ b/health/micro-ui/web/micro-ui-internals/example/package.json @@ -9,9 +9,10 @@ "start": "react-scripts start" }, "devDependencies": { + "@egovernments/digit-ui-module-health-hrms":"0.0.1", "@egovernments/digit-ui-libraries": "1.8.11", "@egovernments/digit-ui-module-workbench": "1.0.12", - "@egovernments/digit-ui-components": "0.0.2-beta.65", + "@egovernments/digit-ui-components": "0.2.0-beta.4", "@egovernments/digit-ui-module-core": "1.8.30", "@egovernments/digit-ui-module-utilities": "1.0.12", "@egovernments/digit-ui-react-components": "1.8.19", diff --git a/health/micro-ui/web/micro-ui-internals/example/public/index.html b/health/micro-ui/web/micro-ui-internals/example/public/index.html index 18d2949ab02..c2010ea9339 100644 --- a/health/micro-ui/web/micro-ui-internals/example/public/index.html +++ b/health/micro-ui/web/micro-ui-internals/example/public/index.html @@ -10,15 +10,16 @@ DIGIT + + + + + - - - - + + - - diff --git a/health/micro-ui/web/micro-ui-internals/example/src/UICustomizations.js b/health/micro-ui/web/micro-ui-internals/example/src/UICustomizations.js index dac4e27ac66..f9676a42206 100644 --- a/health/micro-ui/web/micro-ui-internals/example/src/UICustomizations.js +++ b/health/micro-ui/web/micro-ui-internals/example/src/UICustomizations.js @@ -9,7 +9,6 @@ import { Button as ButtonNew, Dropdown } from "@egovernments/digit-ui-components // these functions will act as middlewares // var Digit = window.Digit || {}; - const businessServiceMap = { "muster roll": "MR", }; @@ -304,8 +303,9 @@ export const UICustomizations = { return ( {String(value ? (column.translate ? t(column.prefix ? `${column.prefix}${value}` : value) : value) : t("ES_COMMON_NA"))} @@ -765,182 +765,182 @@ export const UICustomizations = { } }, }, - MicroplanSearchConfig: { - 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); - - const dic = { - 0: null, - 1: ["DRAFT"], - 2: ["EXECUTION_TO_BE_DONE"], - 3: ["CENSUS_DATA_APPROVAL_IN_PROGRESS", "CENSUS_DATA_APPROVED", "RESOURCE_ESTIMATION_IN_PROGRESS"], - 4: ["RESOURCE_ESTIMATIONS_APPROVED"], - }; - const url = Digit.Hooks.useQueryParams(); - - const tabId = url.tabId || "0"; // Default to '0' if tabId is undefined - data.body.PlanConfigurationSearchCriteria.status = dic[String(tabId)]; - cleanObject(data.body.PlanConfigurationSearchCriteria); - return data; - }, - 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 = []; - - if (row?.status == "DRAFT") { - options = [{ code: "1", name: "MP_ACTIONS_EDIT_SETUP" },{ code: "2", name: "MP_ACTIONS_DOWNLOAD_DRAFT" }]; - } 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) { - console.error(`No file with templateIdentifier '${template}' found`); - return; - } - const campaignName = row?.name || ""; - const customName = type === "Estimations" ? campaignName : `${campaignName}_DRAFT`; - Digit.Utils.campaign.downloadExcelWithCustomName({ - fileStoreId: fileId, - customName: customName, - }); - }; - - const onActionSelect = (e) => { - if (e.name === "MP_ACTIONS_EDIT_SETUP") { - const key = parseInt(row?.additionalDetails?.key); - const resolvedKey = key === 8 ? 7 : key === 9 ? 10 : 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") { - handleDownload({type:"Draft"}); - } - if (e.name == "MP_ACTIONS_VIEW_SUMMARY") { - window.location.href = `/${window.contextPath}/employee/microplan/setup-microplan?key=${10}µplanId=${row.id}&campaignId=${ - row.campaignDetails.id - }&setup-completed=true`; - } - }; - - return ( -
- {microplanFileId && row?.status == "RESOURCE_ESTIMATIONS_APPROVED" ? ( -
- handleDownload({type:"Estimations"})} label={t("WBH_DOWNLOAD_MICROPLAN")} title={t("WBH_DOWNLOAD_MICROPLAN")} isDisabled={!EstimationsfileId} /> -
- ) : ( -
-
- onActionSelect(item)} - /> -
-
- )} -
- ); - - case "NAME_OF_MICROPLAN": - if (value && value !== "NA") { - return ( -
-

{t(value)}

-
- ); - } else { - return ( -
-

{t("NA")}

-
- ); + MicroplanSearchConfig: { + 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); + + const dic = { + 0: null, + 1: ["DRAFT"], + 2: ["EXECUTION_TO_BE_DONE"], + 3: ["CENSUS_DATA_APPROVAL_IN_PROGRESS", "CENSUS_DATA_APPROVED", "RESOURCE_ESTIMATION_IN_PROGRESS"], + 4: ["RESOURCE_ESTIMATIONS_APPROVED"], + }; + const url = Digit.Hooks.useQueryParams(); + + const tabId = url.tabId || "0"; // Default to '0' if tabId is undefined + data.body.PlanConfigurationSearchCriteria.status = dic[String(tabId)]; + cleanObject(data.body.PlanConfigurationSearchCriteria); + return data; + }, + 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; + let options = []; + + if (row?.status == "DRAFT") { + options = [{ code: "1", name: "MP_ACTIONS_EDIT_SETUP" }]; + } else { + options = [{ code: "1", name: "MP_ACTIONS_VIEW_SUMMARY" }]; + } + + const handleDownload = () => { + const files = row?.files; + const file = files.find((item) => item.templateIdentifier === "Population"); + const fileId = file?.filestoreId; + if (!fileId) { + console.error("Population template file not found"); + return; } - - case "MICROPLAN_STATUS": - if (value && value != "NA") { - return

{t(Digit.Utils.locale.getTransformedLocale("MICROPLAN_STATUS_" + value))}

; - } else { - return ( -
-

{t("NA")}

-
- ); + const campaignName = row?.name || ""; + Digit.Utils.campaign.downloadExcelWithCustomName({ + fileStoreId: fileId, + customName: campaignName, + }); + }; + + const onActionSelect = (e) => { + if (e.name === "MP_ACTIONS_EDIT_SETUP") { + const key = parseInt(row?.additionalDetails?.key); + const resolvedKey = key === 8 ? 7 : key === 9 ? 10 : key || 2; + const url = `/${window.contextPath}/employee/microplan/setup-microplan?key=${resolvedKey}µplanId=${row.id}&campaignId=${row.campaignDetails.id}`; + window.location.href = url; } - - case "CAMPAIGN_DISEASE": - if (value && value != "NA") { - return

{t(Digit.Utils.locale.getTransformedLocale("MICROPLAN_DISEASE_" + value))}

; - } else { - return ( -
-

{t("NA")}

-
- ); + if (e.name == "MP_ACTIONS_VIEW_SUMMARY") { + window.location.href = `/${window.contextPath}/employee/microplan/setup-microplan?key=${10}µplanId=${row.id}&campaignId=${ + row.campaignDetails.id + }&setup-completed=true`; } - - case "CAMPAIGN_TYPE": - if (value && value != "NA") { - return

{t(Digit.Utils.locale.getTransformedLocale("MICROPLAN_TYPE_" + value))}

; - } else { - return ( + }; + + return ( +
+ {microplanFileId && row?.status == "RESOURCE_ESTIMATIONS_APPROVED" ? (
-

{t("NA")}

+
- ); - } - - case "DISTIRBUTION_STRATEGY": - if (value && value != "NA") { - return

{t(Digit.Utils.locale.getTransformedLocale("MICROPLAN_DISTRIBUTION_" + value))}

; - } else { - return ( -
-

{t("NA")}

+ ) : ( +
+
+ onActionSelect(item)} + /> +
- ); - } - - default: - return null; // Handle any unexpected keys here if needed - } - }, + )} +
+ ); + + case "NAME_OF_MICROPLAN": + if (value && value !== "NA") { + return ( +
+

{t(value)}

+
+ ); + } else { + return ( +
+

{t("NA")}

+
+ ); + } + + case "MICROPLAN_STATUS": + if (value && value != "NA") { + return

{t(Digit.Utils.locale.getTransformedLocale("MICROPLAN_STATUS_" + value))}

; + } else { + return ( +
+

{t("NA")}

+
+ ); + } + + case "CAMPAIGN_DISEASE": + if (value && value != "NA") { + return

{t(Digit.Utils.locale.getTransformedLocale("MICROPLAN_DISEASE_" + value))}

; + } else { + return ( +
+

{t("NA")}

+
+ ); + } + + case "CAMPAIGN_TYPE": + if (value && value != "NA") { + return

{t(Digit.Utils.locale.getTransformedLocale("MICROPLAN_TYPE_" + value))}

; + } else { + return ( +
+

{t("NA")}

+
+ ); + } + + case "DISTIRBUTION_STRATEGY": + if (value && value != "NA") { + return

{t(Digit.Utils.locale.getTransformedLocale("MICROPLAN_DISTRIBUTION_" + value))}

; + } else { + return ( +
+

{t("NA")}

+
+ ); + } + + default: + return null; // Handle any unexpected keys here if needed + } }, + }, MyMicroplanSearchConfig: { preProcess: (data, additionalDetails) => { const { name, status } = data?.state?.searchForm || {}; @@ -980,19 +980,18 @@ export const UICustomizations = { const roles = rolesCodes.map((item) => item.code); const hasRequiredRole = roles.some((role) => role === "ROOT_POPULATION_DATA_APPROVER" || role === "POPULATION_DATA_APPROVER"); const EstimationsfileId = row?.files.find((item) => item.templateIdentifier === "Estimations")?.filestoreId; - const handleFileDownload=()=>{ + const handleFileDownload = () => { const fileId = row?.files.find((item) => item.templateIdentifier === "Estimations")?.filestoreId; if (!fileId) { console.error("Estimation template file not found"); - return; - } + return; + } const campaignName = row?.name || ""; Digit.Utils.campaign.downloadExcelWithCustomName({ fileStoreId: fileId, - customName: campaignName + customName: campaignName, }); - - } + }; switch (key) { case "ACTIONS": const onActionSelect = (key, row) => { @@ -1021,10 +1020,10 @@ export const UICustomizations = { const navEvent2 = new PopStateEvent("popstate"); window.dispatchEvent(navEvent2); break; - case "DOWNLOAD": - handleFileDownload(); - break; - + case "DOWNLOAD": + handleFileDownload(); + break; + default: console.log(value); break; @@ -1060,7 +1059,7 @@ export const UICustomizations = { icon={"ArrowForward"} type="button" isSuffix={true} - style={{width:"290px"}} + style={{ width: "290px" }} isDisabled={!hasRequiredRole} // className="dm-workbench-download-template-btn dm-hover" onClick={(e) => onActionSelect("START", row)} @@ -1097,7 +1096,7 @@ export const UICustomizations = { title={t("WBH_EDIT")} variation="primary" icon={"Edit"} - style={{width:"290px"}} + style={{ width: "290px" }} type="button" // className="dm-workbench-download-template-btn dm-hover" onClick={(e) => onActionSelect("EDIT", row)} @@ -1313,26 +1312,24 @@ export const UICustomizations = { preProcess: (data) => { return data; }, - getFacilitySearchRequest: ( prop) => { + getFacilitySearchRequest: (prop) => { 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 - ] - } + tenantId: tenantId, + ids: [campaignId], + }, }, changeQueryName: `boundarySearchForPlanFacility`, config: { enabled: true, select: (data) => { const result = data?.CampaignDetails?.[0]?.boundaries?.filter((item) => item.type == prop.lowestHierarchy) || []; - return result + return result; }, }, }; @@ -1351,10 +1348,12 @@ export const UICustomizations = { case "MICROPLAN_FACILITY_SERVINGPOPULATION": return row?.additionalDetails?.servingPopulation; case "MICROPLAN_FACILITY_RESIDINGVILLAGE": - return
- {t(row?.residingBoundary)} - -
+ return ( +
+ {t(row?.residingBoundary)} + +
+ ); case "MICROPLAN_FACILITY_ASSIGNED_VILLAGES": const assignedVillages = row?.serviceBoundaries; return assignedVillages ? assignedVillages.length : null; @@ -1411,4 +1410,60 @@ export const UICustomizations = { UserManagementConfigPlan: { test: "yes", }, -}; \ No newline at end of file + + SearchDefaultConfigMain: { + preProcess: (data) => { + // filterForm + // params + + if (data.state.filterForm && Object.keys(data.state.filterForm).length > 0) { + const updatedParams = {}; // Temporary object to store updates + + if (data.state.filterForm.roles?.code) { + updatedParams.roles = data.state.filterForm.roles.code; + } + + if (typeof data.state.filterForm.isActive === "object" && "code" in data.state.filterForm.isActive) { + updatedParams.isActive = data.state.filterForm.isActive.code; + } + + // Update `data.params` only if `updatedParams` has values + if (Object.keys(updatedParams).length > 0) { + data.params = { ...data.params, ...updatedParams }; + } + } + + return data; + }, + + additionalCustomizations: (row, key, column, value, t, searchResult) => { + console.log("additional customization"); + switch (key) { + case "HR_EMP_ID_LABEL": + return ( + + {value} + + ); + + case "HR_ROLE_NO_LABEL": + return value ? `${value.length}` : t("ES_COMMON_NA"); + + case "HR_DESG_LABEL": + return value.length > 0 ? t(`${value[0].designation}`) : t("ES_COMMON_NA"); + + case "HR_EMPLOYMENT_DEPARTMENT_LABEL": + return value ? t(`${value.department}`) : t("ES_COMMON_NA"); + + case "MASTERS_LOCALITY": + return value ? ( + {String(t(Digit.Utils.locale.getMohallaLocale(value, row?.tenantId)))} + ) : ( + t("ES_COMMON_NA") + ); + default: + return t("ES_COMMON_NA"); + } + }, + }, +}; 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 a6578e601d7..9ec75c80843 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 @@ -13,6 +13,7 @@ import { initUtilitiesComponents } from "@egovernments/digit-ui-module-utilities import { initWorkbenchHCMComponents } from "@egovernments/digit-ui-module-hcmworkbench"; import { initMicroplanComponents } from "@egovernments/digit-ui-module-microplan"; import { initPaymentComponents } from "@egovernments/digit-ui-module-health-payments"; +import { initHRMSComponents } from "@egovernments/digit-ui-module-health-hrms"; var Digit = window.Digit || {}; @@ -72,6 +73,7 @@ const initDigitUI = () => { initCampaignComponents(); initMicroplanComponents(); initPaymentComponents(); + initHRMSComponents(); const moduleReducers = (initData) => initData; diff --git a/health/micro-ui/web/micro-ui-internals/example/src/setupProxy.js b/health/micro-ui/web/micro-ui-internals/example/src/setupProxy.js index 68bcb76c2e8..860aa4bc2c3 100644 --- a/health/micro-ui/web/micro-ui-internals/example/src/setupProxy.js +++ b/health/micro-ui/web/micro-ui-internals/example/src/setupProxy.js @@ -104,7 +104,11 @@ module.exports = function (app) { "/health-muster-roll", "/health-expense/bill/v1/_search", "/health-expense-calculator/v1/_calculate", - "/filestore/v1/files/id" + "/filestore/v1/files/id", + "/health-project/staff/v1/_search", + "/health-project/v1/_search", + "/health-individual", + "/health-hrms/employees" ].forEach((location) => app.use(location, createProxy)); ["/pb-egov-assets"].forEach((location) => app.use(location, assetsProxy)); ["/mdms-v2/v2/_create"].forEach((location) => app.use(location, mdmsProxy)); diff --git a/health/micro-ui/web/micro-ui-internals/package.json b/health/micro-ui/web/micro-ui-internals/package.json index a52da13187e..cd07e053b2f 100644 --- a/health/micro-ui/web/micro-ui-internals/package.json +++ b/health/micro-ui/web/micro-ui-internals/package.json @@ -26,12 +26,14 @@ "dev:workbench-hcm": "cd packages/modules/workbench-hcm && yarn start", "dev:microplan": "cd packages/modules/microplan && yarn start", "dev:healthpayments": "cd packages/modules/health-payments && yarn start", + "dev:healthhrms": "cd packages/modules/health-hrms && yarn start", "build": "run-p build:**", "build:campaign": "cd packages/modules/campaign-manager && yarn build", "build:hcmmicroplan": "cd packages/modules/hcm-microplanning && yarn build", "build:workbench-hcm": "cd packages/modules/workbench-hcm && yarn build", "build:microplan": "cd packages/modules/microplan && yarn build", "build:healthpayments": "cd packages/modules/health-payments && yarn build", + "build:healthhrms": "cd packages/modules/health-hrms && yarn build", "deploy:jenkins": "./scripts/jenkins.sh", "clean": "rm -rf node_modules" }, diff --git a/health/micro-ui/web/micro-ui-internals/packages/css/src/pages/employee/hrmsupdate.scss b/health/micro-ui/web/micro-ui-internals/packages/css/src/pages/employee/hrmsupdate.scss new file mode 100644 index 00000000000..c4a4fb84c0f --- /dev/null +++ b/health/micro-ui/web/micro-ui-internals/packages/css/src/pages/employee/hrmsupdate.scss @@ -0,0 +1,14 @@ + .custom-form{ + .label-field-wrapper{ + width: 100% !important; + } + + .custom-label-pair{ + margin-bottom: 0rem; + } + + .digit-submit-bar{ + width: fit-content; + margin-left: auto; + } +} diff --git a/health/micro-ui/web/micro-ui-internals/packages/css/src/pages/employee/index.scss b/health/micro-ui/web/micro-ui-internals/packages/css/src/pages/employee/index.scss index 01952e2b3a5..c86776c0056 100644 --- a/health/micro-ui/web/micro-ui-internals/packages/css/src/pages/employee/index.scss +++ b/health/micro-ui/web/micro-ui-internals/packages/css/src/pages/employee/index.scss @@ -4,6 +4,7 @@ @import "../../typography.scss"; @import "./villageView.scss"; @import "./facility.scss"; +@import "./hrmsupdate.scss"; .results-table-wrapper{ margin-bottom: 2rem; diff --git a/health/micro-ui/web/micro-ui-internals/packages/modules/health-hrms/ReadMe.md b/health/micro-ui/web/micro-ui-internals/packages/modules/health-hrms/ReadMe.md new file mode 100644 index 00000000000..359190ed9d4 --- /dev/null +++ b/health/micro-ui/web/micro-ui-internals/packages/modules/health-hrms/ReadMe.md @@ -0,0 +1,83 @@ +# egovernments/digit-ui-module-health-hrms + +## Install + +```bash +npm install --save egovernments/digit-ui-module-health-hrms +``` + +## Limitation + +```bash +This Package is more specific to DIGIT-UI's can be used across mission's +``` + +## Usage + +After adding the dependency make sure you have this dependency in + +```bash +frontend/micro-ui/web/package.json +``` + +```json +"@egovernments/digit-ui-module-health-hrms" :"0.0.1", +``` + +then navigate to App.js + +```bash + frontend/micro-ui/web/src/App.js +``` + +```jsx +/** add this import **/ + +import { initHrmsComponents } from "egovernments/digit-ui-module-health-hrms" + +/** inside enabledModules add this new module key **/ + +const enabledModules = ["HRMS"]; + +/** inside init Function call this function **/ + +const initDigitUI = () => { + initHrmsComponents(); +}; + +``` + +## List of features available in this package were as follows + +1. Implement User create and edit functionality. +2. Implement Campaign assign and edit functionality. +3. Enable Activate/Deactivate user functionality. + + + +### Contributors + +- [ramkrishna-egov](https://github.com/ramkrishna-egov) +- [pitabash-eGov](https://github.com/pitabash-eGov) + +## License + +[MIT](https://choosealicense.com/licenses/mit/) + +## Documentation + +Documentation Site (https://core.digit.org/guides/developer-guide/ui-developer-guide/digit-ui) + +[Microplan Module Documentation](https://docs.digit.org/public-health/v1.7/setup/configuration/ui-configuration) + +## Maintainer + +- [pitabash-eGov](https://github.com/pitabash-eGov) + + +### Published from DIGIT Frontend +DIGIT Frontend Repo (https://github.com/egovernments/Digit-Frontend/tree/master) + + +![Logo](https://s3.ap-south-1.amazonaws.com/works-dev-asset/mseva-white-logo.png) + diff --git a/health/micro-ui/web/micro-ui-internals/packages/modules/health-hrms/package.json b/health/micro-ui/web/micro-ui-internals/packages/modules/health-hrms/package.json new file mode 100644 index 00000000000..9c7f27ac418 --- /dev/null +++ b/health/micro-ui/web/micro-ui-internals/packages/modules/health-hrms/package.json @@ -0,0 +1,36 @@ +{ + "name": "@egovernments/digit-ui-module-health-hrms", + "version": "0.0.1", + "description": "HRMS Module UI", + "main": "dist/index.js", + "module": "dist/index.modern.js", + "source": "src/Module.js", + "files": [ + "dist" + ], + "scripts": { + "start": "microbundle-crl watch --no-compress --format modern,cjs", + "build": "microbundle-crl --compress --no-sourcemap --format cjs", + "prepublish": "yarn build" + }, + "peerDependencies": { + "react": "17.0.2", + "react-router-dom": "5.3.0" + }, + "dependencies": { + "@egovernments/digit-ui-react-components": "1.8.14", + "@egovernments/digit-ui-components": "0.2.0-beta.4", + "react": "17.0.2", + "react-date-range": "^1.4.0", + "react-dom": "17.0.2", + "react-hook-form": "6.15.8", + "react-i18next": "11.16.2", + "react-query": "3.6.1", + "react-router-dom": "5.3.0", + "react-data-table-component": "7.6.2" + + }, + "author": "Pitabash ", + "license": "MIT" + } + \ No newline at end of file diff --git a/health/micro-ui/web/micro-ui-internals/packages/modules/health-hrms/src/Module.js b/health/micro-ui/web/micro-ui-internals/packages/modules/health-hrms/src/Module.js new file mode 100644 index 00000000000..6852a73be55 --- /dev/null +++ b/health/micro-ui/web/micro-ui-internals/packages/modules/health-hrms/src/Module.js @@ -0,0 +1,75 @@ +import React from "react"; +import { useRouteMatch } from "react-router-dom"; + +import CreateEmployeePage from "./pages/employee/createEmployee"; + +import EmployeeApp from "./pages/employee"; + +import Jurisdictions from "./components/pageComponents/jurisdiction"; +import { overrideHooks, updateCustomConfigs } from "./hooks/hook_setup"; +import RolesAssigned from "./components/pageComponents/SelectRolesAssigned"; +import BoundaryComponent from "./components/pageComponents/SelectEmployeeBoundary"; + +import AssignCampaign from "./pages/employee/createAssignments"; + +import ResponseScreen from "./pages/employee/service_response"; +import CampaignsAssignment from "./components/pageComponents/CampaignAssignment"; +import InboxSearch from "./pages/employee/search_inbox"; +import ActionPopUp from "./components/pageComponents/popup"; +import EmployeeDetailScreen from "./pages/employee/employeeDetails"; + +import BreadCrumbs from "./components/pageComponents/BreadCrumb"; + +export const HRMSModule = ({ stateCode, userType, tenants }) => { + const modulePrefix= "hcm"; + const hierarchyType = window?.globalConfigs?.getConfig("HIERARCHY_TYPE") || "ADMIN"; + const moduleCode = ["HR", `boundary-${hierarchyType?.toString().toLowerCase()}`]; + const language = Digit.StoreData.getCurrentLanguage(); + const { isLoading, data: store } = Digit.Services.useStore({ stateCode, moduleCode, language,modulePrefix }); + const tenantId = Digit.ULBService.getCurrentTenantId(); + Digit.SessionStorage.set("HRMS_TENANTS", tenants); + + const { isLoading: isPaymentsModuleInitializing } = Digit.Hooks.hrms.useHrmsInitialization({ + tenantId: tenantId, + }); + + const { path, url } = useRouteMatch(); + if (!Digit.Utils.hrmsAccess()) { + return null; + } + + if (userType === "employee") { + return ; + } else return null; +}; + +const componentsToRegister = { + EmployeeDetailScreen, + InboxSearch, + + ActionPopUp, + CampaignsAssignment, + BoundaryComponent, + + Jurisdictions, + RolesAssigned, + AssignCampaign, + ResponseScreen, + + HRMSModule, + + + + HRCreateEmployee: CreateEmployeePage, + + BreadCrumbs, +}; + +export const initHRMSComponents = () => { + overrideHooks(); + updateCustomConfigs(); + + Object.entries(componentsToRegister).forEach(([key, value]) => { + Digit.ComponentRegistryService.setComponent(key, value); + }); +}; diff --git a/health/micro-ui/web/micro-ui-internals/packages/modules/health-hrms/src/components/Utils/cleanup.js b/health/micro-ui/web/micro-ui-internals/packages/modules/health-hrms/src/components/Utils/cleanup.js new file mode 100644 index 00000000000..3191c92e935 --- /dev/null +++ b/health/micro-ui/web/micro-ui-internals/packages/modules/health-hrms/src/components/Utils/cleanup.js @@ -0,0 +1,14 @@ +const cleanup = (payload) => { + if (payload) { + return Object.keys(payload).reduce((acc, key) => { + if (payload[key] === undefined) { + return acc; + } + + // todo: find a better way to check object + acc[key] = typeof payload[key] === "object" ? cleanup(payload[key]) : payload[key]; + return acc; + }, {}); + } +}; +export default cleanup; diff --git a/health/micro-ui/web/micro-ui-internals/packages/modules/health-hrms/src/components/Utils/index.js b/health/micro-ui/web/micro-ui-internals/packages/modules/health-hrms/src/components/Utils/index.js new file mode 100644 index 00000000000..5bb8fb18b50 --- /dev/null +++ b/health/micro-ui/web/micro-ui-internals/packages/modules/health-hrms/src/components/Utils/index.js @@ -0,0 +1,67 @@ +/* methid to get date from epoch */ +export const convertEpochToDate = (dateEpoch) => { + // Returning null in else case because new Date(null) returns initial date from calender + if (dateEpoch) { + const dateFromApi = new Date(dateEpoch); + let month = dateFromApi.getMonth() + 1; + let day = dateFromApi.getDate(); + let year = dateFromApi.getFullYear(); + month = (month > 9 ? "" : "0") + month; + day = (day > 9 ? "" : "0") + day; + return `${year}-${month}-${day}`; + } else { + return null; + } +}; + +export const convertDateToEpoch = (dateString) => { + // Create a Date object from the input date string + const date = new Date(dateString); + + // Convert the date to epoch time (seconds) + return Math.floor(date.getTime()); +}; + +export const convertEpochFormateToDate = (dateEpoch) => { + // Returning null in else case because new Date(null) returns initial date from calender + if (dateEpoch) { + const dateFromApi = new Date(dateEpoch); + let month = dateFromApi.getMonth() + 1; + let day = dateFromApi.getDate(); + let year = dateFromApi.getFullYear(); + month = (month > 9 ? "" : "0") + month; + day = (day > 9 ? "" : "0") + day; + return `${day}/${month}/${year}`; + } else { + return null; + } +}; + +/* function returns only the city which user has access to */ +/* exceptional incase of state level user , where return all cities*/ +export const getCityThatUserhasAccess = (cities = []) => { + const userInfo = Digit.UserService.getUser(); + let roleObject = {}; + userInfo?.info?.roles.map((roleData) => { + roleObject[roleData?.code] = roleObject[roleData?.code] ? [...roleObject[roleData?.code], roleData?.tenantId] : [roleData?.tenantId]; + }); + const tenant = Digit.ULBService.getCurrentTenantId(); + if (roleObject[Digit.Utils?.hrmsRoles?.[0]].includes(Digit.ULBService.getStateId())) { + return cities; + } + return cities.filter((city) => roleObject[Digit.Utils?.hrmsRoles?.[0]]?.includes(city?.code)); +}; + +export const deleteProjectStaff = async (projectStaff) => { + Digit.ProjectService.delete_staff(projectStaff).then((res) => {}); +}; + +export const getProjectDetails = async (projects, tenantId, includeDescendants, includeImmediateChildren) => { + let projectDetails = []; + await Digit.ProjectService.search_project({ tenantId, projects, includeDescendants, includeImmediateChildren }) + .then((res) => { + projectDetails = res?.Project; + }) + .catch((err) => err); + return projectDetails; +}; diff --git a/health/micro-ui/web/micro-ui-internals/packages/modules/health-hrms/src/components/config/campaignAssignmentConfig.js b/health/micro-ui/web/micro-ui-internals/packages/modules/health-hrms/src/components/config/campaignAssignmentConfig.js new file mode 100644 index 00000000000..502a8d5cbb8 --- /dev/null +++ b/health/micro-ui/web/micro-ui-internals/packages/modules/health-hrms/src/components/config/campaignAssignmentConfig.js @@ -0,0 +1,22 @@ +/** + * config for campaign assignment screen: contains the custom component for the screen. + * digit components used:CardLabel, Dropdown, LabelFieldPair, Loader, DatePicker, TextInput. + * + */ + +export const campaignAssignmentConfig = [ + { + head: "HR_CAMPAIGN_ASSIGNMENT_HEADER", + body: [ + { + type: "component", + component: "CampaignsAssignment", + key: "CampaignsAssignment", + withoutLabel: true, + populators: { + name: "CampaignsAssignment", + }, + }, + ], + }, +]; diff --git a/health/micro-ui/web/micro-ui-internals/packages/modules/health-hrms/src/components/config/config.js b/health/micro-ui/web/micro-ui-internals/packages/modules/health-hrms/src/components/config/config.js new file mode 100644 index 00000000000..738c3041293 --- /dev/null +++ b/health/micro-ui/web/micro-ui-internals/packages/modules/health-hrms/src/components/config/config.js @@ -0,0 +1,259 @@ +/** + * config for create/edit user screen: it is used to in the screen to take input about of the new usern and existing user as well. + * digit components used:all digit components used except the boundarycomponent and the Roles assigned component. + * + */ + +export const newConfig = [ + { + head: "HR_LOGIN_DETAILS_HEADER", + body: [ + { + inline: true, + label: "HR_EMP_ID_LABEL", + isMandatory: true, + type: "text", + disable: false, + key: "SelectEmployeeId", + + populators: { + name: "SelectEmployeeId", + error: "Required", + validation: { + pattern: "/^[A-Za-z]+$/", + + ValidationRequired: true, + }, + }, + }, + + { + inline: true, + label: "HR_EMP_PASSWORD_LABEL", + isMandatory: true, + type: "password", + disable: false, + key: "employeePassword", + + populators: { + name: "employeePassword", + error: "CORE_COMMON_APPLICANT_PASSWORD_INVALID", + validation: { + pattern: "/^[A-Za-z]+$/", + type: "password", + ValidationRequired: true, + }, + }, + }, + + { + inline: true, + label: "HR_EMP_CONFIRM_PASSWORD_LABEL", + isMandatory: true, + type: "password", + disable: false, + key: "employeeConfirmPassword", + + populators: { + name: "employeeConfirmPassword", + error: "CORE_COMMON_APPLICANT_CONFIRM_PASSWORD_INVALID", + validation: { + pattern: "/^[A-Za-z]+$/", + type: "password", + ValidationRequired: true, + }, + }, + }, + ], + }, + { + head: "HR_PERSONAL_DETAILS_HEADER", + body: [ + { + inline: false, + label: "HR_EMP_NAME_LABEL", + isMandatory: true, + type: "text", + disable: false, + key: "SelectEmployeeName", + populators: { + name: "SelectEmployeeName", + error: "Required", + validation: { pattern: /^[^{0-9}^\$\"<>?\\\\~!@#$%^()+={}\[\]*,/_:;“”‘’]{1,50}$/i }, + }, + }, + + { + label: "HR_MOB_NO_LABEL", + isMandatory: true, + key: "SelectEmployeePhoneNumber", + type: "number", + disable: false, + populators: { + name: "SelectEmployeePhoneNumber", + error: "CORE_COMMON_MOBILE_ERROR", + validation: { minLength: 10, min: 0, max: 9999999999, ValidationRequired: true }, // 10-digit phone number validation + }, + }, + + { + isMandatory: true, + type: "radio", + key: "genders", + label: "HR_GENDER_LABEL", + disable: false, + populators: { + name: "gender", + optionsKey: "name", + error: "sample required message", + required: true, + mdmsConfig: { + masterName: "GenderType", + moduleName: "common-masters", + localePrefix: "COMMON_GENDER", + }, + }, + }, + + { + inline: true, + label: "HR_BIRTH_DATE_LABEL", + isMandatory: true, + key: "SelectDateofBirthEmployment", + type: "date", + disable: false, + populators: { + + name: "SelectDateofBirthEmployment", + required: true, + error: "Required", + }, + }, + + { + inline: false, + label: "HR_EMAIL_LABEL", + isMandatory: false, + type: "text", + disable: false, + key: "SelectEmployeeEmailId", + populators: { + required: false, + name: "SelectEmployeeEmailId", + error: "Required", + validation: { + pattern: /^(?=^.{1,64}$)((([^<>()\[\]\\.,;:\s$*@'"]+(\.[^<>()\[\]\\.,;:\s@'"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,})))$/i, + }, + }, + }, + + { + inline: false, + label: "HR_CORRESPONDENCE_ADDRESS_LABEL", + isMandatory: false, + type: "text", + disable: false, + populators: { + required: false, + name: "SelectEmployeeCorrespondenceAddress", + error: "Required", + validation: { + pattern: /^(?=^.{1,64}$)((([^<>()\[\]\\.,;:\s$*@'"]+(\.[^<>()\[\]\\.,;:\s@'"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,})))$/i, + }, + }, + }, + ], + }, + + { + head: "HR_NEW_EMPLOYEE_FORM_HEADER", + body: [ + { + isMandatory: true, + key: "SelectEmployeeType", + type: "dropdown", + label: "HR_EMPLOYMENT_TYPE_LABEL", + disable: false, + populators: { + name: "SelectEmployeeType", + optionsKey: "name", + error: "Required", + mdmsConfig: { + masterName: "EmployeeType", + moduleName: "egov-hrms", + localePrefix: "EGOV_HRMS_EMPLOYEETYPE", + }, + }, + }, + + { + inline: true, + label: "Date of appointment", + isMandatory: true, + key: "SelectDateofEmployment", + type: "date", + disable: false, + populators: { name: "SelectDateofEmployment", required: true, error: "Required" }, + }, + + { + isMandatory: true, + key: "SelectEmployeeDepartment", + type: "dropdown", + label: "HR_EMPLOYMENT_DEPARTMENT_LABEL", + disable: false, + populators: { + name: "SelectEmployeeDepartment", + optionsKey: "name", + error: "Required", + mdmsConfig: { + masterName: "Department", + moduleName: "common-masters", + localePrefix: "COMMON_MASTERS_DEPARTMENT", + }, + }, + }, + + { + isMandatory: true, + key: "SelectEmployeeDesignation", + type: "dropdown", + label: "HR_EMPLOYMENT_Designation_LABEL", + disable: false, + populators: { + name: "SelectEmployeeDesignation", + optionsKey: "name", + error: "Required", + mdmsConfig: { + masterName: "Designation", + moduleName: "common-masters", + localePrefix: "COMMON_MASTERS_DESIGNATION", + }, + }, + }, + + { + type: "component", + isMandatory: true, + component: "RolesAssigned", + key: "RolesAssigned", + withoutLabel: true, + populators: { + name: "RolesAssigned", + }, + customProps: {}, + }, + + { + type: "component", + isMandatory: true, + component: "BoundaryComponent", + key: "BoundaryComponent", + withoutLabel: true, + populators: { + name: "BoundaryComponent", + }, + }, + ], + }, +]; diff --git a/health/micro-ui/web/micro-ui-internals/packages/modules/health-hrms/src/components/config/inboxSearchConfig.js b/health/micro-ui/web/micro-ui-internals/packages/modules/health-hrms/src/components/config/inboxSearchConfig.js new file mode 100644 index 00000000000..3fc2a4a677f --- /dev/null +++ b/health/micro-ui/web/micro-ui-internals/packages/modules/health-hrms/src/components/config/inboxSearchConfig.js @@ -0,0 +1,239 @@ +import Urls from "../../services/urls"; + +/** + * config for HRMS Inbox screen: + * @Initial Data Load: On screen load, the system automatically fetches a list of HRMS users. + * @filter section: Allows users to filter the list based on active/inactive status and assigned roles. + * @search section: Enables users to search for specific HRMS users using username, user code, or phone number. + * @link section: Provides navigation to the Create User screen. + */ + +const inboxSearchConfig = () => { + return { + type: "inbox", // Defines the type of configuration (search functionality) + label: "Search Employee", // Label for the search functionality + + sections: { + filter: { + uiConfig: { + type: "filter", + headerStyle: null, + primaryLabel: "Apply Filters", + secondaryLabel: "Clear Filters", + minReqFields: 1, + defaultValues: { + roles: [], + + isActive: { + code: true, + name: "HR_ACTIVATE_HEAD", + }, + }, + fields: [ + { + label: "HR_COMMON_TABLE_COL_ROLE", + type: "dropdown", + isMandatory: false, + disable: false, + populators: { + isDropdownWithChip: true, + name: "roles", + optionsKey: "name", + error: "Error!", + required: false, + + mdmsConfig: { + masterName: "roles", + moduleName: "ACCESSCONTROL-ROLES", + localePrefix: "ACCESSCONTROL_ROLES_ROLES", + }, + }, + }, + { + label: "HR_EMP_STATUS_LABEL", + type: "radio", + isMandatory: false, + disable: false, + addDivider: true, + populators: { + alignVertical: true, + name: "isActive", + options: [ + { + code: false, + name: "HR_DEACTIVATE_HEAD", + }, + { + code: true, + name: "HR_ACTIVATE_HEAD", + }, + ], + optionsKey: "name", + }, + }, + ], + }, + label: "ES_COMMON_FILTERS", + show: true, + }, + + links: { + uiConfig: { + links: [ + { + text: "HR_COMMON_CREATE_EMPLOYEE_HEADER", + url: "/employee/hrms/create", + roles: ["SYSTEM_ADMINISTRATOR", "HRMS_ADMIN"], + hyperlink: true, + }, + ], + label: "HRMS", + logoIcon: { + component: "Opacity", + customClass: "search-icon--projects", + }, + }, + children: {}, + show: true, + }, + + search: { + show: true, // Determines whether the search section is displayed + label: "", // No specific label assigned + children: {}, // No child components included + + uiConfig: { + type: "search", // UI type is a search form + fields: [ + { + type: "text", // Input type (text field) + label: "HR_NAME_LABEL", // Field label + disable: false, // Field is enabled + populators: { + name: "names", // Field name for form data + error: "ERR_INVALID_NAME", // Error message key for validation + style: { marginBottom: "0px" }, // Inline style for UI adjustments + }, + isMandatory: false, // Field is optional + }, + { + type: "text", + label: "HR_USERNAME_LABEL", + disable: false, + populators: { + name: "codes", + error: "ERR_INVALID_NAME", + style: { marginBottom: "0px" }, + }, + isMandatory: false, + }, + { + type: "number", + label: "HR_MOB_NO_LABEL", + disable: false, + populators: { + name: "phone", + error: "ERR_INVALID_PHONE_NUMBER", + style: { marginBottom: "0px" }, + }, + isMandatory: false, + }, + ], + + typeMobile: "filter", // Defines mobile view as a filter + headerLabel: "ES_COMMON_SEARCH", // Header label for search + headerStyle: null, // No custom header style + minReqFields: 0, // Minimum required fields to perform a search + primaryLabel: "Search", // Label for primary search button + + defaultValues: { + // Default search parameters + codes: "", + limit: 10, + names: "", + phone: "", + roles: "", + offset: 0, + // /sortBy: "lastModifiedTime", + tenantId: "mz", + sortOrder: "DESC", + }, + + secondaryLabel: "ES_COMMON_CLEAR_SEARCH", // Label for clear search button + searchWrapperStyles: {}, + }, + labelMobile: "ES_COMMON_SEARCH", // Label for mobile view + }, + + searchResult: { + show: true, // Determines whether the search result section is displayed + children: {}, // No child components included + + uiConfig: { + columns: [ + // Defines columns for search result table + { + label: "HR_EMP_ID_LABEL", + jsonPath: "code", // Maps data from API response + additionalCustomization: true, + }, + { + label: "HR_EMP_NAME_LABEL", + jsonPath: "user.name", + }, + { + label: "HR_ROLE_NO_LABEL", + jsonPath: "user.roles", + additionalCustomization: true, + }, + { + label: "HR_DESG_LABEL", + jsonPath: "assignments", + additionalCustomization: true, + }, + { + label: "HR_EMPLOYMENT_DEPARTMENT_LABEL", + jsonPath: "assignments[0]", + additionalCustomization: true, + }, + ], + rowClassName: "table-row-mdms table-row-mdms-hover", // Table row styles + tableClassName: "pqm-table", // Table styles + resultsJsonPath: "Employees", // API response path for results + enableColumnSort: false, // Enables sorting on columns + enableGlobalSearch: false, // Disables global search + isPaginationRequired: true, // enables pagination + }, + }, + }, + + apiDetails: { + masterName: "commonUiConfig", // Master data module for UI config + moduleName: "SearchDefaultConfigMain", // Configuration module name + requestBody: {}, // Request body (empty for now) + serviceName: Urls.hrms.search, // API endpoint for search + requestParam: { + // Default request parameters for API call + limit: 10, + names: "", + roles: "", + offset: 0, + sortBy: "lastModifiedTime", + tenantId: "mz", + sortOrder: "DESC", + // includeUnassigned:true + }, + tableFormJsonPath: "requestParam", // JSON path for table form data + filterFormJsonPath: "requestParam", // JSON path for filter form data + searchFormJsonPath: "requestParam", // JSON path for search form data + minParametersForFilterForm: 0, // No minimum required fields for filter + minParametersForSearchForm: 0, // No minimum required fields for search + }, + + persistFormData: true, // Keeps form data persisted between searches + additionalSections: {}, // No additional sections + showAsRemovableTagsInMobile: true, // Enables removable search tags in mobile UI + }; +}; + +export default inboxSearchConfig; diff --git a/health/micro-ui/web/micro-ui-internals/packages/modules/health-hrms/src/components/employeeAction.js b/health/micro-ui/web/micro-ui-internals/packages/modules/health-hrms/src/components/employeeAction.js new file mode 100644 index 00000000000..2d8d84788d2 --- /dev/null +++ b/health/micro-ui/web/micro-ui-internals/packages/modules/health-hrms/src/components/employeeAction.js @@ -0,0 +1,307 @@ +import { + CardSubHeader, + CardText, + FormComposer, + Loader, + Modal, + OTPInput, + Toast +} from "@egovernments/digit-ui-react-components"; +import set from "lodash/set"; +import React, {useEffect, useRef, useState} from "react"; +import { useHistory } from "react-router-dom"; +import { configEmployeeActiveApplication } from "./Modal/EmployeeActivation"; +import { configEmployeeApplication } from "./Modal/EmployeeAppliaction"; +import {configEmployeePasswordReset} from "./Modal/EmployeePasswordReset"; +import Header from "@egovernments/digit-ui-module-core/src/components/Header"; + +/** + * handles multiple employee-related actions + * @param {*} param0 + * @returns + * TODO:[need to configure the actions in the MDMS] + */ + +const EmployeeAction = ({ t, action, tenantId, closeModal, submitAction, applicationData, resendOtpFn, setToast}) => { + const history = useHistory(); + const [config, setConfig] = useState({}); + const [file, setFile] = useState(null); + const [uploadedFile, setUploadedFile] = useState(null); + const [error, setError] = useState(null); + const [Reasons, setReasons] = useState([]); + const [selectedReason, selecteReason] = useState(""); + const { isLoading, isError, errors, data, ...rest } = Digit.Hooks.hrms.useHrmsMDMS(tenantId, "egov-hrms", "DeactivationReason"); + const userInfo = Digit.UserService.getUser()?.info; + const [resendOtp, setResendOtpToast] = useState(null); + const [otp, setOtp] = useState(""); + + function maskEmail(email) { + const [localPart, domain] = email?.split('@'); + const maskedLocalPart = localPart?.slice(0, -4) + '****'; + return `${maskedLocalPart}@${domain}`; + } + + var sendOtp = async () => { + resendOtpFn().then((response) => { + setResendOtpToast({key: "success", action: t("OTP_REQUEST_SENT")}); + }).catch((err) => { + setResendOtpToast({key: "error", action: t("OTP_REQUEST_SENT_FAILED")}); + }); + } + + useEffect(() => { + switch (action) { + case "PASSWORD_RESET": + return setConfig( + configEmployeePasswordReset({ t }) + ); + case "DEACTIVATE_EMPLOYEE_HEAD": + return setConfig( + configEmployeeApplication({ + t, + action, + selectFile, + uploadedFile, + setUploadedFile, + selectedReason, + Reasons, + selectReason, + })); + case "ACTIVATE_EMPLOYEE_HEAD": + return setConfig( + configEmployeeActiveApplication({ + t, + action, + selectFile, + uploadedFile, + setUploadedFile, + selectedReason, + Reasons, + selectReason, + employees: applicationData?.Employees[0] || {} + }) + ); + default: + break; + } + }, [action, uploadedFile, Reasons]); + + const Heading = (props) => { + return

{props.label}

; + }; + + function selectReason(e) { + selecteReason(e); + } + const Close = () => ( + + + + + ); + + const CloseBtn = (props) => { + return ( +
+ +
+ ); + }; + + function selectFile(e) { + setFile(e.target.files[0]); + } + useEffect(() => { + setReasons( + data?.["egov-hrms"]?.DeactivationReason.map((ele) => { + ele["i18key"] = "EGOV_HRMS_DEACTIVATIONREASON_" + ele.code; + return ele; + }) + ); + }, [data]); + + useEffect(() => { + (async () => { + setError(null); + if (file) { + if (file.size >= 5242880) { + setError(t("CS_MAXIMUM_UPLOAD_SIZE_EXCEEDED")); + } else { + try { + setUploadedFile(null); + const response = await Digit.UploadServices.Filestorage("HRMS", file, Digit.ULBService.getStateId()); + if (response?.data?.files?.length > 0) { + setUploadedFile(response?.data?.files[0]?.fileStoreId); + } else { + setError(t("CS_FILE_UPLOAD_ERROR")); + } + } catch (err) { + setError(t("CS_FILE_UPLOAD_ERROR")); + } + } + } + })(); + }, [file]); + + async function submit(data) { + // useHRMSUpdate + data.effectiveFrom = new Date(data.effectiveFrom).getTime(); + data.reasonForDeactivation = selectedReason.code; + let Employees = [...applicationData.Employees]; + + switch (action) { + case "DEACTIVATE_EMPLOYEE_HEAD": + if (file) { + let documents = { + referenceType: "DEACTIVATION", + documentId: uploadedFile, + documentName: file.name, + }; + applicationData.Employees[0]["documents"].push(documents); + } + + set(Employees[0], 'deactivationDetails[0].effectiveFrom', new Date()?.getTime()); + set(Employees[0], 'deactivationDetails[0].orderNo', data?.orderNo); + set(Employees[0], 'deactivationDetails[0].reasonForDeactivation', data?.reasonForDeactivation); + set(Employees[0], 'deactivationDetails[0].remarks', data?.remarks); + + Employees[0].isActive = false; + history.replace(`/${window?.contextPath}/employee/hrms/response`, { + Employees, + key: "UPDATE", + action: "DEACTIVATION" + }); + break; + case "ACTIVATE_EMPLOYEE_HEAD": + if (file) { + let documents = { + referenceType: "ACTIVATION", + documentId: uploadedFile, + documentName: file.name, + }; + applicationData.Employees[0]["documents"].push(documents); + } + + set(Employees[0], 'reactivationDetails[0].effectiveFrom', new Date()?.getTime()); + set(Employees[0], 'reactivationDetails[0].orderNo', data?.orderNo); + set(Employees[0], 'reactivationDetails[0].reasonForDeactivation', data?.reasonForDeactivation); + set(Employees[0], 'reactivationDetails[0].remarks', data?.remarks); + Employees[0].isActive = true; + + history.replace(`/${window?.contextPath}/employee/hrms/response`, { + Employees, + key: "UPDATE", + action: "ACTIVATION" + }); + break; + case "PASSWORD_RESET": + if (data?.password && data?.confirmPassword && data.password === data.confirmPassword) { + if ( otp.length !== 6) { + setResendOtpToast({key: "error", action: "CS_OTP_INVALID"}); + setError(t("CS_OTP_INVALID")); + return + } + if (!data.password.match(Digit.Utils.getPattern('Password'))) { + setResendOtpToast({key: "error", action: "CORE_COMMON_APPLICANT_PASSWORD_INVALID"}); + setError(t("CORE_COMMON_APPLICANT_PASSWORD_INVALID")); + return + } + const requestData = { + userName: applicationData.Employees?.[0]?.code, + newPassword: data.confirmPassword, + otpReference: otp, + tenantId, + type: Digit.UserService.getType().toUpperCase() + }; + + Digit.UserService.changePassword(requestData, tenantId).then((response) => { + + setToast({key: "success", action: t("PASSWORD_RESET_SUCCESS")}); + closeModal(); + }).catch((err) => { + setResendOtpToast({key: "error", action: err?.response?.data?.error?.fields?.[0]?.message || t("ES_SOMETHING_WRONG")}); + }); + + } else { + setResendOtpToast({key: "error", action: "CS_PASSWORD_NOT_EQUAL"}); + setError(t("CS_PASSWORD_NOT_EQUAL")); + } + } + } + + + switch (action) { + case "CREATE_EMPLOYEE": + return } + actionCancelLabel={t('CANCEL')} + actionCancelOnSubmit={closeModal} + actionSaveLabel={t('SUBMIT')} + actionSaveOnSubmit={submitAction} + formId="modal-action" + > + + {t('HR_READY_TO_SUBMIT_TEXT')} + + + case "PASSWORD_RESET": + return } + headerBarEnd={} + actionCancelOnSubmit={closeModal} + hideSubmit={true} + formId="modal-action" + > + {resendOtp && ( + setResendOtpToast(null)} + style={{ maxWidth: "670px" }} + /> + )} + + + {`${t(`CS_LOGIN_OTP_TEXT`)} `} + + {" "} + {maskEmail(userInfo?.emailId)} + +

+ {t("CS_RESEND_OTP")} +

+
+
+
+
+ default: + return action && config?.form ? ( + } + headerBarEnd={} + actionCancelOnSubmit={closeModal} + actionSaveLabel={t(config?.label?.submit)} + actionSaveOnSubmit={() => { }} + formId="modal-action" + isDisabled={!selectedReason} + > + + + ) : ( + + ); + } + + +}; +export default EmployeeAction; \ No newline at end of file diff --git a/health/micro-ui/web/micro-ui-internals/packages/modules/health-hrms/src/components/pageComponents/BreadCrumb.js b/health/micro-ui/web/micro-ui-internals/packages/modules/health-hrms/src/components/pageComponents/BreadCrumb.js new file mode 100644 index 00000000000..c28abed58c7 --- /dev/null +++ b/health/micro-ui/web/micro-ui-internals/packages/modules/health-hrms/src/components/pageComponents/BreadCrumb.js @@ -0,0 +1,142 @@ +import React, { useEffect, useState, Fragment } from "react"; +import PropTypes from "prop-types"; +import { Link } from "react-router-dom"; + +const BreadCrumbs = (props) => { + const [expanded, setExpanded] = useState(false); + const [crumbsToDisplay, setCrumbsToDisplay] = useState([...props?.crumbs]); + + useEffect(() => { + if (props?.maxItems && props?.crumbs.length > props?.maxItems && !expanded) { + const startCrumbs = props.crumbs.slice(0, props?.itemsBeforeCollapse || Math.ceil(props.maxItems / 2)); + const endCrumbs = props.crumbs.slice( + -1 * (props?.itemsAfterCollapse || Math.floor(props.maxItems / 2)) + ); + + let updatedCrumbs = startCrumbs.concat( + [{ show: true, content: props?.expandText || "..." }], + endCrumbs + ); + setCrumbsToDisplay(updatedCrumbs); + } else { + setCrumbsToDisplay([...props.crumbs]); + } + }, [props.crumbs, props.maxItems, expanded, props.itemsBeforeCollapse, props.itemsAfterCollapse, props?.expandText]); + + function handleRedirect(path) { + const host = window.location.origin; // Dynamically get the base URL + window.location.href = `${host}${path}`; + } + + function isLast(index) { + // Filter crumbs to only include those that are displayed + let validCrumbs = crumbsToDisplay?.filter((crumb) => crumb?.show === true); + + // Check if all crumbs have the same `internalLink` or `externalLink` + const allHaveSameInternalLink = validCrumbs.every((crumb) => crumb.internalLink === validCrumbs[0].internalLink); + const allHaveSameExternalLink = validCrumbs.every((crumb) => crumb.externalLink === validCrumbs[0].externalLink); + + // If all visible crumbs have the same link, determine last crumb by index + if (allHaveSameInternalLink || allHaveSameExternalLink) { + return index === validCrumbs.length - 1; + } + + // Check if the current crumb is the last one in the validCrumbs list + return ( + validCrumbs?.findIndex((ob) => { + const linkToCheck = ob?.externalLink || ob?.internalLink; // Use externalLink if it exists, else internalLink + const currentLink = crumbsToDisplay?.[index]?.externalLink || crumbsToDisplay?.[index]?.internalLink; + + return linkToCheck === currentLink; + }) === + validCrumbs?.length - 1 + ); + } + + const handleCrumbClick = () => { + setExpanded(!expanded); + }; + + const validCrumbsMain = crumbsToDisplay?.filter((crumb) => crumb?.show === true); + + return ( +
    + {validCrumbsMain?.map((crumb, ci) => { + if (!crumb?.show) return null; + if (crumb?.isBack) + return ( +
  1. + window.history.back()}>{crumb.content} +
  2. + ); + + return ( + +
  3. + {isLast(ci) || (!crumb?.internalLink && !crumb?.externalLink) ? ( + + {crumb?.icon && crumb.icon} + {crumb.content} + + ) : crumb?.externalLink ? ( + handleRedirect(crumb?.externalLink)} + > + {crumb?.icon && crumb.icon} + {crumb.content} + + ) : ( + + {crumb?.icon && crumb.icon} + {crumb.content} + + )} + {!isLast(ci) && ( +
    + {props?.customSeparator ? props?.customSeparator : "/"} +
    + )} +
  4. +
    + ); + })} +
+ ); +}; + +BreadCrumbs.propTypes = { + crumbs: PropTypes.array, + className: PropTypes.string, + style: PropTypes.object, + spanStyle: PropTypes.object, + customSeparator: PropTypes.element, + maxItems: PropTypes.number, + itemsAfterCollapse: PropTypes.number, + itemsBeforeCollapse: PropTypes.number, + expandText: PropTypes.string +}; + +BreadCrumbs.defaultProps = { + successful: true, +}; + +export default BreadCrumbs; diff --git a/health/micro-ui/web/micro-ui-internals/packages/modules/health-hrms/src/components/pageComponents/CampaignAssignment.js b/health/micro-ui/web/micro-ui-internals/packages/modules/health-hrms/src/components/pageComponents/CampaignAssignment.js new file mode 100644 index 00000000000..48b60b51c18 --- /dev/null +++ b/health/micro-ui/web/micro-ui-internals/packages/modules/health-hrms/src/components/pageComponents/CampaignAssignment.js @@ -0,0 +1,169 @@ +import { CardLabel, Dropdown, LabelFieldPair, Loader, DatePicker, TextInput } from "@egovernments/digit-ui-components"; +import React, { useEffect, useState } from "react"; +import { SVG } from "@egovernments/digit-ui-components"; + +const CampaignsAssignment = ({ t, config, onSelect, formData }) => { + const assignedProjects = Digit.SessionStorage.get("staffProjects"); + const userProjectDetails = assignedProjects?.map((project) => ({ + id: project?.id, + projectType: project?.projectType, + projectTypeId: project?.projectTypeId, + boundary: project?.address?.boundary, + boundaryType: project?.address?.boundaryType, + i18text: `${project?.name}_${project?.address?.boundary}`, + })); + const [campaigns, setCampaigns] = useState( + formData?.CampaignsAssignment?.length > 0 ? formData?.CampaignsAssignment : [{ selectedProject: "", fromDate: "", toDate: "" }] + ); + + useEffect(() => { + if (formData?.CampaignsAssignment?.length > 0) { + setCampaigns(formData.CampaignsAssignment); + } + }, [formData?.CampaignsAssignment]); + + const handleAddUnit = () => { + const newCampaign = { selectedProject: "", fromDate: "", toDate: "" }; + const updatedCampaigns = [...campaigns, newCampaign]; + setCampaigns(updatedCampaigns); + onSelect(config.key, updatedCampaigns); + }; + + const handleRemoveUnit = (index) => { + const updatedCampaigns = campaigns.filter((_, i) => i !== index); + setCampaigns(updatedCampaigns); + onSelect(config.key, updatedCampaigns); + }; + + const handleProjectSelect = (index, project) => { + const updatedCampaigns = campaigns.map((campaign, i) => (i === index ? { ...campaign, selectedProject: project } : campaign)); + setCampaigns(updatedCampaigns); + onSelect(config.key, updatedCampaigns); + }; + + const handleDateChange = (index, field, value) => { + const updatedCampaigns = campaigns.map((campaign, i) => (i === index ? { ...campaign, [field]: value } : campaign)); + setCampaigns(updatedCampaigns); + onSelect(config.key, updatedCampaigns); + }; + + const getAvailableProjects = (index) => { + const selectedProjects = campaigns.filter((_, i) => i !== index).map((campaign) => campaign.selectedProject?.id); + + return userProjectDetails.filter((project) => !selectedProjects.includes(project.id)); + }; + + return ( +
+ {campaigns.map((campaign, index) => { + const availableProjects = getAvailableProjects(index); + + return ( +
+ +
+

+ {t("HR_CAMPAIGN_ASSIGNMENT")} {index + 1} +

+
+ {campaigns.length > 1 && ( +
handleRemoveUnit(index)} + style={{ + marginBottom: "16px", + padding: "5px", + cursor: "pointer", + textAlign: "right", + }} + > + +
+ )} +
+ + {/* Campaign Name Dropdown */} + + + {t("HR_CAMPAIGN_NAME_LABEL")} {availableProjects.length > 1 ? "*" : ""} + + project.id === campaign.selectedProject?.id) || null} + optionKey={"i18text"} + option={availableProjects} + select={(value) => handleProjectSelect(index, value)} + t={t} + /> + + + {/* From Date Picker */} + + {t("HR_CAMPAIGN_FROM_DATE_LABEL")} +
+ { + handleDateChange(index, "fromDate", e); + }} + value={campaign?.fromDate} + key={"fromDate"} + disable={false} + /> +
+
+ + {/* To Date Picker */} + + {t("HR_CAMPAIGN_TO_DATE_LABEL")} +
+ { + handleDateChange(index, "toDate", e); + }} + value={formData && formData[config.key] ? formData[config.key][index].toDate : undefined} + key={"toDate"} + disable={false} + /> +
+
+
+ ); + })} + + {formData?.CampaignsAssignment?.length == userProjectDetails?.length ? ( +
+ ) : ( + + )} +
+ ); +}; + +export default CampaignsAssignment; diff --git a/health/micro-ui/web/micro-ui-internals/packages/modules/health-hrms/src/components/pageComponents/DeactivatePopUp.js b/health/micro-ui/web/micro-ui-internals/packages/modules/health-hrms/src/components/pageComponents/DeactivatePopUp.js new file mode 100644 index 00000000000..af95d4ebe3d --- /dev/null +++ b/health/micro-ui/web/micro-ui-internals/packages/modules/health-hrms/src/components/pageComponents/DeactivatePopUp.js @@ -0,0 +1,139 @@ +import React, { Fragment, useState, useEffect } from "react"; +import { useTranslation } from "react-i18next"; +import { PopUp, Button, TextArea, Toast, Dropdown, TextInput, FileUpload, FieldV1 } from "@egovernments/digit-ui-components"; +import { convertEpochToDate } from "../../utils/utlis"; + +const DeactivatePopUp = ({bussnessBtnLabel, label, onClose, onSubmit }) => { + const { t } = useTranslation(); + const tenantId = Digit.ULBService.getCurrentTenantId(); + + const { isLoading, isError, errors, data, ...rest } = Digit.Hooks.hrms.useHrmsMDMS(tenantId, "egov-hrms", "DeactivationReason"); + // state variables + const [comment, setComment] = useState(""); + const [showToast, setShowToast] = useState(null); + const [date, setDate] = useState(convertEpochToDate(Date.now())); + const [reason, setReason] = useState(null); + const [order, setOrder] = useState(null); + + const handleSave = () => { + if (!reason || reason.trim() === "") { + // Show toast if comment is empty + setShowToast({ + key: "error", + label: t("HCM_AM_COMMENT_REQUIRED_ERROR_TOAST_MESSAGE"), + transitionTime: 3000, + }); + return; + } + // remove the toast if comment is valid + setShowToast(null); + // Call the onSubmit function with the valid comment + onSubmit(comment, date, reason, order); + }; + + return ( + <> + { + onClose(); + }} + heading={t(label ? label : `HR_COMMON_DEACTIVATED_EMPLOYEE_HEADER`)} + children={[ +
+
+ {t(`HR_DEACTIVATION_REASON`)} + * +
+ + {}} + option={data?.["egov-hrms"]?.DeactivationReason.map((ele) => { + ele["i18key"] = "EGOV_HRMS_DEACTIVATIONREASON_" + ele.code; + return ele; + })} + optionKey="code" + optionsCustomStyle={{}} + select={(e) => { + setReason(e.code); + }} + t={t} + type="dropdown" + /> +
, + + { + setComment(e.target.value); + }} + type="text" + value={comment || ""} + />, + + { + setDate(e); + }} + disable={true} + value={date} + />, + + , + { + setOrder(e.target.value); + }} + type="text" + value={order || ""} + />, + ]} + onOverlayClick={onClose} + equalWidthButtons={true} + footerChildren={[ +
+ ]} + onOverlayClick={onClose} + equalWidthButtons={true} + footerChildren={[ +