@djb25/digit-ui-module-ekyc 1.0.14 → 1.0.15

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,282 @@
1
+ import React, { useMemo, useState } from "react";
2
+ import { ResponsiveContainer, BarChart, Bar, XAxis, YAxis, Tooltip, CartesianGrid, PieChart, Pie, Cell, Legend } from "recharts";
3
+
4
+ import { Card, SubmitBar, ActionBar, Menu, Loader, Table } from "@djb25/digit-ui-react-components";
5
+
6
+ import { useTranslation } from "react-i18next";
7
+ import { useParams } from "react-router-dom";
8
+
9
+ import AssignEkycModal from "./AssignEkycModal";
10
+
11
+ const SurveyorDetailsDashboard = () => {
12
+ const tenantId = Digit.ULBService.getCurrentTenantId();
13
+
14
+ const [showModal, setShowModal] = useState(false);
15
+ const [showOptions, setShowOptions] = useState(false);
16
+
17
+ const { id: surveyorId } = useParams();
18
+ const ownerIds = Digit.SessionStorage.get("User")?.info?.uuid;
19
+
20
+ const { t } = useTranslation();
21
+
22
+ const searchParams = surveyorId ? { ids: surveyorId } : { ownerIds };
23
+
24
+ const { data: surveyorSearchResponse, isLoading } = Digit.Hooks.fsm.useSurveyorSearch(tenantId, searchParams, { staleTime: Infinity });
25
+
26
+ const roles = Digit.SessionStorage.get("User")?.info?.roles.map((ele) => ele.code);
27
+
28
+ const surveyor = useMemo(() => {
29
+ return surveyorSearchResponse?.surveyors?.[0] || null;
30
+ }, [surveyorSearchResponse]);
31
+
32
+ const knoColumns = React.useMemo(
33
+ () => [
34
+ {
35
+ Header: t("KNO"),
36
+ accessor: "kno",
37
+ },
38
+ {
39
+ Header: t("CONSUMER_NAME"),
40
+ accessor: "consumerName",
41
+ },
42
+ {
43
+ Header: t("MOBILE_NO"),
44
+ accessor: "mobileNumber",
45
+ },
46
+ {
47
+ Header: t("STATUS"),
48
+ accessor: "status",
49
+ Cell: ({ value }) => <span className={`status-badge ${value?.toLowerCase() || ""}`}>{value}</span>,
50
+ },
51
+ {
52
+ Header: t("ASSIGNED_DATE"),
53
+ accessor: "assignedDate",
54
+ },
55
+ {
56
+ Header: t("COMPLETED_DATE"),
57
+ accessor: "completedDate",
58
+ },
59
+ ],
60
+ [t]
61
+ );
62
+
63
+ if (isLoading) {
64
+ return <Loader />;
65
+ }
66
+
67
+ if (!surveyor) {
68
+ return (
69
+ <Card>
70
+ <div style={{ padding: "24px" }}>{t("NO_SURVEYOR_FOUND")}</div>
71
+ </Card>
72
+ );
73
+ }
74
+ const assignedKnos = [
75
+ {
76
+ kno: "123456789",
77
+ consumerName: "Rahul Sharma",
78
+ mobileNumber: "9876543210",
79
+ status: "Completed",
80
+ assignedDate: "01-06-2026",
81
+ completedDate: "02-06-2026",
82
+ },
83
+ {
84
+ kno: "123456790",
85
+ consumerName: "Amit Kumar",
86
+ mobileNumber: "9876543211",
87
+ status: "Pending",
88
+ assignedDate: "03-06-2026",
89
+ completedDate: "-",
90
+ },
91
+ ];
92
+
93
+ const weeklyData = [
94
+ { day: "Mon", completed: 4 },
95
+ { day: "Tue", completed: 6 },
96
+ { day: "Wed", completed: 3 },
97
+ { day: "Thu", completed: 8 },
98
+ { day: "Fri", completed: 5 },
99
+ { day: "Sat", completed: 7 },
100
+ { day: "Sun", completed: 2 },
101
+ ];
102
+
103
+ const statusData = [
104
+ {
105
+ name: "Completed",
106
+ value: surveyor?.completedCases || 0,
107
+ color: "#10B981",
108
+ },
109
+ {
110
+ name: "Pending",
111
+ value: surveyor?.pendingCases || 0,
112
+ color: "#F59E0B",
113
+ },
114
+ {
115
+ name: "Rejected",
116
+ value: surveyor?.rejectedCases || 0,
117
+ color: "#EF4444",
118
+ },
119
+ ];
120
+
121
+ const StatCard = ({ title, value, type }) => (
122
+ <div className={`stat-card ${type}`}>
123
+ <div className="stat-title">{title}</div>
124
+
125
+ <div className="stat-value">{value}</div>
126
+ </div>
127
+ );
128
+
129
+ const options = [{ action: "Assign" }];
130
+
131
+ const fullName = surveyor?.owner?.name || surveyor?.name || "N/A";
132
+
133
+ const employeeId = surveyor?.employeeId || surveyor?.owner?.uuid || surveyor?.id;
134
+
135
+ const handleMenuSelect = (option) => {
136
+ setShowOptions(false); // close menu
137
+ setShowModal(true);
138
+ };
139
+
140
+ return (
141
+ <Card className="surveyor-dashboard">
142
+ {/* Header */}
143
+ <div className="ekyc-dashboard-section">
144
+ <div className="ekyc-dashboard-header">
145
+ <div className="avatar">{fullName?.charAt(0)?.toUpperCase()}</div>
146
+
147
+ <div className="header-content">
148
+ <h2 className="name">{fullName}</h2>
149
+
150
+ <div className="designation">{surveyor?.description || t("FIELD_SURVEYOR")}</div>
151
+
152
+ <div className="employee-id">
153
+ {t("EMPLOYEE_ID")}: {employeeId}
154
+ </div>
155
+ </div>
156
+ </div>
157
+ </div>
158
+
159
+ {/* Stats */}
160
+ <div className="stats-wrapper">
161
+ <StatCard title={t("TODAYS_EKYC")} value={surveyor?.todayCompleted || 0} type="today" />
162
+
163
+ <StatCard title={t("THIS_WEEK")} value={surveyor?.weekCompleted || 0} type="week" />
164
+
165
+ <StatCard title={t("THIS_MONTH")} value={surveyor?.monthCompleted || 0} type="month" />
166
+
167
+ <StatCard title={t("PENDING_CASES")} value={surveyor?.pendingCases || 0} type="pending" />
168
+ </div>
169
+
170
+ {/* Charts */}
171
+ <div className="charts-wrapper">
172
+ {/* Weekly Chart */}
173
+ <div className="chart-card">
174
+ <h3 className="chart-title">{t("WEEKLY_SURVEY_PROGRESS")}</h3>
175
+
176
+ <ResponsiveContainer width="100%" height={300}>
177
+ <BarChart data={weeklyData}>
178
+ <CartesianGrid strokeDasharray="3 3" />
179
+
180
+ <XAxis dataKey="day" />
181
+
182
+ <YAxis />
183
+
184
+ <Tooltip />
185
+
186
+ <Bar dataKey="completed" fill="#0B2559" radius={[6, 6, 0, 0]} />
187
+ </BarChart>
188
+ </ResponsiveContainer>
189
+ </div>
190
+
191
+ {/* Pie Chart */}
192
+ <div className="chart-card">
193
+ <h3 className="chart-title">{t("CASE_DISTRIBUTION")}</h3>
194
+
195
+ <ResponsiveContainer width="100%" height={300}>
196
+ <PieChart>
197
+ <Pie data={statusData} dataKey="value" nameKey="name" outerRadius={90} label>
198
+ {statusData.map((entry, index) => (
199
+ <Cell key={index} fill={entry.color} />
200
+ ))}
201
+ </Pie>
202
+
203
+ <Tooltip />
204
+
205
+ <Legend />
206
+ </PieChart>
207
+ </ResponsiveContainer>
208
+ </div>
209
+ </div>
210
+
211
+ {/* Details */}
212
+ <div className="ekyc-dashboard-section">
213
+ <div className="details-grid">
214
+ <div className="detail-item">
215
+ <span className="label">{t("MOBILE")}:</span>
216
+ <span className="value">{surveyor?.owner?.mobileNumber || surveyor?.mobileNo || "N/A"}</span>
217
+ </div>
218
+
219
+ <div className="detail-item">
220
+ <span className="label">{t("EMAIL")}:</span>
221
+ <span className="value">{surveyor?.owner?.emailId || "N/A"}</span>
222
+ </div>
223
+
224
+ <div className="detail-item">
225
+ <span className="label">{t("GENDER")}:</span>
226
+ <span className="value">{surveyor?.owner?.gender || "N/A"}</span>
227
+ </div>
228
+
229
+ <div className="detail-item">
230
+ <span className="label">{t("STATUS")}:</span>
231
+ <span className="value">{surveyor?.status || "N/A"}</span>
232
+ </div>
233
+
234
+ <div className="detail-item">
235
+ <span className="label">{t("SERVICE_TYPE")}:</span>
236
+ <span className="value">{surveyor?.additionalDetails?.serviceType || "N/A"}</span>
237
+ </div>
238
+
239
+ <div className="detail-item">
240
+ <span className="label">{t("VENDOR_ID")}:</span>
241
+ <span className="value">{surveyor?.vendorId || "N/A"}</span>
242
+ </div>
243
+ </div>
244
+ </div>
245
+
246
+ <Table
247
+ t={t}
248
+ tableTitle={t("ASSIGNED_KNOS")}
249
+ data={assignedKnos}
250
+ columns={knoColumns}
251
+ totalRecords={assignedKnos?.length}
252
+ isPaginationRequired={true}
253
+ pageSizeLimit={10}
254
+ manualPagination={false}
255
+ />
256
+
257
+ {/* Actions */}
258
+ {(!roles.includes("EKYC_SURVEYOR") || roles.includes("EMPLOYEE")) && (
259
+ <ActionBar>
260
+ <SubmitBar label={t("EKYC_ASSIGN_KNOS")} onSubmit={() => setShowOptions((prev) => !prev)} />
261
+
262
+ {showOptions && (
263
+ <Menu
264
+ options={options}
265
+ optionKey={"action"}
266
+ t={t}
267
+ onSelect={handleMenuSelect}
268
+ style={{
269
+ color: "#FFFFFF",
270
+ fontSize: "18px",
271
+ }}
272
+ />
273
+ )}
274
+ </ActionBar>
275
+ )}
276
+
277
+ {showModal && <AssignEkycModal surveyor={surveyor} closeModal={() => setShowModal(false)} />}
278
+ </Card>
279
+ );
280
+ };
281
+
282
+ export default SurveyorDetailsDashboard;
@@ -5,12 +5,26 @@ import { ekycMockData } from "./mockData";
5
5
  import ExecutiveLineChart from "./analytics/charts/ExecutiveLineChart";
6
6
  import ExecutiveBarChart from "./analytics/charts/ExecutiveBarChart";
7
7
  import ExecutivePieChart from "./analytics/charts/ExecutivePieChart";
8
+ import { Loader } from "@djb25/digit-ui-react-components";
8
9
 
9
10
  const VendorDetails = () => {
10
11
  const history = useHistory();
11
- const { vendorId } = useParams();
12
+ const { vendorId = 1 } = useParams();
12
13
  const vendor = useMemo(() => ekycMockData.vendors.find((item) => item.id === Number(vendorId)), [vendorId]);
13
14
 
15
+ const tenantId = Digit.ULBService.getCurrentTenantId();
16
+ const { isLoading, data: dashboardData } = Digit.Hooks.ekyc.useEkycSurveyorDashboard(
17
+ {},
18
+ {
19
+ tenantId,
20
+ offset: 0,
21
+ limit: 10,
22
+ },
23
+ {
24
+ enabled: !!tenantId,
25
+ }
26
+ );
27
+
14
28
  if (!vendor) {
15
29
  return (
16
30
  <div className="ekyc-dashboard-wrapper">
@@ -38,6 +52,9 @@ const VendorDetails = () => {
38
52
  rejected: row.rejected,
39
53
  }));
40
54
 
55
+ console.log(dashboardData);
56
+ if (isLoading) <Loader />;
57
+
41
58
  return (
42
59
  <div className="ekyc-dashboard-wrapper">
43
60
  <div className="dashboard-shell detail-shell">
@@ -0,0 +1,138 @@
1
+ import React from "react";
2
+ import { useHistory } from "react-router-dom";
3
+ import { useTranslation } from "react-i18next";
4
+
5
+ const SupervisorInboxTableConfig = ({
6
+ onPageSizeChange,
7
+ formState,
8
+ totalCount,
9
+ table,
10
+ dispatch,
11
+ checkPathName,
12
+ onSortingByData,
13
+ inboxStyles = {},
14
+ tableStyle = {},
15
+ }) => {
16
+ const { t } = useTranslation();
17
+ const history = useHistory();
18
+
19
+ const userType = Digit.SessionStorage.get("User")?.info?.type?.toLowerCase() || "citizen";
20
+
21
+ const handleReview = (id) => {
22
+ history.push(`/digit-ui/${userType}/ekyc/assign/surveyor-details/${id}`);
23
+ };
24
+
25
+ const limit = formState?.tableForm?.limit || 10;
26
+ const offset = formState?.tableForm?.offset || 0;
27
+
28
+ const tableColumnConfig = [
29
+ {
30
+ Header: t("SURVEYOR_ID"),
31
+ accessor: "id",
32
+ Cell: ({ row }) => {
33
+ const id = row.original?.id;
34
+ return (
35
+ <span
36
+ className="ekyc-application-link"
37
+ style={{ color: "#add8f7", cursor: "pointer", fontWeight: "bold" }}
38
+ onClick={() => handleReview(id)}
39
+ >
40
+ {id || "NA"}
41
+ </span>
42
+ );
43
+ },
44
+ },
45
+
46
+ {
47
+ Header: t("SURVEYOR_NAME"),
48
+ accessor: "surveyorName",
49
+ Cell: ({ row }) => <span>{row.original?.surveyorName || row.original?.name || "NA"}</span>,
50
+ },
51
+
52
+ {
53
+ Header: t("MOBILE_NUMBER"),
54
+ accessor: "mobileNo",
55
+ Cell: ({ row }) => <span>{row.original?.mobileNo || row.original?.owner?.mobileNumber || "NA"}</span>,
56
+ },
57
+
58
+ {
59
+ Header: t("STATUS"),
60
+ accessor: "status",
61
+ Cell: ({ row }) => {
62
+ const status = row.original?.status || "DEFAULT";
63
+ return <span className={`ekyc-status-tag ${status}`}>{t(status)}</span>;
64
+ },
65
+ },
66
+
67
+ {
68
+ Header: t("SERVICE_TYPE"),
69
+ accessor: "serviceType",
70
+ Cell: ({ row }) => <span>{row.original?.serviceType || "NA"}</span>,
71
+ },
72
+ ];
73
+
74
+ return {
75
+ getCellProps: () => ({
76
+ style: {
77
+ padding: "8px",
78
+ fontSize: "12px",
79
+ },
80
+ }),
81
+
82
+ disableSort: false,
83
+ autoSort: false,
84
+ manualPagination: true,
85
+
86
+ currentPage: Math.floor(offset / limit),
87
+
88
+ onPageSizeChange,
89
+
90
+ onNextPage: () =>
91
+ dispatch({
92
+ action: "mutateTableForm",
93
+ data: {
94
+ ...formState.tableForm,
95
+ offset: Number(offset) + Number(limit),
96
+ },
97
+ checkPathName,
98
+ }),
99
+
100
+ onPrevPage: () =>
101
+ dispatch({
102
+ action: "mutateTableForm",
103
+ data: {
104
+ ...formState.tableForm,
105
+ offset: Number(offset) - Number(limit),
106
+ },
107
+ checkPathName,
108
+ }),
109
+
110
+ onLastPage: () =>
111
+ dispatch({
112
+ action: "mutateTableForm",
113
+ data: {
114
+ ...formState.tableForm,
115
+ offset: Math.ceil(totalCount / limit) * limit - Number(limit),
116
+ },
117
+ checkPathName,
118
+ }),
119
+
120
+ onFirstPage: () =>
121
+ dispatch({
122
+ action: "mutateTableForm",
123
+ data: { ...formState.tableForm, offset: 0 },
124
+ checkPathName,
125
+ }),
126
+
127
+ totalRecords: totalCount,
128
+ onSort: onSortingByData,
129
+
130
+ data: table,
131
+ columns: tableColumnConfig,
132
+
133
+ inboxStyles: { ...inboxStyles },
134
+ tableStyle: { ...tableStyle },
135
+ };
136
+ };
137
+
138
+ export default SupervisorInboxTableConfig;
@@ -26,10 +26,11 @@ const useInboxTableConfig = ({
26
26
 
27
27
  const limit = formState?.tableForm?.limit || 10;
28
28
  const offset = formState?.tableForm?.offset || 0;
29
+ const userType = Digit.SessionStorage.get("User")?.info?.type?.toLowerCase() || "citizen";
29
30
 
30
31
  React.useEffect(() => {
31
32
  if (reviewData) {
32
- history.push("/digit-ui/employee/ekyc/review", { kNumber: selectedKno, aadhaarData: reviewData?.aadhaarData, reviewData });
33
+ history.push(`/digit-ui/${userType}/ekyc/review/${selectedKno}`, { aadhaarData: reviewData?.aadhaarData, reviewData });
33
34
  }
34
35
  // eslint-disable-next-line react-hooks/exhaustive-deps
35
36
  }, [reviewData]);
@@ -70,8 +71,8 @@ const useInboxTableConfig = ({
70
71
  accessor: "ekycStatus",
71
72
  Cell: ({ row }) => {
72
73
  const ekycStatus = row.original?.ekycstatus || "NA";
73
- return <span className={`ekyc-status-tag ${ekycStatus}`}>{t(`${ekycStatus}`)}</span>
74
- }
74
+ return <span className={`ekyc-status-tag ${ekycStatus}`}>{t(`${ekycStatus}`)}</span>;
75
+ },
75
76
  },
76
77
  {
77
78
  Header: t("EKYC_REVIEW"),
@@ -12,7 +12,20 @@ const Home = () => {
12
12
  link: `/digit-ui/citizen/ekyc/dashboard`,
13
13
  },
14
14
  ],
15
- links: [
15
+ links: [],
16
+ };
17
+ const citizenInfo = Digit.SessionStorage.get("User")?.info?.roles;
18
+ const roles = citizenInfo.map((ele) => ele.code);
19
+
20
+ if (roles.includes("EKYC_SURVEYOR")) {
21
+ propsForModuleCard.links.push({
22
+ label: t("SURVEYOR_DASHBOARD"),
23
+ link: `/digit-ui/citizen/ekyc/surveyor-dashboard`,
24
+ });
25
+ }
26
+
27
+ if (roles.includes("EKYC_SUPERVISOR") || roles.includes("EKYC_VENDOR")) {
28
+ propsForModuleCard.links.push(
16
29
  {
17
30
  label: t("EKYC_DASHBOARD"),
18
31
  link: `/digit-ui/citizen/ekyc/dashboard`,
@@ -21,20 +34,20 @@ const Home = () => {
21
34
  label: t("EKYC_INBOX"),
22
35
  link: `/digit-ui/citizen/ekyc/inbox`,
23
36
  },
24
- // {
25
- // label: t("EKYC_CREATE_KYC"),
26
- // link: `/digit-ui/citizen/ekyc/create-kyc`
27
- // },
28
- // {
29
- // label: t("EKYC_UPDATE_KYC"),
30
- // link: `/digit-ui/citizen/ekyc/update-kyc`
31
- // },
32
37
  {
33
- label: t("EKYC_MAPPING"),
34
- link: `/digit-ui/citizen/ekyc/mapping`,
35
- },
36
- ],
37
- };
38
+ label: t("EKYC_ASSIGN"),
39
+ link: `/digit-ui/citizen/ekyc/assign`,
40
+ }
41
+ );
42
+ }
43
+
44
+ if (roles.length === 1 && roles.includes("CITIZEN")) {
45
+ propsForModuleCard.links.push({
46
+ label: t("EKYC_STATUS"),
47
+ link: `/digit-ui/citizen/ekyc/:id`,
48
+ });
49
+ }
50
+
38
51
  return <ModuleLinksView links={propsForModuleCard.links} />;
39
52
  };
40
53
 
@@ -10,6 +10,9 @@ import Home from "./Home";
10
10
  import Dashboard from "../../components/Dashboard";
11
11
  import Inbox from "./Inbox";
12
12
  import AddressDetails from "../../components/AddressDetails";
13
+ import AssignEkyc from "../../components/AssignEkyc";
14
+ import SurveyorDetailsCard from "../../components/SurveyorDetailsCard";
15
+ import VendorDetails from "../../components/VendorDetails";
13
16
 
14
17
  const CitizenApp = () => {
15
18
  const { t } = useTranslation();
@@ -31,6 +34,8 @@ const CitizenApp = () => {
31
34
 
32
35
  const breadcrumbs = [{ icon: HomeIcon, path: "/digit-ui/citizen" }, { label: t(getBreadcrumbLabel()) }];
33
36
 
37
+ const roles = Digit.SessionStorage.get("User")?.info?.roles.map((ele) => ele.code);
38
+ const isEkyAction = (!roles.includes("EKYC_SURVEYOR") || roles.includes("EMPLOYEE"))
34
39
  return (
35
40
  <React.Fragment>
36
41
  <div className="ground-container form-container">
@@ -59,7 +64,7 @@ const CitizenApp = () => {
59
64
  path={`${path}/dashboard`}
60
65
  component={() => (
61
66
  <LayoutWrapper layoutClass="normal">
62
- <Dashboard />
67
+ <VendorDetails />
63
68
  </LayoutWrapper>
64
69
  )}
65
70
  />
@@ -116,6 +121,48 @@ const CitizenApp = () => {
116
121
  </LayoutWrapper>
117
122
  )}
118
123
  />
124
+ <PrivateRoute
125
+ path={`${path}/assign`}
126
+ exact
127
+ component={() => (
128
+ <LayoutWrapper layoutClass="normal">
129
+ <AssignEkyc />
130
+ </LayoutWrapper>
131
+ )}
132
+ />
133
+ <PrivateRoute
134
+ path={`${path}/assign/surveyor-details/:id`}
135
+ exact
136
+ component={() => (
137
+ <LayoutWrapper layoutClass="action">
138
+ <SurveyorDetailsCard />
139
+ </LayoutWrapper>
140
+ )}
141
+ />
142
+ <PrivateRoute
143
+ path={`${path}/surveyor-dashboard/:id`}
144
+ component={() => (
145
+ <LayoutWrapper layoutClass="normal">
146
+ <SurveyorDetailsCard />
147
+ </LayoutWrapper>
148
+ )}
149
+ />
150
+ <PrivateRoute
151
+ path={`${path}/surveyor-dashboard`}
152
+ component={() => (
153
+ <LayoutWrapper layoutClass="normal">
154
+ <SurveyorDetailsCard />
155
+ </LayoutWrapper>
156
+ )}
157
+ />
158
+ <PrivateRoute
159
+ path={`${path}/status/:applicationId`}
160
+ component={() => (
161
+ <LayoutWrapper layoutClass="normal">
162
+ <Review />
163
+ </LayoutWrapper>
164
+ )}
165
+ />
119
166
  </Switch>
120
167
  </div>
121
168
  </React.Fragment>