@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.
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/index.modern.js +3334 -3345
- package/dist/index.modern.js.map +1 -1
- package/package.json +1 -1
- package/src/components/AssignEkyc.js +317 -0
- package/src/components/AssignEkycModal.js +362 -0
- package/src/components/EKYCCard.js +6 -4
- package/src/components/Review.js +155 -88
- package/src/components/StatusCards.js +6 -17
- package/src/components/SurveyorDetailsCard.js +282 -0
- package/src/components/VendorDetails.jsx +18 -1
- package/src/hook/SupervisorInboxTableConfig.js +138 -0
- package/src/hook/useInboxTableConfig.js +4 -3
- package/src/pages/citizen/Home.js +27 -14
- package/src/pages/citizen/index.js +48 -1
- package/src/pages/employee/index.js +94 -85
package/src/components/Review.js
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
|
-
import React, { useState } from "react";
|
|
1
|
+
import React, { Fragment, useState } from "react";
|
|
2
2
|
import {
|
|
3
3
|
Card,
|
|
4
|
-
CardHeader,
|
|
5
4
|
CardSubHeader,
|
|
6
5
|
StatusTable,
|
|
7
6
|
Row,
|
|
@@ -14,8 +13,7 @@ import {
|
|
|
14
13
|
GenericFileIcon,
|
|
15
14
|
} from "@djb25/digit-ui-react-components";
|
|
16
15
|
import { useTranslation } from "react-i18next";
|
|
17
|
-
import { useHistory, useLocation } from "react-router-dom";
|
|
18
|
-
|
|
16
|
+
import { useHistory, useLocation, useParams } from "react-router-dom";
|
|
19
17
|
|
|
20
18
|
// ─── Constants ───────────────────────────────────────────────────────────────
|
|
21
19
|
|
|
@@ -25,11 +23,7 @@ const ActionButton = ({ jumpTo, state }) => {
|
|
|
25
23
|
history.push(jumpTo, { ...state, isEditing: true });
|
|
26
24
|
}
|
|
27
25
|
return (
|
|
28
|
-
<LinkButton
|
|
29
|
-
label={<EditIcon style={{ width: "20px", height: "20px", fill: "#F47738" }} />}
|
|
30
|
-
style={{ margin: 0, padding: 0 }}
|
|
31
|
-
onClick={routeTo}
|
|
32
|
-
/>
|
|
26
|
+
<LinkButton label={<EditIcon style={{ width: "20px", height: "20px", fill: "#F47738" }} />} style={{ margin: 0, padding: 0 }} onClick={routeTo} />
|
|
33
27
|
);
|
|
34
28
|
};
|
|
35
29
|
|
|
@@ -56,14 +50,26 @@ const extractReviewData = (searchData, flowState) => {
|
|
|
56
50
|
|
|
57
51
|
return {
|
|
58
52
|
newData: applicationData?.newData || applicationData,
|
|
59
|
-
oldData: applicationData?.oldData || null
|
|
53
|
+
oldData: applicationData?.oldData || null,
|
|
60
54
|
};
|
|
61
55
|
};
|
|
62
56
|
|
|
63
57
|
const ReviewSection = ({ title, fields, newData, oldData, t, jumpTo, state }) => {
|
|
64
58
|
return (
|
|
65
|
-
<div
|
|
66
|
-
|
|
59
|
+
<div
|
|
60
|
+
className="review-section-wrapper"
|
|
61
|
+
style={{ marginBottom: "48px", background: "#fff", borderRadius: "12px", border: "1px solid #EAECF0", overflow: "hidden" }}
|
|
62
|
+
>
|
|
63
|
+
<div
|
|
64
|
+
style={{
|
|
65
|
+
padding: "20px 24px",
|
|
66
|
+
background: "#F9FAFB",
|
|
67
|
+
borderBottom: "1px solid #EAECF0",
|
|
68
|
+
display: "flex",
|
|
69
|
+
justifyContent: "space-between",
|
|
70
|
+
alignItems: "center",
|
|
71
|
+
}}
|
|
72
|
+
>
|
|
67
73
|
<CardSubHeader style={{ margin: 0, fontSize: "18px", color: "#101828", fontWeight: "700" }}>{title}</CardSubHeader>
|
|
68
74
|
{jumpTo && <ActionButton jumpTo={jumpTo} state={state} />}
|
|
69
75
|
</div>
|
|
@@ -72,9 +78,45 @@ const ReviewSection = ({ title, fields, newData, oldData, t, jumpTo, state }) =>
|
|
|
72
78
|
<table style={{ width: "100%", borderCollapse: "collapse", tableLayout: "fixed" }}>
|
|
73
79
|
<thead>
|
|
74
80
|
<tr>
|
|
75
|
-
<th
|
|
76
|
-
|
|
77
|
-
|
|
81
|
+
<th
|
|
82
|
+
style={{
|
|
83
|
+
padding: "16px 0",
|
|
84
|
+
textAlign: "left",
|
|
85
|
+
color: "#667085",
|
|
86
|
+
fontSize: "12px",
|
|
87
|
+
fontWeight: "600",
|
|
88
|
+
textTransform: "uppercase",
|
|
89
|
+
width: "30%",
|
|
90
|
+
}}
|
|
91
|
+
>
|
|
92
|
+
{t("EKYC_FIELD_NAME")}
|
|
93
|
+
</th>
|
|
94
|
+
<th
|
|
95
|
+
style={{
|
|
96
|
+
padding: "16px 0",
|
|
97
|
+
textAlign: "left",
|
|
98
|
+
color: "#667085",
|
|
99
|
+
fontSize: "12px",
|
|
100
|
+
fontWeight: "600",
|
|
101
|
+
textTransform: "uppercase",
|
|
102
|
+
width: "35%",
|
|
103
|
+
}}
|
|
104
|
+
>
|
|
105
|
+
{t("EKYC_EXISTING_INFORMATION")}
|
|
106
|
+
</th>
|
|
107
|
+
<th
|
|
108
|
+
style={{
|
|
109
|
+
padding: "16px 0",
|
|
110
|
+
textAlign: "left",
|
|
111
|
+
color: "#667085",
|
|
112
|
+
fontSize: "12px",
|
|
113
|
+
fontWeight: "600",
|
|
114
|
+
textTransform: "uppercase",
|
|
115
|
+
width: "35%",
|
|
116
|
+
}}
|
|
117
|
+
>
|
|
118
|
+
{t("EKYC_PROPOSED_UPDATES")}
|
|
119
|
+
</th>
|
|
78
120
|
</tr>
|
|
79
121
|
</thead>
|
|
80
122
|
<tbody>
|
|
@@ -85,17 +127,26 @@ const ReviewSection = ({ title, fields, newData, oldData, t, jumpTo, state }) =>
|
|
|
85
127
|
|
|
86
128
|
return (
|
|
87
129
|
<tr key={idx} style={{ borderTop: "1px solid #F2F4F7" }}>
|
|
88
|
-
<td style={{ padding: "16px 0", fontSize: "14px", color: "#344054", fontWeight: "500" }}>
|
|
89
|
-
{t(field.label)}
|
|
90
|
-
</td>
|
|
130
|
+
<td style={{ padding: "16px 0", fontSize: "14px", color: "#344054", fontWeight: "500" }}>{t(field.label)}</td>
|
|
91
131
|
<td style={{ padding: "16px 0", fontSize: "14px", color: "#667085" }}>
|
|
92
132
|
{field.isBool ? boolToYesNo(valOld, t) : checkForNA(valOld)}
|
|
93
133
|
</td>
|
|
94
|
-
<td
|
|
134
|
+
<td
|
|
135
|
+
style={{ padding: "16px 0", fontSize: "14px", color: isChanged ? "#1B8B32" : "#101828", fontWeight: isChanged ? "700" : "400" }}
|
|
136
|
+
>
|
|
95
137
|
<div style={{ display: "flex", alignItems: "center", gap: "8px" }}>
|
|
96
138
|
{field.isBool ? boolToYesNo(valNew, t) : checkForNA(valNew)}
|
|
97
139
|
{isChanged && (
|
|
98
|
-
<span
|
|
140
|
+
<span
|
|
141
|
+
style={{
|
|
142
|
+
background: "#ECFDF3",
|
|
143
|
+
color: "#067647",
|
|
144
|
+
padding: "2px 8px",
|
|
145
|
+
borderRadius: "12px",
|
|
146
|
+
fontSize: "10px",
|
|
147
|
+
fontWeight: "600",
|
|
148
|
+
}}
|
|
149
|
+
>
|
|
99
150
|
{t("EKYC_CHANGED")}
|
|
100
151
|
</span>
|
|
101
152
|
)}
|
|
@@ -112,10 +163,10 @@ const ReviewSection = ({ title, fields, newData, oldData, t, jumpTo, state }) =>
|
|
|
112
163
|
};
|
|
113
164
|
|
|
114
165
|
const Review = () => {
|
|
115
|
-
|
|
116
166
|
const { t } = useTranslation();
|
|
117
167
|
const history = useHistory();
|
|
118
168
|
const location = useLocation();
|
|
169
|
+
let { kno } = useParams();
|
|
119
170
|
|
|
120
171
|
const [agree, setAgree] = useState(false);
|
|
121
172
|
const [isSubmitting, setIsSubmitting] = useState(false);
|
|
@@ -123,8 +174,8 @@ const Review = () => {
|
|
|
123
174
|
const [previewUrl, setPreviewUrl] = useState("");
|
|
124
175
|
|
|
125
176
|
const flowState = location.state || {};
|
|
126
|
-
const {
|
|
127
|
-
const activeKno =
|
|
177
|
+
const { edits = {} } = flowState;
|
|
178
|
+
const activeKno = kno;
|
|
128
179
|
|
|
129
180
|
const { aadhaarData = {}, addressDetails: editedAddress = {}, propertyDetails: editedProperty = {}, meterDetails: editedMeter = {} } = edits;
|
|
130
181
|
|
|
@@ -148,7 +199,8 @@ const Review = () => {
|
|
|
148
199
|
|
|
149
200
|
return {
|
|
150
201
|
connection: {
|
|
151
|
-
consumerName:
|
|
202
|
+
consumerName:
|
|
203
|
+
apiConn?.consumerName || (apiConn?.firstName ? [apiConn.firstName, apiConn.middleName, apiConn.lastName].filter(Boolean).join(" ") : null),
|
|
152
204
|
address: apiConn?.address || apiConn?.addressRaw,
|
|
153
205
|
connectionType: apiConn?.connectionType || apiConn?.connectionCategory,
|
|
154
206
|
meterNumber: apiConn?.meterNumber || apiConn?.meterNo,
|
|
@@ -201,7 +253,7 @@ const Review = () => {
|
|
|
201
253
|
lastBillRaised: apiMeter?.lastBillRaised,
|
|
202
254
|
systemMeterId: apiMeter?.systemMeterId,
|
|
203
255
|
meterPhotoFileStoreId: apiMeter?.meterPhotoFileStoreId,
|
|
204
|
-
}
|
|
256
|
+
},
|
|
205
257
|
};
|
|
206
258
|
};
|
|
207
259
|
|
|
@@ -400,20 +452,8 @@ const Review = () => {
|
|
|
400
452
|
const baseUrl = "/digit-ui/employee/ekyc";
|
|
401
453
|
|
|
402
454
|
return (
|
|
403
|
-
<
|
|
404
|
-
<Card
|
|
405
|
-
{/* ── Header ───────────────────────────────────────────────────── */}
|
|
406
|
-
<div style={{ display: "flex", justifyContent: "space-between", alignItems: "center", marginBottom: "40px", borderBottom: "1px solid #EAECF0", paddingBottom: "20px" }}>
|
|
407
|
-
<CardHeader style={{ margin: 0, fontSize: "28px" }}>{t("EKYC_REVIEW_APPLICATION")}</CardHeader>
|
|
408
|
-
<div style={{
|
|
409
|
-
background: "#F9FAFB", border: "1px solid #EAECF0",
|
|
410
|
-
borderRadius: "24px", padding: "8px 20px",
|
|
411
|
-
fontSize: "14px", color: "#475467", fontWeight: "500"
|
|
412
|
-
}}>
|
|
413
|
-
{t("EKYC_K_NUMBER")}: <span style={{ color: "#101828", fontWeight: "700" }}>{activeKno}</span>
|
|
414
|
-
</div>
|
|
415
|
-
</div>
|
|
416
|
-
|
|
455
|
+
<Fragment>
|
|
456
|
+
<Card className="overflow-y-scroll">
|
|
417
457
|
{/* ── 1. Connection Details ────────────────────────────────────── */}
|
|
418
458
|
<ReviewSection
|
|
419
459
|
title={t("EKYC_CONNECTION_DETAILS")}
|
|
@@ -465,38 +505,46 @@ const Review = () => {
|
|
|
465
505
|
<Row
|
|
466
506
|
label={t("EKYC_DOOR_PHOTO")}
|
|
467
507
|
text={addressData.doorPhotoFilestoreId ? t("EKYC_PHOTO_AVAILABLE") : t("CS_NA")}
|
|
468
|
-
actionButton={
|
|
469
|
-
|
|
470
|
-
<
|
|
471
|
-
|
|
472
|
-
|
|
508
|
+
actionButton={
|
|
509
|
+
addressData.doorPhotoFilestoreId && (
|
|
510
|
+
<div onClick={() => handleViewDocument(addressData.doorPhotoFilestoreId)}>
|
|
511
|
+
<GenericFileIcon style={{ cursor: "pointer", fill: "#F47738" }} />
|
|
512
|
+
</div>
|
|
513
|
+
)
|
|
514
|
+
}
|
|
473
515
|
/>
|
|
474
516
|
<Row
|
|
475
517
|
label={t("EKYC_METER_PHOTO")}
|
|
476
518
|
text={meterData.meterPhotoFileStoreId ? t("EKYC_PHOTO_AVAILABLE") : t("CS_NA")}
|
|
477
|
-
actionButton={
|
|
478
|
-
|
|
479
|
-
<
|
|
480
|
-
|
|
481
|
-
|
|
519
|
+
actionButton={
|
|
520
|
+
meterData.meterPhotoFileStoreId && (
|
|
521
|
+
<div onClick={() => handleViewDocument(meterData.meterPhotoFileStoreId)}>
|
|
522
|
+
<GenericFileIcon style={{ cursor: "pointer", fill: "#F47738" }} />
|
|
523
|
+
</div>
|
|
524
|
+
)
|
|
525
|
+
}
|
|
482
526
|
/>
|
|
483
527
|
<Row
|
|
484
528
|
label={t("EKYC_BUILDING_IMAGE")}
|
|
485
529
|
text={propertyData.buildingImageFileStoreId ? t("EKYC_PHOTO_AVAILABLE") : t("CS_NA")}
|
|
486
|
-
actionButton={
|
|
487
|
-
|
|
488
|
-
<
|
|
489
|
-
|
|
490
|
-
|
|
530
|
+
actionButton={
|
|
531
|
+
propertyData.buildingImageFileStoreId && (
|
|
532
|
+
<div onClick={() => handleViewDocument(propertyData.buildingImageFileStoreId)}>
|
|
533
|
+
<GenericFileIcon style={{ cursor: "pointer", fill: "#F47738" }} />
|
|
534
|
+
</div>
|
|
535
|
+
)
|
|
536
|
+
}
|
|
491
537
|
/>
|
|
492
538
|
<Row
|
|
493
539
|
label={t("EKYC_PROPERTY_DOCUMENTS")}
|
|
494
540
|
text={propertyData.propertyDocumentFileStoreId ? t("EKYC_DOCS_AVAILABLE") : t("CS_NA")}
|
|
495
|
-
actionButton={
|
|
496
|
-
|
|
497
|
-
<
|
|
498
|
-
|
|
499
|
-
|
|
541
|
+
actionButton={
|
|
542
|
+
propertyData.propertyDocumentFileStoreId && (
|
|
543
|
+
<div onClick={() => handleViewDocument(propertyData.propertyDocumentFileStoreId)}>
|
|
544
|
+
<GenericFileIcon style={{ cursor: "pointer", fill: "#F47738" }} />
|
|
545
|
+
</div>
|
|
546
|
+
)
|
|
547
|
+
}
|
|
500
548
|
/>
|
|
501
549
|
</StatusTable>
|
|
502
550
|
</div>
|
|
@@ -510,41 +558,60 @@ const Review = () => {
|
|
|
510
558
|
checked={agree}
|
|
511
559
|
/>
|
|
512
560
|
</div>
|
|
513
|
-
</Card>
|
|
514
561
|
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
label={t("
|
|
518
|
-
onSubmit={
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
<SubmitBar
|
|
522
|
-
label={t("EKYC_APPROVE")}
|
|
523
|
-
onSubmit={handleApprove}
|
|
524
|
-
disabled={!agree}
|
|
525
|
-
/>
|
|
526
|
-
<SubmitBar label={t("EKYC_SUBMIT_APPLICATION")} onSubmit={handleFinalSubmit} disabled={!agree} />
|
|
527
|
-
</ActionBar>
|
|
562
|
+
<ActionBar>
|
|
563
|
+
<SubmitBar label={t("EKYC_REJECT")} onSubmit={handleReject} disabled={!agree} />
|
|
564
|
+
<SubmitBar label={t("EKYC_APPROVE")} onSubmit={handleApprove} disabled={!agree} />
|
|
565
|
+
{/* <SubmitBar label={t("EKYC_SUBMIT_APPLICATION")} onSubmit={handleFinalSubmit} disabled={!agree} /> */}
|
|
566
|
+
</ActionBar>
|
|
567
|
+
</Card>
|
|
528
568
|
|
|
529
569
|
{/* ── Document Preview Modal ────────────────────────────────────── */}
|
|
530
570
|
{showPreview && (
|
|
531
|
-
<div
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
571
|
+
<div
|
|
572
|
+
style={{
|
|
573
|
+
position: "fixed",
|
|
574
|
+
top: 0,
|
|
575
|
+
left: 0,
|
|
576
|
+
width: "100%",
|
|
577
|
+
height: "100%",
|
|
578
|
+
backgroundColor: "rgba(0,0,0,0.7)",
|
|
579
|
+
display: "flex",
|
|
580
|
+
justifyContent: "center",
|
|
581
|
+
alignItems: "center",
|
|
582
|
+
zIndex: 10000,
|
|
583
|
+
}}
|
|
584
|
+
>
|
|
585
|
+
<div
|
|
586
|
+
style={{
|
|
587
|
+
position: "relative",
|
|
588
|
+
backgroundColor: "#fff",
|
|
589
|
+
padding: "30px",
|
|
590
|
+
borderRadius: "12px",
|
|
591
|
+
maxWidth: "600px",
|
|
592
|
+
width: "100%",
|
|
593
|
+
maxHeight: "70vh",
|
|
594
|
+
overflow: "auto",
|
|
595
|
+
boxShadow: "0 20px 25px -5px rgba(0, 0, 0, 0.1), 0 10px 10px -5px rgba(0, 0, 0, 0.04)",
|
|
596
|
+
}}
|
|
597
|
+
>
|
|
541
598
|
<div
|
|
542
599
|
onClick={() => setShowPreview(false)}
|
|
543
600
|
style={{
|
|
544
|
-
position: "absolute",
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
601
|
+
position: "absolute",
|
|
602
|
+
top: "10px",
|
|
603
|
+
right: "10px",
|
|
604
|
+
cursor: "pointer",
|
|
605
|
+
fontWeight: "bold",
|
|
606
|
+
fontSize: "20px",
|
|
607
|
+
color: "#333",
|
|
608
|
+
background: "#eee",
|
|
609
|
+
width: "30px",
|
|
610
|
+
height: "30px",
|
|
611
|
+
display: "flex",
|
|
612
|
+
justifyContent: "center",
|
|
613
|
+
alignItems: "center",
|
|
614
|
+
borderRadius: "50%",
|
|
548
615
|
}}
|
|
549
616
|
>
|
|
550
617
|
×
|
|
@@ -565,7 +632,7 @@ const Review = () => {
|
|
|
565
632
|
</div>
|
|
566
633
|
</div>
|
|
567
634
|
)}
|
|
568
|
-
</
|
|
635
|
+
</Fragment>
|
|
569
636
|
);
|
|
570
637
|
};
|
|
571
638
|
|
|
@@ -16,7 +16,6 @@ const StatusCards = ({ countData }) => {
|
|
|
16
16
|
const pending = countData?.pending || 0;
|
|
17
17
|
const active = countData?.completed || 0;
|
|
18
18
|
const completed = 0;
|
|
19
|
-
const rejected = countData?.rejected || 0;
|
|
20
19
|
|
|
21
20
|
const actualCompleted = countData?.completed || 0;
|
|
22
21
|
const approved = actualCompleted;
|
|
@@ -77,14 +76,11 @@ const StatusCards = ({ countData }) => {
|
|
|
77
76
|
</div>
|
|
78
77
|
<h1 className="status-cards-h1">{t("EKYC_DASHBOARD_TITLE") || "eKYC Verification Dashboard"}</h1>
|
|
79
78
|
<p className="status-cards-subtitle">
|
|
80
|
-
{t("EKYC_DASHBOARD_SUBTITLE") ||
|
|
81
|
-
"Real-time monitoring of consumer verification workflows across all administrative zones."}
|
|
79
|
+
{t("EKYC_DASHBOARD_SUBTITLE") || "Real-time monitoring of consumer verification workflows across all administrative zones."}
|
|
82
80
|
</p>
|
|
83
81
|
</div>
|
|
84
82
|
<div className="total-applications-card">
|
|
85
|
-
<div className="total-label">
|
|
86
|
-
{t("EKYC_TOTAL_APPLICATIONS") || "Total Applications Processed"}
|
|
87
|
-
</div>
|
|
83
|
+
<div className="total-label">{t("EKYC_TOTAL_APPLICATIONS") || "Total Applications Processed"}</div>
|
|
88
84
|
<div className="total-number">{formatNumber(total)}</div>
|
|
89
85
|
<div className="total-badge">↗ +12.4% {t("EKYC_FROM_LAST_QUARTER") || "from last quarter"}</div>
|
|
90
86
|
</div>
|
|
@@ -95,18 +91,13 @@ const StatusCards = ({ countData }) => {
|
|
|
95
91
|
{/* Panel 1: Status Breakdown */}
|
|
96
92
|
<div className="status-panel">
|
|
97
93
|
<div className="panel-title">{t("EKYC_STATUS_BREAKDOWN") || "Status Breakdown"}</div>
|
|
98
|
-
<div className="panel-subtitle">
|
|
99
|
-
{t("EKYC_VERIFICATION_LIFECYCLE") || "Verification lifecycle distribution"}
|
|
100
|
-
</div>
|
|
94
|
+
<div className="panel-subtitle">{t("EKYC_VERIFICATION_LIFECYCLE") || "Verification lifecycle distribution"}</div>
|
|
101
95
|
<div className="breakdown-body">
|
|
102
96
|
<div className="status-legend">
|
|
103
97
|
{legendItems.map((item) => (
|
|
104
98
|
<div key={item.label} className="legend-row">
|
|
105
99
|
<span className="legend-label">
|
|
106
|
-
<span
|
|
107
|
-
className="indicator-dot"
|
|
108
|
-
style={{ background: item.color }}
|
|
109
|
-
/>
|
|
100
|
+
<span className="indicator-dot" style={{ background: item.color }} />
|
|
110
101
|
{item.label}
|
|
111
102
|
</span>
|
|
112
103
|
<span className="legend-value">{formatNumber(item.value)}</span>
|
|
@@ -129,9 +120,7 @@ const StatusCards = ({ countData }) => {
|
|
|
129
120
|
{t("EKYC_SUBMISSION_HEALTH") || "Submission Health"}
|
|
130
121
|
<span className="optimal-badge">{t("EKYC_OPTIMAL") || "Optimal"}</span>
|
|
131
122
|
</div>
|
|
132
|
-
<div className="panel-subtitle">
|
|
133
|
-
{t("EKYC_PLATFORM_EFFICIENCY") || "Platform operational efficiency"}
|
|
134
|
-
</div>
|
|
123
|
+
<div className="panel-subtitle">{t("EKYC_PLATFORM_EFFICIENCY") || "Platform operational efficiency"}</div>
|
|
135
124
|
<div className="health-metrics-row">
|
|
136
125
|
<div className="health-percentage">{healthPct}%</div>
|
|
137
126
|
<div className="health-trend">↗ +2.1%</div>
|
|
@@ -156,4 +145,4 @@ const StatusCards = ({ countData }) => {
|
|
|
156
145
|
);
|
|
157
146
|
};
|
|
158
147
|
|
|
159
|
-
export default StatusCards;
|
|
148
|
+
export default StatusCards;
|