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:
Aditya
2026-05-21 18:49:43 +05:30
co-authored by Claude Opus 4.7
parent bf3e26a0d0
commit b149fef72e
99 changed files with 8575 additions and 2574 deletions
@@ -17,6 +17,7 @@ import { map } from 'rxjs/operators';
import { ClientsService } from '../clients.service';
import { SettingsService } from 'app/settings/settings.service';
import { ConfirmationDialogComponent } from 'app/shared/confirmation-dialog/confirmation-dialog.component';
import { familyAllowed, nomineeAllowed } from '../utils/client-rules';
/** Custom Components */
import { ClientGeneralStepComponent } from '../client-stepper/client-general-step/client-general-step.component';
@@ -121,9 +122,40 @@ export class EditClientComponent {
return this.clientGeneralStep?.createClientForm;
}
/** Total tab count (+1 for Nominees, +1 for Non-Individual Entity KYC) */
/**
* Constitution display name pulled from the live general step (preferred —
* stays in sync if the user changes constitution mid-edit) with a fallback
* to the resolver-provided snapshot. Drives the proprietorship-only nominee
* rule below.
*/
get constitutionLabel(): string {
return (
this.clientGeneralStep?.selectedConstitution?.name ||
this.clientDataAndTemplate?.clientNonPersonDetails?.constitution?.name ||
''
);
}
/** Whether the Family/Nominee tab should appear at all. */
get showFamilyTab(): boolean {
return nomineeAllowed(this.legalFormType, this.constitutionLabel);
}
/** True when the tab should render in nominee-only mode (family rows hidden). */
get familyTabNomineeOnly(): boolean {
return !familyAllowed(this.legalFormType, this.constitutionLabel) && this.showFamilyTab;
}
/** Total tab count varies by legal form + constitution.
* Individual: General + KYC + Address + Family + Preview = 5
* Entity (proprietorship): General + KYC + S&S + Address + Nominees + Preview = 6
* Entity (non-proprietor): General + KYC + S&S + Address + Preview = 5
*/
get totalTabs(): number {
return this.legalFormType === 2 ? 6 : 5;
let count = 4; // General + KYC + Address + Preview
if (this.legalFormType === 2) count++; // S&S only for entities
if (this.showFamilyTab) count++;
return count;
}
/** Get constitution type from general step for entity KYC */
@@ -411,9 +443,10 @@ export class EditClientComponent {
return;
}
// Family tab
// Family tab — only present for individuals and proprietorship entities.
// Skip when hidden so Preview at the same index isn't mistaken for Family.
const familyTabIdx = this.legalFormType === 2 ? 4 : 3;
if (tabIndex === familyTabIdx) {
if (this.showFamilyTab && tabIndex === familyTabIdx) {
this.savingClient = true;
if (this.clientFamilyMembersStep?.hasFamilyMembers) {
this.saveClientFamilyMembers(this.clientId);