feat: add RBI circulars, CKYC, KYC, Superset analytics, passbook modules and UI updates
Add new feature modules (RBI feeds, CKYC, KYC tab, Form60, Superset analytics, passbook), update client family members, dashboard, login page, sidenav, images, translations, environment config, and fix RBI feeds API auth by using relative URLs. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 4.6
parent
07f701f654
commit
73aa69ee02
+55
-75
@@ -9,49 +9,32 @@
|
||||
<h1 mat-dialog-title>{{ data.context }} {{ 'labels.heading.Family Member' | translate }}</h1>
|
||||
|
||||
<form [formGroup]="familyMemberForm">
|
||||
<div class="layout-row-wrap responsive-column align-start-center gap-2px">
|
||||
<mat-form-field class="flex-48">
|
||||
<mat-label>{{ 'labels.inputs.First Name' | translate }}</mat-label>
|
||||
<h3>{{ 'labels.heading.Nominee Details (DA1 / DA5)' | translate }}</h3>
|
||||
|
||||
<div class="layout-row-wrap responsive-column align-start-center">
|
||||
<!-- Nomination Type -->
|
||||
<mat-form-field class="flex-50-minus-25px">
|
||||
<mat-label>{{ 'labels.inputs.Nomination Type' | translate }}</mat-label>
|
||||
<mat-select formControlName="nominationType" required>
|
||||
<mat-option value="DA1">{{ 'labels.inputs.DA1 - Add Nominee' | translate }}</mat-option>
|
||||
<mat-option value="DA5">{{ 'labels.inputs.DA5 - Modify / Cancel Nominee' | translate }}</mat-option>
|
||||
</mat-select>
|
||||
</mat-form-field>
|
||||
|
||||
<!-- Nominee Name -->
|
||||
<mat-form-field class="flex-50-minus-25px">
|
||||
<mat-label>{{ 'labels.inputs.Nominee Name' | translate }}</mat-label>
|
||||
<input formControlName="firstName" required matInput />
|
||||
@if (familyMemberForm.controls.firstName.hasError('required')) {
|
||||
<mat-error>
|
||||
{{ 'labels.inputs.First Name' | translate }} {{ 'labels.commons.is' | translate }}
|
||||
{{ 'labels.inputs.Nominee Name' | translate }} {{ 'labels.commons.is' | translate }}
|
||||
<strong>{{ 'labels.commons.required' | translate }}</strong>
|
||||
</mat-error>
|
||||
}
|
||||
</mat-form-field>
|
||||
|
||||
<mat-form-field class="flex-48">
|
||||
<mat-label>{{ 'labels.inputs.Middle Name' | translate }}</mat-label>
|
||||
<input formControlName="middleName" matInput />
|
||||
</mat-form-field>
|
||||
|
||||
<mat-form-field class="flex-48">
|
||||
<mat-label>{{ 'labels.inputs.Last Name' | translate }}</mat-label>
|
||||
<input formControlName="lastName" required matInput />
|
||||
@if (familyMemberForm.controls.lastName.hasError('required')) {
|
||||
<mat-error>
|
||||
{{ 'labels.inputs.Last Name' | translate }} {{ 'labels.commons.is' | translate }}
|
||||
<strong>{{ 'labels.commons.required' | translate }}</strong>
|
||||
</mat-error>
|
||||
}
|
||||
</mat-form-field>
|
||||
|
||||
<mat-form-field class="flex-48">
|
||||
<mat-label>{{ 'labels.inputs.Qualification' | translate }}</mat-label>
|
||||
<input formControlName="qualification" matInput />
|
||||
</mat-form-field>
|
||||
|
||||
<mat-form-field class="flex-48">
|
||||
<mat-label>{{ 'labels.inputs.Age' | translate }}</mat-label>
|
||||
<input type="number" formControlName="age" matInput [min]="0" disabled />
|
||||
</mat-form-field>
|
||||
|
||||
<mat-checkbox formControlName="isDependent" labelPosition="before" class="flex-48"
|
||||
>{{ 'labels.inputs.Is Dependent' | translate }}?</mat-checkbox
|
||||
>
|
||||
|
||||
<mat-form-field class="flex-48">
|
||||
<!-- Relationship -->
|
||||
<mat-form-field class="flex-50-minus-25px">
|
||||
<mat-label>{{ 'labels.inputs.Relationship' | translate }}</mat-label>
|
||||
<mat-select formControlName="relationshipId" required>
|
||||
@for (relation of data.options.relationshipIdOptions; track relation) {
|
||||
@@ -68,46 +51,8 @@
|
||||
}
|
||||
</mat-form-field>
|
||||
|
||||
<mat-form-field class="flex-48">
|
||||
<mat-label>{{ 'labels.inputs.Gender' | translate }}</mat-label>
|
||||
<mat-select formControlName="genderId" required>
|
||||
@for (gender of data.options.genderIdOptions; track gender) {
|
||||
<mat-option [value]="gender.id">
|
||||
{{ gender.name | translateKey: 'catalogs' }}
|
||||
</mat-option>
|
||||
}
|
||||
</mat-select>
|
||||
@if (familyMemberForm.controls.genderId.hasError('required')) {
|
||||
<mat-error>
|
||||
{{ 'labels.inputs.Gender' | translate }} {{ 'labels.commons.is' | translate }}
|
||||
<strong>{{ 'labels.commons.required' | translate }}</strong>
|
||||
</mat-error>
|
||||
}
|
||||
</mat-form-field>
|
||||
|
||||
<mat-form-field class="flex-48">
|
||||
<mat-label>{{ 'labels.inputs.Profession' | translate }}</mat-label>
|
||||
<mat-select formControlName="professionId">
|
||||
@for (profession of data.options.professionIdOptions; track profession) {
|
||||
<mat-option [value]="profession.id">
|
||||
{{ profession.name | translateKey: 'catalogs' }}
|
||||
</mat-option>
|
||||
}
|
||||
</mat-select>
|
||||
</mat-form-field>
|
||||
|
||||
<mat-form-field class="flex-48">
|
||||
<mat-label>{{ 'labels.inputs.Marital Status' | translate }}</mat-label>
|
||||
<mat-select formControlName="maritalStatusId">
|
||||
@for (maritalStatus of data.options.maritalStatusIdOptions; track maritalStatus) {
|
||||
<mat-option [value]="maritalStatus.id">
|
||||
{{ maritalStatus.name | translateKey: 'catalogs' }}
|
||||
</mat-option>
|
||||
}
|
||||
</mat-select>
|
||||
</mat-form-field>
|
||||
|
||||
<mat-form-field class="flex-98" (click)="dueDatePicker.open()">
|
||||
<!-- Date of Birth -->
|
||||
<mat-form-field class="flex-50-minus-25px" (click)="dueDatePicker.open()">
|
||||
<mat-label>{{ 'labels.inputs.Date Of Birth' | translate }}</mat-label>
|
||||
<input
|
||||
formControlName="dateOfBirth"
|
||||
@@ -119,6 +64,41 @@
|
||||
<mat-datepicker-toggle matSuffix [for]="dueDatePicker"></mat-datepicker-toggle>
|
||||
<mat-datepicker #dueDatePicker></mat-datepicker>
|
||||
</mat-form-field>
|
||||
|
||||
<!-- Percentage Share -->
|
||||
<mat-form-field class="flex-50-minus-25px">
|
||||
<mat-label>{{ 'labels.inputs.Percentage Share' | translate }} (%)</mat-label>
|
||||
<input type="number" formControlName="percentageShare" matInput min="0" max="100" />
|
||||
</mat-form-field>
|
||||
|
||||
<!-- Nominee is Minor -->
|
||||
<mat-checkbox formControlName="isDependent" labelPosition="before" class="flex-50-minus-25px">
|
||||
{{ 'labels.inputs.Nominee is Minor' | translate }}?
|
||||
</mat-checkbox>
|
||||
</div>
|
||||
|
||||
<!-- Guardian Details (shown when minor) -->
|
||||
@if (familyMemberForm.get('isDependent').value) {
|
||||
<h3>{{ 'labels.heading.Guardian Details (If Minor)' | translate }}</h3>
|
||||
<div class="layout-row-wrap responsive-column align-start-center">
|
||||
<mat-form-field class="flex-50-minus-25px">
|
||||
<mat-label>{{ 'labels.inputs.Guardian Name' | translate }}</mat-label>
|
||||
<input formControlName="guardianName" matInput />
|
||||
</mat-form-field>
|
||||
|
||||
<mat-form-field class="flex-50-minus-25px">
|
||||
<mat-label>{{ 'labels.inputs.Relationship with Minor' | translate }}</mat-label>
|
||||
<input formControlName="guardianRelationship" matInput />
|
||||
</mat-form-field>
|
||||
</div>
|
||||
}
|
||||
|
||||
<!-- Remarks -->
|
||||
<div class="layout-row-wrap responsive-column align-start-center">
|
||||
<mat-form-field class="flex-fill">
|
||||
<mat-label>{{ 'labels.inputs.Remarks' | translate }}</mat-label>
|
||||
<input formControlName="remarks" matInput />
|
||||
</mat-form-field>
|
||||
</div>
|
||||
|
||||
<mat-dialog-actions align="center">
|
||||
|
||||
+12
@@ -19,4 +19,16 @@ form {
|
||||
.layout-row-wrap {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
@media screen and (width >= 960px) {
|
||||
.layout-row-wrap > .flex-fill:nth-child(odd),
|
||||
.layout-row-wrap > .flex-50-minus-25px:nth-child(odd) {
|
||||
margin-right: 25px;
|
||||
}
|
||||
|
||||
.layout-row-wrap > .flex-fill:last-child,
|
||||
.layout-row-wrap > .flex-50-minus-25px:last-child {
|
||||
margin-right: 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+15
-69
@@ -56,54 +56,17 @@ export class ClientFamilyMemberDialogComponent implements OnInit {
|
||||
this.createFamilyMemberForm();
|
||||
if (this.data.context === 'Edit') {
|
||||
this.familyMemberForm.patchValue({
|
||||
nominationType: this.data.member.nominationType || 'DA1',
|
||||
firstName: this.data.member.firstName,
|
||||
middleName: this.data.member.middleName,
|
||||
lastName: this.data.member.lastName,
|
||||
qualification: this.data.member.qualification,
|
||||
age: this.data.member.age,
|
||||
isDependent: this.data.member.isDependent,
|
||||
relationshipId: this.data.member.relationshipId,
|
||||
genderId: this.data.member.genderId,
|
||||
professionId: this.data.member.professionId,
|
||||
maritalStatusId: this.data.member.maritalStatusId,
|
||||
dateOfBirth: this.data.member.dateOfBirth && new Date(this.data.member.dateOfBirth)
|
||||
dateOfBirth: this.data.member.dateOfBirth && new Date(this.data.member.dateOfBirth),
|
||||
percentageShare: this.data.member.percentageShare ?? 100,
|
||||
isDependent: this.data.member.isDependent,
|
||||
guardianName: this.data.member.guardianName || '',
|
||||
guardianRelationship: this.data.member.guardianRelationship || '',
|
||||
remarks: this.data.member.remarks || ''
|
||||
});
|
||||
}
|
||||
|
||||
// Add subscription to date of birth changes to update age
|
||||
this.familyMemberForm.get('dateOfBirth').valueChanges.subscribe((dateOfBirth: any) => {
|
||||
if (dateOfBirth) {
|
||||
const age = this.calculateAge(dateOfBirth);
|
||||
this.familyMemberForm.get('age').setValue(age);
|
||||
} else {
|
||||
this.familyMemberForm.get('age').setValue('');
|
||||
}
|
||||
});
|
||||
|
||||
// If a date of birth is already set, calculate the age
|
||||
const currentDob = this.familyMemberForm.get('dateOfBirth').value;
|
||||
if (currentDob) {
|
||||
const age = this.calculateAge(currentDob);
|
||||
this.familyMemberForm.get('age').setValue(age);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculates age from date of birth
|
||||
* @param {Date} dateOfBirth Date of Birth
|
||||
* @returns {number} Age
|
||||
*/
|
||||
calculateAge(dateOfBirth: Date): number {
|
||||
const today = new Date(this.settingsService.businessDate);
|
||||
const birthDate = new Date(dateOfBirth);
|
||||
let age = today.getFullYear() - birthDate.getFullYear();
|
||||
const monthDiff = today.getMonth() - birthDate.getMonth();
|
||||
|
||||
if (monthDiff < 0 || (monthDiff === 0 && today.getDate() < birthDate.getDate())) {
|
||||
age--;
|
||||
}
|
||||
|
||||
return age;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -111,30 +74,21 @@ export class ClientFamilyMemberDialogComponent implements OnInit {
|
||||
*/
|
||||
createFamilyMemberForm() {
|
||||
this.familyMemberForm = this.formBuilder.group({
|
||||
nominationType: ['DA1'],
|
||||
firstName: [
|
||||
'',
|
||||
Validators.required
|
||||
],
|
||||
middleName: [''],
|
||||
lastName: [
|
||||
'',
|
||||
Validators.required
|
||||
],
|
||||
qualification: [''],
|
||||
age: [
|
||||
{ value: '', disabled: true }],
|
||||
isDependent: [''],
|
||||
relationshipId: [
|
||||
'',
|
||||
Validators.required
|
||||
],
|
||||
genderId: [
|
||||
'',
|
||||
Validators.required
|
||||
],
|
||||
professionId: [''],
|
||||
maritalStatusId: [''],
|
||||
dateOfBirth: ['']
|
||||
dateOfBirth: [''],
|
||||
percentageShare: [100],
|
||||
isDependent: [false],
|
||||
guardianName: [''],
|
||||
guardianRelationship: [''],
|
||||
remarks: ['']
|
||||
});
|
||||
}
|
||||
|
||||
@@ -142,27 +96,19 @@ export class ClientFamilyMemberDialogComponent implements OnInit {
|
||||
* Returns Formatted Family Member
|
||||
*/
|
||||
get familyMember() {
|
||||
// Get form values including disabled controls like age
|
||||
const formValue = {
|
||||
...this.familyMemberForm.getRawValue()
|
||||
...this.familyMemberForm.value
|
||||
};
|
||||
|
||||
const locale = this.settingsService.language.code;
|
||||
const dateFormat = this.settingsService.dateFormat;
|
||||
const prevDateOfBirth: Date = formValue.dateOfBirth;
|
||||
|
||||
// Calculate age from dateOfBirth if present
|
||||
if (prevDateOfBirth) {
|
||||
if (formValue.dateOfBirth instanceof Date) {
|
||||
formValue.dateOfBirth = this.dateUtils.formatDate(prevDateOfBirth, dateFormat);
|
||||
}
|
||||
// Ensure age is calculated even if it wasn't already
|
||||
if (!formValue.age && prevDateOfBirth) {
|
||||
formValue.age = this.calculateAge(prevDateOfBirth);
|
||||
}
|
||||
} else {
|
||||
// If no date of birth, remove age and dateOfBirth from submission
|
||||
delete formValue.age;
|
||||
delete formValue.dateOfBirth;
|
||||
}
|
||||
|
||||
|
||||
+13
-15
@@ -20,10 +20,10 @@
|
||||
<mat-expansion-panel class="family-member">
|
||||
<mat-expansion-panel-header>
|
||||
<mat-panel-title>
|
||||
{{ member.firstName }} {{ member.middleName ? member.middleName + ' ' + member.lastName : member.lastName }}
|
||||
{{ member.firstName }}
|
||||
</mat-panel-title>
|
||||
<mat-panel-description>
|
||||
{{ member.relationship }}
|
||||
{{ member.relationshipId | find: clientTemplate.familyMemberOptions.relationshipIdOptions : 'id' : 'name' }}
|
||||
</mat-panel-description>
|
||||
</mat-expansion-panel-header>
|
||||
<mat-divider></mat-divider>
|
||||
@@ -36,23 +36,21 @@
|
||||
</button>
|
||||
</div>
|
||||
<p>
|
||||
{{ 'labels.inputs.First Name' | translate }} : {{ member.firstName }}<br />
|
||||
{{ 'labels.inputs.Middle Name' | translate }} : {{ member.middleName }}<br />
|
||||
{{ 'labels.inputs.Last Name' | translate }} : {{ member.lastName }}<br />
|
||||
{{ 'labels.inputs.Qualification' | translate }} : {{ member.qualification }}<br />
|
||||
{{ 'labels.inputs.Nomination Type' | translate }} : {{ member.nominationType }}<br />
|
||||
{{ 'labels.inputs.Nominee Name' | translate }} : {{ member.firstName }}<br />
|
||||
{{ 'labels.inputs.Relationship' | translate }} :
|
||||
{{ member.relationshipId | find: clientTemplate.familyMemberOptions.relationshipIdOptions : 'id' : 'name'
|
||||
}}<br />
|
||||
{{ 'labels.inputs.Age' | translate }} : {{ member.age }}<br />
|
||||
{{ 'labels.inputs.Is Dependent' | translate }} : {{ member.isDependent ? 'Yes' : 'No' }}<br />
|
||||
{{ 'labels.inputs.Marital Status' | translate }} :
|
||||
{{ member.maritalStatusId | find: clientTemplate.familyMemberOptions.maritalStatusIdOptions : 'id' : 'name'
|
||||
}}<br />
|
||||
{{ 'labels.inputs.Gender' | translate }} :
|
||||
{{ member.genderId | find: clientTemplate.familyMemberOptions.genderIdOptions : 'id' : 'name' }}<br />
|
||||
{{ 'labels.inputs.Profession' | translate }} :
|
||||
{{ member.professionId | find: clientTemplate.familyMemberOptions.professionIdOptions : 'id' : 'name' }}<br />
|
||||
{{ 'labels.inputs.Date Of Birth' | translate }} : {{ member.dateOfBirth | dateFormat }}<br />
|
||||
{{ 'labels.inputs.Percentage Share' | translate }} : {{ member.percentageShare }}%<br />
|
||||
{{ 'labels.inputs.Nominee is Minor' | translate }} : {{ member.isDependent ? 'Yes' : 'No' }}<br />
|
||||
@if (member.isDependent) {
|
||||
{{ 'labels.inputs.Guardian Name' | translate }} : {{ member.guardianName }}<br />
|
||||
{{ 'labels.inputs.Relationship with Minor' | translate }} : {{ member.guardianRelationship }}<br />
|
||||
}
|
||||
@if (member.remarks) {
|
||||
{{ 'labels.inputs.Remarks' | translate }} : {{ member.remarks }}<br />
|
||||
}
|
||||
</p>
|
||||
</mat-expansion-panel>
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user