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
@@ -7,7 +7,6 @@
-->
<div class="personal-data-container mat-typography">
<!-- Personal Information -->
<div class="pd-section">
<div class="pd-section__header">
@@ -50,13 +49,15 @@
@if (clientViewData.dateOfBirth) {
<div class="pd-field">
<div class="pd-field__label">{{ 'labels.inputs.Date of Birth' | translate }}</div>
<div class="pd-field__value">{{ clientViewData.dateOfBirth | dateFormat:'DD-MMMM-YYYY' }}</div>
<div class="pd-field__value">{{ clientViewData.dateOfBirth | dateFormat: 'DD-MMMM-YYYY' }}</div>
</div>
}
@if (clientViewData.ageYears != null) {
<div class="pd-field">
<div class="pd-field__label">Age</div>
<div class="pd-field__value">{{ clientViewData.ageYears }}y {{ clientViewData.ageMonths || 0 }}m {{ clientViewData.ageDays || 0 }}d</div>
<div class="pd-field__value">
{{ clientViewData.ageYears }}y {{ clientViewData.ageMonths || 0 }}m {{ clientViewData.ageDays || 0 }}d
</div>
</div>
}
@if (clientViewData.gender) {
@@ -71,11 +72,39 @@
<div class="pd-field__value">{{ clientViewData.maritalStatus.name }}</div>
</div>
}
@if (clientViewData.educationLevel) {
<div class="pd-field">
<div class="pd-field__label">Education Level</div>
<div class="pd-field__value">{{ clientViewData.educationLevel.name }}</div>
</div>
}
@if (clientViewData.degreeQualification) {
<div class="pd-field">
<div class="pd-field__label">Degree / Qualification</div>
<div class="pd-field__value">{{ clientViewData.degreeQualification.name }}</div>
</div>
}
@if (clientViewData.religion) {
<div class="pd-field">
<div class="pd-field__label">Religion</div>
<div class="pd-field__value">{{ clientViewData.religion.name }}</div>
</div>
}
@if (clientViewData.socialCategory) {
<div class="pd-field">
<div class="pd-field__label">Social Category</div>
<div class="pd-field__value">{{ clientViewData.socialCategory.name }}</div>
</div>
}
@if (clientViewData.isMinor != null) {
<div class="pd-field">
<div class="pd-field__label">Minor</div>
<div class="pd-field__value">
<span class="pd-verify-badge" [class.pd-verify-badge--verified]="!clientViewData.isMinor" [class.pd-verify-badge--pending]="clientViewData.isMinor">
<span
class="pd-verify-badge"
[class.pd-verify-badge--verified]="!clientViewData.isMinor"
[class.pd-verify-badge--pending]="clientViewData.isMinor"
>
{{ clientViewData.isMinor ? 'Yes (Age < 10)' : 'No' }}
</span>
</div>
@@ -84,7 +113,11 @@
<div class="pd-field">
<div class="pd-field__label">{{ 'labels.inputs.Is staff' | translate }}</div>
<div class="pd-field__value">
<span class="pd-verify-badge" [class.pd-verify-badge--verified]="clientViewData.isStaff" [class.pd-verify-badge--pending]="!clientViewData.isStaff">
<span
class="pd-verify-badge"
[class.pd-verify-badge--verified]="clientViewData.isStaff"
[class.pd-verify-badge--pending]="!clientViewData.isStaff"
>
{{ clientViewData.isStaff ? 'Yes' : 'No' }}
</span>
</div>
@@ -100,7 +133,7 @@
@if (clientViewData.dateOfBirth) {
<div class="pd-field">
<div class="pd-field__label">{{ 'labels.inputs.Incorporation Date' | translate }}</div>
<div class="pd-field__value">{{ clientViewData.dateOfBirth | dateFormat:'DD-MM-YYYY' }}</div>
<div class="pd-field__value">{{ clientViewData.dateOfBirth | dateFormat: 'DD-MM-YYYY' }}</div>
</div>
}
}
@@ -112,7 +145,9 @@
}
<div class="pd-field">
<div class="pd-field__label">Nationality</div>
<div class="pd-field__value">{{ clientViewData.nationalityId || clientViewData.nationality || 'Indian' }}</div>
<div class="pd-field__value">
{{ clientViewData.nationalityId || clientViewData.nationality || 'Indian' }}
</div>
</div>
</div>
</div>
@@ -176,7 +211,9 @@
@if (clientViewData.clientNonPersonDetails.incorpValidityTillDate) {
<div class="pd-field">
<div class="pd-field__label">{{ 'labels.inputs.Incorporation Validity Till Date' | translate }}</div>
<div class="pd-field__value">{{ clientViewData.clientNonPersonDetails.incorpValidityTillDate | dateFormat:'DD-MM-YYYY' }}</div>
<div class="pd-field__value">
{{ clientViewData.clientNonPersonDetails.incorpValidityTillDate | dateFormat: 'DD-MM-YYYY' }}
</div>
</div>
}
@if (clientViewData.clientNonPersonDetails.incorpNumber) {
@@ -221,7 +258,9 @@
<div class="pd-field">
<div class="pd-field__label">{{ 'labels.inputs.Email' | translate }}</div>
<div class="pd-field__value">
<span class="pd-contact-icon"><i class="fa fa-envelope-o"></i> {{ clientViewData.emailAddress || '-' }}</span>
<span class="pd-contact-icon"
><i class="fa fa-envelope-o"></i> {{ clientViewData.emailAddress || '-' }}</span
>
</div>
</div>
</div>
@@ -240,15 +279,19 @@
<div class="pd-field">
<div class="pd-field__label">Mobile DIP Status</div>
<div class="pd-field__value">
@if (clientViewData.mobileVerified === true || clientViewData.mobileVerified === 'true' || clientViewData.mobileVerified === 1
|| clientViewData.dipVerified === true || clientViewData.dipVerified === 'true' || clientViewData.dipVerified === 1) {
@if (
clientViewData.mobileVerified === true ||
clientViewData.mobileVerified === 'true' ||
clientViewData.mobileVerified === 1 ||
clientViewData.dipVerified === true ||
clientViewData.dipVerified === 'true' ||
clientViewData.dipVerified === 1
) {
<span class="pd-verify-badge pd-verify-badge--verified">
<i class="fa fa-check-circle"></i> Verified
</span>
} @else {
<span class="pd-verify-badge pd-verify-badge--pending">
<i class="fa fa-clock-o"></i> Pending
</span>
<span class="pd-verify-badge pd-verify-badge--pending"> <i class="fa fa-clock-o"></i> Pending </span>
}
</div>
</div>
@@ -258,26 +301,21 @@
<div class="pd-field__value monospace">{{ formatDateTime(clientViewData.dipTimestamp) }}</div>
</div>
}
@if (clientViewData.dipLookupLogId) {
<div class="pd-field">
<div class="pd-field__label">DIP Lookup Log ID</div>
<div class="pd-field__value monospace">{{ clientViewData.dipLookupLogId }}</div>
</div>
}
<!-- Alternate Mobile DIP -->
@if (clientViewData.alternateMobileNo) {
<div class="pd-field">
<div class="pd-field__label">Alternate Mobile DIP Status</div>
<div class="pd-field__value">
@if (clientViewData.alternateDipVerified === true || clientViewData.alternateDipVerified === 'true' || clientViewData.alternateDipVerified === 1) {
@if (
clientViewData.alternateDipVerified === true ||
clientViewData.alternateDipVerified === 'true' ||
clientViewData.alternateDipVerified === 1
) {
<span class="pd-verify-badge pd-verify-badge--verified">
<i class="fa fa-check-circle"></i> Verified
</span>
} @else {
<span class="pd-verify-badge pd-verify-badge--pending">
<i class="fa fa-clock-o"></i> Pending
</span>
<span class="pd-verify-badge pd-verify-badge--pending"> <i class="fa fa-clock-o"></i> Pending </span>
}
</div>
</div>
@@ -287,93 +325,91 @@
<div class="pd-field__value monospace">{{ formatDateTime(clientViewData.alternateDipTimestamp) }}</div>
</div>
}
@if (clientViewData.alternateDipLookupLogId) {
<div class="pd-field">
<div class="pd-field__label">Alternate DIP Log ID</div>
<div class="pd-field__value monospace">{{ clientViewData.alternateDipLookupLogId }}</div>
</div>
}
}
<!-- Sanctions / Name Screening -->
<div class="pd-field">
<div class="pd-field__label">Name Screening (Sanctions)</div>
<div class="pd-field__value">
@if (clientViewData.nameVerified === true || clientViewData.nameVerified === 'true' || clientViewData.nameVerified === 1) {
@if (
clientViewData.nameVerified === true ||
clientViewData.nameVerified === 'true' ||
clientViewData.nameVerified === 1
) {
<span class="pd-verify-badge pd-verify-badge--verified"><i class="fa fa-check-circle"></i> Clear</span>
} @else if (clientViewData.nameVerified === false || clientViewData.nameVerified === 'false' || clientViewData.nameVerified === 0) {
<span class="pd-verify-badge pd-verify-badge--danger"><i class="fa fa-exclamation-triangle"></i> Match Found</span>
} @else if (
clientViewData.nameVerified === false ||
clientViewData.nameVerified === 'false' ||
clientViewData.nameVerified === 0
) {
<span class="pd-verify-badge pd-verify-badge--danger"
><i class="fa fa-exclamation-triangle"></i> Match Found</span
>
} @else {
<span class="pd-verify-badge pd-verify-badge--pending"><i class="fa fa-clock-o"></i> Pending</span>
}
</div>
</div>
@if (clientViewData.screeningLogId) {
<div class="pd-field">
<div class="pd-field__label">Screening Log ID</div>
<div class="pd-field__value monospace">{{ clientViewData.screeningLogId }}</div>
</div>
}
</div>
</div>
</div>
<!-- Financial & Classification (Individual only) -->
@if (clientViewData?.legalForm?.id !== 2) {
<div class="pd-section">
<div class="pd-section__header">
<i class="fa fa-chart-line"></i>
<h3>Financial &amp; Classification</h3>
</div>
<div class="pd-section__body">
<div class="pd-grid">
<div class="pd-field">
<div class="pd-field__label">Monthly Income</div>
<div class="pd-field__value">
@if (clientViewData.monthlyIncome != null && clientViewData.monthlyIncome !== '') {
<span class="monospace">&#8377; {{ clientViewData.monthlyIncome | number }}</span>
} @else {
-
}
<div class="pd-section">
<div class="pd-section__header">
<i class="fa fa-chart-line"></i>
<h3>Financial &amp; Classification</h3>
</div>
<div class="pd-section__body">
<div class="pd-grid">
<div class="pd-field">
<div class="pd-field__label">Monthly Income</div>
<div class="pd-field__value">
@if (clientViewData.monthlyIncome != null && clientViewData.monthlyIncome !== '') {
<span class="monospace">&#8377; {{ clientViewData.monthlyIncome | number }}</span>
} @else {
-
}
</div>
</div>
<div class="pd-field">
<div class="pd-field__label">Annual Turnover (Last FY)</div>
<div class="pd-field__value">
@if (clientViewData.annualTurnover != null && clientViewData.annualTurnover !== '') {
<span class="monospace">&#8377; {{ clientViewData.annualTurnover | number }}</span>
} @else {
-
}
</div>
</div>
@if (clientViewData.clientType) {
<div class="pd-field">
<div class="pd-field__label">{{ 'labels.inputs.Client Type' | translate }}</div>
<div class="pd-field__value">{{ clientViewData.clientType.name }}</div>
</div>
}
@if (clientViewData.clientClassification) {
<div class="pd-field">
<div class="pd-field__label">{{ 'labels.inputs.Client Classification' | translate }}</div>
<div class="pd-field__value">{{ clientViewData.clientClassification.name }}</div>
</div>
}
@if (clientViewData.occupationCategory) {
<div class="pd-field">
<div class="pd-field__label">{{ 'labels.inputs.Occupation Category' | translate }}</div>
<div class="pd-field__value">{{ clientViewData.occupationCategory.name }}</div>
</div>
}
@if (clientViewData.occupation) {
<div class="pd-field">
<div class="pd-field__label">{{ 'labels.inputs.Occupation' | translate }}</div>
<div class="pd-field__value">{{ clientViewData.occupation.name }}</div>
</div>
}
</div>
<div class="pd-field">
<div class="pd-field__label">Annual Turnover (Last FY)</div>
<div class="pd-field__value">
@if (clientViewData.annualTurnover != null && clientViewData.annualTurnover !== '') {
<span class="monospace">&#8377; {{ clientViewData.annualTurnover | number }}</span>
} @else {
-
}
</div>
</div>
@if (clientViewData.clientType) {
<div class="pd-field">
<div class="pd-field__label">{{ 'labels.inputs.Client Type' | translate }}</div>
<div class="pd-field__value">{{ clientViewData.clientType.name }}</div>
</div>
}
@if (clientViewData.clientClassification) {
<div class="pd-field">
<div class="pd-field__label">{{ 'labels.inputs.Client Classification' | translate }}</div>
<div class="pd-field__value">{{ clientViewData.clientClassification.name }}</div>
</div>
}
@if (clientViewData.occupationCategory) {
<div class="pd-field">
<div class="pd-field__label">{{ 'labels.inputs.Occupation Category' | translate }}</div>
<div class="pd-field__value">{{ clientViewData.occupationCategory.name }}</div>
</div>
}
@if (clientViewData.occupation) {
<div class="pd-field">
<div class="pd-field__label">{{ 'labels.inputs.Occupation' | translate }}</div>
<div class="pd-field__value">{{ clientViewData.occupation.name }}</div>
</div>
}
</div>
</div>
</div>
}
<!-- Guardian Details (Minor) -->
@@ -436,19 +472,19 @@
@if (clientViewData.timeline?.submittedOnDate) {
<div class="pd-field">
<div class="pd-field__label">{{ 'labels.inputs.Submitted On' | translate }}</div>
<div class="pd-field__value">{{ clientViewData.timeline.submittedOnDate | dateFormat:'DD-MM-YYYY' }}</div>
<div class="pd-field__value">{{ clientViewData.timeline.submittedOnDate | dateFormat: 'DD-MM-YYYY' }}</div>
</div>
}
@if (clientViewData.activationDate) {
<div class="pd-field">
<div class="pd-field__label">{{ 'labels.inputs.Activation Date' | translate }}</div>
<div class="pd-field__value">{{ clientViewData.activationDate | dateFormat:'DD-MM-YYYY' }}</div>
<div class="pd-field__value">{{ clientViewData.activationDate | dateFormat: 'DD-MM-YYYY' }}</div>
</div>
}
@if (clientViewData.timeline?.closedOnDate) {
<div class="pd-field">
<div class="pd-field__label">{{ 'labels.inputs.Closed Date' | translate }}</div>
<div class="pd-field__value">{{ clientViewData.timeline.closedOnDate | dateFormat:'DD-MM-YYYY' }}</div>
<div class="pd-field__value">{{ clientViewData.timeline.closedOnDate | dateFormat: 'DD-MM-YYYY' }}</div>
</div>
}
</div>
@@ -467,10 +503,14 @@
<div class="pd-field">
<div class="pd-field__label">{{ 'labels.inputs.Client Status' | translate }}</div>
<div class="pd-field__value">
<span class="pd-field__value status-badge"
<span
class="pd-field__value status-badge"
[class.status-active]="clientViewData.status.value === 'Active'"
[class.status-closed]="clientViewData.status.value === 'Closed'"
[class.status-pending]="clientViewData.status.value !== 'Active' && clientViewData.status.value !== 'Closed'">
[class.status-pending]="
clientViewData.status.value !== 'Active' && clientViewData.status.value !== 'Closed'
"
>
{{ 'labels.status.' + clientViewData.status.value | translate }}
</span>
</div>
@@ -485,5 +525,4 @@
</div>
</div>
</div>
</div>