Skip to content

Commit

Permalink
register
Browse files Browse the repository at this point in the history
  • Loading branch information
suryansh-egov committed Jan 7, 2025
1 parent 1071972 commit cb810e8
Show file tree
Hide file tree
Showing 14 changed files with 897 additions and 48 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
"@egovernments/digit-ui-module-utilities": "1.0.3",
"@egovernments/digit-ui-react-components": "1.8.12",
"@egovernments/digit-ui-module-hcmworkbench": "0.1.0",
"@egovernments/digit-ui-module-campaign-manager": "0.3.0",
"@egovernments/digit-ui-module-campaign-manager": "0.4.0",
"@egovernments/digit-ui-module-microplan": "0.0.1",
"@egovernments/digit-ui-module-health-payments": "0.0.1",
"http-proxy-middleware": "^1.0.5",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,9 @@ module.exports = function (app) {
"/plan-service",
"/health-project",
"/service-request",
"/census-service"
"/census-service",
"/health-attendance",
"/health-individual"
].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));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -236,4 +236,55 @@
> div:nth-of-type(1) {
width: 69%;
}
}
}

.attendanceCell {
display: flex;
}

.chip-container {
display: flex;
align-items: center;
gap: 0.5rem; /* Adjust the spacing between chips and the button */
}

.chip-wrapper {
display: inline-flex;
}

.more-button {
margin-left: 0.5rem; /* Adjust the spacing between chips and the + button */
}

/* Container for the progress bar */
.progress-bar-container {
position: relative;
width: 20rem;
max-width: 20rem;
height: 20px;
background-color: #f3f3f3;
border-radius: 10px;
overflow: hidden;
border: 1px solid #d6d5d4;
}

/* The fill of the progress bar */
.progress-bar-fill {
height: 100%;
background-color: #2BD27F; /* Use your PRIMARY_COLOR */
transition: width 0.4s ease-in-out;
display: flex;
align-items: center;
justify-content: center;
}

/* Text inside the progress bar */
.progress-bar-text {
position: absolute;
width: 100%;
text-align: center;
font-size: 14px;
color: #fff;
font-weight: bold;
pointer-events: none;
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@egovernments/digit-ui-module-campaign-manager",
"version": "0.3.0",
"version": "0.4.0",
"description": "Campaign",
"main": "dist/index.js",
"module": "dist/index.modern.js",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,9 @@ import MapView from "./components/MapView";
import NoResultsFound from "./components/NoResultsFound";
import UploadDataMappingWrapper from "./components/UploadDataMappingWrapper";
import DataUploadWrapper from "./components/DataUploadWrapper";
import Attendance from "./pages/employee/Attendance";
import IndividualUserTable from "./components/IndividualUserTable";
import ProgressBar from "./components/ProgressBar";

/**
* MDMS Module name
Expand Down Expand Up @@ -175,6 +178,9 @@ const componentsToRegister = {
NoResultsFound,
UploadDataMappingWrapper,
DataUploadWrapper,
Attendance,
IndividualUserTable,
ProgressBar
};

const overrideHooks = () => {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,257 @@
import React, { useState, useCallback, useEffect } from 'react';
import { Card, Button, PopUp, Loader, Chip, TextInput } from "@egovernments/digit-ui-components";
import DataTable from "react-data-table-component";
import { CustomSVG } from "@egovernments/digit-ui-components";
import { tableCustomStyle } from "./tableCustomStyle";
import { useTranslation } from "react-i18next";
import ProgressBar from './ProgressBar';

const SupervisorPopup = ({ setShowPopUp, supervisors }) => {
const { t } = useTranslation();
return (
<PopUp
className="wrapper-popup-boundary-chips"
style={{ maxWidth: "40%" }}
type="default"
heading={t("SUPERVISORS_ASSIGNED")}
footerChildren={[]}
onOverlayClick={() => setShowPopUp(false)}
onClose={() => setShowPopUp(false)}
>
<div className="digit-tag-container userAccessCell"
style={{
display: "flex",
flexWrap: "wrap",
justifyContent: "flex-start",
gap: "8px"
}}>
{supervisors.map((supervisor, index) => (
<Chip
key={index}
text={supervisor}
hideClose={true}
/>
))}
</div>
</PopUp>
);
};

const IndividualUserTable = ({ tenantId, staffAttendeeIds = [], supervisorName = "" }) => {
const { t } = useTranslation();
const [totalRows, setTotalRows] = useState(0);
const [currentPage, setCurrentPage] = useState(1);
const [rowsPerPage, setRowsPerPage] = useState(5);
const [searchQuery, setSearchQuery] = useState('');
const [paginatedData, setPaginatedData] = useState([]);
const [chipPopUpRowId, setChipPopUpRowId] = useState(null);

const individualUsers = {
url: `/health-individual/v1/_search`,
params: {
tenantId: tenantId,
limit: 1000,
offset: 0
},
body: {
Individual: {},
},
};

const { isLoading, data, isFetching } = Digit.Hooks.useCustomAPIHook(individualUsers);

const getDisplayData = useCallback(() => {
if (!data?.Individual) return [];

const filteredData = data.Individual.filter(user => {
const userName = user.name?.givenName?.toLowerCase() || '';
return userName.includes(searchQuery.toLowerCase());
}).map(user => ({
...user,
isAssigned: staffAttendeeIds.includes(user.id)
}));

setTotalRows(filteredData.length);

const startIndex = (currentPage - 1) * rowsPerPage;
const endIndex = startIndex + rowsPerPage;
return filteredData.slice(startIndex, endIndex);
}, [data, searchQuery, staffAttendeeIds, currentPage, rowsPerPage]);

useEffect(() => {
if (data?.Individual) {
setPaginatedData(getDisplayData());
}
}, [data, searchQuery, currentPage, rowsPerPage, getDisplayData]);

const handlePaginationChange = (page) => {
setCurrentPage(page);
};

const handleRowsPerPageChange = (newPerPage) => {
setRowsPerPage(newPerPage);
setCurrentPage(1);
};

const handleSearchChange = (e) => {
setSearchQuery(e.target.value);
setCurrentPage(1);
};

const handleAssign = (userId) => {
//code to be written
};

const handleUnassign = (userId) => {
//code to be written
};

const columns = [
{
name: t('Name'),
selector: row => row.name?.givenName || '',
sortable: true,
},
{
name: t('Mobile Number'),
selector: row => row.mobileNumber || '',
sortable: true,
},
{
name: t("USER_TYPE"),
selector: row => row?.userDetails?.type || '',
sortable: true
},
{
name: t('Assigned Supervisor'),
selector: row => row.isAssigned ? supervisorName : t('Not Assigned'),
sortable: true,
grow: 2,
cell: row => {
const supervisors = row.isAssigned ? [supervisorName] : [];

return (
<div className="digit-tag-container">
{supervisors.length > 0 ? (
<div className="chip-container">
{supervisors.slice(0, 2).map((supervisor, index) => (
<div key={index} className="chip-wrapper">
<Chip
text={supervisor}
hideClose={true}
/>
</div>
))}

{supervisors.length > 2 && (
<Button
label={`+${supervisors.length - 2} ${t("ES_MORE")}`}
variation="link"
onClick={() => setChipPopUpRowId(row.id)}
className="more-button"
style={{
height: "2rem",
minWidth: "4.188rem",
minHeight: "2rem",
padding: "0.5rem"
}}
textStyles={{
fontSize: "0.875rem",
fontWeight: "400",
color: "#C84C0E",
}}
/>
)}

{chipPopUpRowId === row.id && (
<SupervisorPopup
setShowPopUp={setChipPopUpRowId}
supervisors={supervisors}
/>
)}
</div>
) : (
<span className="text-gray-400">{t('Not Assigned')}</span>
)}
</div>
);
},
},
{
name: t('Actions'),
cell: row => (
<div>
{row.isAssigned ? (
<Button
label={t('Unassign')}
variation="secondary"
icon="Close"
onClick={() => handleUnassign(row.id)}
/>
) : (
<Button
label={t('Assign')}
variation="primary"
icon="CheckCircle"
onClick={() => handleAssign(row.id)}
/>
)}
</div>
)
},
];

return (
<div className="w-full">
{isLoading && <Loader />}
{!isLoading && (
<div>
<Card type={"secondary"} style={{ maxWidth: "100%", overflow: "auto", marginBottom: "1rem" }}>
<div>
<div style={{ marginBottom: "0.5rem" }}>{t("USER_NAME")}</div>
<TextInput
style={{ maxWidth: "fit-content" }}
disabled={false}
className="textinput-example"
type="text"
name={t("USER_NAME")}
value={searchQuery}
onChange={handleSearchChange}
placeholder={t("SEARCH_BY_NAME")}
/>
</div>
</Card>

<DataTable
columns={columns}
data={paginatedData}
progressPending={isLoading || isFetching}
progressComponent={<Loader />}
pagination
paginationServer
customStyles={tableCustomStyle}
paginationTotalRows={totalRows}
onChangePage={handlePaginationChange}
onChangeRowsPerPage={handleRowsPerPageChange}
paginationPerPage={rowsPerPage}
sortIcon={<CustomSVG.SortUp width="16px" height="16px" fill="#0b4b66" />}
paginationRowsPerPageOptions={[5, 10, 15, 20]}
noDataComponent={<div>{t('No records found')}</div>}
/>

{/* Progress Bar Section */}
<div style={{ display: "flex", justifyContent: "space-between", alignItems: "center", marginTop: "1rem" }}>
<div style={{ display: "flex", alignItems: "center", gap: "1rem" }}>
<span style={{ fontWeight: 600 }}>{t("REGISTER_ASSIGNED_USERS")}</span>
<ProgressBar amount={40} total={100} />
<span style={{ fontWeight: 600 }}>{`${40}%`}</span>
</div>
</div>
</div>
)}
</div>
);

};

export default IndividualUserTable;
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import React from 'react';

const ProgressBar = ({ amount, total }) => {
const percentage = Math.min((amount / total) * 100, 100);

return (
<div className="progress-bar-container">
<div className="progress-bar-fill" style={{ width: `${percentage}%` }}>
<span className="progress-bar-text">{`${percentage.toFixed(1)}%`}</span>
</div>
</div>
);
};

export default ProgressBar;
Loading

0 comments on commit cb810e8

Please sign in to comment.