feat: client extra fields + KYC home-visit & video-KYC dialogs

- Add Education Level, Degree/Qualification, Religion, Social Category dropdowns (individual clients) with dependent filtering on the create/edit/preview/view flows
- Add Agriculture Income & Non-Agriculture Income fields under Financial & Classification
- Gate Save with a Verify Client alert dialog when sanctions screening is not yet performed
- Trim Office Name and CKYC Number columns from clients list; widen table to fill container
- Remove DIP/Screening log IDs from preview and personal-data tabs
- Rename "Branch Visit" to "Home Visit" across KYC management
- Wire Take Action: open dedicated dialogs for Schedule Home Visit (officer + datetime) and Send Video KYC link (channels + officer + 48h expiry + session preview)
- Migrate Signatory and Guardian image dialogs to inject() for prefer-inject lint rule

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
Aditya
2026-04-27 16:36:58 +05:30
co-authored by Claude Opus 4.7
parent d72e969dc3
commit 52e3395345
15 changed files with 4021 additions and 997 deletions
@@ -34,7 +34,11 @@
--km-g900: #0f172a;
display: block;
font-family: 'DM Sans', system-ui, -apple-system, sans-serif;
font-family:
'DM Sans',
system-ui,
-apple-system,
sans-serif;
background: var(--km-g50);
color: var(--km-g800);
font-size: 14px;
@@ -130,7 +134,7 @@
background: #fff;
border: 1px solid var(--km-g200);
border-radius: 12px;
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.08);
box-shadow: 0 1px 3px rgb(0 0 0 / 8%);
}
.km-ch {
@@ -172,11 +176,30 @@
flex-shrink: 0;
}
.km-ci-t { background: var(--km-teal-l); color: var(--km-teal); }
.km-ci-a { background: var(--km-amber-l); color: var(--km-amber); }
.km-ci-r { background: var(--km-red-l); color: var(--km-red); }
.km-ci-b { background: var(--km-blue-l); color: var(--km-blue); }
.km-ci-g { background: var(--km-green-l); color: var(--km-green); }
.km-ci-t {
background: var(--km-teal-l);
color: var(--km-teal);
}
.km-ci-a {
background: var(--km-amber-l);
color: var(--km-amber);
}
.km-ci-r {
background: var(--km-red-l);
color: var(--km-red);
}
.km-ci-b {
background: var(--km-blue-l);
color: var(--km-blue);
}
.km-ci-g {
background: var(--km-green-l);
color: var(--km-green);
}
/* Badges */
.km-b {
@@ -189,17 +212,53 @@
font-weight: 500;
}
.km-b-gr { background: var(--km-green-l); color: var(--km-green); }
.km-b-am { background: var(--km-amber-l); color: var(--km-amber); }
.km-b-re { background: var(--km-red-l); color: var(--km-red); }
.km-b-or { background: var(--km-orange-l); color: var(--km-orange); }
.km-b-bl { background: var(--km-blue-l); color: var(--km-blue); }
.km-b-te { background: var(--km-teal-l); color: var(--km-teal); }
.km-b-gy { background: var(--km-g100); color: var(--km-g600); }
.km-b-nv { background: #e8edf5; color: var(--km-navy); }
.km-b-gr {
background: var(--km-green-l);
color: var(--km-green);
}
.km-ml-auto { margin-left: auto; }
.km-ml-12 { margin-left: 12px; }
.km-b-am {
background: var(--km-amber-l);
color: var(--km-amber);
}
.km-b-re {
background: var(--km-red-l);
color: var(--km-red);
}
.km-b-or {
background: var(--km-orange-l);
color: var(--km-orange);
}
.km-b-bl {
background: var(--km-blue-l);
color: var(--km-blue);
}
.km-b-te {
background: var(--km-teal-l);
color: var(--km-teal);
}
.km-b-gy {
background: var(--km-g100);
color: var(--km-g600);
}
.km-b-nv {
background: #e8edf5;
color: var(--km-navy);
}
.km-ml-auto {
margin-left: auto;
}
.km-ml-12 {
margin-left: 12px;
}
/* Buttons */
.km-btn {
@@ -216,14 +275,57 @@
transition: all 0.15s;
}
.km-btn-t { background: var(--km-teal); border-color: var(--km-teal); color: #fff; &:hover { opacity: 0.9; } }
.km-btn-ot { background: #fff; border-color: var(--km-teal); color: var(--km-teal); &:hover { background: var(--km-teal-l); } }
.km-btn-n { background: var(--km-navy); border-color: var(--km-navy); color: #fff; }
.km-btn-a { background: var(--km-amber); border-color: var(--km-amber); color: #fff; }
.km-btn-r { background: var(--km-red); border-color: var(--km-red); color: #fff; }
.km-btn-g { background: #fff; border-color: var(--km-g300); color: var(--km-g600); &:hover { background: var(--km-g50); } }
.km-btn-t {
background: var(--km-teal);
border-color: var(--km-teal);
color: #fff;
.km-w { width: 100%; }
&:hover {
opacity: 0.9;
}
}
.km-btn-ot {
background: #fff;
border-color: var(--km-teal);
color: var(--km-teal);
&:hover {
background: var(--km-teal-l);
}
}
.km-btn-n {
background: var(--km-navy);
border-color: var(--km-navy);
color: #fff;
}
.km-btn-a {
background: var(--km-amber);
border-color: var(--km-amber);
color: #fff;
}
.km-btn-r {
background: var(--km-red);
border-color: var(--km-red);
color: #fff;
}
.km-btn-g {
background: #fff;
border-color: var(--km-g300);
color: var(--km-g600);
&:hover {
background: var(--km-g50);
}
}
.km-w {
width: 100%;
}
/* Stat row */
.km-stat-row {
@@ -238,12 +340,12 @@
border: 1px solid var(--km-g200);
border-radius: 12px;
padding: 14px;
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.08);
box-shadow: 0 1px 3px rgb(0 0 0 / 8%);
cursor: pointer;
transition: all 0.15s;
&:hover {
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
box-shadow: 0 4px 12px rgb(0 0 0 / 10%);
}
}
@@ -370,11 +472,30 @@
font-weight: 600;
}
.km-sp-ac { background: var(--km-green-l); color: var(--km-green); }
.km-sp-fr { background: var(--km-amber-l); color: var(--km-amber); }
.km-sp-in { background: var(--km-orange-l); color: var(--km-orange); }
.km-sp-do { background: var(--km-red-l); color: var(--km-red); }
.km-sp-al { background: #fef9c3; color: #92400e; }
.km-sp-ac {
background: var(--km-green-l);
color: var(--km-green);
}
.km-sp-fr {
background: var(--km-amber-l);
color: var(--km-amber);
}
.km-sp-in {
background: var(--km-orange-l);
color: var(--km-orange);
}
.km-sp-do {
background: var(--km-red-l);
color: var(--km-red);
}
.km-sp-al {
background: #fef9c3;
color: #92400e;
}
/* Progress bar */
.km-pbar {
@@ -424,10 +545,25 @@
font-weight: 600;
}
.km-d-ok { background: var(--km-green-l); color: var(--km-green); }
.km-d-pe { background: var(--km-amber-l); color: var(--km-amber); }
.km-d-fa { background: var(--km-red-l); color: var(--km-red); }
.km-d-tr { background: var(--km-blue-l); color: var(--km-blue); }
.km-d-ok {
background: var(--km-green-l);
color: var(--km-green);
}
.km-d-pe {
background: var(--km-amber-l);
color: var(--km-amber);
}
.km-d-fa {
background: var(--km-red-l);
color: var(--km-red);
}
.km-d-tr {
background: var(--km-blue-l);
color: var(--km-blue);
}
/* Pagination */
.km-pagination {
@@ -489,12 +625,41 @@
flex-shrink: 0;
}
.km-nd1 { background: var(--km-blue-l); border-color: #93c5fd; color: var(--km-blue); }
.km-nd2 { background: var(--km-amber-l); border-color: #fcd34d; color: var(--km-amber); }
.km-nd3 { background: var(--km-orange-l); border-color: #fdba74; color: var(--km-orange); }
.km-ndf { background: var(--km-red-l); border-color: #fca5a5; color: var(--km-red); }
.km-ndi { background: #fee2e2; border-color: #f87171; color: #991b1b; }
.km-ndd { background: var(--km-g100); border-color: var(--km-g300); color: var(--km-g500); }
.km-nd1 {
background: var(--km-blue-l);
border-color: #93c5fd;
color: var(--km-blue);
}
.km-nd2 {
background: var(--km-amber-l);
border-color: #fcd34d;
color: var(--km-amber);
}
.km-nd3 {
background: var(--km-orange-l);
border-color: #fdba74;
color: var(--km-orange);
}
.km-ndf {
background: var(--km-red-l);
border-color: #fca5a5;
color: var(--km-red);
}
.km-ndi {
background: #fee2e2;
border-color: #f87171;
color: #991b1b;
}
.km-ndd {
background: var(--km-g100);
border-color: var(--km-g300);
color: var(--km-g500);
}
.km-nl {
width: 1px;
@@ -509,9 +674,13 @@
color: var(--km-g800);
}
.km-warn { color: var(--km-amber); }
.km-warn-o { color: var(--km-orange); }
.km-warn-d { color: var(--km-g600); }
.km-warn {
color: var(--km-amber);
}
.km-warn-o {
color: var(--km-orange);
}
.km-ns {
font-size: 11px;
@@ -520,9 +689,20 @@
margin-bottom: 5px;
}
.km-ok { color: var(--km-green); font-weight: 600; }
.km-pending { color: var(--km-amber); font-weight: 600; }
.km-fail { color: var(--km-red); font-weight: 600; }
.km-ok {
color: var(--km-green);
font-weight: 600;
}
.km-pending {
color: var(--km-amber);
font-weight: 600;
}
.km-fail {
color: var(--km-red);
font-weight: 600;
}
.km-ntags {
display: flex;
@@ -541,12 +721,41 @@
border: 1px solid;
}
.km-cp-sms { background: #eff6ff; color: #1d4ed8; border-color: #93c5fd; }
.km-cp-mail { background: #f0fdf4; color: #15803d; border-color: #86efac; }
.km-cp-ivr { background: #faf5ff; color: #7c3aed; border-color: #c4b5fd; }
.km-cp-post { background: #fff7ed; color: #c2410c; border-color: #fdba74; }
.km-cp-vis { background: var(--km-teal-l); color: var(--km-teal); border-color: #5eead4; }
.km-cp-vid { background: #ede9fe; color: #5b21b6; border-color: #a78bfa; }
.km-cp-sms {
background: #eff6ff;
color: #1d4ed8;
border-color: #93c5fd;
}
.km-cp-mail {
background: #f0fdf4;
color: #15803d;
border-color: #86efac;
}
.km-cp-ivr {
background: #faf5ff;
color: #7c3aed;
border-color: #c4b5fd;
}
.km-cp-post {
background: #fff7ed;
color: #c2410c;
border-color: #fdba74;
}
.km-cp-vis {
background: var(--km-teal-l);
color: var(--km-teal);
border-color: #5eead4;
}
.km-cp-vid {
background: #ede9fe;
color: #5b21b6;
border-color: #a78bfa;
}
.km-row-actions {
margin-top: 8px;
@@ -574,9 +783,20 @@
background: var(--km-teal-l);
}
.km-channel-i { font-size: 16px; margin-bottom: 3px; }
.km-channel-n { font-size: 11px; font-weight: 600; }
.km-channel-d { font-size: 10px; color: var(--km-g500); }
.km-channel-i {
font-size: 16px;
margin-bottom: 3px;
}
.km-channel-n {
font-size: 11px;
font-weight: 600;
}
.km-channel-d {
font-size: 10px;
color: var(--km-g500);
}
/* Meta items */
.km-mi {
@@ -618,15 +838,79 @@
transition: all 0.15s;
&:hover {
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
box-shadow: 0 4px 12px rgb(0 0 0 / 10%);
}
}
.km-sc-ac { border-color: #86efac; background: var(--km-green-l); .km-sc-l, .km-sc-d { color: #166534; } .km-sc-n { color: var(--km-green); } }
.km-sc-fr { border-color: #fcd34d; background: var(--km-amber-l); .km-sc-l, .km-sc-d { color: #92400e; } .km-sc-n { color: var(--km-amber); } }
.km-sc-in { border-color: #fdba74; background: var(--km-orange-l); .km-sc-l, .km-sc-d { color: #7c2d12; } .km-sc-n { color: var(--km-orange); } }
.km-sc-do { border-color: #fca5a5; background: var(--km-red-l); .km-sc-l, .km-sc-d { color: #7f1d1d; } .km-sc-n { color: var(--km-red); } }
.km-sc-al { border-color: #fde047; background: #fef9c3; .km-sc-l, .km-sc-d { color: #713f12; } .km-sc-n { color: #92400e; } }
.km-sc-ac {
border-color: #86efac;
background: var(--km-green-l);
.km-sc-l,
.km-sc-d {
color: #166534;
}
.km-sc-n {
color: var(--km-green);
}
}
.km-sc-fr {
border-color: #fcd34d;
background: var(--km-amber-l);
.km-sc-l,
.km-sc-d {
color: #92400e;
}
.km-sc-n {
color: var(--km-amber);
}
}
.km-sc-in {
border-color: #fdba74;
background: var(--km-orange-l);
.km-sc-l,
.km-sc-d {
color: #7c2d12;
}
.km-sc-n {
color: var(--km-orange);
}
}
.km-sc-do {
border-color: #fca5a5;
background: var(--km-red-l);
.km-sc-l,
.km-sc-d {
color: #7f1d1d;
}
.km-sc-n {
color: var(--km-red);
}
}
.km-sc-al {
border-color: #fde047;
background: #fef9c3;
.km-sc-l,
.km-sc-d {
color: #713f12;
}
.km-sc-n {
color: #92400e;
}
}
.km-sc-l {
font-size: 10px;
@@ -719,7 +1003,7 @@
.km-overlay {
position: fixed;
inset: 0;
background: rgba(0, 0, 0, 0.45);
background: rgb(0 0 0 / 45%);
z-index: 1200;
display: flex;
align-items: center;
@@ -735,7 +1019,7 @@
max-height: 90vh;
display: flex;
flex-direction: column;
box-shadow: 0 20px 60px rgba(0, 0, 0, 0.2);
box-shadow: 0 20px 60px rgb(0 0 0 / 20%);
}
.km-mh {
@@ -787,7 +1071,9 @@
margin-left: auto;
flex-shrink: 0;
&:hover { background: var(--km-g100); }
&:hover {
background: var(--km-g100);
}
}
.km-mbody {
@@ -863,7 +1149,9 @@
}
}
.km-ps-done::after { background: var(--km-teal); }
.km-ps-done::after {
background: var(--km-teal);
}
.km-ps-dot {
width: 28px;
@@ -881,9 +1169,23 @@
position: relative;
}
.km-ps-done .km-ps-dot { background: var(--km-teal); border-color: var(--km-teal); color: #fff; }
.km-ps-current .km-ps-dot { background: #fff; border-color: var(--km-amber); color: var(--km-amber); }
.km-ps-danger .km-ps-dot { background: #fff; border-color: var(--km-red); color: var(--km-red); }
.km-ps-done .km-ps-dot {
background: var(--km-teal);
border-color: var(--km-teal);
color: #fff;
}
.km-ps-current .km-ps-dot {
background: #fff;
border-color: var(--km-amber);
color: var(--km-amber);
}
.km-ps-danger .km-ps-dot {
background: #fff;
border-color: var(--km-red);
color: var(--km-red);
}
.km-ps-label {
font-size: 10px;
@@ -893,9 +1195,19 @@
max-width: 70px;
}
.km-ps-done .km-ps-label { color: var(--km-teal); }
.km-ps-current .km-ps-label { color: var(--km-amber); font-weight: 600; }
.km-ps-danger .km-ps-label { color: var(--km-red); font-weight: 600; }
.km-ps-done .km-ps-label {
color: var(--km-teal);
}
.km-ps-current .km-ps-label {
color: var(--km-amber);
font-weight: 600;
}
.km-ps-danger .km-ps-label {
color: var(--km-red);
font-weight: 600;
}
/* Next action banner */
.km-next-banner {
@@ -908,15 +1220,45 @@
gap: 12px;
}
.km-nb-alert { background: var(--km-amber-l); border-color: #fcd34d; }
.km-nb-urgent { background: var(--km-orange-l); border-color: #fdba74; }
.km-nb-freeze { background: var(--km-amber-l); border-color: #fcd34d; }
.km-nb-inop { background: var(--km-orange-l); border-color: #fdba74; }
.km-nb-dormant { background: var(--km-red-l); border-color: #fca5a5; }
.km-nb-alert {
background: var(--km-amber-l);
border-color: #fcd34d;
}
.km-nb-icon { font-size: 22px; flex-shrink: 0; }
.km-nb-title { font-size: 13px; font-weight: 700; margin-bottom: 2px; }
.km-nb-sub { font-size: 12px; }
.km-nb-urgent {
background: var(--km-orange-l);
border-color: #fdba74;
}
.km-nb-freeze {
background: var(--km-amber-l);
border-color: #fcd34d;
}
.km-nb-inop {
background: var(--km-orange-l);
border-color: #fdba74;
}
.km-nb-dormant {
background: var(--km-red-l);
border-color: #fca5a5;
}
.km-nb-icon {
font-size: 22px;
flex-shrink: 0;
}
.km-nb-title {
font-size: 13px;
font-weight: 700;
margin-bottom: 2px;
}
.km-nb-sub {
font-size: 12px;
}
/* Modal stat strip */
.km-mstat-row {
@@ -969,7 +1311,9 @@
padding: 12px 0;
border-bottom: 1px solid var(--km-g100);
&:last-child { border-bottom: none; }
&:last-child {
border-bottom: none;
}
}
.km-mti-dot {
@@ -985,14 +1329,36 @@
flex-shrink: 0;
}
.km-mti-done { background: var(--km-green-l); border-color: var(--km-green); color: var(--km-green); }
.km-mti-pend { background: var(--km-amber-l); border-color: var(--km-amber); color: var(--km-amber); }
.km-mti-done {
background: var(--km-green-l);
border-color: var(--km-green);
color: var(--km-green);
}
.km-mti-text { font-size: 13px; font-weight: 500; }
.km-done { color: var(--km-g700); }
.km-pend { color: var(--km-amber); }
.km-mti-pend {
background: var(--km-amber-l);
border-color: var(--km-amber);
color: var(--km-amber);
}
.km-mti-sub { font-size: 11px; color: var(--km-g400); margin-top: 2px; }
.km-mti-text {
font-size: 13px;
font-weight: 500;
}
.km-done {
color: var(--km-g700);
}
.km-pend {
color: var(--km-amber);
}
.km-mti-sub {
font-size: 11px;
color: var(--km-g400);
margin-top: 2px;
}
.km-pending-row {
text-align: center;
@@ -1009,8 +1375,15 @@
color: var(--km-g400);
}
.km-empty-i { font-size: 28px; margin-bottom: 8px; }
.km-empty-s { font-size: 12px; margin-top: 4px; }
.km-empty-i {
font-size: 28px;
margin-bottom: 8px;
}
.km-empty-s {
font-size: 12px;
margin-top: 4px;
}
/* Evidence */
.km-map {
@@ -1069,8 +1442,15 @@
gap: 12px;
}
.km-action-t { font-size: 13px; font-weight: 600; }
.km-action-d { font-size: 12px; color: var(--km-g500); }
.km-action-t {
font-size: 13px;
font-weight: 600;
}
.km-action-d {
font-size: 12px;
color: var(--km-g500);
}
/* Toast */
.km-toast {
@@ -1094,12 +1474,178 @@
}
}
@media (max-width: 900px) {
@media (width <= 900px) {
.km-stat-row,
.km-sc-row { grid-template-columns: repeat(2, 1fr); }
.km-sc-row {
grid-template-columns: repeat(2, 1fr);
}
.km-r2,
.km-notif-grid { grid-template-columns: 1fr; }
.km-mstat-row { grid-template-columns: repeat(2, 1fr); }
.km-prog-steps { flex-wrap: wrap; gap: 10px; }
.km-ps::after { display: none; }
.km-notif-grid {
grid-template-columns: 1fr;
}
.km-mstat-row {
grid-template-columns: repeat(2, 1fr);
}
.km-prog-steps {
flex-wrap: wrap;
gap: 10px;
}
.km-ps::after {
display: none;
}
}
/* Home Visit Schedule Dialog */
.hv-modal {
width: 520px;
}
.hv-body {
padding: 18px 22px;
display: flex;
flex-direction: column;
gap: 14px;
overflow: auto;
}
.hv-addr {
background: #f8fafc;
border: 1px solid var(--km-g200);
border-radius: 10px;
padding: 12px 14px;
}
.hv-addr-label {
font-size: 11px;
font-weight: 600;
text-transform: uppercase;
letter-spacing: 0.06em;
color: #64748b;
margin-bottom: 4px;
}
.hv-addr-name {
font-size: 14px;
font-weight: 600;
color: #0f172a;
margin-bottom: 2px;
}
.hv-addr-text {
font-size: 13px;
color: #334155;
line-height: 1.4;
}
.hv-addr-branch {
margin-top: 6px;
font-size: 12px;
color: #64748b;
}
.hv-row {
display: flex;
flex-direction: column;
gap: 6px;
}
.hv-label {
font-size: 12px;
font-weight: 600;
color: #334155;
}
.hv-req {
color: #dc2626;
margin-left: 2px;
}
.hv-input {
width: 100%;
padding: 9px 12px;
border: 1px solid var(--km-g200);
border-radius: 8px;
font-size: 13px;
color: #0f172a;
background: #fff;
font-family: inherit;
transition:
border-color 0.15s,
box-shadow 0.15s;
}
.hv-input:focus {
outline: none;
border-color: var(--km-teal);
box-shadow: 0 0 0 3px rgb(20 184 166 / 15%);
}
.hv-textarea {
resize: vertical;
min-height: 60px;
}
.hv-footer {
padding: 14px 22px;
border-top: 1px solid var(--km-g200);
display: flex;
justify-content: flex-end;
gap: 10px;
flex-shrink: 0;
}
.km-btn:disabled {
opacity: 0.5;
cursor: not-allowed;
}
/* Video KYC Dialog */
.vkyc-ic {
color: var(--km-teal);
margin-right: 6px;
font-size: 12px;
}
.vkyc-chans {
display: flex;
gap: 18px;
flex-wrap: wrap;
}
.vkyc-chan {
display: inline-flex;
align-items: center;
gap: 6px;
font-size: 13px;
color: #334155;
cursor: pointer;
user-select: none;
}
.vkyc-chan input {
accent-color: var(--km-teal);
width: 15px;
height: 15px;
cursor: pointer;
}
.vkyc-hint {
font-size: 11px;
color: #64748b;
margin-top: 2px;
}
.vkyc-link {
background: #f1f5f9;
border: 1px dashed #cbd5e1;
border-radius: 8px;
padding: 9px 12px;
font-family: 'Roboto Mono', 'DM Mono', monospace;
font-size: 12px;
color: #0f172a;
word-break: break-all;
}