@djb25/digit-ui-module-ekyc 1.0.7 → 1.0.8
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.
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/index.modern.js +1307 -592
- package/dist/index.modern.js.map +1 -1
- package/package.json +1 -1
- package/src/Module.js +17 -1
- package/src/components/ConnectionDetailsView.js +180 -59
- package/src/components/DesktopInbox.js +70 -72
- package/src/components/EKYCCard.js +4 -0
- package/src/components/SearchConsumer.js +104 -94
- package/src/components/StatusCards.js +93 -115
- package/src/pages/citizen/index.js +90 -0
- package/src/pages/employee/AadhaarVerification.js +3 -3
- package/src/pages/employee/AddressDetails.js +3 -2
- package/src/pages/employee/Create.js +19 -21
- package/src/pages/employee/Mapping.js +11 -0
- package/src/pages/employee/MeterDetails.js +486 -0
- package/src/pages/employee/PropertyInfo.js +10 -9
- package/src/pages/employee/Review.js +63 -7
- package/src/pages/employee/index.js +14 -1
|
@@ -1,7 +1,6 @@
|
|
|
1
|
-
import React, { useState
|
|
2
|
-
import { TextInput, Card,
|
|
1
|
+
import React, { useState } from "react";
|
|
2
|
+
import { TextInput, Card, HomeIcon } from "@djb25/digit-ui-react-components";
|
|
3
3
|
import { useTranslation } from "react-i18next";
|
|
4
|
-
import StatusCards from "./StatusCards";
|
|
5
4
|
|
|
6
5
|
const SearchConsumer = ({ onSearch, searchParams, FilterComponent, children, ...props }) => {
|
|
7
6
|
const { t } = useTranslation();
|
|
@@ -23,110 +22,121 @@ const SearchConsumer = ({ onSearch, searchParams, FilterComponent, children, ...
|
|
|
23
22
|
};
|
|
24
23
|
|
|
25
24
|
return (
|
|
26
|
-
<div className="
|
|
27
|
-
<div className="
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
className="sidebar-title-card"
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
<
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
<div>
|
|
40
|
-
{FilterComponent && (
|
|
41
|
-
<FilterComponent
|
|
42
|
-
defaultSearchParams={props.defaultSearchParams}
|
|
43
|
-
onFilterChange={props.onSearch}
|
|
44
|
-
searchParams={searchParams}
|
|
45
|
-
type="desktop"
|
|
46
|
-
moduleCode="EKYC"
|
|
47
|
-
/>
|
|
48
|
-
)}
|
|
25
|
+
<div className="ekyc-employee-container">
|
|
26
|
+
<div className="search-consumer-wrapper">
|
|
27
|
+
<div className="header-wrapper">
|
|
28
|
+
{/* Sidebar Title Card — flush top, full width */}
|
|
29
|
+
<Card className="sidebar-title-card">
|
|
30
|
+
<div className="icon-container">
|
|
31
|
+
<HomeIcon />
|
|
32
|
+
</div>
|
|
33
|
+
<div className="title-text">
|
|
34
|
+
{t("EKYC_SEARCH_CONSUMER_HEADER")}
|
|
35
|
+
</div>
|
|
36
|
+
</Card>
|
|
49
37
|
</div>
|
|
50
|
-
</div>
|
|
51
38
|
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
<div className="filter-label" style={{ fontWeight: "600", marginBottom: "8px", fontSize: "14px", color: "#505A5F" }}>
|
|
66
|
-
{t("EKYC_K_NUMBER")}
|
|
67
|
-
</div>
|
|
68
|
-
<div style={{ position: "relative" }}>
|
|
69
|
-
<TextInput
|
|
70
|
-
value={_searchParams?.kNumber}
|
|
71
|
-
onChange={(e) => onChange("kNumber", e.target.value)}
|
|
72
|
-
placeholder={t("EKYC_K_NUMBER_PLACEHOLDER")}
|
|
73
|
-
style={{ borderRadius: "8px", paddingLeft: "12px", height: "44px" }}
|
|
74
|
-
/>
|
|
39
|
+
{/* Main Content */}
|
|
40
|
+
<div className="main-content-wrapper">
|
|
41
|
+
{/* Top Row: Search Card + Stats Cards */}
|
|
42
|
+
<div className="search-stats-row">
|
|
43
|
+
{/* Identity Lookup Card */}
|
|
44
|
+
<div className="identity-lookup-card">
|
|
45
|
+
{/* Card Title */}
|
|
46
|
+
<div className="lookup-card-title">
|
|
47
|
+
<div className="lookup-icon-bg">
|
|
48
|
+
<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="#3A7BD5" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
|
|
49
|
+
<circle cx="11" cy="11" r="8" />
|
|
50
|
+
<line x1="21" y1="21" x2="16.65" y2="16.65" />
|
|
51
|
+
</svg>
|
|
75
52
|
</div>
|
|
53
|
+
<span className="lookup-title-text">
|
|
54
|
+
{t("EKYC_IDENTITY_LOOKUP") || "Identity Lookup"}
|
|
55
|
+
</span>
|
|
76
56
|
</div>
|
|
77
57
|
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
58
|
+
{/* Inputs Row */}
|
|
59
|
+
<form onSubmit={onSubmit}>
|
|
60
|
+
<div className="inputs-row">
|
|
61
|
+
<div className="input-group">
|
|
62
|
+
<label>
|
|
63
|
+
{t("EKYC_K_NUMBER") || "K Number"}
|
|
64
|
+
<span className="info-badge">i</span>
|
|
65
|
+
</label>
|
|
66
|
+
<TextInput
|
|
67
|
+
value={_searchParams?.kNumber}
|
|
68
|
+
onChange={(e) => onChange("kNumber", e.target.value)}
|
|
69
|
+
placeholder={t("EKYC_K_NUMBER_PLACEHOLDER") || "e.g. 8234910234"}
|
|
70
|
+
/>
|
|
71
|
+
</div>
|
|
72
|
+
|
|
73
|
+
<div className="input-group">
|
|
74
|
+
<label>
|
|
75
|
+
{t("EKYC_K_NAME") || "K Name"}
|
|
76
|
+
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="#3A7BD5" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
|
|
77
|
+
<path d="M20 21v-2a4 4 0 0 0-4-4H8a4 4 0 0 0-4 4v2" />
|
|
78
|
+
<circle cx="12" cy="7" r="4" />
|
|
79
|
+
</svg>
|
|
80
|
+
</label>
|
|
81
|
+
<TextInput
|
|
82
|
+
value={_searchParams?.kName}
|
|
83
|
+
onChange={(e) => onChange("kName", e.target.value)}
|
|
84
|
+
placeholder={t("EKYC_K_NAME_PLACEHOLDER") || "Consumer name search"}
|
|
85
|
+
/>
|
|
86
|
+
</div>
|
|
81
87
|
</div>
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
88
|
+
|
|
89
|
+
{/* Actions Row */}
|
|
90
|
+
<div className="actions-row">
|
|
91
|
+
<button type="button" onClick={onClear} className="clear-btn">
|
|
92
|
+
{t("ES_COMMON_CLEAR") || "Clear"}
|
|
93
|
+
</button>
|
|
94
|
+
<button type="submit" className="search-btn">
|
|
95
|
+
{t("ES_COMMON_SEARCH") || "Execute Search"}
|
|
96
|
+
</button>
|
|
89
97
|
</div>
|
|
90
|
-
</
|
|
98
|
+
</form>
|
|
91
99
|
</div>
|
|
92
|
-
<div style={{ display: "flex", justifyContent: "flex-end", marginTop: "20px" }}>
|
|
93
|
-
<div style={{ display: "flex", gap: "12px", alignItems: "center" }}>
|
|
94
|
-
<button
|
|
95
|
-
type="button"
|
|
96
|
-
onClick={onClear}
|
|
97
|
-
style={{
|
|
98
|
-
background: "none",
|
|
99
|
-
border: "none",
|
|
100
|
-
color: "#0076f3ff",
|
|
101
|
-
fontWeight: "600",
|
|
102
|
-
cursor: "pointer",
|
|
103
|
-
fontSize: "14px",
|
|
104
|
-
padding: "10px",
|
|
105
|
-
}}
|
|
106
|
-
>
|
|
107
|
-
{t("ES_COMMON_CLEAR")}
|
|
108
|
-
</button>
|
|
109
100
|
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
101
|
+
{/* Right Stats Column */}
|
|
102
|
+
<div className="stats-column">
|
|
103
|
+
{/* Today's Audits Card */}
|
|
104
|
+
<div className="audits-card">
|
|
105
|
+
<div className="audits-label">{t("EKYC_TODAYS_AUDITS") || "Today's Audits"}</div>
|
|
106
|
+
<div className="audits-count">{props.countData?.todaysAudits || 24}</div>
|
|
107
|
+
<div className="audits-change">
|
|
108
|
+
<span>↗</span>
|
|
109
|
+
{props.countData?.auditChange || "12% increase from yesterday"}
|
|
110
|
+
</div>
|
|
111
|
+
<div className="audits-watermark">M</div>
|
|
112
|
+
</div>
|
|
113
|
+
|
|
114
|
+
{/* Queue Status Card */}
|
|
115
|
+
<div className="queue-card">
|
|
116
|
+
<div className="queue-label">{t("EKYC_QUEUE_STATUS") || "Queue Status"}</div>
|
|
117
|
+
<div className="queue-content">
|
|
118
|
+
<div className="queue-status-text">
|
|
119
|
+
{props.countData?.pendingCount || 3} Pending
|
|
120
|
+
</div>
|
|
121
|
+
<div className="avatar-group">
|
|
122
|
+
{[0, 1].map((i) => (
|
|
123
|
+
<div key={i} className="avatar-item">
|
|
124
|
+
{String.fromCharCode(65 + i)}
|
|
125
|
+
</div>
|
|
126
|
+
))}
|
|
127
|
+
<div className="avatar-more">+1</div>
|
|
128
|
+
</div>
|
|
129
|
+
</div>
|
|
122
130
|
</div>
|
|
123
131
|
</div>
|
|
124
|
-
</
|
|
125
|
-
|
|
126
|
-
|
|
132
|
+
</div>
|
|
133
|
+
|
|
134
|
+
{/* Children (ConnectionDetailsView or placeholder) */}
|
|
135
|
+
{children}
|
|
136
|
+
</div>
|
|
127
137
|
</div>
|
|
128
138
|
</div>
|
|
129
139
|
);
|
|
130
140
|
};
|
|
131
141
|
|
|
132
|
-
export default SearchConsumer;
|
|
142
|
+
export default SearchConsumer;
|
|
@@ -8,166 +8,144 @@ const StatusCards = ({ countData }) => {
|
|
|
8
8
|
const { t } = useTranslation();
|
|
9
9
|
const chartRef1 = useRef(null);
|
|
10
10
|
const chartInstance1 = useRef(null);
|
|
11
|
-
const chartRef2 = useRef(null);
|
|
12
|
-
const chartInstance2 = useRef(null);
|
|
13
11
|
|
|
14
12
|
const total = countData?.total || 0;
|
|
15
13
|
const pending = countData?.pending || 0;
|
|
16
|
-
const active = countData?.completed || 0;
|
|
17
|
-
const completed = 0;
|
|
14
|
+
const active = countData?.completed || 0;
|
|
15
|
+
const completed = 0;
|
|
18
16
|
const rejected = countData?.rejected || 0;
|
|
19
17
|
|
|
20
18
|
const actualCompleted = countData?.completed || 0;
|
|
21
|
-
const applied = total;
|
|
22
19
|
const approved = actualCompleted;
|
|
23
20
|
|
|
24
21
|
const efficiency = total > 0 ? Math.round((actualCompleted / total) * 100) : 0;
|
|
22
|
+
const healthPct = total > 0 ? Math.round((approved / total) * 100) : 0;
|
|
23
|
+
|
|
24
|
+
const formatNumber = (num) => new Intl.NumberFormat("en-IN").format(num || 0);
|
|
25
25
|
|
|
26
26
|
useEffect(() => {
|
|
27
|
-
// Chart 1: Status Breakdown
|
|
28
27
|
if (chartRef1.current) {
|
|
29
28
|
if (chartInstance1.current) chartInstance1.current.destroy();
|
|
30
29
|
const ctx1 = chartRef1.current.getContext("2d");
|
|
31
30
|
chartInstance1.current = new Chart(ctx1, {
|
|
32
31
|
type: "doughnut",
|
|
33
32
|
data: {
|
|
34
|
-
labels: [t("EKYC_ACTIVE"), t("
|
|
35
|
-
datasets: [
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
33
|
+
labels: [t("EKYC_ACTIVE"), t("EKYC_PENDING"), t("EKYC_COMPLETED")],
|
|
34
|
+
datasets: [
|
|
35
|
+
{
|
|
36
|
+
data: [active, pending, completed],
|
|
37
|
+
backgroundColor: ["#0c2a52", "#77B6EA", "#c8ddf5"],
|
|
38
|
+
borderColor: ["#ffffff", "#ffffff", "#ffffff"],
|
|
39
|
+
borderWidth: 2,
|
|
40
|
+
hoverOffset: 4,
|
|
41
|
+
},
|
|
42
|
+
],
|
|
42
43
|
},
|
|
43
44
|
options: {
|
|
44
45
|
cutout: "75%",
|
|
45
46
|
plugins: { legend: { display: false } },
|
|
46
|
-
maintainAspectRatio:
|
|
47
|
+
maintainAspectRatio: false,
|
|
47
48
|
responsive: true,
|
|
48
|
-
aspectRatio: 1,
|
|
49
|
-
},
|
|
50
|
-
});
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
// Chart 2: Applied vs Approved
|
|
54
|
-
if (chartRef2.current) {
|
|
55
|
-
if (chartInstance2.current) chartInstance2.current.destroy();
|
|
56
|
-
const ctx2 = chartRef2.current.getContext("2d");
|
|
57
|
-
chartInstance2.current = new Chart(ctx2, {
|
|
58
|
-
type: "doughnut",
|
|
59
|
-
data: {
|
|
60
|
-
labels: [t("EKYC_APPROVED"), t("EKYC_OTHERS")],
|
|
61
|
-
datasets: [{
|
|
62
|
-
data: [approved, Math.max(0, applied - approved)],
|
|
63
|
-
backgroundColor: ["#219653", "#E0E0E0"],
|
|
64
|
-
borderColor: ["#ffffff", "#ffffff"],
|
|
65
|
-
borderWidth: 2,
|
|
66
|
-
hoverOffset: 4,
|
|
67
|
-
}],
|
|
68
|
-
},
|
|
69
|
-
options: {
|
|
70
|
-
cutout: "75%",
|
|
71
|
-
plugins: { legend: { display: false } },
|
|
72
|
-
maintainAspectRatio: true,
|
|
73
|
-
responsive: true,
|
|
74
|
-
aspectRatio: 1,
|
|
75
49
|
},
|
|
76
50
|
});
|
|
77
51
|
}
|
|
78
52
|
|
|
79
53
|
return () => {
|
|
80
54
|
if (chartInstance1.current) chartInstance1.current.destroy();
|
|
81
|
-
if (chartInstance2.current) chartInstance2.current.destroy();
|
|
82
55
|
};
|
|
83
|
-
}, [pending, completed, active,
|
|
56
|
+
}, [pending, completed, active, t]);
|
|
84
57
|
|
|
85
|
-
const
|
|
86
|
-
|
|
87
|
-
|
|
58
|
+
const legendItems = [
|
|
59
|
+
{ color: "#0c2a52", label: t("EKYC_ACTIVE"), value: active },
|
|
60
|
+
{ color: "#77B6EA", label: t("EKYC_PENDING"), value: pending },
|
|
61
|
+
{ color: "#c8ddf5", label: t("EKYC_COMPLETED"), value: completed },
|
|
62
|
+
];
|
|
88
63
|
|
|
89
64
|
return (
|
|
90
|
-
<div
|
|
91
|
-
<div
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
<div style={{ display: "flex", flexDirection: "column", gap: "12px" }}>
|
|
100
|
-
{/* Active */}
|
|
101
|
-
<div style={{ display: "flex", alignItems: "center", gap: "10px" }}>
|
|
102
|
-
<span style={{ width: "12px", height: "12px", borderRadius: "50%", backgroundColor: "#1a3a6b", flexShrink: 0 }} />
|
|
103
|
-
<span style={{ fontSize: "14px", color: "#333" }}>
|
|
104
|
-
{t("EKYC_ACTIVE")}: <strong style={{ color: "#1a3a6b" }}>{formatNumber(active)}</strong>
|
|
105
|
-
</span>
|
|
106
|
-
</div>
|
|
107
|
-
|
|
108
|
-
{/* Pending */}
|
|
109
|
-
<div style={{ display: "flex", alignItems: "center", gap: "10px" }}>
|
|
110
|
-
<span style={{ width: "12px", height: "12px", borderRadius: "50%", backgroundColor: "#3d84ed", flexShrink: 0 }} />
|
|
111
|
-
<span style={{ fontSize: "14px", color: "#333" }}>
|
|
112
|
-
{t("EKYC_PENDING")}: <strong style={{ color: "#1a3a6b" }}>{formatNumber(pending)}</strong>
|
|
113
|
-
</span>
|
|
65
|
+
<div className="ekyc-employee-container">
|
|
66
|
+
<div className="status-cards-wrapper">
|
|
67
|
+
{/* Header */}
|
|
68
|
+
<div className="status-cards-header">
|
|
69
|
+
<div>
|
|
70
|
+
<div className="eyebrow">
|
|
71
|
+
<span className="eyebrow-dot" />
|
|
72
|
+
{t("EKYC_INSTITUTIONAL_OVERVIEW") || "Institutional Performance Overview"}
|
|
114
73
|
</div>
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
{/* Total Section */}
|
|
125
|
-
<div style={{ marginTop: "20px", padding: "16px", background: "#f8faff", borderRadius: "8px", border: "1px solid #eef2f6" }}>
|
|
126
|
-
<div style={{ fontSize: "32px", fontWeight: "800", color: "#1a3a6b", lineHeight: 1 }}>
|
|
127
|
-
{formatNumber(total)}
|
|
128
|
-
</div>
|
|
129
|
-
<div style={{ fontSize: "12px", color: "#667085", marginTop: "4px", fontWeight: "600" }}>
|
|
130
|
-
{t("EKYC_TOTAL_APPLICATIONS") || "Total Applications Applied"}
|
|
131
|
-
</div>
|
|
74
|
+
<h1 className="status-cards-h1">{t("EKYC_DASHBOARD_TITLE") || "eKYC Verification Dashboard"}</h1>
|
|
75
|
+
<p className="status-cards-subtitle">
|
|
76
|
+
{t("EKYC_DASHBOARD_SUBTITLE") ||
|
|
77
|
+
"Real-time monitoring of consumer verification workflows across all administrative zones."}
|
|
78
|
+
</p>
|
|
79
|
+
</div>
|
|
80
|
+
<div className="total-applications-card">
|
|
81
|
+
<div className="total-label">
|
|
82
|
+
{t("EKYC_TOTAL_APPLICATIONS") || "Total Applications Processed"}
|
|
132
83
|
</div>
|
|
84
|
+
<div className="total-number">{formatNumber(total)}</div>
|
|
85
|
+
<div className="total-badge">↗ +12.4% {t("EKYC_FROM_LAST_QUARTER") || "from last quarter"}</div>
|
|
133
86
|
</div>
|
|
134
87
|
</div>
|
|
135
88
|
|
|
136
|
-
{/*
|
|
137
|
-
<div
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
<div
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
89
|
+
{/* Panels */}
|
|
90
|
+
<div className="status-panels-grid">
|
|
91
|
+
{/* Panel 1: Status Breakdown */}
|
|
92
|
+
<div className="status-panel">
|
|
93
|
+
<div className="panel-title">{t("EKYC_STATUS_BREAKDOWN") || "Status Breakdown"}</div>
|
|
94
|
+
<div className="panel-subtitle">
|
|
95
|
+
{t("EKYC_VERIFICATION_LIFECYCLE") || "Verification lifecycle distribution"}
|
|
96
|
+
</div>
|
|
97
|
+
<div className="breakdown-body">
|
|
98
|
+
<div className="status-legend">
|
|
99
|
+
{legendItems.map((item) => (
|
|
100
|
+
<div key={item.label} className="legend-row">
|
|
101
|
+
<span className="legend-label">
|
|
102
|
+
<span
|
|
103
|
+
className="indicator-dot"
|
|
104
|
+
style={{ background: item.color }}
|
|
105
|
+
/>
|
|
106
|
+
{item.label}
|
|
107
|
+
</span>
|
|
108
|
+
<span className="legend-value">{formatNumber(item.value)}</span>
|
|
109
|
+
</div>
|
|
110
|
+
))}
|
|
111
|
+
</div>
|
|
112
|
+
<div className="chart-wrapper">
|
|
113
|
+
<canvas ref={chartRef1} style={{ width: "100%", height: "100%" }} />
|
|
114
|
+
<div className="chart-center">
|
|
115
|
+
<div className="chart-percentage">{efficiency}%</div>
|
|
116
|
+
<div className="chart-label">{t("EKYC_COMPLETE") || "Complete"}</div>
|
|
149
117
|
</div>
|
|
150
118
|
</div>
|
|
151
119
|
</div>
|
|
152
|
-
<div style={{ marginTop: "8px", fontSize: "11px", fontWeight: "700", color: "#888", textTransform: "uppercase" }}>{t("EKYC_STATUS_BREAKDOWN")}</div>
|
|
153
120
|
</div>
|
|
154
121
|
|
|
155
|
-
{/*
|
|
156
|
-
<div
|
|
157
|
-
<div
|
|
158
|
-
|
|
159
|
-
<
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
122
|
+
{/* Panel 2: Submission Health */}
|
|
123
|
+
<div className="status-panel">
|
|
124
|
+
<div className="panel-title">
|
|
125
|
+
{t("EKYC_SUBMISSION_HEALTH") || "Submission Health"}
|
|
126
|
+
<span className="optimal-badge">{t("EKYC_OPTIMAL") || "Optimal"}</span>
|
|
127
|
+
</div>
|
|
128
|
+
<div className="panel-subtitle">
|
|
129
|
+
{t("EKYC_PLATFORM_EFFICIENCY") || "Platform operational efficiency"}
|
|
130
|
+
</div>
|
|
131
|
+
<div className="health-metrics-row">
|
|
132
|
+
<div className="health-percentage">{healthPct}%</div>
|
|
133
|
+
<div className="health-trend">↗ +2.1%</div>
|
|
134
|
+
</div>
|
|
135
|
+
<div className="status-progress-bar">
|
|
136
|
+
<div className="progress-fill" style={{ width: `${healthPct}%` }} />
|
|
137
|
+
</div>
|
|
138
|
+
<div className="mini-metrics-grid">
|
|
139
|
+
<div className="metric-box">
|
|
140
|
+
<div className="metric-label">{t("EKYC_AVG_LATENCY") || "Avg Latency"}</div>
|
|
141
|
+
<div className="metric-value">1.2s</div>
|
|
142
|
+
</div>
|
|
143
|
+
<div className="metric-box">
|
|
144
|
+
<div className="metric-label">{t("EKYC_ERROR_RATE") || "Error Rate"}</div>
|
|
145
|
+
<div className="metric-value">0.04%</div>
|
|
166
146
|
</div>
|
|
167
147
|
</div>
|
|
168
|
-
<div style={{ marginTop: "8px", fontSize: "11px", fontWeight: "700", color: "#888", textTransform: "uppercase" }}>{t("EKYC_SUBMISSION_HEALTH")}</div>
|
|
169
148
|
</div>
|
|
170
|
-
|
|
171
149
|
</div>
|
|
172
150
|
</div>
|
|
173
151
|
</div>
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
import { AppContainer, PrivateRoute, ModuleHeader, ArrowLeft, HomeIcon } from "@djb25/digit-ui-react-components";
|
|
2
|
+
import React from "react";
|
|
3
|
+
import { useTranslation } from "react-i18next";
|
|
4
|
+
import { Switch, useLocation, useRouteMatch } from "react-router-dom";
|
|
5
|
+
import Create from "../employee/Create";
|
|
6
|
+
import AadhaarVerification from "../employee/AadhaarVerification";
|
|
7
|
+
import AddressDetails from "../employee/AddressDetails";
|
|
8
|
+
import PropertyInfo from "../employee/PropertyInfo";
|
|
9
|
+
import MeterDetails from "../employee/MeterDetails";
|
|
10
|
+
import Review from "../employee/Review";
|
|
11
|
+
|
|
12
|
+
const CitizenApp = () => {
|
|
13
|
+
const { t } = useTranslation();
|
|
14
|
+
const location = useLocation();
|
|
15
|
+
const { path } = useRouteMatch();
|
|
16
|
+
|
|
17
|
+
sessionStorage.removeItem("revalidateddone");
|
|
18
|
+
|
|
19
|
+
const getBreadcrumbLabel = () => {
|
|
20
|
+
const pathname = location.pathname;
|
|
21
|
+
if (pathname.includes("/create-kyc")) return "EKYC_CREATE_KYC";
|
|
22
|
+
if (pathname.includes("/aadhaar-verification")) return "EKYC_AADHAAR_VERIFICATION";
|
|
23
|
+
if (pathname.includes("/address-details")) return "EKYC_ADDRESS_DETAILS";
|
|
24
|
+
if (pathname.includes("/property-info")) return "EKYC_PROPERTY_INFO";
|
|
25
|
+
if (pathname.includes("/meter-details")) return "EKYC_METER_DETAILS";
|
|
26
|
+
if (pathname.includes("/review")) return "EKYC_REVIEW";
|
|
27
|
+
return "EKYC_HOME";
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
const breadcrumbs = [
|
|
31
|
+
{ icon: HomeIcon, path: "/digit-ui/citizen" },
|
|
32
|
+
{ label: t(getBreadcrumbLabel()) }
|
|
33
|
+
];
|
|
34
|
+
|
|
35
|
+
return (
|
|
36
|
+
<AppContainer>
|
|
37
|
+
<div className="ground-container employee-app-container form-container">
|
|
38
|
+
<ModuleHeader
|
|
39
|
+
leftContent={
|
|
40
|
+
<React.Fragment>
|
|
41
|
+
<ArrowLeft className="icon" />
|
|
42
|
+
{t("CS_COMMON_BACK")}
|
|
43
|
+
</React.Fragment>
|
|
44
|
+
}
|
|
45
|
+
onLeftClick={() => window.history.back()}
|
|
46
|
+
breadcrumbs={breadcrumbs}
|
|
47
|
+
/>
|
|
48
|
+
|
|
49
|
+
<Switch>
|
|
50
|
+
<PrivateRoute
|
|
51
|
+
path={`${path}/create-kyc`}
|
|
52
|
+
component={() => <Create />}
|
|
53
|
+
/>
|
|
54
|
+
|
|
55
|
+
<PrivateRoute
|
|
56
|
+
path={`${path}/aadhaar-verification`}
|
|
57
|
+
component={() => <AadhaarVerification />}
|
|
58
|
+
/>
|
|
59
|
+
|
|
60
|
+
<PrivateRoute
|
|
61
|
+
path={`${path}/address-details`}
|
|
62
|
+
component={() => <AddressDetails />}
|
|
63
|
+
/>
|
|
64
|
+
|
|
65
|
+
<PrivateRoute
|
|
66
|
+
path={`${path}/property-info`}
|
|
67
|
+
component={() => <PropertyInfo />}
|
|
68
|
+
/>
|
|
69
|
+
|
|
70
|
+
<PrivateRoute
|
|
71
|
+
path={`${path}/meter-details`}
|
|
72
|
+
component={() => <MeterDetails />}
|
|
73
|
+
/>
|
|
74
|
+
|
|
75
|
+
<PrivateRoute
|
|
76
|
+
path={`${path}/review`}
|
|
77
|
+
component={() => <Review />}
|
|
78
|
+
/>
|
|
79
|
+
|
|
80
|
+
<PrivateRoute
|
|
81
|
+
path={`${path}/`}
|
|
82
|
+
component={() => <Create />}
|
|
83
|
+
/>
|
|
84
|
+
</Switch>
|
|
85
|
+
</div>
|
|
86
|
+
</AppContainer>
|
|
87
|
+
);
|
|
88
|
+
};
|
|
89
|
+
|
|
90
|
+
export default CitizenApp;
|
|
@@ -327,7 +327,6 @@ const AadhaarVerification = () => {
|
|
|
327
327
|
};
|
|
328
328
|
|
|
329
329
|
return (
|
|
330
|
-
<div className="ground-container employee-app-container form-container">
|
|
331
330
|
<div className="inbox-container">
|
|
332
331
|
<style>{`
|
|
333
332
|
@keyframes fadeSlideIn {
|
|
@@ -366,6 +365,7 @@ const AadhaarVerification = () => {
|
|
|
366
365
|
{ label: t("EKYC_STEP_AADHAAR") || "Aadhaar", done: showAddressSection, active: !showAddressSection },
|
|
367
366
|
{ label: t("EKYC_STEP_ADDRESS") || "Address", done: addressData !== null, active: showAddressSection && addressData === null },
|
|
368
367
|
{ label: t("EKYC_STEP_PROPERTY") || "Property", done: false, active: false },
|
|
368
|
+
{ label: t("EKYC_STEP_METER") || "Meter", done: false, active: false },
|
|
369
369
|
{ label: t("EKYC_STEP_REVIEW") || "Review", done: false, active: false },
|
|
370
370
|
].map((step, i) => (
|
|
371
371
|
<div className="ekyc-sidebar-step" key={i}>
|
|
@@ -374,7 +374,7 @@ const AadhaarVerification = () => {
|
|
|
374
374
|
? <CheckIcon size={11} color="#fff" />
|
|
375
375
|
: i + 1}
|
|
376
376
|
</div>
|
|
377
|
-
{i <
|
|
377
|
+
{i < 4 && <div className="ekyc-step-line" />}
|
|
378
378
|
<div className={`ekyc-step-label${step.done ? " done" : step.active ? " active" : ""}`}>
|
|
379
379
|
{step.label}
|
|
380
380
|
</div>
|
|
@@ -561,6 +561,7 @@ const AadhaarVerification = () => {
|
|
|
561
561
|
<div>
|
|
562
562
|
<div className="ekyc-field-label">
|
|
563
563
|
{t("EKYC_WHATSAPP_NUMBER") || "WhatsApp Number"}
|
|
564
|
+
<span style={styles.optionalTag}>{t("EKYC_OPTIONAL") || "Optional"}</span>
|
|
564
565
|
</div>
|
|
565
566
|
<IconInput
|
|
566
567
|
icon={<WhatsappIcon size={15} />}
|
|
@@ -641,7 +642,6 @@ const AadhaarVerification = () => {
|
|
|
641
642
|
</Card>
|
|
642
643
|
</div>
|
|
643
644
|
</div>
|
|
644
|
-
</div>
|
|
645
645
|
);
|
|
646
646
|
};
|
|
647
647
|
|
|
@@ -718,10 +718,11 @@ const AddressDetails = ({ isSection = false, onComplete, parentState }) => {
|
|
|
718
718
|
{ label: t("EKYC_STEP_AADHAAR") || "Aadhaar", done: true, active: false },
|
|
719
719
|
{ label: t("EKYC_STEP_ADDRESS") || "Address", done: false, active: true },
|
|
720
720
|
{ label: t("EKYC_STEP_PROPERTY") || "Property", done: false, active: false },
|
|
721
|
+
{ label: t("EKYC_STEP_METER") || "Meter", done: false, active: false },
|
|
721
722
|
{ label: t("EKYC_STEP_REVIEW") || "Review", done: false, active: false },
|
|
722
723
|
].map((step, i) => (
|
|
723
|
-
<div key={i} style={{ display: "flex", gap: "10px", alignItems: "flex-start", position: "relative", paddingBottom: i <
|
|
724
|
-
{i <
|
|
724
|
+
<div key={i} style={{ display: "flex", gap: "10px", alignItems: "flex-start", position: "relative", paddingBottom: i < 4 ? "18px" : 0 }}>
|
|
725
|
+
{i < 4 && (
|
|
725
726
|
<div style={{ position: "absolute", left: "10px", top: "22px", width: "1px", height: "calc(100% - 10px)", background: "#EAECF0" }} />
|
|
726
727
|
)}
|
|
727
728
|
<div style={{
|