@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.
@@ -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 className="review-section-wrapper" style={{ marginBottom: "48px", background: "#fff", borderRadius: "12px", border: "1px solid #EAECF0", overflow: "hidden" }}>
66
- <div style={{ padding: "20px 24px", background: "#F9FAFB", borderBottom: "1px solid #EAECF0", display: "flex", justifyContent: "space-between", alignItems: "center" }}>
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 style={{ padding: "16px 0", textAlign: "left", color: "#667085", fontSize: "12px", fontWeight: "600", textTransform: "uppercase", width: "30%" }}>{t("EKYC_FIELD_NAME")}</th>
76
- <th style={{ padding: "16px 0", textAlign: "left", color: "#667085", fontSize: "12px", fontWeight: "600", textTransform: "uppercase", width: "35%" }}>{t("EKYC_EXISTING_INFORMATION")}</th>
77
- <th style={{ padding: "16px 0", textAlign: "left", color: "#667085", fontSize: "12px", fontWeight: "600", textTransform: "uppercase", width: "35%" }}>{t("EKYC_PROPOSED_UPDATES")}</th>
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 style={{ padding: "16px 0", fontSize: "14px", color: isChanged ? "#1B8B32" : "#101828", fontWeight: isChanged ? "700" : "400" }}>
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 style={{ background: "#ECFDF3", color: "#067647", padding: "2px 8px", borderRadius: "12px", fontSize: "10px", fontWeight: "600" }}>
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 { kNumber, kno, edits = {} } = flowState;
127
- const activeKno = kNumber || kno;
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: apiConn?.consumerName || (apiConn?.firstName ? [apiConn.firstName, apiConn.middleName, apiConn.lastName].filter(Boolean).join(" ") : null),
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
- <div className="employeeCard overflow-y-scroll">
404
- <Card style={{ padding: "32px" }}>
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={addressData.doorPhotoFilestoreId && (
469
- <div onClick={() => handleViewDocument(addressData.doorPhotoFilestoreId)}>
470
- <GenericFileIcon style={{ cursor: "pointer", fill: "#F47738" }} />
471
- </div>
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={meterData.meterPhotoFileStoreId && (
478
- <div onClick={() => handleViewDocument(meterData.meterPhotoFileStoreId)}>
479
- <GenericFileIcon style={{ cursor: "pointer", fill: "#F47738" }} />
480
- </div>
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={propertyData.buildingImageFileStoreId && (
487
- <div onClick={() => handleViewDocument(propertyData.buildingImageFileStoreId)}>
488
- <GenericFileIcon style={{ cursor: "pointer", fill: "#F47738" }} />
489
- </div>
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={propertyData.propertyDocumentFileStoreId && (
496
- <div onClick={() => handleViewDocument(propertyData.propertyDocumentFileStoreId)}>
497
- <GenericFileIcon style={{ cursor: "pointer", fill: "#F47738" }} />
498
- </div>
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
- <ActionBar style={{ position: "static", marginTop: "32px", display: "flex", justifyContent: "flex-end" }}>
516
- <SubmitBar
517
- label={t("EKYC_REJECT")}
518
- onSubmit={handleReject}
519
- disabled={!agree}
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 style={{
532
- position: "fixed", top: 0, left: 0, width: "100%", height: "100%",
533
- backgroundColor: "rgba(0,0,0,0.7)", display: "flex", justifyContent: "center",
534
- alignItems: "center", zIndex: 10000
535
- }}>
536
- <div style={{
537
- position: "relative", backgroundColor: "#fff", padding: "30px",
538
- borderRadius: "12px", maxWidth: "600px", width: "100%", maxHeight: "70vh", overflow: "auto",
539
- boxShadow: "0 20px 25px -5px rgba(0, 0, 0, 0.1), 0 10px 10px -5px rgba(0, 0, 0, 0.04)"
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", top: "10px", right: "10px", cursor: "pointer",
545
- fontWeight: "bold", fontSize: "20px", color: "#333", background: "#eee",
546
- width: "30px", height: "30px", display: "flex", justifyContent: "center",
547
- alignItems: "center", borderRadius: "50%"
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
- </div>
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;