merging code

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Nitesh Yadav
2026-04-20 14:26:25 +05:30
co-authored by Claude Sonnet 4.6
322 changed files with 28779 additions and 4976 deletions
@@ -109,11 +109,11 @@ export class NomineeTabComponent implements OnInit {
editNomType: string = 'DA1';
get hasAccounts(): boolean {
return this.accountGroups.some(g => g.accounts.length > 0);
return this.accountGroups.some((g) => g.accounts.length > 0);
}
get selectedGroup(): AccountGroup | undefined {
return this.accountGroups.find(g => g.type === this.selectedType);
return this.accountGroups.find((g) => g.type === this.selectedType);
}
get selectedAccount(): any {
@@ -154,13 +154,43 @@ export class NomineeTabComponent implements OnInit {
next: (data: any) => {
this.loading = false;
this.accountGroups = [
{ type: 'savings', apiType: 'SB', label: 'Savings Account', icon: 'savings', accounts: this.filterActive(data.savingsAccounts) },
{ type: 'current', apiType: 'CB', label: 'Current Account', icon: 'account_balance', accounts: this.filterActive(data.currentAccounts) },
{ type: 'fd', apiType: 'FD', label: 'Fixed Deposit', icon: 'lock', accounts: this.filterActive(data.fixedDepositAccounts) },
{ type: 'rd', apiType: 'RD', label: 'Recurring Deposit', icon: 'autorenew', accounts: this.filterActive(data.recurringDepositAccounts) },
{ type: 'loan', apiType: 'LA', label: 'Loan Account', icon: 'credit_score', accounts: this.filterActive(data.loanAccounts) }
{
type: 'savings',
apiType: 'SB',
label: 'Savings Account',
icon: 'savings',
accounts: this.filterActive(data.savingsAccounts)
},
{
type: 'current',
apiType: 'CB',
label: 'Current Account',
icon: 'account_balance',
accounts: this.filterActive(data.currentAccounts)
},
{
type: 'fd',
apiType: 'FD',
label: 'Fixed Deposit',
icon: 'lock',
accounts: this.filterActive(data.fixedDepositAccounts)
},
{
type: 'rd',
apiType: 'RD',
label: 'Recurring Deposit',
icon: 'autorenew',
accounts: this.filterActive(data.recurringDepositAccounts)
},
{
type: 'loan',
apiType: 'LA',
label: 'Loan Account',
icon: 'credit_score',
accounts: this.filterActive(data.loanAccounts)
}
];
const firstWithAccounts = this.accountGroups.find(g => g.accounts.length > 0);
const firstWithAccounts = this.accountGroups.find((g) => g.accounts.length > 0);
if (firstWithAccounts) {
this.selectedType = firstWithAccounts.type;
// Auto-select if only 1 account in the group
@@ -170,18 +200,16 @@ export class NomineeTabComponent implements OnInit {
}
}
},
error: () => { this.loading = false; }
error: () => {
this.loading = false;
}
});
}
private filterActive(accounts: any[]): any[] {
if (!accounts) return [];
// Include all non-closed accounts (active, disbursed, pending, etc.)
return accounts.filter((a: any) =>
a.status?.active ||
a.status?.value === 'Active' ||
!a.status?.closed
);
return accounts.filter((a: any) => a.status?.active || a.status?.value === 'Active' || !a.status?.closed);
}
onTypeChange(): void {
@@ -198,7 +226,9 @@ export class NomineeTabComponent implements OnInit {
onAccountChange(): void {
this.nominees = [];
this.resetAddForm();
if (this.selectedAccountId) { this.loadNominees(); }
if (this.selectedAccountId) {
this.loadNominees();
}
}
private loadNominees(): void {
@@ -210,9 +240,12 @@ export class NomineeTabComponent implements OnInit {
this.nomineesLoading = false;
this.nominees = Array.isArray(data) ? data : [];
// Enrich each nominee with profile image & signature
this.nominees.forEach(n => this.enrichNomineeImages(n));
this.nominees.forEach((n) => this.enrichNomineeImages(n));
},
error: () => { this.nomineesLoading = false; this.nominees = []; }
error: () => {
this.nomineesLoading = false;
this.nominees = [];
}
});
}
@@ -224,7 +257,9 @@ export class NomineeTabComponent implements OnInit {
// Profile image
this.clientsService.getClientProfileImage(cid).subscribe({
next: (img: any) => {
if (img) { nominee.profileImageUrl = this.sanitizer.bypassSecurityTrustResourceUrl(img); }
if (img) {
nominee.profileImageUrl = this.sanitizer.bypassSecurityTrustResourceUrl(img);
}
},
error: () => {}
});
@@ -232,8 +267,8 @@ export class NomineeTabComponent implements OnInit {
// Signature
this.clientsService.getClientDocuments(cid).subscribe({
next: (docs: any[]) => {
const sigDoc = docs?.find((d: any) =>
d.name?.toLowerCase().includes('signature') || d.description?.toLowerCase().includes('signature')
const sigDoc = docs?.find(
(d: any) => d.name?.toLowerCase().includes('signature') || d.description?.toLowerCase().includes('signature')
);
if (sigDoc) {
this.clientsService.getClientSignatureImage(cid, sigDoc.id.toString()).subscribe({
@@ -253,7 +288,10 @@ export class NomineeTabComponent implements OnInit {
onSearch(text: string): void {
this.searchText = text;
clearTimeout(this.searchTimer);
if (!text || text.length < 2) { this.searchResults = []; return; }
if (!text || text.length < 2) {
this.searchResults = [];
return;
}
this.searching = true;
this.searchTimer = setTimeout(() => {
this.clientsService.searchByText(text, 0, 8).subscribe({
@@ -262,13 +300,19 @@ export class NomineeTabComponent implements OnInit {
this.searching = false;
this.clientsService.enrichSearchResults(this.searchResults);
},
error: () => { this.searchResults = []; this.searching = false; }
error: () => {
this.searchResults = [];
this.searching = false;
}
});
}, 400);
}
dismissSearch(): void {
setTimeout(() => { this.searchResults = []; this.searching = false; }, 200);
setTimeout(() => {
this.searchResults = [];
this.searching = false;
}, 200);
}
selectClient(client: any): void {
@@ -291,11 +335,18 @@ export class NomineeTabComponent implements OnInit {
this.linkedSignatureImage = null;
this.linkedKycStatus = null;
let pending = 4;
const done = () => { pending--; if (pending <= 0) { this.fetchingDetails = false; } };
const done = () => {
pending--;
if (pending <= 0) {
this.fetchingDetails = false;
}
};
this.clientsService.getClientData(clientId.toString()).subscribe({
next: (data: any) => {
if (data?.dateOfBirth) { this.selectedClient = { ...this.selectedClient, dateOfBirth: data.dateOfBirth }; }
if (data?.dateOfBirth) {
this.selectedClient = { ...this.selectedClient, dateOfBirth: data.dateOfBirth };
}
done();
},
error: () => done()
@@ -304,8 +355,15 @@ export class NomineeTabComponent implements OnInit {
this.clientsService.getClientKyc(clientId.toString()).subscribe({
next: (kyc: any) => {
if (kyc) {
this.selectedClient = { ...this.selectedClient, panNumber: kyc.panNumber, aadhaarMasked: kyc.aadhaarNumberMasked };
this.linkedKycStatus = { panVerified: kyc.panVerified || false, aadhaarVerified: kyc.aadhaarVerified || false };
this.selectedClient = {
...this.selectedClient,
panNumber: kyc.panNumber,
aadhaarMasked: kyc.aadhaarNumberMasked
};
this.linkedKycStatus = {
panVerified: kyc.panVerified || false,
aadhaarVerified: kyc.aadhaarVerified || false
};
}
done();
},
@@ -313,19 +371,31 @@ export class NomineeTabComponent implements OnInit {
});
this.clientsService.getClientProfileImage(clientId.toString()).subscribe({
next: (img: any) => { if (img) { this.linkedProfileImage = this.sanitizer.bypassSecurityTrustResourceUrl(img); } done(); },
next: (img: any) => {
if (img) {
this.linkedProfileImage = this.sanitizer.bypassSecurityTrustResourceUrl(img);
}
done();
},
error: () => done()
});
this.clientsService.getClientDocuments(clientId.toString()).subscribe({
next: (docs: any[]) => {
const sigDoc = docs?.find((d: any) => d.name?.toLowerCase().includes('signature') || d.description?.toLowerCase().includes('signature'));
const sigDoc = docs?.find(
(d: any) => d.name?.toLowerCase().includes('signature') || d.description?.toLowerCase().includes('signature')
);
if (sigDoc) {
this.clientsService.getClientSignatureImage(clientId.toString(), sigDoc.id.toString()).subscribe({
next: (blob: Blob) => { this.linkedSignatureImage = this.sanitizer.bypassSecurityTrustUrl(URL.createObjectURL(blob)); done(); },
next: (blob: Blob) => {
this.linkedSignatureImage = this.sanitizer.bypassSecurityTrustUrl(URL.createObjectURL(blob));
done();
},
error: () => done()
});
} else { done(); }
} else {
done();
}
},
error: () => done()
});
@@ -336,12 +406,22 @@ export class NomineeTabComponent implements OnInit {
onGuardianSearch(text: string): void {
this.guardianSearchText = text;
clearTimeout(this.guardianSearchTimer);
if (!text || text.length < 2) { this.guardianSearchResults = []; return; }
if (!text || text.length < 2) {
this.guardianSearchResults = [];
return;
}
this.guardianSearching = true;
this.guardianSearchTimer = setTimeout(() => {
this.clientsService.searchByText(text, 0, 8).subscribe({
next: (data: any) => { this.guardianSearchResults = data?.content || []; this.guardianSearching = false; this.clientsService.enrichSearchResults(this.guardianSearchResults); },
error: () => { this.guardianSearchResults = []; this.guardianSearching = false; }
next: (data: any) => {
this.guardianSearchResults = data?.content || [];
this.guardianSearching = false;
this.clientsService.enrichSearchResults(this.guardianSearchResults);
},
error: () => {
this.guardianSearchResults = [];
this.guardianSearching = false;
}
});
}, 400);
}
@@ -385,7 +465,9 @@ export class NomineeTabComponent implements OnInit {
this.loadNominees();
this.resetAddForm();
},
error: () => { this.nomineeSaving = false; }
error: () => {
this.nomineeSaving = false;
}
});
}
@@ -395,26 +477,30 @@ export class NomineeTabComponent implements OnInit {
// Resolve the linked client ID — could be nomineeClientId or nested
const clientId = nominee.nomineeClientId || nominee.linkedClientId || nominee.clientId;
const displayName = nominee.nomineeDisplayName || nominee.firstName || '';
import('../../client-stepper/client-family-members-step/client-family-member-dialog/client-family-member-dialog.component').then(m => {
this.dialog.open(m.ClientFamilyMemberDialogComponent, {
data: {
context: 'View',
member: {
firstName: displayName,
relationshipId: nominee.relationshipId,
dateOfBirth: nominee.nomineeDateOfBirth || nominee.dateOfBirth,
linkedClientId: clientId,
linkedClientName: displayName,
isAlive: true,
isDependent: nominee.nomineeIsMinor,
panNumber: nominee.panNumber || '',
aadhaarNumber: nominee.aadhaarMasked || ''
import('../../client-stepper/client-family-members-step/client-family-member-dialog/client-family-member-dialog.component').then(
(m) => {
this.dialog.open(m.ClientFamilyMemberDialogComponent, {
data: {
context: 'View',
member: {
firstName: displayName,
relationshipId: nominee.relationshipId,
dateOfBirth: nominee.nomineeDateOfBirth || nominee.dateOfBirth,
linkedClientId: clientId,
linkedClientName: displayName,
isAlive: true,
isDependent: nominee.nomineeIsMinor,
panNumber: nominee.panNumber || '',
aadhaarNumber: nominee.aadhaarMasked || ''
},
options: { relationshipIdOptions: this.relationshipOptions }
},
options: { relationshipIdOptions: this.relationshipOptions }
},
width: '640px', maxWidth: '95vw', panelClass: 'fm-dialog-panel'
});
});
width: '640px',
maxWidth: '95vw',
panelClass: 'fm-dialog-panel'
});
}
);
}
editNominee(nominee: any, index: number): void {
@@ -424,10 +510,12 @@ export class NomineeTabComponent implements OnInit {
this.editNomType = nominee.nominationType || 'DA1';
}
cancelEdit(): void { this.editingIndex = null; }
cancelEdit(): void {
this.editingIndex = null;
}
maxShareForEdit(index: number): number {
return 100 - this.nominees.reduce((sum, n, i) => i === index ? sum : sum + (n.percentageShare || 0), 0);
return 100 - this.nominees.reduce((sum, n, i) => (i === index ? sum : sum + (n.percentageShare || 0)), 0);
}
saveEdit(nominee: any, index: number): void {
@@ -468,7 +556,8 @@ export class NomineeTabComponent implements OnInit {
this.dialog.open(ImageZoomDialogComponent, {
data: { imageSrc, title },
panelClass: 'image-zoom-panel',
maxWidth: '90vw', maxHeight: '90vh'
maxWidth: '90vw',
maxHeight: '90vh'
});
}