feat: KYC re-verify UX, family/nominee tab gating, savings dialogs, cfcfrms shell
- KYC tab: fix Verify (PAN) and Send OTP (Aadhaar) being disabled in edit mode; unmask Aadhaar input and show on-file masked value as hint; resolve kycId from id/kycId/resourceId fallbacks. - Client stepper/view: add familyAllowed / nomineeAllowed predicates + CanActivate route guards. Family tab hidden for non-individuals, Nominee tab hidden for non-proprietor entities. Family-members step accepts a nomineeOnly input for proprietorship clients. Add/Edit/Delete buttons inside family-members and nominee tabs gated by canAdd. - cfcfrms: add cfcfrms-shell wrapper, restyle complaint/fraud/mule/escalate pages and dashboard. - Savings: identity-verify and transaction-confirm dialogs, manage / activate / add-charge flows, account preview styling. - Tasks, core shell, account-nominees, icons: minor style and behaviour updates. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 4.7
parent
bf3e26a0d0
commit
b149fef72e
+33
-17
@@ -16,29 +16,45 @@
|
||||
<div class="step-header__left">
|
||||
<fa-icon icon="users" class="step-header__icon"></fa-icon>
|
||||
<div>
|
||||
<h3 class="step-header__title">Family Members</h3>
|
||||
<p class="step-header__sub">Add family members and dependents of the client.</p>
|
||||
@if (nomineeOnly) {
|
||||
<h3 class="step-header__title">Nominees</h3>
|
||||
<p class="step-header__sub">
|
||||
Nominees for this client. Family members are not applicable for this entity type.
|
||||
</p>
|
||||
} @else {
|
||||
<h3 class="step-header__title">Family Members</h3>
|
||||
<p class="step-header__sub">Add family members and dependents of the client.</p>
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@if (nomineeOnly) {
|
||||
<div class="fm-step__empty">
|
||||
<mat-icon class="fm-step__empty-icon">shield</mat-icon>
|
||||
<span>Nominees are managed per account from the <strong>Nominees</strong> tab once accounts are opened.</span>
|
||||
</div>
|
||||
}
|
||||
|
||||
<!-- ═══ FAMILY MEMBERS ═══ -->
|
||||
<div class="fm-step__header">
|
||||
<div class="fm-step__title">
|
||||
<fa-icon icon="users" class="fm-step__icon"></fa-icon>
|
||||
<span>Family Members</span>
|
||||
@if (clientFamilyMembers.length > 0) {
|
||||
<span class="fm-step__count">{{ clientFamilyMembers.length }}</span>
|
||||
@if (!nomineeOnly) {
|
||||
<div class="fm-step__header">
|
||||
<div class="fm-step__title">
|
||||
<fa-icon icon="users" class="fm-step__icon"></fa-icon>
|
||||
<span>Family Members</span>
|
||||
@if (clientFamilyMembers.length > 0) {
|
||||
<span class="fm-step__count">{{ clientFamilyMembers.length }}</span>
|
||||
}
|
||||
</div>
|
||||
@if (!readOnly) {
|
||||
<button mat-flat-button color="primary" type="button" class="fm-step__add-btn" (click)="addFamilyMember()">
|
||||
<mat-icon>add</mat-icon> Add Member
|
||||
</button>
|
||||
}
|
||||
</div>
|
||||
@if (!readOnly) {
|
||||
<button mat-flat-button color="primary" type="button" class="fm-step__add-btn" (click)="addFamilyMember()">
|
||||
<mat-icon>add</mat-icon> Add Member
|
||||
</button>
|
||||
}
|
||||
</div>
|
||||
}
|
||||
|
||||
@if (clientFamilyMembers.length === 0) {
|
||||
@if (!nomineeOnly && clientFamilyMembers.length === 0) {
|
||||
<div class="fm-step__empty fm-step__empty--required">
|
||||
<mat-icon class="fm-step__empty-icon">people_outline</mat-icon>
|
||||
<span>No family members added yet.</span>
|
||||
@@ -47,14 +63,14 @@
|
||||
}
|
||||
|
||||
<!-- Spouse hint for married clients -->
|
||||
@if (isMarried && !hasSpouse) {
|
||||
@if (!nomineeOnly && isMarried && !hasSpouse) {
|
||||
<div class="fm-spouse-hint">
|
||||
<mat-icon class="fm-spouse-hint__icon">favorite</mat-icon>
|
||||
<span>Marital status is <strong>Married</strong>. Consider adding spouse as a family member.</span>
|
||||
</div>
|
||||
}
|
||||
|
||||
@if (clientFamilyMembers.length > 0) {
|
||||
@if (!nomineeOnly && clientFamilyMembers.length > 0) {
|
||||
<div class="fm-table">
|
||||
<div class="fm-table__header">
|
||||
<span class="fm-table__col fm-table__col--name">Name</span>
|
||||
|
||||
+7
@@ -52,6 +52,12 @@ export class ClientFamilyMembersStepComponent implements OnInit {
|
||||
@Input() maritalStatusOptions: any[] = [];
|
||||
/** Read-only mode — hides add/edit/delete buttons */
|
||||
@Input() readOnly = false;
|
||||
/**
|
||||
* When true, hide the family-member section entirely. Used for clients that
|
||||
* are eligible for nominees but not for family members (e.g. proprietorship
|
||||
* entities — see {@link nomineeAllowed} / {@link familyAllowed}).
|
||||
*/
|
||||
@Input() nomineeOnly = false;
|
||||
|
||||
/** Family Members */
|
||||
clientFamilyMembers: any[] = [];
|
||||
@@ -131,6 +137,7 @@ export class ClientFamilyMembersStepComponent implements OnInit {
|
||||
}
|
||||
|
||||
addFamilyMember() {
|
||||
if (this.nomineeOnly || this.readOnly) return;
|
||||
const ref = this.dialog.open(ClientFamilyMemberDialogComponent, {
|
||||
data: {
|
||||
context: 'Add',
|
||||
|
||||
+2
-2
@@ -1024,8 +1024,8 @@
|
||||
}
|
||||
}
|
||||
|
||||
<!-- Family Members (Individual only) -->
|
||||
@if (client?.legalFormId !== 2) {
|
||||
<!-- Family Members — hidden when client isn't eligible (entities other than proprietorship). -->
|
||||
@if (showFamilyPreview) {
|
||||
<div class="info-card">
|
||||
<div class="card-header">
|
||||
<fa-icon icon="users" class="card-icon"></fa-icon>
|
||||
|
||||
@@ -24,6 +24,7 @@ import { DateFormatPipe } from '../../../pipes/date-format.pipe';
|
||||
import { YesnoPipe } from '../../../pipes/yesno.pipe';
|
||||
import { STANDALONE_SHARED_IMPORTS } from 'app/standalone-shared.module';
|
||||
import { LegalFormId } from 'app/clients/models/legal-form.enum';
|
||||
import { familyAllowed, nomineeAllowed } from 'app/clients/utils/client-rules';
|
||||
|
||||
/**
|
||||
* Client Preview Step Component
|
||||
@@ -69,6 +70,11 @@ export class ClientPreviewStepComponent {
|
||||
@Input() nominees: any[] = [];
|
||||
/** Family members from family step */
|
||||
@Input() familyMembers: any[] = [];
|
||||
/**
|
||||
* Constitution display name for entity clients — drives the proprietorship-only
|
||||
* nominee rule so the preview matches what's eligible elsewhere.
|
||||
*/
|
||||
@Input() constitutionLabel: string = '';
|
||||
/** Marital Status ID from general step */
|
||||
@Input() maritalStatusId: number | null = null;
|
||||
/** Marital Status Options */
|
||||
@@ -99,6 +105,14 @@ export class ClientPreviewStepComponent {
|
||||
/** Form submission event */
|
||||
@Output() submitEvent = new EventEmitter();
|
||||
|
||||
get showFamilyPreview(): boolean {
|
||||
return familyAllowed(this.client?.legalFormId, this.constitutionLabel);
|
||||
}
|
||||
|
||||
get showNomineePreview(): boolean {
|
||||
return nomineeAllowed(this.client?.legalFormId, this.constitutionLabel);
|
||||
}
|
||||
|
||||
/** Expose enum to template */
|
||||
readonly LegalFormId = LegalFormId;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user