+ {microplanFileId && row?.status == "RESOURCE_ESTIMATIONS_APPROVED" ? (
- );
- }
-
- 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 (
+
+ );
+ } else {
+ return (
+
+ );
+ }
+
+ case "MICROPLAN_STATUS":
+ if (value && value != "NA") {
+ return
{t(Digit.Utils.locale.getTransformedLocale("MICROPLAN_STATUS_" + value))}
;
+ } else {
+ return (
+
+ );
+ }
+
+ case "CAMPAIGN_DISEASE":
+ if (value && value != "NA") {
+ return
{t(Digit.Utils.locale.getTransformedLocale("MICROPLAN_DISEASE_" + value))}
;
+ } else {
+ return (
+
+ );
+ }
+
+ case "CAMPAIGN_TYPE":
+ if (value && value != "NA") {
+ return
{t(Digit.Utils.locale.getTransformedLocale("MICROPLAN_TYPE_" + value))}
;
+ } else {
+ return (
+
+ );
+ }
+
+ case "DISTIRBUTION_STRATEGY":
+ if (value && value != "NA") {
+ return
{t(Digit.Utils.locale.getTransformedLocale("MICROPLAN_DISTRIBUTION_" + value))}
;
+ } else {
+ return (
+
+ );
+ }
+
+ 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)
+
+
+
+
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 (
+ -
+ window.history.back()}>{crumb.content}
+
+ );
+
+ return (
+
+ -
+ {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 : "/"}
+
+ )}
+
+
+ );
+ })}
+
+ );
+};
+
+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={[
+
+
+ {
+
+ {t("HR_NEW_EMPLOYEE_FORM_HEADER")}
+
+ }
+
+ {
+
+ 0 ? data.Employees[0].assignments[0].department : "NA",
+ value: data?.Employees ? data?.Employees[0]?.employeeType : t(`CORE_COMMON_NA`),
+ },
+ // {
+ // inline: true,
+ // label: t("EMPLOYEE_RESPONSE_CREATE_LABEL"),
+ // type: "text",
+ // value: "USR-003682",
+ // },
+ {
+ inline: true,
+ label: t("HR_COMMON_TABLE_COL_DEPT"),
+ type: "text",
+ value:
+ data?.Employees?.[0]?.assignments?.length > 0
+ ? data.Employees[0].assignments[0].department
+ : "COMMON_MASTERS_DEPARTMENT_undefined",
+ },
+ {
+ inline: true,
+ label: t("HR_APPOINTMENT_DATE_LABEL"),
+ type: "text",
+ value: data?.Employees?.[0]?.dateOfAppointment ? convertEpochToDate(data.Employees[0].dateOfAppointment) : t(`CORE_COMMON_NA`),
+ },
+ ],
+ header: t("HR_PROFESSIONAL_DETAILS_FORM_HEADER"),
+ subHeader: "",
+ },
+
+ // custom card
+
+ {
+ cardType: "primary",
+ fieldPairs: [
+ {
+ label: "",
+ value: "",
+ type: "custom",
+ inline: false,
+ renderCustomContent: (value) => {
+ return (
+ {
+ return {
+ cardType: "primary",
+ fieldPairs: [
+ {
+ inline: true,
+ label: t("HR_HIERARCHY_LABEL"),
+ type: "text",
+ value: element?.hierarchy || t(`CORE_COMMON_NA`),
+ },
+ {
+ inline: true,
+ label: t("HR_BOUNDARY_TYPE_LABEL"),
+ type: "text",
+ value: element?.boundaryType || t(`CORE_COMMON_NA`),
+ },
+ {
+ inline: true,
+ label: t("HR_BOUNDARY_LABEL"),
+ value: element?.boundary || t(`CORE_COMMON_NA`),
+ },
+ {
+ inline: true,
+ label: t("HR_ROLE_LABEL"),
+ value: data?.Employees?.[0]?.user?.roles
+ ?.filter((ele) => ele.tenantId == element?.tenantId)
+ .map((ele) => t(`ACCESSCONTROL_ROLES_ROLES_` + ele?.code)),
+ },
+ ],
+ header: "",
+ subHeader: `${t("HR_JURISDICTION")} ${index + 1}`,
+ };
+ })
+ : []
+ }
+ />
+ );
+ },
+ },
+ ],
+ header: t("HR_JURISDICTION_DETAILS_HEADER"),
+ subHeader: "",
+ },
+
+ // campaign data
+ {
+ cardType: "primary",
+ fieldPairs: [
+ {
+ label: "",
+ value: "",
+ type: "custom",
+ inline: false,
+ renderCustomContent: (value) => {
+ return (
+ {
+ return {
+ cardType: "primary",
+ fieldPairs: [
+ {
+ inline: true,
+ label: t("HR_CAMPAIGN_LABEL"),
+ type: "text",
+ value: element?.name || t(`CORE_COMMON_NA`),
+ },
+ {
+ inline: true,
+ label: t("HR_ASMT_FROM_DATE_LABEL"),
+ type: "text",
+ value: element?.startDate ? convertEpochToDate(element?.startDate) : t(`CORE_COMMON_NA`),
+ },
+ {
+ inline: true,
+ label: t("HR_ASMT_TO_DATE_LABEL"),
+ value: element?.endDate ? convertEpochToDate(element?.endDate) : t(`CORE_COMMON_NA`),
+ },
+ ],
+ header: "",
+ subHeader: `${t("HR_ASSIGNMENT")} ${index + 1}`,
+ };
+ })
+ : []
+ }
+ />
+ );
+ },
+ },
+ ],
+ header: t("HR_ASSIGN_DET_HEADER"),
+ subHeader: "",
+ },
+
+ //end of campaign data
+ ]}
+ style={{}}
+ subHeader="Subheading"
+ type="primary"
+ />
+
+ }
+
+ {/* action bar */}
+ {
+
+ );
+};
+
+export default EmployeeDetailScreen;
diff --git a/health/micro-ui/web/micro-ui-internals/packages/modules/health-hrms/src/pages/employee/index.js b/health/micro-ui/web/micro-ui-internals/packages/modules/health-hrms/src/pages/employee/index.js
new file mode 100644
index 00000000000..1c78fa0c7d9
--- /dev/null
+++ b/health/micro-ui/web/micro-ui-internals/packages/modules/health-hrms/src/pages/employee/index.js
@@ -0,0 +1,84 @@
+import { PrivateRoute } from "@egovernments/digit-ui-react-components";
+import React, { useEffect } from "react";
+import { useTranslation } from "react-i18next";
+import { Link, Switch, useLocation } from "react-router-dom";
+import { BreadCrumbs } from "@egovernments/digit-ui-components";
+
+const EmployeeApp = ({ path }) => {
+ const { t } = useTranslation();
+ const location = useLocation();
+ const mobileView = innerWidth <= 640;
+ const tenantId = Digit.ULBService.getCurrentTenantId();
+
+ const EmployeeDetails = Digit?.ComponentRegistryService?.getComponent("EmployeeDetailScreen");
+ const Inbox = Digit?.ComponentRegistryService?.getComponent("InboxSearch");
+ const CreateEmployee = Digit?.ComponentRegistryService?.getComponent("HRCreateEmployee");
+ const AssignCampaign = Digit?.ComponentRegistryService?.getComponent("AssignCampaign");
+ const ResponseScreen = Digit?.ComponentRegistryService?.getComponent("ResponseScreen");
+
+ const BreadCrumbs = Digit?.ComponentRegistryService?.getComponent("BreadCrumbs");
+
+ return (
+