@djb25/digit-ui-module-ekyc 1.0.13 → 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;
@@ -0,0 +1,231 @@
1
+ import React, { useMemo } from "react";
2
+ import { useHistory, useParams } from "react-router-dom";
3
+ import { FaArrowLeft, FaUsers, FaCheckCircle, FaClock, FaExclamationTriangle, FaMapMarkedAlt } from "react-icons/fa";
4
+ import { ekycMockData } from "./mockData";
5
+ import ExecutiveLineChart from "./analytics/charts/ExecutiveLineChart";
6
+ import ExecutiveBarChart from "./analytics/charts/ExecutiveBarChart";
7
+ import ExecutivePieChart from "./analytics/charts/ExecutivePieChart";
8
+ import { Loader } from "@djb25/digit-ui-react-components";
9
+
10
+ const VendorDetails = () => {
11
+ const history = useHistory();
12
+ const { vendorId = 1 } = useParams();
13
+ const vendor = useMemo(() => ekycMockData.vendors.find((item) => item.id === Number(vendorId)), [vendorId]);
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
+
28
+ if (!vendor) {
29
+ return (
30
+ <div className="ekyc-dashboard-wrapper">
31
+ <div className="dashboard-shell">
32
+ <div className="detail-header">
33
+ <button className="back-button" onClick={() => history.goBack()}>
34
+ <FaArrowLeft /> Back
35
+ </button>
36
+ </div>
37
+ <div className="empty-state">
38
+ <h2>Vendor analytics not found</h2>
39
+ <p>The selected vendor does not exist in the current report. Please return to the dashboard.</p>
40
+ </div>
41
+ </div>
42
+ </div>
43
+ );
44
+ }
45
+
46
+ const zoneRows = vendor.zones.slice(0, 8);
47
+
48
+ const performanceData = vendor.dailyPerformance.map((row) => ({
49
+ day: row.day,
50
+ completed: row.completed,
51
+ pending: row.pending,
52
+ rejected: row.rejected,
53
+ }));
54
+
55
+ console.log(dashboardData);
56
+ if (isLoading) <Loader />;
57
+
58
+ return (
59
+ <div className="ekyc-dashboard-wrapper">
60
+ <div className="dashboard-shell detail-shell">
61
+ <section className="kpi-grid detail-kpi-grid">
62
+ {[
63
+ {
64
+ label: "Assigned Connections",
65
+ value: vendor.assignedConnections,
66
+ icon: <FaUsers />,
67
+ variant: "primary",
68
+ },
69
+ {
70
+ label: "Agency eKYC",
71
+ value: vendor.completedEkyc,
72
+ icon: <FaCheckCircle />,
73
+ variant: "success",
74
+ },
75
+ {
76
+ label: "Self eKYC",
77
+ value: vendor.selfEkyc,
78
+ icon: <FaUsers />,
79
+ variant: "info",
80
+ },
81
+ {
82
+ label: "Pending",
83
+ value: vendor.pending,
84
+ icon: <FaClock />,
85
+ variant: "warning",
86
+ },
87
+ {
88
+ label: "Rejected",
89
+ value: vendor.rejected,
90
+ icon: <FaExclamationTriangle />,
91
+ variant: "danger",
92
+ },
93
+ {
94
+ label: "Success Rate",
95
+ value: `${vendor.successRate}%`,
96
+ icon: <FaCheckCircle />,
97
+ variant: "success",
98
+ },
99
+ ].map((item) => (
100
+ <article key={item.label} className={`kpi-card card-${item.variant}`}>
101
+ <div className="kpi-icon">{item.icon}</div>
102
+ <div>
103
+ <p className="kpi-title">{item.label}</p>
104
+ <h2>{item.value?.toLocaleString?.() ?? item.value}</h2>
105
+ </div>
106
+ </article>
107
+ ))}
108
+ </section>
109
+
110
+ <section className="analytics-grid detail-analytics-grid">
111
+ <div className="analytics-panel glass-card">
112
+ <div className="section-header">
113
+ <h2>Daily Completion Trend</h2>
114
+ <span className="badge success">Performance</span>
115
+ </div>
116
+ <ExecutiveLineChart data={performanceData} dataKey="completed" name="Completed" />
117
+ </div>
118
+
119
+ <div className="analytics-panel glass-card">
120
+ <div className="section-header">
121
+ <h2>Pending vs Completed</h2>
122
+ <span className="badge warning">Workload</span>
123
+ </div>
124
+ <ExecutiveBarChart
125
+ data={performanceData}
126
+ categories={[
127
+ { key: "completed", name: "Completed" },
128
+ { key: "pending", name: "Pending" },
129
+ ]}
130
+ xKey="day"
131
+ />
132
+ </div>
133
+
134
+ <div className="analytics-panel glass-card">
135
+ <div className="section-header">
136
+ <h2>Self vs Agency Split</h2>
137
+ <span className="badge info">Adoption</span>
138
+ </div>
139
+ <ExecutivePieChart
140
+ data={[
141
+ { label: "Agency eKYC", value: vendor.completedEkyc },
142
+ { label: "Citizen Self eKYC", value: vendor.selfEkyc },
143
+ ]}
144
+ dataKey="value"
145
+ labelKey="label"
146
+ />
147
+ </div>
148
+ </section>
149
+
150
+ <section className="zone-section detail-zone-section">
151
+ <div className="section-header">
152
+ <div>
153
+ <h2>
154
+ <FaMapMarkedAlt /> Zone-wise Jurisdiction Analytics
155
+ </h2>
156
+ <p>Drill into the current operational load and heatmap intensity for this vendor.</p>
157
+ </div>
158
+ </div>
159
+ <div className="table-wrapper glass-card">
160
+ <table>
161
+ <thead>
162
+ <tr>
163
+ <th>Zone</th>
164
+ <th>Cluster</th>
165
+ <th>Assigned</th>
166
+ <th>Agency eKYC</th>
167
+ <th>Pending</th>
168
+ <th>Activity Score</th>
169
+ </tr>
170
+ </thead>
171
+ <tbody>
172
+ {zoneRows.map((row, index) => (
173
+ <tr key={`${row.location}-${index}`}>
174
+ <td>{row.location}</td>
175
+ <td>{row.cluster || row.district}</td>
176
+ <td>{row.activeDemand?.toLocaleString() ?? "—"}</td>
177
+ <td>{row.pppZones?.toLocaleString() ?? "—"}</td>
178
+ <td>{row.inactiveDemand?.toLocaleString() ?? "—"}</td>
179
+ <td>
180
+ <span className={`status-badge ${row.intensityScore > 65 ? "danger" : row.intensityScore > 45 ? "warning" : "success"}`}>
181
+ {row.intensityScore}%
182
+ </span>
183
+ </td>
184
+ </tr>
185
+ ))}
186
+ </tbody>
187
+ </table>
188
+ </div>
189
+ </section>
190
+
191
+ <section className="bottom-grid detail-bottom-grid">
192
+ <div className="cards-summary glass-card">
193
+ <h2>Operational Efficiency</h2>
194
+ <div className="efficiency-grid">
195
+ <div className="efficiency-box">
196
+ <h3>{vendor.activeSurveyors}</h3>
197
+ <p>Active Surveyors</p>
198
+ </div>
199
+ <div className="efficiency-box">
200
+ <h3>{vendor.supervisors}</h3>
201
+ <p>Supervisors</p>
202
+ </div>
203
+ <div className="efficiency-box">
204
+ <h3>{vendor.progress}%</h3>
205
+ <p>Execution Rate</p>
206
+ </div>
207
+ <div className="efficiency-box">
208
+ <h3>{vendor.dailyPerformance.slice(-1)[0]?.completed?.toLocaleString()}</h3>
209
+ <p>Latest Day Completed</p>
210
+ </div>
211
+ </div>
212
+ </div>
213
+
214
+ <div className="cards-summary glass-card">
215
+ <h2>Supervisor Pulse</h2>
216
+ <div className="pulse-list">
217
+ {vendor.jurisdictions.map((zone) => (
218
+ <div key={zone} className="pulse-row">
219
+ <span>{zone}</span>
220
+ <span>{Math.max(12, Math.round(Math.random() * 38))} active</span>
221
+ </div>
222
+ ))}
223
+ </div>
224
+ </div>
225
+ </section>
226
+ </div>
227
+ </div>
228
+ );
229
+ };
230
+
231
+ export default VendorDetails;
@@ -0,0 +1,30 @@
1
+ import React from "react";
2
+ import { ResponsiveContainer, BarChart, Bar, XAxis, YAxis, Tooltip, CartesianGrid, Legend } from "recharts";
3
+
4
+ const ExecutiveBarChart = ({ data = [], categories = [], xKey = "label" }) => {
5
+ return (
6
+ <div className="chart-card" style={{ minHeight: 320 }}>
7
+ <ResponsiveContainer width="100%" height={320}>
8
+ <BarChart data={data} margin={{ top: 12, right: 16, left: 0, bottom: 0 }}>
9
+ <CartesianGrid stroke="rgba(148, 163, 184, 0.12)" strokeDasharray="4 4" />
10
+ <XAxis dataKey={xKey} axisLine={false} tickLine={false} tick={{ fill: "#cbd5e1" }} />
11
+ <YAxis axisLine={false} tickLine={false} tick={{ fill: "#cbd5e1" }} />
12
+ <Tooltip contentStyle={{ background: "#0f172a", border: "none", borderRadius: 14 }} itemStyle={{ color: "#f8fafc" }} />
13
+ <Legend verticalAlign="top" align="right" iconType="circle" wrapperStyle={{ color: "#cbd5e1" }} />
14
+ {categories.map((series, index) => (
15
+ <Bar
16
+ key={series.key}
17
+ dataKey={series.key}
18
+ name={series.name}
19
+ fill={index === 0 ? "#34d399" : "#60a5fa"}
20
+ radius={[12, 12, 0, 0]}
21
+ barSize={24}
22
+ />
23
+ ))}
24
+ </BarChart>
25
+ </ResponsiveContainer>
26
+ </div>
27
+ );
28
+ };
29
+
30
+ export default ExecutiveBarChart;
@@ -0,0 +1,159 @@
1
+ // import React from "react";
2
+ // import { ResponsiveContainer, LineChart, Line, XAxis, YAxis, Tooltip, CartesianGrid, Legend } from "recharts";
3
+
4
+ // const ExecutiveLineChart = ({ data = [], dataKey = "completed", name = "Value" }) => {
5
+ // return (
6
+ // <div className="chart-card" style={{ minHeight: 320 }}>
7
+ // <ResponsiveContainer width="100%" height={320}>
8
+ // <LineChart data={data} margin={{ top: 12, right: 16, left: 0, bottom: 0 }}>
9
+ // <CartesianGrid stroke="rgba(148, 163, 184, 0.12)" strokeDasharray="4 4" />
10
+ // <XAxis dataKey="label" axisLine={false} tickLine={false} tick={{ fill: "#cbd5e1" }} />
11
+ // <YAxis axisLine={false} tickLine={false} tick={{ fill: "#cbd5e1" }} />
12
+ // <Tooltip contentStyle={{ background: "#0f172a", border: "none", borderRadius: 14, color: "#f8fafc" }} itemStyle={{ color: "#f8fafc" }} />
13
+ // <Legend verticalAlign="top" align="right" iconType="circle" wrapperStyle={{ color: "#cbd5e1" }} />
14
+ // <Line
15
+ // type="monotone"
16
+ // dataKey={dataKey}
17
+ // name={name}
18
+ // stroke="#38bdf8"
19
+ // strokeWidth={3}
20
+ // dot={{ r: 4 }}
21
+ // activeDot={{ r: 6, strokeWidth: 2, fill: "#60a5fa" }}
22
+ // />
23
+ // </LineChart>
24
+ // </ResponsiveContainer>
25
+ // </div>
26
+ // );
27
+ // };
28
+
29
+ // export default ExecutiveLineChart;
30
+
31
+ import React from "react";
32
+ import { ResponsiveContainer, LineChart, Line, XAxis, YAxis, Tooltip, CartesianGrid, Legend } from "recharts";
33
+
34
+ const ExecutiveLineChart = ({ data = [] }) => {
35
+ const formattedData = data.map((item) => ({
36
+ ...item,
37
+
38
+ agencyKyc: item.completed || 0,
39
+
40
+ selfKyc: Math.round((item.completed || 0) * 0.42),
41
+
42
+ totalKyc: (item.completed || 0) + Math.round((item.completed || 0) * 0.42),
43
+ }));
44
+
45
+ return (
46
+ <div className="chart-card executive-line-chart">
47
+ <ResponsiveContainer width="100%" height={340}>
48
+ <LineChart
49
+ data={formattedData}
50
+ margin={{
51
+ top: 20,
52
+ right: 12,
53
+ left: 0,
54
+ bottom: 0,
55
+ }}
56
+ >
57
+ <CartesianGrid stroke="#e2e8f0" strokeDasharray="3 3" vertical={false} />
58
+
59
+ <XAxis
60
+ dataKey="label"
61
+ axisLine={false}
62
+ tickLine={false}
63
+ tick={{
64
+ fill: "#64748b",
65
+ fontSize: 12,
66
+ fontWeight: 600,
67
+ }}
68
+ />
69
+
70
+ <YAxis
71
+ axisLine={false}
72
+ tickLine={false}
73
+ tick={{
74
+ fill: "#64748b",
75
+ fontSize: 12,
76
+ }}
77
+ />
78
+
79
+ <Tooltip
80
+ cursor={{
81
+ stroke: "#cbd5e1",
82
+ strokeWidth: 1,
83
+ }}
84
+ contentStyle={{
85
+ background: "#ffffff",
86
+ border: "1px solid #e2e8f0",
87
+ borderRadius: 18,
88
+ boxShadow: "0 10px 30px rgba(15,23,42,0.08)",
89
+ }}
90
+ labelStyle={{
91
+ color: "#0f172a",
92
+ fontWeight: 700,
93
+ marginBottom: 10,
94
+ }}
95
+ />
96
+
97
+ <Legend
98
+ verticalAlign="top"
99
+ align="right"
100
+ iconType="circle"
101
+ wrapperStyle={{
102
+ paddingBottom: 18,
103
+ color: "#475569",
104
+ fontWeight: 600,
105
+ }}
106
+ />
107
+
108
+ {/* TOTAL */}
109
+
110
+ <Line
111
+ type="monotone"
112
+ dataKey="totalKyc"
113
+ name="Total eKYC"
114
+ stroke="#0f172a"
115
+ strokeWidth={4}
116
+ dot={false}
117
+ activeDot={{
118
+ r: 6,
119
+ }}
120
+ />
121
+
122
+ {/* AGENCY */}
123
+
124
+ <Line
125
+ type="monotone"
126
+ dataKey="agencyKyc"
127
+ name="Agency eKYC"
128
+ stroke="#3b82f6"
129
+ strokeWidth={3}
130
+ dot={{
131
+ r: 3,
132
+ }}
133
+ activeDot={{
134
+ r: 6,
135
+ }}
136
+ />
137
+
138
+ {/* SELF */}
139
+
140
+ <Line
141
+ type="monotone"
142
+ dataKey="selfKyc"
143
+ name="Self eKYC"
144
+ stroke="#10b981"
145
+ strokeWidth={3}
146
+ dot={{
147
+ r: 3,
148
+ }}
149
+ activeDot={{
150
+ r: 6,
151
+ }}
152
+ />
153
+ </LineChart>
154
+ </ResponsiveContainer>
155
+ </div>
156
+ );
157
+ };
158
+
159
+ export default ExecutiveLineChart;