saving account,current account and rd account modify based on new update
This commit is contained in:
@@ -96,6 +96,9 @@
|
|||||||
[currentAccountSettingsForm]="currentAccountSettingsForm"
|
[currentAccountSettingsForm]="currentAccountSettingsForm"
|
||||||
[currentAccountTermsForm]="currentAccountTermsForm"
|
[currentAccountTermsForm]="currentAccountTermsForm"
|
||||||
[currentAccount]="currentAccount"
|
[currentAccount]="currentAccount"
|
||||||
|
[currentAccountDigital]="currentAccountDigital"
|
||||||
|
[currentAccountNominee]="currentAccountNominee"
|
||||||
|
[currentAccountCurrencyFlags]="currentAccountCurrencyFlags"
|
||||||
(submitEvent)="submit()"
|
(submitEvent)="submit()"
|
||||||
>
|
>
|
||||||
</mifosx-current-account-preview-step>
|
</mifosx-current-account-preview-step>
|
||||||
|
|||||||
+19
-7
@@ -66,14 +66,15 @@ export class CreateCurrentAccountComponent {
|
|||||||
/** Current Account Product Template */
|
/** Current Account Product Template */
|
||||||
currentAccountProductTemplate: any;
|
currentAccountProductTemplate: any;
|
||||||
|
|
||||||
/** Current Account Details Step */
|
|
||||||
@ViewChild(CurrentAccountDetailsStepComponent, { static: true })
|
@ViewChild(CurrentAccountDetailsStepComponent, { static: true })
|
||||||
currentAccountDetailsStep: CurrentAccountDetailsStepComponent;
|
currentAccountDetailsStep: CurrentAccountDetailsStepComponent;
|
||||||
|
|
||||||
/** Current Account Currency Step */
|
@ViewChild(CurrentAccountCurrencyStepComponent)
|
||||||
@ViewChild(CurrentAccountCurrencyStepComponent, { static: true })
|
|
||||||
currentAccountCurrencyStep: CurrentAccountCurrencyStepComponent;
|
currentAccountCurrencyStep: CurrentAccountCurrencyStepComponent;
|
||||||
|
|
||||||
|
@ViewChild(CurrentAccountDigitalStepComponent)
|
||||||
|
currentAccountDigitalStep: CurrentAccountDigitalStepComponent;
|
||||||
|
|
||||||
constructor() {
|
constructor() {
|
||||||
this.route.data.subscribe((data: { currentAccountTemplate: any }) => {
|
this.route.data.subscribe((data: { currentAccountTemplate: any }) => {
|
||||||
this.currentAccountTemplate = data.currentAccountTemplate;
|
this.currentAccountTemplate = data.currentAccountTemplate;
|
||||||
@@ -107,12 +108,23 @@ export class CreateCurrentAccountComponent {
|
|||||||
return new FormGroup({});
|
return new FormGroup({});
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Retrieves current account object.
|
|
||||||
*/
|
|
||||||
get currentAccount() {
|
get currentAccount() {
|
||||||
|
return { ...this.currentAccountDetailsStep.currentAccountDetails };
|
||||||
|
}
|
||||||
|
|
||||||
|
get currentAccountDigital() {
|
||||||
|
return this.currentAccountDigitalStep?.currentAccountDigital ?? null;
|
||||||
|
}
|
||||||
|
|
||||||
|
get currentAccountNominee() {
|
||||||
|
return this.currentAccountCurrencyStep?.nomineeData ?? null;
|
||||||
|
}
|
||||||
|
|
||||||
|
get currentAccountCurrencyFlags() {
|
||||||
return {
|
return {
|
||||||
...this.currentAccountDetailsStep.currentAccountDetails
|
balanceSwapOption: this.currentAccountCurrencyStep?.balanceSwapOption ?? false,
|
||||||
|
msme: this.currentAccountCurrencyStep?.msme ?? false,
|
||||||
|
autoDebitFacility: this.currentAccountCurrencyStep?.autoDebitFacility ?? false
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+3
-3
@@ -59,8 +59,9 @@
|
|||||||
{{ currentAccountProductTemplate?.dormancyAlert ? 'Yes' : 'No' }}
|
{{ currentAccountProductTemplate?.dormancyAlert ? 'Yes' : 'No' }}
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
|
@if (currentAccountProductTemplate?.dormancyAlert) {
|
||||||
<mifosx-dormancy-alert-panel [productTemplate]="currentAccountProductTemplate"></mifosx-dormancy-alert-panel>
|
<mifosx-dormancy-alert-panel [productTemplate]="currentAccountProductTemplate"></mifosx-dormancy-alert-panel>
|
||||||
|
}
|
||||||
|
|
||||||
<div class="sac-alert">
|
<div class="sac-alert">
|
||||||
<div class="sac-alert__content">
|
<div class="sac-alert__content">
|
||||||
@@ -71,7 +72,6 @@
|
|||||||
{{ currentAccountProductTemplate?.nominationFacility ? 'Yes' : 'No' }}
|
{{ currentAccountProductTemplate?.nominationFacility ? 'Yes' : 'No' }}
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@if (currentAccountProductTemplate?.nominationFacility) {
|
@if (currentAccountProductTemplate?.nominationFacility) {
|
||||||
<mifosx-nominee-form (nomineeChange)="onNomineeChange($event)"></mifosx-nominee-form>
|
<mifosx-nominee-form (nomineeChange)="onNomineeChange($event)"></mifosx-nominee-form>
|
||||||
}
|
}
|
||||||
|
|||||||
+190
@@ -0,0 +1,190 @@
|
|||||||
|
<!--
|
||||||
|
Copyright since 2025 Mifos Initiative
|
||||||
|
|
||||||
|
This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
|
License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
|
file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||||
|
-->
|
||||||
|
|
||||||
|
<!-- Header -->
|
||||||
|
<div class="abd-header">
|
||||||
|
<div class="abd-header__icon">
|
||||||
|
<mat-icon>person_pin</mat-icon>
|
||||||
|
</div>
|
||||||
|
<div class="abd-header__text">
|
||||||
|
<h2 class="abd-header__title">Add Beneficiary / Nominee</h2>
|
||||||
|
<p class="abd-header__sub">Register a nominee for this account as per Indian banking norms</p>
|
||||||
|
</div>
|
||||||
|
<button mat-icon-button class="abd-header__close" type="button" (click)="cancel()">
|
||||||
|
<mat-icon>close</mat-icon>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<mat-dialog-content>
|
||||||
|
<form [formGroup]="form" class="abd-form">
|
||||||
|
<!-- Mode Toggle -->
|
||||||
|
<div class="abd-mode-toggle">
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
class="abd-mode-btn"
|
||||||
|
[class.abd-mode-btn--active]="mode === 'search'"
|
||||||
|
(click)="switchMode('search')"
|
||||||
|
>
|
||||||
|
<mat-icon>manage_search</mat-icon> Linked Client
|
||||||
|
</button>
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
class="abd-mode-btn"
|
||||||
|
[class.abd-mode-btn--active]="mode === 'manual'"
|
||||||
|
(click)="switchMode('manual')"
|
||||||
|
>
|
||||||
|
<mat-icon>edit_note</mat-icon> Manual Entry
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Search Mode -->
|
||||||
|
@if (mode === 'search') {
|
||||||
|
<div class="abd-search-section">
|
||||||
|
<mat-form-field appearance="outline" class="abd-full-width">
|
||||||
|
<mat-label>Search Client by Name / CIF</mat-label>
|
||||||
|
<mat-icon matPrefix class="abd-prefix-icon">search</mat-icon>
|
||||||
|
<input
|
||||||
|
matInput
|
||||||
|
formControlName="searchText"
|
||||||
|
(input)="onSearchInput($event.target.value)"
|
||||||
|
autocomplete="off"
|
||||||
|
placeholder="Type at least 2 characters..."
|
||||||
|
/>
|
||||||
|
@if (isSearching) {
|
||||||
|
<mat-progress-spinner matSuffix diameter="18" mode="indeterminate"></mat-progress-spinner>
|
||||||
|
}
|
||||||
|
@if (selectedClient) {
|
||||||
|
<button matSuffix mat-icon-button type="button" (click)="clearSelection()">
|
||||||
|
<mat-icon>close</mat-icon>
|
||||||
|
</button>
|
||||||
|
}
|
||||||
|
</mat-form-field>
|
||||||
|
|
||||||
|
@if (searchResults.length > 0) {
|
||||||
|
<div class="abd-search-results">
|
||||||
|
@for (client of searchResults; track client) {
|
||||||
|
<div class="abd-result-item" (click)="selectClient(client)">
|
||||||
|
<div class="abd-result-avatar">{{ (client.displayName || '?')[0].toUpperCase() }}</div>
|
||||||
|
<div class="abd-result-body">
|
||||||
|
<span class="abd-result-name">{{ client.displayName }}</span>
|
||||||
|
<span class="abd-result-meta">
|
||||||
|
@if (client.cifNumber) {
|
||||||
|
<span class="abd-chip">{{ client.cifNumber }}</span>
|
||||||
|
}
|
||||||
|
@if (client.officeName) {
|
||||||
|
<span class="abd-chip">{{ client.officeName }}</span>
|
||||||
|
}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
<mat-icon class="abd-result-arrow">chevron_right</mat-icon>
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
|
||||||
|
@if (selectedClient) {
|
||||||
|
<div class="abd-selected-card">
|
||||||
|
<div class="abd-selected-avatar">{{ (selectedClient.displayName || '?')[0].toUpperCase() }}</div>
|
||||||
|
<div class="abd-selected-info">
|
||||||
|
<span class="abd-selected-name">{{ selectedClient.displayName }}</span>
|
||||||
|
<span class="abd-selected-sub">{{ selectedClient.cifNumber || selectedClient.accountNumber }}</span>
|
||||||
|
</div>
|
||||||
|
<span class="abd-badge abd-badge--linked">Linked</span>
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
|
||||||
|
<!-- Name field (manual or auto-filled) -->
|
||||||
|
<mat-form-field appearance="outline" class="abd-full-width abd-mt">
|
||||||
|
<mat-label>Nominee / Beneficiary Name <span class="abd-required">*</span></mat-label>
|
||||||
|
<input matInput formControlName="name" [readonly]="mode === 'search' && !!selectedClient" />
|
||||||
|
<mat-error>Name is required</mat-error>
|
||||||
|
</mat-form-field>
|
||||||
|
|
||||||
|
<!-- Row: Relationship + DOB -->
|
||||||
|
<div class="abd-row">
|
||||||
|
<mat-form-field appearance="outline" class="abd-flex">
|
||||||
|
<mat-label>Relationship <span class="abd-required">*</span></mat-label>
|
||||||
|
<mat-select formControlName="relationship">
|
||||||
|
@for (r of relationships; track r) {
|
||||||
|
<mat-option [value]="r">{{ r }}</mat-option>
|
||||||
|
}
|
||||||
|
</mat-select>
|
||||||
|
<mat-error>Relationship is required</mat-error>
|
||||||
|
</mat-form-field>
|
||||||
|
|
||||||
|
<mat-form-field appearance="outline" class="abd-flex" (click)="dobPicker.open()">
|
||||||
|
<mat-label>Date of Birth</mat-label>
|
||||||
|
<input matInput [matDatepicker]="dobPicker" formControlName="dateOfBirth" readonly />
|
||||||
|
<mat-datepicker-toggle matSuffix [for]="dobPicker"></mat-datepicker-toggle>
|
||||||
|
<mat-datepicker #dobPicker></mat-datepicker>
|
||||||
|
</mat-form-field>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Share % -->
|
||||||
|
<div class="abd-share-row">
|
||||||
|
<mat-form-field appearance="outline" class="abd-share-field">
|
||||||
|
<mat-label>Share % <span class="abd-required">*</span></mat-label>
|
||||||
|
<input matInput type="number" formControlName="sharePercentage" min="1" max="100" />
|
||||||
|
<span matSuffix class="abd-pct">%</span>
|
||||||
|
<mat-error>Enter 1–100</mat-error>
|
||||||
|
</mat-form-field>
|
||||||
|
<div class="abd-quick-pct">
|
||||||
|
@for (p of [25, 33, 50, 100]; track p) {
|
||||||
|
<button type="button" class="abd-pct-chip" (click)="form.get('sharePercentage').setValue(p)">{{ p }}%</button>
|
||||||
|
}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Minor Toggle -->
|
||||||
|
<div class="abd-minor-toggle">
|
||||||
|
<mat-slide-toggle formControlName="isMinor" color="primary">
|
||||||
|
Nominee is a Minor (below 18 years)
|
||||||
|
</mat-slide-toggle>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Guardian fields (if minor) -->
|
||||||
|
@if (isMinor) {
|
||||||
|
<div class="abd-guardian-box">
|
||||||
|
<div class="abd-guardian-label">
|
||||||
|
<mat-icon>supervisor_account</mat-icon>
|
||||||
|
Guardian Details
|
||||||
|
</div>
|
||||||
|
<div class="abd-row">
|
||||||
|
<mat-form-field appearance="outline" class="abd-flex">
|
||||||
|
<mat-label>Guardian Name</mat-label>
|
||||||
|
<input matInput formControlName="guardianName" />
|
||||||
|
</mat-form-field>
|
||||||
|
<mat-form-field appearance="outline" class="abd-flex">
|
||||||
|
<mat-label>Guardian Relationship</mat-label>
|
||||||
|
<mat-select formControlName="guardianRelationship">
|
||||||
|
@for (r of guardianRelationships; track r) {
|
||||||
|
<mat-option [value]="r">{{ r }}</mat-option>
|
||||||
|
}
|
||||||
|
</mat-select>
|
||||||
|
</mat-form-field>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
</form>
|
||||||
|
</mat-dialog-content>
|
||||||
|
|
||||||
|
<mat-dialog-actions class="abd-actions">
|
||||||
|
<button mat-stroked-button type="button" (click)="cancel()">Cancel</button>
|
||||||
|
<button
|
||||||
|
mat-flat-button
|
||||||
|
color="primary"
|
||||||
|
type="button"
|
||||||
|
class="abd-btn-add"
|
||||||
|
[disabled]="form.get('name').invalid || form.get('relationship').invalid || form.get('sharePercentage').invalid"
|
||||||
|
(click)="confirm()"
|
||||||
|
>
|
||||||
|
<mat-icon>check</mat-icon> Add Nominee
|
||||||
|
</button>
|
||||||
|
</mat-dialog-actions>
|
||||||
+415
@@ -0,0 +1,415 @@
|
|||||||
|
/**
|
||||||
|
* Copyright since 2025 Mifos Initiative
|
||||||
|
*
|
||||||
|
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||||
|
*/
|
||||||
|
|
||||||
|
$primary: #1a56db;
|
||||||
|
$primary-light: #eff6ff;
|
||||||
|
$primary-border: #bfdbfe;
|
||||||
|
$success: #057a55;
|
||||||
|
$success-light: #f3faf7;
|
||||||
|
$success-border: #84e1bc;
|
||||||
|
$orange: #d03801;
|
||||||
|
$orange-light: #fff8f1;
|
||||||
|
$orange-border: #fcd9bd;
|
||||||
|
$border: #e5e7eb;
|
||||||
|
$text: #111827;
|
||||||
|
$muted: #6b7280;
|
||||||
|
$radius: 10px;
|
||||||
|
|
||||||
|
mifosx-add-beneficiary-dialog {
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Header
|
||||||
|
.abd-header {
|
||||||
|
display: flex;
|
||||||
|
align-items: flex-start;
|
||||||
|
gap: 12px;
|
||||||
|
padding: 18px 20px 14px;
|
||||||
|
border-bottom: 1px solid $border;
|
||||||
|
background: linear-gradient(135deg, #f0f7ff 0%, #fff 60%);
|
||||||
|
|
||||||
|
&__icon {
|
||||||
|
width: 42px;
|
||||||
|
height: 42px;
|
||||||
|
border-radius: 10px;
|
||||||
|
background: $primary;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
flex-shrink: 0;
|
||||||
|
|
||||||
|
mat-icon {
|
||||||
|
color: #fff;
|
||||||
|
font-size: 22px;
|
||||||
|
width: 22px;
|
||||||
|
height: 22px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&__text {
|
||||||
|
flex: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
&__title {
|
||||||
|
margin: 0;
|
||||||
|
font-size: 15px;
|
||||||
|
font-weight: 700;
|
||||||
|
color: $text;
|
||||||
|
}
|
||||||
|
|
||||||
|
&__sub {
|
||||||
|
margin: 3px 0 0;
|
||||||
|
font-size: 11.5px;
|
||||||
|
color: $muted;
|
||||||
|
}
|
||||||
|
|
||||||
|
&__close {
|
||||||
|
color: $muted;
|
||||||
|
margin: -4px -8px 0 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Form
|
||||||
|
.abd-form {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 0;
|
||||||
|
width: 500px;
|
||||||
|
max-width: 100%;
|
||||||
|
padding: 4px 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.abd-full-width {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.abd-mt {
|
||||||
|
margin-top: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Mode toggle
|
||||||
|
.abd-mode-toggle {
|
||||||
|
display: flex;
|
||||||
|
gap: 8px;
|
||||||
|
margin: 14px 0 10px;
|
||||||
|
background: #f9fafb;
|
||||||
|
border: 1px solid $border;
|
||||||
|
border-radius: 10px;
|
||||||
|
padding: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.abd-mode-btn {
|
||||||
|
flex: 1;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
gap: 6px;
|
||||||
|
padding: 8px 14px;
|
||||||
|
border-radius: 8px;
|
||||||
|
border: 1.5px solid transparent;
|
||||||
|
background: transparent;
|
||||||
|
font-size: 13px;
|
||||||
|
font-weight: 600;
|
||||||
|
color: $muted;
|
||||||
|
cursor: pointer;
|
||||||
|
transition: all 0.15s;
|
||||||
|
|
||||||
|
mat-icon {
|
||||||
|
font-size: 16px;
|
||||||
|
width: 16px;
|
||||||
|
height: 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
&--active {
|
||||||
|
background: #fff;
|
||||||
|
border-color: $primary-border;
|
||||||
|
color: $primary;
|
||||||
|
box-shadow: 0 1px 4px rgb(0 0 0 / 8%);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Search
|
||||||
|
.abd-search-section {
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
|
||||||
|
.abd-prefix-icon {
|
||||||
|
font-size: 18px;
|
||||||
|
width: 18px;
|
||||||
|
height: 18px;
|
||||||
|
color: $muted;
|
||||||
|
margin-right: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.abd-search-results {
|
||||||
|
position: absolute;
|
||||||
|
z-index: 200;
|
||||||
|
top: calc(100% - 8px);
|
||||||
|
left: 0;
|
||||||
|
right: 0;
|
||||||
|
background: #fff;
|
||||||
|
border: 1px solid $border;
|
||||||
|
border-radius: $radius;
|
||||||
|
box-shadow: 0 8px 24px rgb(0 0 0 / 12%);
|
||||||
|
max-height: 220px;
|
||||||
|
overflow-y: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.abd-result-item {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 10px;
|
||||||
|
padding: 10px 14px;
|
||||||
|
cursor: pointer;
|
||||||
|
border-bottom: 1px solid #f3f4f6;
|
||||||
|
transition: background 0.1s;
|
||||||
|
|
||||||
|
&:last-child {
|
||||||
|
border-bottom: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
background: $primary-light;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.abd-result-avatar {
|
||||||
|
width: 32px;
|
||||||
|
height: 32px;
|
||||||
|
border-radius: 50%;
|
||||||
|
background: linear-gradient(135deg, #6366f1, $primary);
|
||||||
|
color: #fff;
|
||||||
|
font-size: 13px;
|
||||||
|
font-weight: 700;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
flex-shrink: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.abd-result-body {
|
||||||
|
flex: 1;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 2px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.abd-result-name {
|
||||||
|
font-size: 13px;
|
||||||
|
font-weight: 600;
|
||||||
|
color: $text;
|
||||||
|
}
|
||||||
|
|
||||||
|
.abd-result-meta {
|
||||||
|
display: flex;
|
||||||
|
gap: 5px;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
}
|
||||||
|
|
||||||
|
.abd-chip {
|
||||||
|
font-size: 10px;
|
||||||
|
padding: 1px 7px;
|
||||||
|
border-radius: 999px;
|
||||||
|
background: #f3f4f6;
|
||||||
|
color: $muted;
|
||||||
|
font-weight: 500;
|
||||||
|
}
|
||||||
|
|
||||||
|
.abd-result-arrow {
|
||||||
|
font-size: 18px;
|
||||||
|
width: 18px;
|
||||||
|
height: 18px;
|
||||||
|
color: $primary;
|
||||||
|
opacity: 0.4;
|
||||||
|
transition: all 0.1s;
|
||||||
|
|
||||||
|
.abd-result-item:hover & {
|
||||||
|
opacity: 1;
|
||||||
|
transform: translateX(2px);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Selected card
|
||||||
|
.abd-selected-card {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 10px;
|
||||||
|
padding: 10px 14px;
|
||||||
|
background: $success-light;
|
||||||
|
border: 1.5px solid $success-border;
|
||||||
|
border-radius: $radius;
|
||||||
|
margin-top: 6px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.abd-selected-avatar {
|
||||||
|
width: 36px;
|
||||||
|
height: 36px;
|
||||||
|
border-radius: 50%;
|
||||||
|
background: linear-gradient(135deg, #10b981, $success);
|
||||||
|
color: #fff;
|
||||||
|
font-size: 14px;
|
||||||
|
font-weight: 700;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
flex-shrink: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.abd-selected-info {
|
||||||
|
flex: 1;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 2px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.abd-selected-name {
|
||||||
|
font-size: 13px;
|
||||||
|
font-weight: 700;
|
||||||
|
color: #065f46;
|
||||||
|
}
|
||||||
|
|
||||||
|
.abd-selected-sub {
|
||||||
|
font-size: 11px;
|
||||||
|
color: #047857;
|
||||||
|
}
|
||||||
|
|
||||||
|
.abd-badge {
|
||||||
|
font-size: 10px;
|
||||||
|
font-weight: 700;
|
||||||
|
padding: 3px 10px;
|
||||||
|
border-radius: 999px;
|
||||||
|
text-transform: uppercase;
|
||||||
|
letter-spacing: 0.04em;
|
||||||
|
|
||||||
|
&--linked {
|
||||||
|
background: $success;
|
||||||
|
color: #fff;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Row layout
|
||||||
|
.abd-row {
|
||||||
|
display: flex;
|
||||||
|
gap: 12px;
|
||||||
|
margin-top: 8px;
|
||||||
|
|
||||||
|
@media (width <= 500px) {
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.abd-flex {
|
||||||
|
flex: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Share %
|
||||||
|
.abd-share-row {
|
||||||
|
display: flex;
|
||||||
|
align-items: flex-start;
|
||||||
|
gap: 12px;
|
||||||
|
margin-top: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.abd-share-field {
|
||||||
|
flex: 0 0 150px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.abd-pct {
|
||||||
|
font-size: 15px;
|
||||||
|
font-weight: 600;
|
||||||
|
color: $muted;
|
||||||
|
margin-right: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.abd-quick-pct {
|
||||||
|
display: flex;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
gap: 6px;
|
||||||
|
padding-top: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.abd-pct-chip {
|
||||||
|
padding: 5px 12px;
|
||||||
|
border-radius: 8px;
|
||||||
|
border: 1.5px solid $border;
|
||||||
|
background: #fff;
|
||||||
|
font-size: 12px;
|
||||||
|
font-weight: 600;
|
||||||
|
color: $muted;
|
||||||
|
cursor: pointer;
|
||||||
|
transition: all 0.12s;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
border-color: $primary;
|
||||||
|
background: $primary-light;
|
||||||
|
color: $primary;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Required star
|
||||||
|
.abd-required {
|
||||||
|
color: #e02424;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Minor toggle
|
||||||
|
.abd-minor-toggle {
|
||||||
|
margin-top: 14px;
|
||||||
|
padding: 12px 14px;
|
||||||
|
background: #fffbeb;
|
||||||
|
border: 1px solid #fde68a;
|
||||||
|
border-radius: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Guardian box
|
||||||
|
.abd-guardian-box {
|
||||||
|
margin-top: 10px;
|
||||||
|
padding: 14px;
|
||||||
|
background: $orange-light;
|
||||||
|
border: 1.5px solid $orange-border;
|
||||||
|
border-radius: $radius;
|
||||||
|
}
|
||||||
|
|
||||||
|
.abd-guardian-label {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 6px;
|
||||||
|
font-size: 12px;
|
||||||
|
font-weight: 700;
|
||||||
|
color: $orange;
|
||||||
|
text-transform: uppercase;
|
||||||
|
letter-spacing: 0.04em;
|
||||||
|
margin-bottom: 10px;
|
||||||
|
|
||||||
|
mat-icon {
|
||||||
|
font-size: 16px;
|
||||||
|
width: 16px;
|
||||||
|
height: 16px;
|
||||||
|
color: $orange;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Actions
|
||||||
|
.abd-actions {
|
||||||
|
padding: 12px 20px 16px !important;
|
||||||
|
border-top: 1px solid $border;
|
||||||
|
gap: 10px;
|
||||||
|
justify-content: flex-end !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.abd-btn-add {
|
||||||
|
border-radius: 8px !important;
|
||||||
|
padding: 0 18px !important;
|
||||||
|
gap: 4px;
|
||||||
|
|
||||||
|
mat-icon {
|
||||||
|
font-size: 18px;
|
||||||
|
width: 18px;
|
||||||
|
height: 18px;
|
||||||
|
}
|
||||||
|
}
|
||||||
+167
@@ -0,0 +1,167 @@
|
|||||||
|
/**
|
||||||
|
* Copyright since 2025 Mifos Initiative
|
||||||
|
*
|
||||||
|
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import { Component, inject, OnDestroy, ViewEncapsulation } from '@angular/core';
|
||||||
|
import { UntypedFormBuilder, UntypedFormGroup, Validators, ReactiveFormsModule } from '@angular/forms';
|
||||||
|
import { MatDialogRef, MatDialogContent, MatDialogActions } from '@angular/material/dialog';
|
||||||
|
import { MatProgressSpinner } from '@angular/material/progress-spinner';
|
||||||
|
import { MatIcon } from '@angular/material/icon';
|
||||||
|
import { MatSlideToggle } from '@angular/material/slide-toggle';
|
||||||
|
import { ClientsService } from 'app/clients/clients.service';
|
||||||
|
import { STANDALONE_SHARED_IMPORTS } from 'app/standalone-shared.module';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'mifosx-add-beneficiary-dialog',
|
||||||
|
templateUrl: './add-beneficiary-dialog.component.html',
|
||||||
|
styleUrl: './add-beneficiary-dialog.component.scss',
|
||||||
|
encapsulation: ViewEncapsulation.None,
|
||||||
|
imports: [
|
||||||
|
...STANDALONE_SHARED_IMPORTS,
|
||||||
|
MatDialogContent,
|
||||||
|
MatDialogActions,
|
||||||
|
MatProgressSpinner,
|
||||||
|
MatIcon,
|
||||||
|
MatSlideToggle,
|
||||||
|
ReactiveFormsModule
|
||||||
|
]
|
||||||
|
})
|
||||||
|
export class AddBeneficiaryDialogComponent implements OnDestroy {
|
||||||
|
private fb = inject(UntypedFormBuilder);
|
||||||
|
private clientsService = inject(ClientsService);
|
||||||
|
dialogRef = inject(MatDialogRef<AddBeneficiaryDialogComponent>);
|
||||||
|
|
||||||
|
/** Toggle between linked client and manual entry */
|
||||||
|
mode: 'search' | 'manual' = 'search';
|
||||||
|
|
||||||
|
form: UntypedFormGroup = this.fb.group({
|
||||||
|
searchText: [''],
|
||||||
|
name: [
|
||||||
|
'',
|
||||||
|
Validators.required
|
||||||
|
],
|
||||||
|
relationship: [
|
||||||
|
'',
|
||||||
|
Validators.required
|
||||||
|
],
|
||||||
|
dateOfBirth: [null],
|
||||||
|
sharePercentage: [
|
||||||
|
null,
|
||||||
|
[
|
||||||
|
Validators.required,
|
||||||
|
Validators.min(1),
|
||||||
|
Validators.max(100)
|
||||||
|
]
|
||||||
|
],
|
||||||
|
isMinor: [false],
|
||||||
|
guardianName: [''],
|
||||||
|
guardianRelationship: ['']
|
||||||
|
});
|
||||||
|
|
||||||
|
searchResults: any[] = [];
|
||||||
|
selectedClient: any = null;
|
||||||
|
isSearching = false;
|
||||||
|
private searchTimer: any = null;
|
||||||
|
|
||||||
|
readonly relationships = [
|
||||||
|
'Spouse',
|
||||||
|
'Son',
|
||||||
|
'Daughter',
|
||||||
|
'Father',
|
||||||
|
'Mother',
|
||||||
|
'Brother',
|
||||||
|
'Sister',
|
||||||
|
'Grandson',
|
||||||
|
'Granddaughter',
|
||||||
|
'Father-in-law',
|
||||||
|
'Mother-in-law',
|
||||||
|
'Other'
|
||||||
|
];
|
||||||
|
|
||||||
|
readonly guardianRelationships = [
|
||||||
|
'Father',
|
||||||
|
'Mother',
|
||||||
|
'Guardian',
|
||||||
|
'Natural Guardian'
|
||||||
|
];
|
||||||
|
|
||||||
|
get isMinor(): boolean {
|
||||||
|
return this.form.get('isMinor').value;
|
||||||
|
}
|
||||||
|
|
||||||
|
switchMode(m: 'search' | 'manual'): void {
|
||||||
|
this.mode = m;
|
||||||
|
this.selectedClient = null;
|
||||||
|
this.searchResults = [];
|
||||||
|
this.form.patchValue({ searchText: '', name: '' });
|
||||||
|
}
|
||||||
|
|
||||||
|
onSearchInput(value: string): void {
|
||||||
|
if (this.searchTimer) clearTimeout(this.searchTimer);
|
||||||
|
this.selectedClient = null;
|
||||||
|
if (!value || value.trim().length < 2) {
|
||||||
|
this.searchResults = [];
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
this.isSearching = true;
|
||||||
|
this.searchTimer = setTimeout(() => {
|
||||||
|
this.clientsService.searchByText(value.trim(), 0, 10).subscribe({
|
||||||
|
next: (res: any) => {
|
||||||
|
this.searchResults = res?.content || [];
|
||||||
|
this.isSearching = false;
|
||||||
|
},
|
||||||
|
error: () => {
|
||||||
|
this.searchResults = [];
|
||||||
|
this.isSearching = false;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}, 400);
|
||||||
|
}
|
||||||
|
|
||||||
|
selectClient(client: any): void {
|
||||||
|
this.selectedClient = client;
|
||||||
|
this.form.patchValue({
|
||||||
|
searchText: client.displayName,
|
||||||
|
name: client.displayName
|
||||||
|
});
|
||||||
|
this.searchResults = [];
|
||||||
|
}
|
||||||
|
|
||||||
|
clearSelection(): void {
|
||||||
|
this.selectedClient = null;
|
||||||
|
this.form.patchValue({ searchText: '', name: '' });
|
||||||
|
this.searchResults = [];
|
||||||
|
}
|
||||||
|
|
||||||
|
confirm(): void {
|
||||||
|
if (
|
||||||
|
this.form.get('name').invalid ||
|
||||||
|
this.form.get('relationship').invalid ||
|
||||||
|
this.form.get('sharePercentage').invalid
|
||||||
|
)
|
||||||
|
return;
|
||||||
|
const v = this.form.getRawValue();
|
||||||
|
this.dialogRef.close({
|
||||||
|
clientId: this.selectedClient?.id || null,
|
||||||
|
name: v.name,
|
||||||
|
relationship: v.relationship,
|
||||||
|
dateOfBirth: v.dateOfBirth,
|
||||||
|
sharePercentage: v.sharePercentage,
|
||||||
|
isMinor: v.isMinor,
|
||||||
|
guardianName: v.isMinor ? v.guardianName : null,
|
||||||
|
guardianRelationship: v.isMinor ? v.guardianRelationship : null
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
cancel(): void {
|
||||||
|
this.dialogRef.close(null);
|
||||||
|
}
|
||||||
|
|
||||||
|
ngOnDestroy(): void {
|
||||||
|
if (this.searchTimer) clearTimeout(this.searchTimer);
|
||||||
|
}
|
||||||
|
}
|
||||||
+135
@@ -0,0 +1,135 @@
|
|||||||
|
<!--
|
||||||
|
Copyright since 2025 Mifos Initiative
|
||||||
|
|
||||||
|
This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
|
License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
|
file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||||
|
-->
|
||||||
|
|
||||||
|
<!-- Dialog Header -->
|
||||||
|
<div class="arc-header">
|
||||||
|
<div class="arc-header__icon">
|
||||||
|
<mat-icon>person_add</mat-icon>
|
||||||
|
</div>
|
||||||
|
<div class="arc-header__text">
|
||||||
|
<h2 class="arc-header__title">Add Related Client / Partner</h2>
|
||||||
|
<p class="arc-header__sub">Search and link an existing client with their ownership share</p>
|
||||||
|
</div>
|
||||||
|
<button mat-icon-button class="arc-header__close" (click)="cancel()">
|
||||||
|
<mat-icon>close</mat-icon>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<mat-dialog-content>
|
||||||
|
<form [formGroup]="form" class="arc-dialog-form">
|
||||||
|
<!-- Step 1: Client Search -->
|
||||||
|
<div class="arc-step-label">
|
||||||
|
<span class="arc-step-badge">1</span>
|
||||||
|
<span>Select Client</span>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="arc-search-section">
|
||||||
|
<mat-form-field appearance="outline" class="arc-full-width">
|
||||||
|
<mat-label>Search by Name / CIF / Account No</mat-label>
|
||||||
|
<mat-icon matPrefix class="arc-search-icon">search</mat-icon>
|
||||||
|
<input
|
||||||
|
matInput
|
||||||
|
formControlName="searchText"
|
||||||
|
(input)="onSearchInput($event.target.value)"
|
||||||
|
autocomplete="off"
|
||||||
|
placeholder="Type at least 2 characters..."
|
||||||
|
/>
|
||||||
|
@if (isSearching) {
|
||||||
|
<mat-progress-spinner matSuffix diameter="18" mode="indeterminate"></mat-progress-spinner>
|
||||||
|
}
|
||||||
|
@if (selectedClient) {
|
||||||
|
<button matSuffix mat-icon-button type="button" (click)="clearSelection()">
|
||||||
|
<mat-icon>close</mat-icon>
|
||||||
|
</button>
|
||||||
|
}
|
||||||
|
</mat-form-field>
|
||||||
|
|
||||||
|
<!-- Search Results -->
|
||||||
|
@if (searchResults.length > 0) {
|
||||||
|
<div class="arc-search-results">
|
||||||
|
@for (client of searchResults; track client) {
|
||||||
|
<div class="arc-search-result-item" (click)="selectClient(client)">
|
||||||
|
<div class="arc-result-avatar">
|
||||||
|
{{ (client.displayName || '?')[0].toUpperCase() }}
|
||||||
|
</div>
|
||||||
|
<div class="arc-result-body">
|
||||||
|
<span class="arc-result-name">{{ client.displayName }}</span>
|
||||||
|
<span class="arc-result-meta">
|
||||||
|
@if (client.cifNumber) {
|
||||||
|
<span class="arc-chip">{{ client.cifNumber }}</span>
|
||||||
|
}
|
||||||
|
@if (client.officeName) {
|
||||||
|
<span class="arc-chip">{{ client.officeName }}</span>
|
||||||
|
}
|
||||||
|
@if (client.status?.value) {
|
||||||
|
<span class="arc-chip arc-chip--status" [class.arc-chip--active]="client.status?.id === 300">
|
||||||
|
{{ client.status.value }}
|
||||||
|
</span>
|
||||||
|
}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
<mat-icon class="arc-result-arrow">chevron_right</mat-icon>
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Selected Client Card -->
|
||||||
|
@if (selectedClient) {
|
||||||
|
<div class="arc-selected-client">
|
||||||
|
<div class="arc-selected-avatar">
|
||||||
|
{{ (selectedClient.displayName || '?')[0].toUpperCase() }}
|
||||||
|
</div>
|
||||||
|
<div class="arc-client-info">
|
||||||
|
<span class="arc-client-name">{{ selectedClient.displayName }}</span>
|
||||||
|
<span class="arc-client-sub">{{ selectedClient.cifNumber || selectedClient.accountNumber || 'N/A' }}</span>
|
||||||
|
</div>
|
||||||
|
<span class="arc-selected-badge">Selected</span>
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
|
||||||
|
<!-- Step 2: Share Percentage -->
|
||||||
|
<div class="arc-step-label arc-step-label--mt">
|
||||||
|
<span class="arc-step-badge">2</span>
|
||||||
|
<span>Ownership Share</span>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="arc-share-row">
|
||||||
|
<mat-form-field appearance="outline" class="arc-share-field">
|
||||||
|
<mat-label>Share Percentage</mat-label>
|
||||||
|
<input matInput type="number" formControlName="sharePercentage" min="1" max="100" />
|
||||||
|
<span matSuffix class="arc-percent-suffix">%</span>
|
||||||
|
<mat-error>Enter a value between 1 and 100</mat-error>
|
||||||
|
</mat-form-field>
|
||||||
|
|
||||||
|
<div class="arc-share-hints">
|
||||||
|
@for (hint of [25, 33, 50, 100]; track hint) {
|
||||||
|
<button type="button" class="arc-hint-chip" (click)="form.get('sharePercentage').setValue(hint)">
|
||||||
|
{{ hint }}%
|
||||||
|
</button>
|
||||||
|
}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</mat-dialog-content>
|
||||||
|
|
||||||
|
<mat-dialog-actions class="arc-actions">
|
||||||
|
<button mat-stroked-button type="button" (click)="cancel()" class="arc-btn-cancel">Cancel</button>
|
||||||
|
<button
|
||||||
|
mat-flat-button
|
||||||
|
color="primary"
|
||||||
|
type="button"
|
||||||
|
class="arc-btn-add"
|
||||||
|
[disabled]="!selectedClient || form.get('sharePercentage').invalid"
|
||||||
|
(click)="confirm()"
|
||||||
|
>
|
||||||
|
<mat-icon>add</mat-icon>
|
||||||
|
Add Partner
|
||||||
|
</button>
|
||||||
|
</mat-dialog-actions>
|
||||||
+359
@@ -0,0 +1,359 @@
|
|||||||
|
/**
|
||||||
|
* Copyright since 2025 Mifos Initiative
|
||||||
|
*
|
||||||
|
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||||
|
*/
|
||||||
|
|
||||||
|
// ── Tokens ───────────────────────────────────────────────────────────────────
|
||||||
|
$primary: #2563eb;
|
||||||
|
$primary-light: #eff6ff;
|
||||||
|
$primary-border: #bfdbfe;
|
||||||
|
$success: #16a34a;
|
||||||
|
$success-light: #f0fdf4;
|
||||||
|
$success-border: #bbf7d0;
|
||||||
|
$border: #e5e7eb;
|
||||||
|
$text: #111827;
|
||||||
|
$text-muted: #6b7280;
|
||||||
|
$radius: 10px;
|
||||||
|
|
||||||
|
// ── Dialog wrapper ────────────────────────────────────────────────────────────
|
||||||
|
mifosx-add-related-client-dialog {
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ── Header ────────────────────────────────────────────────────────────────────
|
||||||
|
.arc-header {
|
||||||
|
display: flex;
|
||||||
|
align-items: flex-start;
|
||||||
|
gap: 12px;
|
||||||
|
padding: 20px 20px 14px;
|
||||||
|
border-bottom: 1px solid $border;
|
||||||
|
|
||||||
|
&__icon {
|
||||||
|
width: 40px;
|
||||||
|
height: 40px;
|
||||||
|
border-radius: 10px;
|
||||||
|
background: $primary-light;
|
||||||
|
border: 1px solid $primary-border;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
flex-shrink: 0;
|
||||||
|
|
||||||
|
mat-icon {
|
||||||
|
color: $primary;
|
||||||
|
font-size: 20px;
|
||||||
|
width: 20px;
|
||||||
|
height: 20px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&__text {
|
||||||
|
flex: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
&__title {
|
||||||
|
margin: 0;
|
||||||
|
font-size: 15px;
|
||||||
|
font-weight: 700;
|
||||||
|
color: $text;
|
||||||
|
line-height: 1.3;
|
||||||
|
}
|
||||||
|
|
||||||
|
&__sub {
|
||||||
|
margin: 3px 0 0;
|
||||||
|
font-size: 12px;
|
||||||
|
color: $text-muted;
|
||||||
|
}
|
||||||
|
|
||||||
|
&__close {
|
||||||
|
margin-top: -4px;
|
||||||
|
margin-right: -8px;
|
||||||
|
color: $text-muted;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ── Dialog content ────────────────────────────────────────────────────────────
|
||||||
|
.arc-dialog-form {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 0;
|
||||||
|
width: 440px;
|
||||||
|
max-width: 100%;
|
||||||
|
padding-top: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ── Step labels ───────────────────────────────────────────────────────────────
|
||||||
|
.arc-step-label {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 8px;
|
||||||
|
margin: 16px 0 10px;
|
||||||
|
font-size: 12px;
|
||||||
|
font-weight: 700;
|
||||||
|
color: $text-muted;
|
||||||
|
text-transform: uppercase;
|
||||||
|
letter-spacing: 0.04em;
|
||||||
|
|
||||||
|
&--mt {
|
||||||
|
margin-top: 20px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.arc-step-badge {
|
||||||
|
width: 20px;
|
||||||
|
height: 20px;
|
||||||
|
border-radius: 50%;
|
||||||
|
background: $primary;
|
||||||
|
color: #fff;
|
||||||
|
font-size: 11px;
|
||||||
|
font-weight: 700;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
flex-shrink: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ── Search ────────────────────────────────────────────────────────────────────
|
||||||
|
.arc-full-width {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.arc-search-section {
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
|
||||||
|
.arc-search-icon {
|
||||||
|
font-size: 18px;
|
||||||
|
width: 18px;
|
||||||
|
height: 18px;
|
||||||
|
color: $text-muted;
|
||||||
|
margin-right: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.arc-search-results {
|
||||||
|
position: absolute;
|
||||||
|
z-index: 200;
|
||||||
|
top: calc(100% - 8px);
|
||||||
|
left: 0;
|
||||||
|
right: 0;
|
||||||
|
background: #fff;
|
||||||
|
border: 1px solid $border;
|
||||||
|
border-radius: $radius;
|
||||||
|
box-shadow: 0 8px 24px rgb(0 0 0 / 12%);
|
||||||
|
max-height: 240px;
|
||||||
|
overflow-y: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.arc-search-result-item {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 10px;
|
||||||
|
padding: 10px 14px;
|
||||||
|
cursor: pointer;
|
||||||
|
border-bottom: 1px solid #f3f4f6;
|
||||||
|
transition: background 0.12s;
|
||||||
|
|
||||||
|
&:last-child {
|
||||||
|
border-bottom: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
background: $primary-light;
|
||||||
|
|
||||||
|
.arc-result-arrow {
|
||||||
|
opacity: 1;
|
||||||
|
transform: translateX(2px);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.arc-result-avatar {
|
||||||
|
width: 34px;
|
||||||
|
height: 34px;
|
||||||
|
border-radius: 50%;
|
||||||
|
background: linear-gradient(135deg, #6366f1, #2563eb);
|
||||||
|
color: #fff;
|
||||||
|
font-size: 13px;
|
||||||
|
font-weight: 700;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
flex-shrink: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.arc-result-body {
|
||||||
|
flex: 1;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 3px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.arc-result-name {
|
||||||
|
font-size: 13px;
|
||||||
|
font-weight: 600;
|
||||||
|
color: $text;
|
||||||
|
}
|
||||||
|
|
||||||
|
.arc-result-meta {
|
||||||
|
display: flex;
|
||||||
|
gap: 6px;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
}
|
||||||
|
|
||||||
|
.arc-chip {
|
||||||
|
font-size: 10px;
|
||||||
|
padding: 1px 7px;
|
||||||
|
border-radius: 999px;
|
||||||
|
background: #f3f4f6;
|
||||||
|
color: $text-muted;
|
||||||
|
font-weight: 500;
|
||||||
|
|
||||||
|
&--status {
|
||||||
|
background: #fef3c7;
|
||||||
|
color: #92400e;
|
||||||
|
}
|
||||||
|
|
||||||
|
&--active {
|
||||||
|
background: #dcfce7;
|
||||||
|
color: #166534;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.arc-result-arrow {
|
||||||
|
font-size: 18px;
|
||||||
|
width: 18px;
|
||||||
|
height: 18px;
|
||||||
|
color: $primary;
|
||||||
|
opacity: 0;
|
||||||
|
transition:
|
||||||
|
opacity 0.12s,
|
||||||
|
transform 0.12s;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ── Selected client ───────────────────────────────────────────────────────────
|
||||||
|
.arc-selected-client {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 12px;
|
||||||
|
padding: 12px 14px;
|
||||||
|
background: $success-light;
|
||||||
|
border: 1.5px solid $success-border;
|
||||||
|
border-radius: $radius;
|
||||||
|
margin-top: 6px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.arc-selected-avatar {
|
||||||
|
width: 38px;
|
||||||
|
height: 38px;
|
||||||
|
border-radius: 50%;
|
||||||
|
background: linear-gradient(135deg, #22c55e, #16a34a);
|
||||||
|
color: #fff;
|
||||||
|
font-size: 14px;
|
||||||
|
font-weight: 700;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
flex-shrink: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.arc-client-info {
|
||||||
|
flex: 1;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 2px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.arc-client-name {
|
||||||
|
font-size: 13px;
|
||||||
|
font-weight: 700;
|
||||||
|
color: #166534;
|
||||||
|
}
|
||||||
|
|
||||||
|
.arc-client-sub {
|
||||||
|
font-size: 11px;
|
||||||
|
color: #15803d;
|
||||||
|
}
|
||||||
|
|
||||||
|
.arc-selected-badge {
|
||||||
|
font-size: 10px;
|
||||||
|
font-weight: 700;
|
||||||
|
padding: 3px 10px;
|
||||||
|
border-radius: 999px;
|
||||||
|
background: $success;
|
||||||
|
color: #fff;
|
||||||
|
text-transform: uppercase;
|
||||||
|
letter-spacing: 0.05em;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ── Share percentage ──────────────────────────────────────────────────────────
|
||||||
|
.arc-share-row {
|
||||||
|
display: flex;
|
||||||
|
align-items: flex-start;
|
||||||
|
gap: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.arc-share-field {
|
||||||
|
flex: 0 0 160px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.arc-percent-suffix {
|
||||||
|
font-size: 15px;
|
||||||
|
font-weight: 600;
|
||||||
|
color: $text-muted;
|
||||||
|
margin-right: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.arc-share-hints {
|
||||||
|
display: flex;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
gap: 6px;
|
||||||
|
padding-top: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.arc-hint-chip {
|
||||||
|
padding: 5px 12px;
|
||||||
|
border-radius: 8px;
|
||||||
|
border: 1.5px solid $border;
|
||||||
|
background: #fff;
|
||||||
|
font-size: 12px;
|
||||||
|
font-weight: 600;
|
||||||
|
color: $text-muted;
|
||||||
|
cursor: pointer;
|
||||||
|
transition:
|
||||||
|
border-color 0.12s,
|
||||||
|
background 0.12s,
|
||||||
|
color 0.12s;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
border-color: $primary;
|
||||||
|
background: $primary-light;
|
||||||
|
color: $primary;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ── Actions ───────────────────────────────────────────────────────────────────
|
||||||
|
.arc-actions {
|
||||||
|
padding: 12px 20px 16px !important;
|
||||||
|
border-top: 1px solid $border;
|
||||||
|
gap: 10px;
|
||||||
|
justify-content: flex-end !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.arc-btn-cancel {
|
||||||
|
border-radius: 8px !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.arc-btn-add {
|
||||||
|
border-radius: 8px !important;
|
||||||
|
padding: 0 18px !important;
|
||||||
|
gap: 4px;
|
||||||
|
|
||||||
|
mat-icon {
|
||||||
|
font-size: 18px;
|
||||||
|
width: 18px;
|
||||||
|
height: 18px;
|
||||||
|
}
|
||||||
|
}
|
||||||
+104
@@ -0,0 +1,104 @@
|
|||||||
|
/**
|
||||||
|
* Copyright since 2025 Mifos Initiative
|
||||||
|
*
|
||||||
|
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import { Component, inject, OnDestroy, ViewEncapsulation } from '@angular/core';
|
||||||
|
import { UntypedFormBuilder, UntypedFormGroup, Validators, ReactiveFormsModule } from '@angular/forms';
|
||||||
|
import { MatDialogRef, MatDialogContent, MatDialogActions } from '@angular/material/dialog';
|
||||||
|
import { MatProgressSpinner } from '@angular/material/progress-spinner';
|
||||||
|
import { MatIcon } from '@angular/material/icon';
|
||||||
|
import { ClientsService } from 'app/clients/clients.service';
|
||||||
|
import { STANDALONE_SHARED_IMPORTS } from 'app/standalone-shared.module';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'mifosx-add-related-client-dialog',
|
||||||
|
templateUrl: './add-related-client-dialog.component.html',
|
||||||
|
styleUrl: './add-related-client-dialog.component.scss',
|
||||||
|
encapsulation: ViewEncapsulation.None,
|
||||||
|
imports: [
|
||||||
|
...STANDALONE_SHARED_IMPORTS,
|
||||||
|
MatDialogContent,
|
||||||
|
MatDialogActions,
|
||||||
|
MatProgressSpinner,
|
||||||
|
MatIcon,
|
||||||
|
ReactiveFormsModule
|
||||||
|
]
|
||||||
|
})
|
||||||
|
export class AddRelatedClientDialogComponent implements OnDestroy {
|
||||||
|
private fb = inject(UntypedFormBuilder);
|
||||||
|
private clientsService = inject(ClientsService);
|
||||||
|
dialogRef = inject(MatDialogRef<AddRelatedClientDialogComponent>);
|
||||||
|
|
||||||
|
form: UntypedFormGroup = this.fb.group({
|
||||||
|
searchText: [''],
|
||||||
|
sharePercentage: [
|
||||||
|
null,
|
||||||
|
[
|
||||||
|
Validators.required,
|
||||||
|
Validators.min(1),
|
||||||
|
Validators.max(100)
|
||||||
|
]
|
||||||
|
]
|
||||||
|
});
|
||||||
|
|
||||||
|
searchResults: any[] = [];
|
||||||
|
selectedClient: any = null;
|
||||||
|
isSearching = false;
|
||||||
|
private searchTimer: any = null;
|
||||||
|
|
||||||
|
onSearchInput(value: string): void {
|
||||||
|
if (this.searchTimer) clearTimeout(this.searchTimer);
|
||||||
|
this.selectedClient = null;
|
||||||
|
if (!value || value.trim().length < 2) {
|
||||||
|
this.searchResults = [];
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
this.isSearching = true;
|
||||||
|
this.searchTimer = setTimeout(() => {
|
||||||
|
this.clientsService.searchByText(value.trim(), 0, 10).subscribe({
|
||||||
|
next: (res: any) => {
|
||||||
|
this.searchResults = res?.content || [];
|
||||||
|
this.isSearching = false;
|
||||||
|
},
|
||||||
|
error: () => {
|
||||||
|
this.searchResults = [];
|
||||||
|
this.isSearching = false;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}, 400);
|
||||||
|
}
|
||||||
|
|
||||||
|
selectClient(client: any): void {
|
||||||
|
this.selectedClient = client;
|
||||||
|
this.form.patchValue({ searchText: client.displayName });
|
||||||
|
this.searchResults = [];
|
||||||
|
}
|
||||||
|
|
||||||
|
clearSelection(): void {
|
||||||
|
this.selectedClient = null;
|
||||||
|
this.form.patchValue({ searchText: '' });
|
||||||
|
this.searchResults = [];
|
||||||
|
}
|
||||||
|
|
||||||
|
confirm(): void {
|
||||||
|
if (!this.selectedClient || this.form.get('sharePercentage').invalid) return;
|
||||||
|
this.dialogRef.close({
|
||||||
|
clientId: this.selectedClient.id,
|
||||||
|
clientName: this.selectedClient.displayName,
|
||||||
|
clientCif: this.selectedClient.cifNumber || this.selectedClient.accountNumber || '',
|
||||||
|
sharePercentage: this.form.get('sharePercentage').value
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
cancel(): void {
|
||||||
|
this.dialogRef.close(null);
|
||||||
|
}
|
||||||
|
|
||||||
|
ngOnDestroy(): void {
|
||||||
|
if (this.searchTimer) clearTimeout(this.searchTimer);
|
||||||
|
}
|
||||||
|
}
|
||||||
+202
@@ -131,6 +131,208 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
<!-- ══ Non-Individual Account Details (Indian Banking Style) ═════ -->
|
||||||
|
@if (isNonIndividualClient && currentAccountProductSelected) {
|
||||||
|
<div class="ni-card">
|
||||||
|
<!-- Card Header -->
|
||||||
|
<div class="ni-card__header">
|
||||||
|
<div class="ni-card__header-left">
|
||||||
|
<div class="ni-card__header-icon">
|
||||||
|
<i class="fas fa-building"></i>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<h3 class="ni-card__title">Non-Individual Account Details</h3>
|
||||||
|
<span class="ni-card__sub">As per RBI / Indian banking norms for non-individual entities</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<span class="ni-pill ni-pill--entity">Entity Account</span>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- ── A. Partners / Members ─────────────────────────────── -->
|
||||||
|
<div class="ni-block">
|
||||||
|
<div class="ni-block__head">
|
||||||
|
<div class="ni-block__head-left">
|
||||||
|
<span class="ni-block__letter">A</span>
|
||||||
|
<div>
|
||||||
|
<span class="ni-block__title">Partners / Members</span>
|
||||||
|
<span class="ni-block__hint">Authorised persons linked to this entity account</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<button
|
||||||
|
mat-flat-button
|
||||||
|
color="primary"
|
||||||
|
type="button"
|
||||||
|
class="ni-add-btn"
|
||||||
|
(click)="openAddRelatedClientDialog()"
|
||||||
|
>
|
||||||
|
<mat-icon>person_add</mat-icon> Add Partner
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
@if (relatedClients.length > 0) {
|
||||||
|
<div class="ni-table-wrap">
|
||||||
|
<table class="ni-tbl">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th class="ni-th ni-th--sr">Sr.</th>
|
||||||
|
<th class="ni-th">Partner Name</th>
|
||||||
|
<th class="ni-th">CIF No.</th>
|
||||||
|
<th class="ni-th ni-th--center">Ownership %</th>
|
||||||
|
<th class="ni-th ni-th--center">Signing Authority</th>
|
||||||
|
<th class="ni-th ni-th--center">Action</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
@for (c of relatedClients; track c; let i = $index) {
|
||||||
|
<tr class="ni-tr" [class.ni-tr--mandatory]="c.isMandatory">
|
||||||
|
<td class="ni-td ni-td--sr">{{ i + 1 }}</td>
|
||||||
|
<td class="ni-td">
|
||||||
|
<div class="ni-client-cell">
|
||||||
|
<div class="ni-avatar" [class.ni-avatar--mandatory]="c.isMandatory">
|
||||||
|
{{ c.clientName[0].toUpperCase() }}
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<span class="ni-client-name">{{ c.clientName }}</span>
|
||||||
|
@if (c.isMandatory) {
|
||||||
|
<span class="ni-mandatory-tag">Mandatory Signatory</span>
|
||||||
|
}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
<td class="ni-td">
|
||||||
|
<span class="ni-mono">{{ c.clientCif || '—' }}</span>
|
||||||
|
</td>
|
||||||
|
<td class="ni-td ni-td--center">
|
||||||
|
<span class="ni-pct-badge" [class.ni-pct-badge--full]="c.sharePercentage === 100">
|
||||||
|
{{ c.sharePercentage }}%
|
||||||
|
</span>
|
||||||
|
</td>
|
||||||
|
<td class="ni-td ni-td--center">
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
class="ni-sign-toggle"
|
||||||
|
[class.ni-sign-toggle--mandatory]="c.isMandatory"
|
||||||
|
[class.ni-sign-toggle--optional]="!c.isMandatory"
|
||||||
|
(click)="toggleMandatory(c)"
|
||||||
|
[title]="c.isMandatory ? 'Click to set Optional' : 'Click to set Mandatory'"
|
||||||
|
>
|
||||||
|
<mat-icon>{{ c.isMandatory ? 'lock' : 'lock_open' }}</mat-icon>
|
||||||
|
{{ c.isMandatory ? 'Mandatory' : 'Optional' }}
|
||||||
|
</button>
|
||||||
|
</td>
|
||||||
|
<td class="ni-td ni-td--center">
|
||||||
|
<button
|
||||||
|
mat-icon-button
|
||||||
|
color="warn"
|
||||||
|
type="button"
|
||||||
|
(click)="removeRelatedClient(i)"
|
||||||
|
class="ni-del-btn"
|
||||||
|
>
|
||||||
|
<mat-icon>delete_outline</mat-icon>
|
||||||
|
</button>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
}
|
||||||
|
</tbody>
|
||||||
|
<tfoot>
|
||||||
|
<tr class="ni-tr-total">
|
||||||
|
<td colspan="3" class="ni-td ni-td--total-label">Total Ownership</td>
|
||||||
|
<td class="ni-td ni-td--center">
|
||||||
|
<span
|
||||||
|
class="ni-pct-badge"
|
||||||
|
[class.ni-pct-badge--ok]="totalSharePercentage === 100"
|
||||||
|
[class.ni-pct-badge--warn]="totalSharePercentage !== 100"
|
||||||
|
>
|
||||||
|
{{ totalSharePercentage }}%
|
||||||
|
</span>
|
||||||
|
</td>
|
||||||
|
<td class="ni-td ni-td--center">
|
||||||
|
<span class="ni-mandatory-count-badge">
|
||||||
|
<mat-icon>lock</mat-icon> {{ mandatoryCount }} Mandatory
|
||||||
|
</span>
|
||||||
|
</td>
|
||||||
|
<td></td>
|
||||||
|
</tr>
|
||||||
|
</tfoot>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
@if (totalSharePercentage !== 100) {
|
||||||
|
<div class="ni-alert ni-alert--warn">
|
||||||
|
<mat-icon>warning_amber</mat-icon>
|
||||||
|
Total ownership is {{ totalSharePercentage }}%. It must equal 100%.
|
||||||
|
</div>
|
||||||
|
} @else {
|
||||||
|
<div class="ni-alert ni-alert--ok">
|
||||||
|
<mat-icon>check_circle</mat-icon>
|
||||||
|
Ownership allocation is complete (100%).
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
} @else {
|
||||||
|
<div class="ni-empty-state">
|
||||||
|
<mat-icon>group_add</mat-icon>
|
||||||
|
<span>No partners added yet. Click <strong>Add Partner</strong> to begin.</span>
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- ── B. Mode of Operation / Signatory Rights (auto from partners) ── -->
|
||||||
|
<div class="ni-block ni-block--sep">
|
||||||
|
<div class="ni-block__head">
|
||||||
|
<div class="ni-block__head-left">
|
||||||
|
<span class="ni-block__letter ni-block__letter--b">B</span>
|
||||||
|
<div>
|
||||||
|
<span class="ni-block__title">Mode of Operation / Signatory Rights</span>
|
||||||
|
<span class="ni-block__hint">Auto-computed from Mandatory partners — you can override manually</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
@if (signatoryRights) {
|
||||||
|
<span class="ni-auto-badge"> <mat-icon>auto_awesome</mat-icon> Auto </span>
|
||||||
|
}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
@if (relatedClients.length === 0) {
|
||||||
|
<div class="ni-empty-state">
|
||||||
|
<mat-icon>how_to_vote</mat-icon>
|
||||||
|
<span>Add partners in Section A and set Mandatory/Optional to auto-compute the mode.</span>
|
||||||
|
</div>
|
||||||
|
} @else {
|
||||||
|
<div class="ni-signatory-grid">
|
||||||
|
@for (opt of signatoryRightsOptions; track opt.value) {
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
class="ni-sig-card"
|
||||||
|
[class.ni-sig-card--selected]="signatoryRights === opt.value"
|
||||||
|
(click)="signatoryRights = opt.value"
|
||||||
|
>
|
||||||
|
<mat-icon class="ni-sig-card__icon">{{ opt.icon }}</mat-icon>
|
||||||
|
<div class="ni-sig-card__code">{{ opt.label }}</div>
|
||||||
|
<div class="ni-sig-card__desc">{{ opt.sublabel }}</div>
|
||||||
|
@if (signatoryRights === opt.value) {
|
||||||
|
<mat-icon class="ni-sig-card__check">check_circle</mat-icon>
|
||||||
|
}
|
||||||
|
</button>
|
||||||
|
}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="ni-mode-summary" [class.ni-mode-summary--set]="signatoryRights">
|
||||||
|
@if (signatoryRights) {
|
||||||
|
<mat-icon>how_to_vote</mat-icon>
|
||||||
|
<span
|
||||||
|
>Mode of Operation: <strong>{{ selectedSignatoryLabel }}</strong></span
|
||||||
|
>
|
||||||
|
<span class="ni-mode-summary__from">
|
||||||
|
({{ mandatoryCount }} Mandatory + {{ relatedClients.length - mandatoryCount }} Optional partner(s))
|
||||||
|
</span>
|
||||||
|
} @else {
|
||||||
|
<mat-icon>info</mat-icon>
|
||||||
|
<span>Set Mandatory/Optional for partners above to auto-select mode.</span>
|
||||||
|
}
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
|
||||||
<div class="layout-row align-center gap-2percent margin-t responsive-column">
|
<div class="layout-row align-center gap-2percent margin-t responsive-column">
|
||||||
<button mat-raised-button matStepperPrevious disabled>
|
<button mat-raised-button matStepperPrevious disabled>
|
||||||
<fa-icon icon="arrow-left" class="m-r-10"></fa-icon>
|
<fa-icon icon="arrow-left" class="m-r-10"></fa-icon>
|
||||||
|
|||||||
+608
@@ -104,6 +104,614 @@ $gray-900: #202124;
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ── Non-Individual Section (Indian Banking Style) ─────────────────────────
|
||||||
|
|
||||||
|
$ni-primary: #1a56db;
|
||||||
|
$ni-green: #057a55;
|
||||||
|
$ni-orange: #d03801;
|
||||||
|
$ni-border: #e5e7eb;
|
||||||
|
$ni-bg: #f9fafb;
|
||||||
|
|
||||||
|
.ni-card {
|
||||||
|
margin-top: 16px;
|
||||||
|
border: 1.5px solid #c3dafe;
|
||||||
|
border-radius: 12px;
|
||||||
|
overflow: hidden;
|
||||||
|
background: #fff;
|
||||||
|
|
||||||
|
&__header {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: space-between;
|
||||||
|
padding: 14px 20px;
|
||||||
|
background: linear-gradient(135deg, #1e3a8a 0%, #1a56db 100%);
|
||||||
|
}
|
||||||
|
|
||||||
|
&__header-left {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
&__header-icon {
|
||||||
|
width: 38px;
|
||||||
|
height: 38px;
|
||||||
|
border-radius: 8px;
|
||||||
|
background: rgba(255 255 255 / 20%);
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
|
||||||
|
i {
|
||||||
|
color: #fff;
|
||||||
|
font-size: 17px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&__title {
|
||||||
|
margin: 0;
|
||||||
|
font-size: 14px;
|
||||||
|
font-weight: 700;
|
||||||
|
color: #fff;
|
||||||
|
}
|
||||||
|
|
||||||
|
&__sub {
|
||||||
|
margin: 2px 0 0;
|
||||||
|
font-size: 11px;
|
||||||
|
color: rgba(255 255 255 / 75%);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.ni-pill {
|
||||||
|
padding: 4px 12px;
|
||||||
|
border-radius: 999px;
|
||||||
|
font-size: 11px;
|
||||||
|
font-weight: 700;
|
||||||
|
letter-spacing: 0.05em;
|
||||||
|
text-transform: uppercase;
|
||||||
|
|
||||||
|
&--entity {
|
||||||
|
background: rgba(255 255 255 / 20%);
|
||||||
|
color: #fff;
|
||||||
|
border: 1px solid rgba(255 255 255 / 30%);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Block
|
||||||
|
.ni-block {
|
||||||
|
padding: 16px 20px 4px;
|
||||||
|
|
||||||
|
&--sep {
|
||||||
|
border-top: 1.5px dashed #e5e7eb;
|
||||||
|
padding-top: 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
&__head {
|
||||||
|
display: flex;
|
||||||
|
align-items: flex-start;
|
||||||
|
justify-content: space-between;
|
||||||
|
margin-bottom: 14px;
|
||||||
|
}
|
||||||
|
|
||||||
|
&__head-left {
|
||||||
|
display: flex;
|
||||||
|
align-items: flex-start;
|
||||||
|
gap: 10px;
|
||||||
|
|
||||||
|
&--alone {
|
||||||
|
margin-bottom: 14px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&__letter {
|
||||||
|
width: 26px;
|
||||||
|
height: 26px;
|
||||||
|
border-radius: 6px;
|
||||||
|
background: $ni-primary;
|
||||||
|
color: #fff;
|
||||||
|
font-size: 13px;
|
||||||
|
font-weight: 800;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
flex-shrink: 0;
|
||||||
|
margin-top: 1px;
|
||||||
|
|
||||||
|
&--b {
|
||||||
|
background: $ni-green;
|
||||||
|
}
|
||||||
|
|
||||||
|
&--c {
|
||||||
|
background: #7c3aed;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&__title {
|
||||||
|
display: block;
|
||||||
|
font-size: 13px;
|
||||||
|
font-weight: 700;
|
||||||
|
color: #111827;
|
||||||
|
}
|
||||||
|
|
||||||
|
&__hint {
|
||||||
|
display: block;
|
||||||
|
font-size: 11px;
|
||||||
|
color: #6b7280;
|
||||||
|
margin-top: 1px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.ni-add-btn {
|
||||||
|
border-radius: 8px !important;
|
||||||
|
font-size: 12px !important;
|
||||||
|
padding: 0 14px !important;
|
||||||
|
height: 34px !important;
|
||||||
|
gap: 4px;
|
||||||
|
|
||||||
|
mat-icon {
|
||||||
|
font-size: 16px;
|
||||||
|
width: 16px;
|
||||||
|
height: 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
&--accent {
|
||||||
|
background: $ni-green !important;
|
||||||
|
color: #fff !important;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Table
|
||||||
|
.ni-table-wrap {
|
||||||
|
overflow-x: auto;
|
||||||
|
border: 1px solid $ni-border;
|
||||||
|
border-radius: 8px;
|
||||||
|
margin-bottom: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ni-tbl {
|
||||||
|
width: 100%;
|
||||||
|
border-collapse: collapse;
|
||||||
|
font-size: 13px;
|
||||||
|
|
||||||
|
thead {
|
||||||
|
background: #f8faff;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.ni-th {
|
||||||
|
padding: 9px 12px;
|
||||||
|
font-size: 11px;
|
||||||
|
font-weight: 700;
|
||||||
|
color: #374151;
|
||||||
|
text-transform: uppercase;
|
||||||
|
letter-spacing: 0.04em;
|
||||||
|
border-bottom: 1.5px solid $ni-border;
|
||||||
|
text-align: left;
|
||||||
|
white-space: nowrap;
|
||||||
|
|
||||||
|
&--sr {
|
||||||
|
width: 40px;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
&--center {
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.ni-tr {
|
||||||
|
transition: background 0.1s;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
background: #f9fafb;
|
||||||
|
}
|
||||||
|
|
||||||
|
&--mandatory {
|
||||||
|
background: #fffbf0;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
background: #fff8e6;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.ni-tr-total {
|
||||||
|
background: #f0f4ff;
|
||||||
|
border-top: 1.5px solid #c3dafe;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ni-td {
|
||||||
|
padding: 10px 12px;
|
||||||
|
color: #111827;
|
||||||
|
border-bottom: 1px solid #f3f4f6;
|
||||||
|
|
||||||
|
&--sr {
|
||||||
|
text-align: center;
|
||||||
|
color: #6b7280;
|
||||||
|
font-size: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
&--center {
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
&--total-label {
|
||||||
|
font-weight: 700;
|
||||||
|
font-size: 12px;
|
||||||
|
color: #374151;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.ni-client-cell {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ni-avatar {
|
||||||
|
width: 30px;
|
||||||
|
height: 30px;
|
||||||
|
border-radius: 50%;
|
||||||
|
background: linear-gradient(135deg, #6366f1, $ni-primary);
|
||||||
|
color: #fff;
|
||||||
|
font-size: 12px;
|
||||||
|
font-weight: 700;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
flex-shrink: 0;
|
||||||
|
|
||||||
|
&--green {
|
||||||
|
background: linear-gradient(135deg, #10b981, $ni-green);
|
||||||
|
}
|
||||||
|
|
||||||
|
&--mandatory {
|
||||||
|
background: linear-gradient(135deg, #f59e0b, #d97706);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.ni-client-name {
|
||||||
|
display: block;
|
||||||
|
font-weight: 600;
|
||||||
|
color: #111827;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ni-mandatory-tag {
|
||||||
|
display: inline-block;
|
||||||
|
font-size: 9.5px;
|
||||||
|
font-weight: 700;
|
||||||
|
color: #b45309;
|
||||||
|
background: #fef3c7;
|
||||||
|
border: 1px solid #fde68a;
|
||||||
|
border-radius: 4px;
|
||||||
|
padding: 1px 6px;
|
||||||
|
margin-top: 2px;
|
||||||
|
text-transform: uppercase;
|
||||||
|
letter-spacing: 0.04em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ni-mandatory-count-badge {
|
||||||
|
display: inline-flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 3px;
|
||||||
|
font-size: 11px;
|
||||||
|
font-weight: 700;
|
||||||
|
color: #92400e;
|
||||||
|
background: #fef3c7;
|
||||||
|
border: 1px solid #fde68a;
|
||||||
|
border-radius: 6px;
|
||||||
|
padding: 3px 8px;
|
||||||
|
|
||||||
|
mat-icon {
|
||||||
|
font-size: 12px;
|
||||||
|
width: 12px;
|
||||||
|
height: 12px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Signing authority toggle in table
|
||||||
|
.ni-sign-toggle {
|
||||||
|
display: inline-flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 4px;
|
||||||
|
padding: 4px 12px;
|
||||||
|
border-radius: 20px;
|
||||||
|
border: 1.5px solid;
|
||||||
|
font-size: 11.5px;
|
||||||
|
font-weight: 700;
|
||||||
|
cursor: pointer;
|
||||||
|
transition: all 0.15s;
|
||||||
|
white-space: nowrap;
|
||||||
|
|
||||||
|
mat-icon {
|
||||||
|
font-size: 13px;
|
||||||
|
width: 13px;
|
||||||
|
height: 13px;
|
||||||
|
}
|
||||||
|
|
||||||
|
&--mandatory {
|
||||||
|
border-color: #d97706;
|
||||||
|
background: #fffbeb;
|
||||||
|
color: #92400e;
|
||||||
|
}
|
||||||
|
|
||||||
|
&--optional {
|
||||||
|
border-color: #d1d5db;
|
||||||
|
background: #f9fafb;
|
||||||
|
color: #6b7280;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
border-color: #d97706;
|
||||||
|
color: #92400e;
|
||||||
|
background: #fffbeb;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.ni-nom-info {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 1px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ni-guardian-hint {
|
||||||
|
font-size: 10.5px;
|
||||||
|
color: #6b7280;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ni-mono {
|
||||||
|
font-family: monospace;
|
||||||
|
font-size: 12px;
|
||||||
|
color: #374151;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ni-pct-badge {
|
||||||
|
display: inline-flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
padding: 3px 10px;
|
||||||
|
border-radius: 999px;
|
||||||
|
font-size: 12px;
|
||||||
|
font-weight: 700;
|
||||||
|
background: #e0e7ff;
|
||||||
|
color: $ni-primary;
|
||||||
|
min-width: 52px;
|
||||||
|
|
||||||
|
&--ok {
|
||||||
|
background: #d1fae5;
|
||||||
|
color: $ni-green;
|
||||||
|
}
|
||||||
|
|
||||||
|
&--warn {
|
||||||
|
background: #fef3c7;
|
||||||
|
color: #92400e;
|
||||||
|
}
|
||||||
|
|
||||||
|
&--full {
|
||||||
|
background: #d1fae5;
|
||||||
|
color: $ni-green;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.ni-rel-badge {
|
||||||
|
font-size: 11px;
|
||||||
|
padding: 2px 8px;
|
||||||
|
border-radius: 6px;
|
||||||
|
background: #f3f4f6;
|
||||||
|
color: #374151;
|
||||||
|
font-weight: 500;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ni-minor-badge {
|
||||||
|
font-size: 10px;
|
||||||
|
padding: 2px 8px;
|
||||||
|
border-radius: 999px;
|
||||||
|
background: #fef3c7;
|
||||||
|
color: #92400e;
|
||||||
|
font-weight: 700;
|
||||||
|
text-transform: uppercase;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ni-td-dash {
|
||||||
|
color: #d1d5db;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ni-del-btn {
|
||||||
|
width: 28px !important;
|
||||||
|
height: 28px !important;
|
||||||
|
line-height: 28px !important;
|
||||||
|
|
||||||
|
mat-icon {
|
||||||
|
font-size: 17px;
|
||||||
|
width: 17px;
|
||||||
|
height: 17px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Alerts
|
||||||
|
.ni-alert {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 7px;
|
||||||
|
padding: 8px 12px;
|
||||||
|
border-radius: 8px;
|
||||||
|
font-size: 12px;
|
||||||
|
font-weight: 500;
|
||||||
|
margin-bottom: 12px;
|
||||||
|
|
||||||
|
mat-icon {
|
||||||
|
font-size: 16px;
|
||||||
|
width: 16px;
|
||||||
|
height: 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
&--warn {
|
||||||
|
background: #fffbeb;
|
||||||
|
color: #92400e;
|
||||||
|
border: 1px solid #fde68a;
|
||||||
|
}
|
||||||
|
|
||||||
|
&--ok {
|
||||||
|
background: #f0fdf4;
|
||||||
|
color: $ni-green;
|
||||||
|
border: 1px solid #bbf7d0;
|
||||||
|
}
|
||||||
|
|
||||||
|
&--sm {
|
||||||
|
margin-top: 8px;
|
||||||
|
margin-bottom: 14px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Empty state
|
||||||
|
.ni-empty-state {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 8px;
|
||||||
|
padding: 16px 12px;
|
||||||
|
font-size: 13px;
|
||||||
|
color: #9ca3af;
|
||||||
|
font-style: italic;
|
||||||
|
margin-bottom: 10px;
|
||||||
|
|
||||||
|
mat-icon {
|
||||||
|
font-size: 20px;
|
||||||
|
width: 20px;
|
||||||
|
height: 20px;
|
||||||
|
color: #d1d5db;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Auto badge on section header
|
||||||
|
.ni-auto-badge {
|
||||||
|
display: inline-flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 4px;
|
||||||
|
padding: 3px 10px;
|
||||||
|
border-radius: 999px;
|
||||||
|
font-size: 11px;
|
||||||
|
font-weight: 700;
|
||||||
|
background: #fffbeb;
|
||||||
|
color: #92400e;
|
||||||
|
border: 1px solid #fde68a;
|
||||||
|
|
||||||
|
mat-icon {
|
||||||
|
font-size: 12px;
|
||||||
|
width: 12px;
|
||||||
|
height: 12px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Mode summary bar below signatory cards
|
||||||
|
.ni-mode-summary {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 8px;
|
||||||
|
padding: 9px 14px;
|
||||||
|
border-radius: 8px;
|
||||||
|
font-size: 12.5px;
|
||||||
|
font-weight: 500;
|
||||||
|
margin-top: 4px;
|
||||||
|
background: #f3f4f6;
|
||||||
|
color: #6b7280;
|
||||||
|
border: 1px solid #e5e7eb;
|
||||||
|
|
||||||
|
mat-icon {
|
||||||
|
font-size: 16px;
|
||||||
|
width: 16px;
|
||||||
|
height: 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
&--set {
|
||||||
|
background: #f0fdf4;
|
||||||
|
color: $ni-green;
|
||||||
|
border-color: #bbf7d0;
|
||||||
|
}
|
||||||
|
|
||||||
|
&__from {
|
||||||
|
font-size: 11px;
|
||||||
|
color: #9ca3af;
|
||||||
|
font-style: italic;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ── Signatory / Mode of Operation cards ──────────────────────────────────
|
||||||
|
.ni-signatory-grid {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: repeat(4, 1fr);
|
||||||
|
gap: 10px;
|
||||||
|
margin-bottom: 10px;
|
||||||
|
|
||||||
|
@media (width <= 700px) {
|
||||||
|
grid-template-columns: repeat(2, 1fr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.ni-sig-card {
|
||||||
|
position: relative;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
gap: 6px;
|
||||||
|
padding: 18px 10px 14px;
|
||||||
|
border-radius: 12px;
|
||||||
|
border: 1.5px solid $ni-border;
|
||||||
|
background: #fff;
|
||||||
|
cursor: pointer;
|
||||||
|
transition: all 0.15s;
|
||||||
|
text-align: center;
|
||||||
|
|
||||||
|
&:hover:not(.ni-sig-card--selected) {
|
||||||
|
border-color: #93c5fd;
|
||||||
|
background: #f0f9ff;
|
||||||
|
transform: translateY(-1px);
|
||||||
|
}
|
||||||
|
|
||||||
|
&--selected {
|
||||||
|
border-color: $ni-primary;
|
||||||
|
background: #eff6ff;
|
||||||
|
box-shadow: 0 0 0 3px rgba(37 99 235 / 12%);
|
||||||
|
transform: translateY(-1px);
|
||||||
|
}
|
||||||
|
|
||||||
|
&__icon {
|
||||||
|
font-size: 22px;
|
||||||
|
width: 22px;
|
||||||
|
height: 22px;
|
||||||
|
color: #6b7280;
|
||||||
|
|
||||||
|
.ni-sig-card--selected & {
|
||||||
|
color: $ni-primary;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&__code {
|
||||||
|
font-size: 15px;
|
||||||
|
font-weight: 800;
|
||||||
|
color: #1e3a8a;
|
||||||
|
font-family: monospace;
|
||||||
|
letter-spacing: 0.02em;
|
||||||
|
}
|
||||||
|
|
||||||
|
&__desc {
|
||||||
|
font-size: 10.5px;
|
||||||
|
font-weight: 500;
|
||||||
|
color: #6b7280;
|
||||||
|
line-height: 1.3;
|
||||||
|
}
|
||||||
|
|
||||||
|
&__check {
|
||||||
|
position: absolute;
|
||||||
|
top: 7px;
|
||||||
|
right: 7px;
|
||||||
|
font-size: 15px;
|
||||||
|
width: 15px;
|
||||||
|
height: 15px;
|
||||||
|
color: $ni-primary;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// ── Account Feature Toggles ────────────────────────────────────────────────
|
// ── Account Feature Toggles ────────────────────────────────────────────────
|
||||||
.sad-toggles {
|
.sad-toggles {
|
||||||
display: flex;
|
display: flex;
|
||||||
|
|||||||
+130
-2
@@ -14,10 +14,27 @@ import { Dates } from 'app/core/utils/dates';
|
|||||||
/** Custom Services */
|
/** Custom Services */
|
||||||
import { CurrentAccountsService } from 'app/current-accounts/current-accounts.service';
|
import { CurrentAccountsService } from 'app/current-accounts/current-accounts.service';
|
||||||
import { SettingsService } from 'app/settings/settings.service';
|
import { SettingsService } from 'app/settings/settings.service';
|
||||||
|
import { ClientsService } from 'app/clients/clients.service';
|
||||||
|
import { MatDialog } from '@angular/material/dialog';
|
||||||
import { MatStepperPrevious, MatStepperNext } from '@angular/material/stepper';
|
import { MatStepperPrevious, MatStepperNext } from '@angular/material/stepper';
|
||||||
|
import {
|
||||||
|
MatTable,
|
||||||
|
MatColumnDef,
|
||||||
|
MatHeaderCellDef,
|
||||||
|
MatHeaderCell,
|
||||||
|
MatCellDef,
|
||||||
|
MatCell,
|
||||||
|
MatHeaderRowDef,
|
||||||
|
MatHeaderRow,
|
||||||
|
MatRowDef,
|
||||||
|
MatRow
|
||||||
|
} from '@angular/material/table';
|
||||||
|
import { MatIcon } from '@angular/material/icon';
|
||||||
|
import { FormsModule } from '@angular/forms';
|
||||||
import { FaIconComponent } from '@fortawesome/angular-fontawesome';
|
import { FaIconComponent } from '@fortawesome/angular-fontawesome';
|
||||||
import { STANDALONE_SHARED_IMPORTS } from 'app/standalone-shared.module';
|
import { STANDALONE_SHARED_IMPORTS } from 'app/standalone-shared.module';
|
||||||
import { IntroducerSearchComponent } from 'app/shared/introducer-search/introducer-search.component';
|
import { IntroducerSearchComponent } from 'app/shared/introducer-search/introducer-search.component';
|
||||||
|
import { AddRelatedClientDialogComponent } from './add-related-client-dialog/add-related-client-dialog.component';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Current Account Details Step
|
* Current Account Details Step
|
||||||
@@ -31,13 +48,27 @@ import { IntroducerSearchComponent } from 'app/shared/introducer-search/introduc
|
|||||||
MatStepperPrevious,
|
MatStepperPrevious,
|
||||||
FaIconComponent,
|
FaIconComponent,
|
||||||
MatStepperNext,
|
MatStepperNext,
|
||||||
IntroducerSearchComponent
|
IntroducerSearchComponent,
|
||||||
|
MatTable,
|
||||||
|
MatColumnDef,
|
||||||
|
MatHeaderCellDef,
|
||||||
|
MatHeaderCell,
|
||||||
|
MatCellDef,
|
||||||
|
MatCell,
|
||||||
|
MatHeaderRowDef,
|
||||||
|
MatHeaderRow,
|
||||||
|
MatRowDef,
|
||||||
|
MatRow,
|
||||||
|
MatIcon,
|
||||||
|
FormsModule
|
||||||
]
|
]
|
||||||
})
|
})
|
||||||
export class CurrentAccountDetailsStepComponent implements OnInit {
|
export class CurrentAccountDetailsStepComponent implements OnInit {
|
||||||
private formBuilder = inject(UntypedFormBuilder);
|
private formBuilder = inject(UntypedFormBuilder);
|
||||||
private currentAccountsService = inject(CurrentAccountsService);
|
private currentAccountsService = inject(CurrentAccountsService);
|
||||||
private settingsService = inject(SettingsService);
|
private settingsService = inject(SettingsService);
|
||||||
|
private clientsService = inject(ClientsService);
|
||||||
|
private dialog = inject(MatDialog);
|
||||||
private dateUtils = inject(Dates);
|
private dateUtils = inject(Dates);
|
||||||
private cdr = inject(ChangeDetectorRef);
|
private cdr = inject(ChangeDetectorRef);
|
||||||
|
|
||||||
@@ -59,6 +90,26 @@ export class CurrentAccountDetailsStepComponent implements OnInit {
|
|||||||
|
|
||||||
currentAccountProductSelected = false;
|
currentAccountProductSelected = false;
|
||||||
introducerId: number | null = null;
|
introducerId: number | null = null;
|
||||||
|
introducerName: string | null = null;
|
||||||
|
introducerCif: string | null = null;
|
||||||
|
|
||||||
|
/** Non-Individual section */
|
||||||
|
isNonIndividualClient = false;
|
||||||
|
relatedClients: Array<{
|
||||||
|
clientId: number;
|
||||||
|
clientName: string;
|
||||||
|
clientCif: string;
|
||||||
|
sharePercentage: number;
|
||||||
|
isMandatory: boolean;
|
||||||
|
}> = [];
|
||||||
|
signatoryRights = '';
|
||||||
|
|
||||||
|
readonly signatoryRightsOptions = [
|
||||||
|
{ value: 'ANYONE', label: 'E or S', sublabel: 'Either or Survivor', icon: 'how_to_vote' },
|
||||||
|
{ value: 'ONE_MANDATORY', label: 'J/One', sublabel: 'Joint – One Mandatory', icon: 'group' },
|
||||||
|
{ value: 'TWO_MANDATORY', label: 'J/Two', sublabel: 'Joint – Two Mandatory', icon: 'groups' },
|
||||||
|
{ value: 'ONLY_ONE', label: 'Single', sublabel: 'Only 1 Person', icon: 'person' }
|
||||||
|
];
|
||||||
|
|
||||||
/** Current Account Template with product data */
|
/** Current Account Template with product data */
|
||||||
@Output() currentAccountProductTemplate = new EventEmitter();
|
@Output() currentAccountProductTemplate = new EventEmitter();
|
||||||
@@ -73,6 +124,13 @@ export class CurrentAccountDetailsStepComponent implements OnInit {
|
|||||||
ngOnInit() {
|
ngOnInit() {
|
||||||
this.maxDate = this.settingsService.businessDate;
|
this.maxDate = this.settingsService.businessDate;
|
||||||
this.buildDependencies();
|
this.buildDependencies();
|
||||||
|
if (this.currentAccountTemplate?.clientId) {
|
||||||
|
this.clientsService.getClientData(String(this.currentAccountTemplate.clientId)).subscribe((client: any) => {
|
||||||
|
this.isNonIndividualClient = client?.legalForm?.id === 2;
|
||||||
|
this.cdr.detectChanges();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
if (this.currentAccountTemplate) {
|
if (this.currentAccountTemplate) {
|
||||||
this.productData = this.currentAccountTemplate.productOptions;
|
this.productData = this.currentAccountTemplate.productOptions;
|
||||||
if (this.currentAccountTemplate.currentAccountProductId) {
|
if (this.currentAccountTemplate.currentAccountProductId) {
|
||||||
@@ -178,14 +236,84 @@ export class CurrentAccountDetailsStepComponent implements OnInit {
|
|||||||
/**
|
/**
|
||||||
* Returns current account form value.
|
* Returns current account form value.
|
||||||
*/
|
*/
|
||||||
onIntroducerChange(event: { clientId: number; displayName: string } | null): void {
|
onIntroducerChange(event: { clientId: number; displayName: string; cifNumber?: string } | null): void {
|
||||||
this.introducerId = event?.clientId ?? null;
|
this.introducerId = event?.clientId ?? null;
|
||||||
|
this.introducerName = event?.displayName ?? null;
|
||||||
|
this.introducerCif = event?.cifNumber ?? null;
|
||||||
|
}
|
||||||
|
|
||||||
|
openAddRelatedClientDialog(): void {
|
||||||
|
const ref = this.dialog.open(AddRelatedClientDialogComponent, {
|
||||||
|
width: '500px',
|
||||||
|
panelClass: 'arc-dialog-panel',
|
||||||
|
disableClose: true
|
||||||
|
});
|
||||||
|
ref.afterClosed().subscribe((result) => {
|
||||||
|
if (result) {
|
||||||
|
const duplicate = this.relatedClients.some((c) => c.clientCif && c.clientCif === result.clientCif);
|
||||||
|
if (duplicate) {
|
||||||
|
alert(`Partner with CIF ${result.clientCif} is already added.`);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
this.relatedClients = [
|
||||||
|
...this.relatedClients,
|
||||||
|
{ ...result, isMandatory: false }];
|
||||||
|
this.autoSetSignatoryRights();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
removeRelatedClient(index: number): void {
|
||||||
|
this.relatedClients = this.relatedClients.filter((_, i) => i !== index);
|
||||||
|
this.autoSetSignatoryRights();
|
||||||
|
}
|
||||||
|
|
||||||
|
toggleMandatory(client: any): void {
|
||||||
|
client.isMandatory = !client.isMandatory;
|
||||||
|
this.autoSetSignatoryRights();
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Auto-compute Mode of Operation based on mandatory count */
|
||||||
|
autoSetSignatoryRights(): void {
|
||||||
|
const mandatory = this.relatedClients.filter((c) => c.isMandatory).length;
|
||||||
|
if (mandatory === 0) {
|
||||||
|
this.signatoryRights = 'ANYONE';
|
||||||
|
} else if (mandatory === 1) {
|
||||||
|
this.signatoryRights = 'ONE_MANDATORY';
|
||||||
|
} else {
|
||||||
|
this.signatoryRights = 'TWO_MANDATORY';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
get totalSharePercentage(): number {
|
||||||
|
return this.relatedClients.reduce((sum, c) => sum + (c.sharePercentage || 0), 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
get mandatoryCount(): number {
|
||||||
|
return this.relatedClients.filter((c) => c.isMandatory).length;
|
||||||
|
}
|
||||||
|
|
||||||
|
get selectedSignatoryLabel(): string {
|
||||||
|
const opt = this.signatoryRightsOptions.find((x) => x.value === this.signatoryRights);
|
||||||
|
return opt ? opt.sublabel : '';
|
||||||
}
|
}
|
||||||
|
|
||||||
get currentAccountDetails() {
|
get currentAccountDetails() {
|
||||||
const value = this.currentAccountDetailsForm.getRawValue();
|
const value = this.currentAccountDetailsForm.getRawValue();
|
||||||
if (this.introducerId) {
|
if (this.introducerId) {
|
||||||
value.introducerId = this.introducerId;
|
value.introducerId = this.introducerId;
|
||||||
|
value.introducerName = this.introducerName;
|
||||||
|
value.introducerCif = this.introducerCif;
|
||||||
|
}
|
||||||
|
if (this.isNonIndividualClient) {
|
||||||
|
value.signatoryRights = this.signatoryRights || null;
|
||||||
|
value.partners = this.relatedClients.map((c) => ({
|
||||||
|
clientId: c.clientId,
|
||||||
|
clientName: c.clientName,
|
||||||
|
clientCif: c.clientCif,
|
||||||
|
sharePercentage: c.sharePercentage,
|
||||||
|
isMandatory: c.isMandatory
|
||||||
|
}));
|
||||||
}
|
}
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
|||||||
+333
-118
@@ -7,10 +7,11 @@
|
|||||||
-->
|
-->
|
||||||
|
|
||||||
<div class="preview-wrapper">
|
<div class="preview-wrapper">
|
||||||
<!-- Details -->
|
<!-- ══ 1. Account Details ════════════════════════════════════════ -->
|
||||||
<div class="preview-section">
|
<div class="preview-section">
|
||||||
<div class="preview-section__header">
|
<div class="preview-section__header">
|
||||||
<span class="preview-section__title">{{ 'labels.heading.Details' | translate }}</span>
|
<i class="fas fa-info-circle preview-section__icon"></i>
|
||||||
|
<span class="preview-section__title">Account Details</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="preview-body">
|
<div class="preview-body">
|
||||||
<div class="preview-grid preview-grid--three">
|
<div class="preview-grid preview-grid--three">
|
||||||
@@ -38,27 +39,28 @@
|
|||||||
<mifosx-external-identifier externalId="{{ currentAccount.externalId }}"></mifosx-external-identifier>
|
<mifosx-external-identifier externalId="{{ currentAccount.externalId }}"></mifosx-external-identifier>
|
||||||
</span>
|
</span>
|
||||||
} @else {
|
} @else {
|
||||||
<span class="preview-value">{{ 'labels.inputs.Unassigned' | translate }}</span>
|
<span class="preview-value preview-muted">Unassigned</span>
|
||||||
}
|
}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- Product Classification -->
|
<!-- ══ 2. Product Classification ════════════════════════════════ -->
|
||||||
@if (
|
@if (
|
||||||
currentAccountProductTemplate?.accountType ||
|
currentAccountProductTemplate?.accountType ||
|
||||||
currentAccountProductTemplate?.customerSegment ||
|
currentAccountProductTemplate?.customerSegment ||
|
||||||
currentAccountProductTemplate?.productCode ||
|
currentAccountProductTemplate?.productCode ||
|
||||||
|
currentAccountProductTemplate?.previewAccountNo ||
|
||||||
currentAccountProductTemplate?.effectiveDate ||
|
currentAccountProductTemplate?.effectiveDate ||
|
||||||
currentAccountProductTemplate?.effectiveTo ||
|
currentAccountProductTemplate?.effectiveTo ||
|
||||||
currentAccountProductTemplate?.endDate ||
|
currentAccountProductTemplate?.endDate
|
||||||
currentAccountProductTemplate?.introducerRequired !== undefined ||
|
|
||||||
currentAccountProductTemplate?.shareLinkingEnabled !== undefined
|
|
||||||
) {
|
) {
|
||||||
<div class="preview-section">
|
<div class="preview-section">
|
||||||
<div class="preview-section__header">
|
<div class="preview-section__header">
|
||||||
|
<i class="fas fa-tags preview-section__icon"></i>
|
||||||
<span class="preview-section__title">Product Classification</span>
|
<span class="preview-section__title">Product Classification</span>
|
||||||
|
<span class="preview-section__badge">From Product</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="preview-body">
|
<div class="preview-body">
|
||||||
<div class="preview-grid preview-grid--three">
|
<div class="preview-grid preview-grid--three">
|
||||||
@@ -77,9 +79,15 @@
|
|||||||
@if (currentAccountProductTemplate?.productCode) {
|
@if (currentAccountProductTemplate?.productCode) {
|
||||||
<div class="preview-field">
|
<div class="preview-field">
|
||||||
<span class="preview-label">Product Code</span>
|
<span class="preview-label">Product Code</span>
|
||||||
<span class="preview-value">{{ currentAccountProductTemplate?.productCode }}</span>
|
<span class="preview-value preview-mono">{{ currentAccountProductTemplate?.productCode }}</span>
|
||||||
</div>
|
</div>
|
||||||
}
|
}
|
||||||
|
<div class="preview-field">
|
||||||
|
<span class="preview-label">Account No</span>
|
||||||
|
<span class="preview-value preview-mono">{{
|
||||||
|
currentAccountProductTemplate?.previewAccountNo || currentAccountTemplate?.accountNo || 'Auto-generated'
|
||||||
|
}}</span>
|
||||||
|
</div>
|
||||||
@if (currentAccountProductTemplate?.effectiveDate) {
|
@if (currentAccountProductTemplate?.effectiveDate) {
|
||||||
<div class="preview-field">
|
<div class="preview-field">
|
||||||
<span class="preview-label">Effective Date</span>
|
<span class="preview-label">Effective Date</span>
|
||||||
@@ -98,141 +106,348 @@
|
|||||||
<span class="preview-value">{{ currentAccountProductTemplate?.endDate | dateFormat }}</span>
|
<span class="preview-value">{{ currentAccountProductTemplate?.endDate | dateFormat }}</span>
|
||||||
</div>
|
</div>
|
||||||
}
|
}
|
||||||
@if (
|
<div class="preview-field">
|
||||||
currentAccountProductTemplate?.introducerRequired !== undefined &&
|
<span class="preview-label">Introducer Required</span>
|
||||||
currentAccountProductTemplate?.introducerRequired !== null
|
<span
|
||||||
) {
|
class="preview-value preview-badge"
|
||||||
|
[class.preview-badge--yes]="currentAccountProductTemplate?.introducerRequired"
|
||||||
|
>
|
||||||
|
{{ currentAccountProductTemplate?.introducerRequired | yesNo }}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
<div class="preview-field">
|
||||||
|
<span class="preview-label">Share Linking Enabled</span>
|
||||||
|
<span
|
||||||
|
class="preview-value preview-badge"
|
||||||
|
[class.preview-badge--yes]="currentAccountProductTemplate?.shareLinkingEnabled"
|
||||||
|
>
|
||||||
|
{{ currentAccountProductTemplate?.shareLinkingEnabled | yesNo }}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
|
||||||
|
<!-- ══ 3. Introducer Details (if selected) ══════════════════════ -->
|
||||||
|
@if (currentAccount?.introducerId) {
|
||||||
|
<div class="preview-section">
|
||||||
|
<div class="preview-section__header">
|
||||||
|
<i class="fas fa-user-tie preview-section__icon"></i>
|
||||||
|
<span class="preview-section__title">Introducer Details</span>
|
||||||
|
</div>
|
||||||
|
<div class="preview-body">
|
||||||
|
<div class="preview-grid preview-grid--three">
|
||||||
|
<div class="preview-field">
|
||||||
|
<span class="preview-label">Name</span>
|
||||||
|
<span class="preview-value">{{ currentAccount?.introducerName || '—' }}</span>
|
||||||
|
</div>
|
||||||
|
@if (currentAccount?.introducerCif) {
|
||||||
<div class="preview-field">
|
<div class="preview-field">
|
||||||
<span class="preview-label">Introducer Required</span>
|
<span class="preview-label">CIF No</span>
|
||||||
<span
|
<span class="preview-value preview-mono">{{ currentAccount.introducerCif }}</span>
|
||||||
class="preview-value preview-badge"
|
|
||||||
[class.preview-badge--yes]="currentAccountProductTemplate?.introducerRequired"
|
|
||||||
>
|
|
||||||
{{ currentAccountProductTemplate?.introducerRequired | yesNo }}
|
|
||||||
</span>
|
|
||||||
</div>
|
</div>
|
||||||
}
|
}
|
||||||
@if (
|
<div class="preview-field">
|
||||||
currentAccountProductTemplate?.shareLinkingEnabled !== undefined &&
|
<span class="preview-label">Client ID</span>
|
||||||
currentAccountProductTemplate?.shareLinkingEnabled !== null
|
<span class="preview-value preview-mono">{{ currentAccount.introducerId }}</span>
|
||||||
) {
|
</div>
|
||||||
<div class="preview-field">
|
</div>
|
||||||
<span class="preview-label">Share Linking Enabled</span>
|
</div>
|
||||||
<span
|
</div>
|
||||||
class="preview-value preview-badge"
|
}
|
||||||
[class.preview-badge--yes]="currentAccountProductTemplate?.shareLinkingEnabled"
|
|
||||||
>
|
<!-- ══ 4. Currency & Account Flags ══════════════════════════════ -->
|
||||||
{{ currentAccountProductTemplate?.shareLinkingEnabled | yesNo }}
|
<div class="preview-section">
|
||||||
|
<div class="preview-section__header">
|
||||||
|
<i class="fas fa-coins preview-section__icon"></i>
|
||||||
|
<span class="preview-section__title">Currency & Account Flags</span>
|
||||||
|
</div>
|
||||||
|
<div class="preview-body">
|
||||||
|
<div class="preview-grid preview-grid--three">
|
||||||
|
<div class="preview-field">
|
||||||
|
<span class="preview-label">Currency</span>
|
||||||
|
<span class="preview-value">{{ currencyName }}</span>
|
||||||
|
</div>
|
||||||
|
<div class="preview-field">
|
||||||
|
<span class="preview-label">Decimal Places</span>
|
||||||
|
<span class="preview-value">{{ decimalPlaces }}</span>
|
||||||
|
</div>
|
||||||
|
<div class="preview-field">
|
||||||
|
<span class="preview-label">Currency In Multiples Of</span>
|
||||||
|
<span class="preview-value">{{ inMultiplesOf }}</span>
|
||||||
|
</div>
|
||||||
|
<div class="preview-field">
|
||||||
|
<span class="preview-label">Balance Swap Option</span>
|
||||||
|
<span
|
||||||
|
class="preview-value preview-badge"
|
||||||
|
[class.preview-badge--yes]="currentAccountCurrencyFlags?.balanceSwapOption"
|
||||||
|
>
|
||||||
|
{{ currentAccountCurrencyFlags?.balanceSwapOption | yesNo }}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
<div class="preview-field">
|
||||||
|
<span class="preview-label">MSME</span>
|
||||||
|
<span class="preview-value preview-badge" [class.preview-badge--yes]="currentAccountCurrencyFlags?.msme">
|
||||||
|
{{ currentAccountCurrencyFlags?.msme | yesNo }}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
<div class="preview-field">
|
||||||
|
<span class="preview-label">Auto Debit Facility</span>
|
||||||
|
<span
|
||||||
|
class="preview-value preview-badge"
|
||||||
|
[class.preview-badge--yes]="currentAccountCurrencyFlags?.autoDebitFacility"
|
||||||
|
>
|
||||||
|
{{ currentAccountCurrencyFlags?.autoDebitFacility | yesNo }}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
<div class="preview-field">
|
||||||
|
<span class="preview-label">Dormancy Alert</span>
|
||||||
|
<span
|
||||||
|
class="preview-value preview-badge"
|
||||||
|
[class.preview-badge--yes]="currentAccountProductTemplate?.dormancyAlert"
|
||||||
|
>
|
||||||
|
{{ currentAccountProductTemplate?.dormancyAlert | yesNo }}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
<div class="preview-field">
|
||||||
|
<span class="preview-label">Nomination Facility</span>
|
||||||
|
<span
|
||||||
|
class="preview-value preview-badge"
|
||||||
|
[class.preview-badge--yes]="currentAccountProductTemplate?.nominationFacility"
|
||||||
|
>
|
||||||
|
{{ currentAccountProductTemplate?.nominationFacility | yesNo }}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- ══ 5. Dormancy Monitoring ════════════════════════════════════ -->
|
||||||
|
@if (currentAccountProductTemplate?.dormancyAlert || currentAccountProductTemplate?.isDormancyTrackingActive) {
|
||||||
|
<div class="preview-section">
|
||||||
|
<div class="preview-section__header">
|
||||||
|
<i class="fas fa-moon preview-section__icon"></i>
|
||||||
|
<span class="preview-section__title">Dormancy Monitoring</span>
|
||||||
|
<span
|
||||||
|
class="preview-section__badge"
|
||||||
|
[class.preview-section__badge--active]="currentAccountProductTemplate?.isDormancyTrackingActive"
|
||||||
|
>
|
||||||
|
{{ currentAccountProductTemplate?.isDormancyTrackingActive ? 'Active' : 'Inactive' }}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
<div class="preview-body">
|
||||||
|
<div class="preview-dormancy-timeline">
|
||||||
|
<div class="preview-dorm-step">
|
||||||
|
<div class="preview-dorm-step__dot preview-dorm-step__dot--inactive"></div>
|
||||||
|
<div class="preview-dorm-step__body">
|
||||||
|
<span class="preview-dorm-step__label">Inactive</span>
|
||||||
|
<span class="preview-dorm-step__days">
|
||||||
|
@if (currentAccountProductTemplate?.daysToInactive != null) {
|
||||||
|
After {{ currentAccountProductTemplate.daysToInactive }} days of no transaction
|
||||||
|
} @else {
|
||||||
|
Not configured
|
||||||
|
}
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="preview-dorm-connector"></div>
|
||||||
|
<div class="preview-dorm-step">
|
||||||
|
<div class="preview-dorm-step__dot preview-dorm-step__dot--dormant"></div>
|
||||||
|
<div class="preview-dorm-step__body">
|
||||||
|
<span class="preview-dorm-step__label">Dormant</span>
|
||||||
|
<span class="preview-dorm-step__days">
|
||||||
|
@if (currentAccountProductTemplate?.daysToDormancy != null) {
|
||||||
|
{{ currentAccountProductTemplate.daysToDormancy }} days after inactive
|
||||||
|
} @else {
|
||||||
|
Not configured
|
||||||
|
}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="preview-dorm-connector"></div>
|
||||||
|
<div class="preview-dorm-step">
|
||||||
|
<div class="preview-dorm-step__dot preview-dorm-step__dot--escheat"></div>
|
||||||
|
<div class="preview-dorm-step__body">
|
||||||
|
<span class="preview-dorm-step__label">Escheat</span>
|
||||||
|
<span class="preview-dorm-step__days">
|
||||||
|
@if (currentAccountProductTemplate?.daysToEscheat != null) {
|
||||||
|
{{ currentAccountProductTemplate.daysToEscheat }} days after dormant
|
||||||
|
} @else {
|
||||||
|
Not configured
|
||||||
|
}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="preview-dorm-flags">
|
||||||
|
<span class="preview-dorm-flag" [class.preview-dorm-flag--on]="currentAccountProductTemplate?.dormancyAlert">
|
||||||
|
<i class="fas fa-bell"></i> Alert
|
||||||
|
{{ currentAccountProductTemplate?.dormancyAlert ? 'Enabled' : 'Disabled' }}
|
||||||
|
</span>
|
||||||
|
<span
|
||||||
|
class="preview-dorm-flag"
|
||||||
|
[class.preview-dorm-flag--on]="currentAccountProductTemplate?.isDormancyTrackingActive"
|
||||||
|
>
|
||||||
|
<i class="fas fa-eye"></i> Tracking
|
||||||
|
{{ currentAccountProductTemplate?.isDormancyTrackingActive ? 'Active' : 'Inactive' }}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
|
||||||
|
<!-- ══ 6. Nominee Details (if filled) ═══════════════════════════ -->
|
||||||
|
@if (currentAccountNominee) {
|
||||||
|
<div class="preview-section">
|
||||||
|
<div class="preview-section__header">
|
||||||
|
<i class="fas fa-user-shield preview-section__icon"></i>
|
||||||
|
<span class="preview-section__title">Nominee Details</span>
|
||||||
|
<span class="preview-section__badge">
|
||||||
|
{{ currentAccountNominee?.mode === 'linked' ? 'Linked Client' : 'Manual Entry' }}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
<div class="preview-body">
|
||||||
|
<div class="preview-grid preview-grid--three">
|
||||||
|
<div class="preview-field">
|
||||||
|
<span class="preview-label">Name</span>
|
||||||
|
<span class="preview-value">{{
|
||||||
|
currentAccountNominee?.fullName || currentAccountNominee?.displayName || '—'
|
||||||
|
}}</span>
|
||||||
|
</div>
|
||||||
|
@if (currentAccountNominee?.cifNumber) {
|
||||||
|
<div class="preview-field">
|
||||||
|
<span class="preview-label">CIF No</span>
|
||||||
|
<span class="preview-value preview-mono">{{ currentAccountNominee.cifNumber }}</span>
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
<div class="preview-field">
|
||||||
|
<span class="preview-label">Relationship</span>
|
||||||
|
<span class="preview-value">{{ currentAccountNominee?.relationship || '—' }}</span>
|
||||||
|
</div>
|
||||||
|
<div class="preview-field">
|
||||||
|
<span class="preview-label">Share %</span>
|
||||||
|
<span class="preview-value">{{ currentAccountNominee?.nomineeShare ?? '—' }}%</span>
|
||||||
|
</div>
|
||||||
|
@if (currentAccountNominee?.dateOfBirth) {
|
||||||
|
<div class="preview-field">
|
||||||
|
<span class="preview-label">Date of Birth</span>
|
||||||
|
<span class="preview-value">{{ currentAccountNominee?.dateOfBirth | dateFormat }}</span>
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
@if (currentAccountNominee?.nationality) {
|
||||||
|
<div class="preview-field">
|
||||||
|
<span class="preview-label">Nationality</span>
|
||||||
|
<span class="preview-value">{{ currentAccountNominee?.nationality }}</span>
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
@if (currentAccountNominee?.mobileNo) {
|
||||||
|
<div class="preview-field">
|
||||||
|
<span class="preview-label">Mobile No</span>
|
||||||
|
<span class="preview-value preview-mono">{{ currentAccountNominee?.mobileNo }}</span>
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
@if (currentAccountNominee?.aadhaarNumber) {
|
||||||
|
<div class="preview-field">
|
||||||
|
<span class="preview-label">Aadhaar No</span>
|
||||||
|
<span class="preview-value preview-mono">{{ currentAccountNominee?.aadhaarNumber }}</span>
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
@if (currentAccountNominee?.panNumber) {
|
||||||
|
<div class="preview-field">
|
||||||
|
<span class="preview-label">PAN No</span>
|
||||||
|
<span class="preview-value preview-mono">{{ currentAccountNominee?.panNumber }}</span>
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
@if (currentAccountNominee?.guardianName) {
|
||||||
|
<div class="preview-field">
|
||||||
|
<span class="preview-label">Guardian Name</span>
|
||||||
|
<span class="preview-value">{{ currentAccountNominee?.guardianName }}</span>
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
@if (currentAccountNominee?.guardianRelationship) {
|
||||||
|
<div class="preview-field">
|
||||||
|
<span class="preview-label">Guardian Relationship</span>
|
||||||
|
<span class="preview-value">{{ currentAccountNominee?.guardianRelationship }}</span>
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
@if (currentAccountNominee?.remarks) {
|
||||||
|
<div class="preview-field">
|
||||||
|
<span class="preview-label">Remarks</span>
|
||||||
|
<span class="preview-value">{{ currentAccountNominee?.remarks }}</span>
|
||||||
|
</div>
|
||||||
}
|
}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
}
|
}
|
||||||
|
|
||||||
<!-- Currency -->
|
<!-- ══ 7. Non-Individual Details (if applicable) ════════════════ -->
|
||||||
<div class="preview-section">
|
@if (currentAccount?.partners?.length > 0) {
|
||||||
<div class="preview-section__header">
|
<div class="preview-section">
|
||||||
<span class="preview-section__title">{{ 'labels.heading.Currency' | translate }}</span>
|
<div class="preview-section__header">
|
||||||
</div>
|
<i class="fas fa-building preview-section__icon"></i>
|
||||||
<div class="preview-body">
|
<span class="preview-section__title">Non-Individual Account Details</span>
|
||||||
<div class="preview-grid preview-grid--three">
|
</div>
|
||||||
<div class="preview-field">
|
<div class="preview-body">
|
||||||
<span class="preview-label">{{ 'labels.inputs.Currency' | translate }}</span>
|
<!-- Partners -->
|
||||||
<span class="preview-value">{{ currentAccountTermsForm?.get('currencyCode')?.value }}</span>
|
<div class="preview-ni-label">Partners / Members</div>
|
||||||
|
<div class="preview-ni-table-wrap">
|
||||||
|
<table class="preview-ni-tbl">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th>Partner Name</th>
|
||||||
|
<th>CIF No</th>
|
||||||
|
<th>Ownership %</th>
|
||||||
|
<th>Signing Authority</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
@for (p of currentAccount.partners; track p.clientId) {
|
||||||
|
<tr>
|
||||||
|
<td>{{ p.clientName || '—' }}</td>
|
||||||
|
<td class="preview-mono">{{ p.clientCif || '—' }}</td>
|
||||||
|
<td>{{ p.sharePercentage }}%</td>
|
||||||
|
<td>
|
||||||
|
<span class="preview-badge" [class.preview-badge--yes]="p.isMandatory">
|
||||||
|
{{ p.isMandatory ? 'Mandatory' : 'Optional' }}
|
||||||
|
</span>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
}
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
</div>
|
</div>
|
||||||
<div class="preview-field">
|
<!-- Signatory Rights -->
|
||||||
<span class="preview-label">{{ 'labels.inputs.Decimal Places' | translate }}</span>
|
@if (currentAccount?.signatoryRights) {
|
||||||
<span class="preview-value">{{ currentAccountProductTemplate?.currency?.decimalPlaces }}</span>
|
<div class="preview-ni-mode">
|
||||||
</div>
|
<i class="fas fa-how_to_vote"></i>
|
||||||
<div class="preview-field">
|
<span class="preview-ni-mode__label">Mode of Operation:</span>
|
||||||
<span class="preview-label">{{ 'labels.inputs.Currency In Multiples Of' | translate }}</span>
|
<strong>{{ currentAccount.signatoryRights }}</strong>
|
||||||
<span class="preview-value">{{ currentAccountProductTemplate?.currency?.inMultiplesOf }}</span>
|
|
||||||
</div>
|
|
||||||
@if (
|
|
||||||
currentAccountProductTemplate?.dormancyAlert !== undefined &&
|
|
||||||
currentAccountProductTemplate?.dormancyAlert !== null
|
|
||||||
) {
|
|
||||||
<div class="preview-field">
|
|
||||||
<span class="preview-label">Dormancy Alert</span>
|
|
||||||
<span
|
|
||||||
class="preview-value preview-badge"
|
|
||||||
[class.preview-badge--yes]="currentAccountProductTemplate?.dormancyAlert"
|
|
||||||
>
|
|
||||||
{{ currentAccountProductTemplate?.dormancyAlert | yesNo }}
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
}
|
|
||||||
@if (
|
|
||||||
currentAccountProductTemplate?.balanceSwapOption !== undefined &&
|
|
||||||
currentAccountProductTemplate?.balanceSwapOption !== null
|
|
||||||
) {
|
|
||||||
<div class="preview-field">
|
|
||||||
<span class="preview-label">Balance Swap Option</span>
|
|
||||||
<span
|
|
||||||
class="preview-value preview-badge"
|
|
||||||
[class.preview-badge--yes]="currentAccountProductTemplate?.balanceSwapOption"
|
|
||||||
>
|
|
||||||
{{ currentAccountProductTemplate?.balanceSwapOption | yesNo }}
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
}
|
|
||||||
@if (currentAccountProductTemplate?.msme !== undefined && currentAccountProductTemplate?.msme !== null) {
|
|
||||||
<div class="preview-field">
|
|
||||||
<span class="preview-label">MSME</span>
|
|
||||||
<span class="preview-value preview-badge" [class.preview-badge--yes]="currentAccountProductTemplate?.msme">
|
|
||||||
{{ currentAccountProductTemplate?.msme | yesNo }}
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
}
|
|
||||||
@if (
|
|
||||||
currentAccountProductTemplate?.nominationFacility !== undefined &&
|
|
||||||
currentAccountProductTemplate?.nominationFacility !== null
|
|
||||||
) {
|
|
||||||
<div class="preview-field">
|
|
||||||
<span class="preview-label">Nomination Facility</span>
|
|
||||||
<span
|
|
||||||
class="preview-value preview-badge"
|
|
||||||
[class.preview-badge--yes]="currentAccountProductTemplate?.nominationFacility"
|
|
||||||
>
|
|
||||||
{{ currentAccountProductTemplate?.nominationFacility | yesNo }}
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
}
|
|
||||||
@if (
|
|
||||||
currentAccountProductTemplate?.autoDebitFacility !== undefined &&
|
|
||||||
currentAccountProductTemplate?.autoDebitFacility !== null
|
|
||||||
) {
|
|
||||||
<div class="preview-field">
|
|
||||||
<span class="preview-label">Auto Debit Facility</span>
|
|
||||||
<span
|
|
||||||
class="preview-value preview-badge"
|
|
||||||
[class.preview-badge--yes]="currentAccountProductTemplate?.autoDebitFacility"
|
|
||||||
>
|
|
||||||
{{ currentAccountProductTemplate?.autoDebitFacility | yesNo }}
|
|
||||||
</span>
|
|
||||||
</div>
|
</div>
|
||||||
}
|
}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
}
|
||||||
|
|
||||||
|
<!-- ══ 8. Digital Facilities ════════════════════════════════════ -->
|
||||||
@if (hasDigitalSection) {
|
@if (hasDigitalSection) {
|
||||||
<div class="preview-section">
|
<div class="preview-section">
|
||||||
<div class="preview-section__header">
|
<div class="preview-section__header">
|
||||||
<span class="preview-section__title">Digital</span>
|
<i class="fas fa-mobile-alt preview-section__icon"></i>
|
||||||
|
<span class="preview-section__title">Digital Facilities</span>
|
||||||
|
<span class="preview-section__badge preview-section__badge--digital">User Configured</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="preview-body">
|
<div class="preview-body">
|
||||||
<div class="preview-grid preview-grid--three">
|
<div class="preview-digital-grid">
|
||||||
@for (facility of digitalFacilityLabels; track facility.key) {
|
@for (facility of digitalFacilityLabels; track facility.key) {
|
||||||
<div class="preview-field">
|
<div class="preview-digital-card" [class.preview-digital-card--on]="digitalFacilityConfig?.[facility.key]">
|
||||||
<span class="preview-label">{{ facility.label }}</span>
|
<span class="preview-digital-label">{{ facility.label }}</span>
|
||||||
<span
|
<span
|
||||||
class="preview-value preview-badge"
|
class="preview-digital-status"
|
||||||
[class.preview-badge--yes]="digitalPreview?.accountFacilityConfig?.[facility.key]"
|
[class.preview-digital-status--on]="digitalFacilityConfig?.[facility.key]"
|
||||||
>
|
>
|
||||||
{{ digitalPreview?.accountFacilityConfig?.[facility.key] | yesNo }}
|
{{ digitalFacilityConfig?.[facility.key] ? 'Enabled' : 'Disabled' }}
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
}
|
}
|
||||||
|
|||||||
+300
-24
@@ -9,29 +9,65 @@
|
|||||||
.preview-wrapper {
|
.preview-wrapper {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
gap: 1.25rem;
|
gap: 1rem;
|
||||||
padding: 0.5rem 0;
|
padding: 0.5rem 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.preview-section {
|
.preview-section {
|
||||||
border: 1px solid #e0e0e0;
|
border: 1px solid #e2e8f0;
|
||||||
border-radius: 8px;
|
border-radius: 10px;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
background: #fff;
|
background: #fff;
|
||||||
box-shadow: 0 1px 3px rgb(0 0 0 / 6%);
|
box-shadow: 0 1px 4px rgb(0 0 0 / 5%);
|
||||||
|
|
||||||
&__header {
|
&__header {
|
||||||
background: #f5f5f5;
|
display: flex;
|
||||||
border-bottom: 1px solid #e0e0e0;
|
align-items: center;
|
||||||
|
gap: 8px;
|
||||||
|
background: #f8fafc;
|
||||||
|
border-bottom: 1px solid #e2e8f0;
|
||||||
padding: 0.6rem 1rem;
|
padding: 0.6rem 1rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
&__icon {
|
||||||
|
font-size: 13px;
|
||||||
|
color: #0ea5e9;
|
||||||
|
width: 16px;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
&__title {
|
&__title {
|
||||||
font-size: 0.95rem;
|
font-size: 0.82rem;
|
||||||
font-weight: 600;
|
font-weight: 700;
|
||||||
color: #333;
|
color: #1e293b;
|
||||||
text-transform: uppercase;
|
text-transform: uppercase;
|
||||||
letter-spacing: 0.04em;
|
letter-spacing: 0.06em;
|
||||||
|
flex: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
&__badge {
|
||||||
|
display: inline-flex;
|
||||||
|
align-items: center;
|
||||||
|
padding: 2px 10px;
|
||||||
|
border-radius: 999px;
|
||||||
|
font-size: 10px;
|
||||||
|
font-weight: 700;
|
||||||
|
background: #dbeafe;
|
||||||
|
color: #1d4ed8;
|
||||||
|
border: 1px solid #bfdbfe;
|
||||||
|
text-transform: uppercase;
|
||||||
|
|
||||||
|
&--digital {
|
||||||
|
background: #fef3c7;
|
||||||
|
color: #92400e;
|
||||||
|
border-color: #fde68a;
|
||||||
|
}
|
||||||
|
|
||||||
|
&--active {
|
||||||
|
background: #dcfce7 !important;
|
||||||
|
color: #15803d !important;
|
||||||
|
border-color: #bbf7d0 !important;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -41,7 +77,7 @@
|
|||||||
|
|
||||||
.preview-grid {
|
.preview-grid {
|
||||||
display: grid;
|
display: grid;
|
||||||
gap: 0.75rem 1.5rem;
|
gap: 0.85rem 1.5rem;
|
||||||
|
|
||||||
&--three {
|
&--three {
|
||||||
grid-template-columns: repeat(3, 1fr);
|
grid-template-columns: repeat(3, 1fr);
|
||||||
@@ -59,36 +95,276 @@
|
|||||||
.preview-field {
|
.preview-field {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
gap: 0.15rem;
|
gap: 0.2rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
.preview-label {
|
.preview-label {
|
||||||
font-size: 0.72rem;
|
font-size: 0.68rem;
|
||||||
color: #888;
|
color: #94a3b8;
|
||||||
font-weight: 500;
|
font-weight: 600;
|
||||||
text-transform: uppercase;
|
text-transform: uppercase;
|
||||||
letter-spacing: 0.04em;
|
letter-spacing: 0.05em;
|
||||||
}
|
}
|
||||||
|
|
||||||
.preview-value {
|
.preview-value {
|
||||||
font-size: 0.92rem;
|
font-size: 0.9rem;
|
||||||
color: #222;
|
color: #1e293b;
|
||||||
font-weight: 500;
|
font-weight: 500;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.preview-muted {
|
||||||
|
color: #94a3b8;
|
||||||
|
font-style: italic;
|
||||||
|
}
|
||||||
|
|
||||||
|
.preview-mono {
|
||||||
|
font-family: monospace;
|
||||||
|
font-size: 0.88rem;
|
||||||
|
color: #334155;
|
||||||
|
}
|
||||||
|
|
||||||
.preview-badge {
|
.preview-badge {
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
padding: 0.1rem 0.55rem;
|
padding: 0.15rem 0.6rem;
|
||||||
border-radius: 12px;
|
border-radius: 12px;
|
||||||
font-size: 0.78rem;
|
font-size: 0.75rem;
|
||||||
font-weight: 600;
|
font-weight: 600;
|
||||||
background: #ffebee;
|
background: #fef2f2;
|
||||||
color: #c62828;
|
color: #dc2626;
|
||||||
width: fit-content;
|
width: fit-content;
|
||||||
|
|
||||||
&--yes {
|
&--yes {
|
||||||
background: #e8f5e9;
|
background: #f0fdf4;
|
||||||
color: #2e7d32;
|
color: #15803d;
|
||||||
|
}
|
||||||
|
|
||||||
|
&--warn {
|
||||||
|
background: #fef3c7;
|
||||||
|
color: #92400e;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Digital facilities grid
|
||||||
|
.preview-digital-grid {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: repeat(4, 1fr);
|
||||||
|
gap: 8px;
|
||||||
|
|
||||||
|
@media (width <= 900px) {
|
||||||
|
grid-template-columns: repeat(3, 1fr);
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (width <= 600px) {
|
||||||
|
grid-template-columns: repeat(2, 1fr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.preview-digital-card {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 4px;
|
||||||
|
padding: 10px 12px;
|
||||||
|
border: 1.5px solid #e2e8f0;
|
||||||
|
border-radius: 8px;
|
||||||
|
background: #f8fafc;
|
||||||
|
|
||||||
|
&--on {
|
||||||
|
border-color: #86efac;
|
||||||
|
background: #f0fdf4;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.preview-digital-label {
|
||||||
|
font-size: 11px;
|
||||||
|
font-weight: 600;
|
||||||
|
color: #475569;
|
||||||
|
}
|
||||||
|
|
||||||
|
.preview-digital-status {
|
||||||
|
font-size: 11px;
|
||||||
|
font-weight: 700;
|
||||||
|
color: #dc2626;
|
||||||
|
|
||||||
|
&--on {
|
||||||
|
color: #15803d;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ── Dormancy Monitoring ───────────────────────────────────────────
|
||||||
|
.preview-dormancy-timeline {
|
||||||
|
display: flex;
|
||||||
|
align-items: flex-start;
|
||||||
|
margin-bottom: 14px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.preview-dorm-step {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
gap: 6px;
|
||||||
|
flex: 1;
|
||||||
|
|
||||||
|
&__dot {
|
||||||
|
width: 36px;
|
||||||
|
height: 36px;
|
||||||
|
border-radius: 50%;
|
||||||
|
border: 3px solid;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
flex-shrink: 0;
|
||||||
|
|
||||||
|
&--inactive {
|
||||||
|
border-color: #f59e0b;
|
||||||
|
background: #fffbeb;
|
||||||
|
|
||||||
|
&::after {
|
||||||
|
content: '';
|
||||||
|
width: 10px;
|
||||||
|
height: 10px;
|
||||||
|
border-radius: 50%;
|
||||||
|
background: #f59e0b;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&--dormant {
|
||||||
|
border-color: #ef4444;
|
||||||
|
background: #fef2f2;
|
||||||
|
|
||||||
|
&::after {
|
||||||
|
content: '';
|
||||||
|
width: 10px;
|
||||||
|
height: 10px;
|
||||||
|
border-radius: 50%;
|
||||||
|
background: #ef4444;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&--escheat {
|
||||||
|
border-color: #7c3aed;
|
||||||
|
background: #f5f3ff;
|
||||||
|
|
||||||
|
&::after {
|
||||||
|
content: '';
|
||||||
|
width: 10px;
|
||||||
|
height: 10px;
|
||||||
|
border-radius: 50%;
|
||||||
|
background: #7c3aed;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&__body {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
text-align: center;
|
||||||
|
gap: 2px;
|
||||||
|
}
|
||||||
|
|
||||||
|
&__label {
|
||||||
|
font-size: 12px;
|
||||||
|
font-weight: 700;
|
||||||
|
color: #1e293b;
|
||||||
|
}
|
||||||
|
|
||||||
|
&__days {
|
||||||
|
font-size: 10.5px;
|
||||||
|
color: #64748b;
|
||||||
|
line-height: 1.3;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.preview-dorm-connector {
|
||||||
|
flex: 0 0 40px;
|
||||||
|
height: 3px;
|
||||||
|
background: linear-gradient(90deg, #e2e8f0, #cbd5e1);
|
||||||
|
margin-top: 16px;
|
||||||
|
border-radius: 2px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.preview-dorm-flags {
|
||||||
|
display: flex;
|
||||||
|
gap: 10px;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
}
|
||||||
|
|
||||||
|
.preview-dorm-flag {
|
||||||
|
display: inline-flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 5px;
|
||||||
|
padding: 4px 12px;
|
||||||
|
border-radius: 20px;
|
||||||
|
font-size: 11.5px;
|
||||||
|
font-weight: 600;
|
||||||
|
background: #f1f5f9;
|
||||||
|
color: #94a3b8;
|
||||||
|
border: 1px solid #e2e8f0;
|
||||||
|
|
||||||
|
i {
|
||||||
|
font-size: 11px;
|
||||||
|
}
|
||||||
|
|
||||||
|
&--on {
|
||||||
|
background: #f0fdf4;
|
||||||
|
color: #15803d;
|
||||||
|
border-color: #bbf7d0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Non-Individual section
|
||||||
|
.preview-ni-label {
|
||||||
|
font-size: 11px;
|
||||||
|
font-weight: 700;
|
||||||
|
color: #64748b;
|
||||||
|
text-transform: uppercase;
|
||||||
|
letter-spacing: 0.05em;
|
||||||
|
margin-bottom: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.preview-ni-table-wrap {
|
||||||
|
overflow-x: auto;
|
||||||
|
border: 1px solid #e2e8f0;
|
||||||
|
border-radius: 8px;
|
||||||
|
margin-bottom: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.preview-ni-tbl {
|
||||||
|
width: 100%;
|
||||||
|
border-collapse: collapse;
|
||||||
|
font-size: 13px;
|
||||||
|
|
||||||
|
th {
|
||||||
|
padding: 8px 12px;
|
||||||
|
font-size: 11px;
|
||||||
|
font-weight: 700;
|
||||||
|
color: #374151;
|
||||||
|
text-transform: uppercase;
|
||||||
|
background: #f8fafc;
|
||||||
|
border-bottom: 1px solid #e2e8f0;
|
||||||
|
text-align: left;
|
||||||
|
}
|
||||||
|
|
||||||
|
td {
|
||||||
|
padding: 9px 12px;
|
||||||
|
color: #1e293b;
|
||||||
|
border-bottom: 1px solid #f3f4f6;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.preview-ni-mode {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 8px;
|
||||||
|
font-size: 13px;
|
||||||
|
color: #374151;
|
||||||
|
padding: 8px 12px;
|
||||||
|
background: #f0fdf4;
|
||||||
|
border: 1px solid #bbf7d0;
|
||||||
|
border-radius: 8px;
|
||||||
|
|
||||||
|
&__label {
|
||||||
|
font-weight: 600;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+25
-12
@@ -83,18 +83,15 @@ export class CurrentAccountPreviewStepComponent implements OnChanges {
|
|||||||
|
|
||||||
private translateService = inject(TranslateService);
|
private translateService = inject(TranslateService);
|
||||||
|
|
||||||
/** Current Account Product Template */
|
|
||||||
@Input() currentAccountProductTemplate: any;
|
@Input() currentAccountProductTemplate: any;
|
||||||
/** Current Account Template */
|
|
||||||
@Input() currentAccountTemplate: any;
|
@Input() currentAccountTemplate: any;
|
||||||
/** Current Account Terms Form */
|
|
||||||
@Input() currentAccountTermsForm: any;
|
@Input() currentAccountTermsForm: any;
|
||||||
/** Current Account Term Form */
|
|
||||||
@Input() currentAccountTermForm: any;
|
@Input() currentAccountTermForm: any;
|
||||||
/** Current Account Settings Form */
|
|
||||||
@Input() currentAccountSettingsForm: any;
|
@Input() currentAccountSettingsForm: any;
|
||||||
/** Current Account */
|
|
||||||
@Input() currentAccount: any;
|
@Input() currentAccount: any;
|
||||||
|
@Input() currentAccountDigital: any;
|
||||||
|
@Input() currentAccountNominee: any;
|
||||||
|
@Input() currentAccountCurrencyFlags: any;
|
||||||
@Input() activeClientMembers?: any;
|
@Input() activeClientMembers?: any;
|
||||||
|
|
||||||
/** Table Data Source */
|
/** Table Data Source */
|
||||||
@@ -136,15 +133,31 @@ export class CurrentAccountPreviewStepComponent implements OnChanges {
|
|||||||
return this.currentAccountSettingsForm?.getRawValue?.() || this.currentAccount || {};
|
return this.currentAccountSettingsForm?.getRawValue?.() || this.currentAccount || {};
|
||||||
}
|
}
|
||||||
|
|
||||||
get digitalPreview(): any {
|
get digitalFacilityConfig(): any {
|
||||||
return this.currentAccountProductTemplate || {};
|
return (
|
||||||
|
this.currentAccountDigital?.accountFacilityConfig ??
|
||||||
|
this.currentAccountProductTemplate?.accountFacilityConfig ??
|
||||||
|
null
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
get hasDigitalSection(): boolean {
|
get hasDigitalSection(): boolean {
|
||||||
return !!(
|
return !!this.digitalFacilityConfig;
|
||||||
this.digitalPreview?.accountFacilityConfig ||
|
}
|
||||||
this.digitalPreview?.accountFacilityLimits?.length ||
|
|
||||||
this.digitalPreview?.depositLimitKyc
|
get currencyName(): string {
|
||||||
|
return (
|
||||||
|
this.currentAccountProductTemplate?.currency?.name ||
|
||||||
|
this.currentAccountTermsForm?.get?.('currencyCode')?.value ||
|
||||||
|
'—'
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
get decimalPlaces(): string | number {
|
||||||
|
return this.currentAccountProductTemplate?.currency?.decimalPlaces ?? '—';
|
||||||
|
}
|
||||||
|
|
||||||
|
get inMultiplesOf(): string | number {
|
||||||
|
return this.currentAccountProductTemplate?.currency?.inMultiplesOf ?? '—';
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+4
@@ -98,6 +98,10 @@
|
|||||||
[recurringDepositsAccountProductTemplate]="recurringDepositsAccountProductTemplate"
|
[recurringDepositsAccountProductTemplate]="recurringDepositsAccountProductTemplate"
|
||||||
[recurringDepositAccountData]="recurringDepositAccountData"
|
[recurringDepositAccountData]="recurringDepositAccountData"
|
||||||
[rdInterestRates]="rdInterestRates"
|
[rdInterestRates]="rdInterestRates"
|
||||||
|
[rdNominee]="rdNominee"
|
||||||
|
[rdCurrencyFlags]="rdCurrencyFlags"
|
||||||
|
[rdTenureDays]="rdTenureDays"
|
||||||
|
[rdApplicableSlab]="rdApplicableSlab"
|
||||||
(submitEvent)="submit()"
|
(submitEvent)="submit()"
|
||||||
>
|
>
|
||||||
</mifosx-recurring-deposits-account-preview-step>
|
</mifosx-recurring-deposits-account-preview-step>
|
||||||
|
|||||||
+24
-1
@@ -65,9 +65,12 @@ export class CreateRecurringDepositsAccountComponent {
|
|||||||
@ViewChild(RecurringDepositsAccountDetailsStepComponent, { static: true })
|
@ViewChild(RecurringDepositsAccountDetailsStepComponent, { static: true })
|
||||||
recurringDepositsAccountDetailsStep: RecurringDepositsAccountDetailsStepComponent;
|
recurringDepositsAccountDetailsStep: RecurringDepositsAccountDetailsStepComponent;
|
||||||
|
|
||||||
@ViewChild(RecurringDepositsAccountCurrencyStepComponent, { static: true })
|
@ViewChild(RecurringDepositsAccountCurrencyStepComponent)
|
||||||
recurringDepositsAccountCurrencyStep: RecurringDepositsAccountCurrencyStepComponent;
|
recurringDepositsAccountCurrencyStep: RecurringDepositsAccountCurrencyStepComponent;
|
||||||
|
|
||||||
|
@ViewChild(RecurringDepositsAccountInterestRateChartStepComponent)
|
||||||
|
recurringDepositsAccountChartStep: RecurringDepositsAccountInterestRateChartStepComponent;
|
||||||
|
|
||||||
/** Recurring Deposits Account Template */
|
/** Recurring Deposits Account Template */
|
||||||
recurringDepositsAccountTemplate: any;
|
recurringDepositsAccountTemplate: any;
|
||||||
/** Recurring Deposit Account Product Template */
|
/** Recurring Deposit Account Product Template */
|
||||||
@@ -115,6 +118,26 @@ export class CreateRecurringDepositsAccountComponent {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
get rdNominee() {
|
||||||
|
return this.recurringDepositsAccountCurrencyStep?.nomineeData ?? null;
|
||||||
|
}
|
||||||
|
|
||||||
|
get rdTenureDays(): number | null {
|
||||||
|
return this.recurringDepositsAccountChartStep?.tenureDays ?? null;
|
||||||
|
}
|
||||||
|
|
||||||
|
get rdApplicableSlab(): any | null {
|
||||||
|
return this.recurringDepositsAccountChartStep?.applicableSlab ?? null;
|
||||||
|
}
|
||||||
|
|
||||||
|
get rdCurrencyFlags() {
|
||||||
|
return {
|
||||||
|
balanceSwapOption: this.recurringDepositsAccountCurrencyStep?.balanceSwapOption ?? false,
|
||||||
|
msme: this.recurringDepositsAccountCurrencyStep?.msme ?? false,
|
||||||
|
autoDebitFacility: this.recurringDepositsAccountCurrencyStep?.autoDebitFacility ?? false
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Submits the recurring deposit form to create a new recurring deposit account
|
* Submits the recurring deposit form to create a new recurring deposit account
|
||||||
*/
|
*/
|
||||||
|
|||||||
+5
-5
@@ -60,10 +60,11 @@
|
|||||||
{{ recurringDepositsAccountProductTemplate?.dormancyAlert ? 'Yes' : 'No' }}
|
{{ recurringDepositsAccountProductTemplate?.dormancyAlert ? 'Yes' : 'No' }}
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
|
@if (recurringDepositsAccountProductTemplate?.dormancyAlert) {
|
||||||
<mifosx-dormancy-alert-panel
|
<mifosx-dormancy-alert-panel
|
||||||
[productTemplate]="recurringDepositsAccountProductTemplate"
|
[productTemplate]="recurringDepositsAccountProductTemplate"
|
||||||
></mifosx-dormancy-alert-panel>
|
></mifosx-dormancy-alert-panel>
|
||||||
|
}
|
||||||
|
|
||||||
<div class="racc-alert">
|
<div class="racc-alert">
|
||||||
<div class="racc-alert__content">
|
<div class="racc-alert__content">
|
||||||
@@ -74,7 +75,6 @@
|
|||||||
{{ recurringDepositsAccountProductTemplate?.nominationFacility ? 'Yes' : 'No' }}
|
{{ recurringDepositsAccountProductTemplate?.nominationFacility ? 'Yes' : 'No' }}
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@if (recurringDepositsAccountProductTemplate?.nominationFacility) {
|
@if (recurringDepositsAccountProductTemplate?.nominationFacility) {
|
||||||
<mifosx-nominee-form (nomineeChange)="onNomineeChange($event)"></mifosx-nominee-form>
|
<mifosx-nominee-form (nomineeChange)="onNomineeChange($event)"></mifosx-nominee-form>
|
||||||
}
|
}
|
||||||
|
|||||||
+7
-1
@@ -61,6 +61,8 @@ export class RecurringDepositsAccountDetailsStepComponent implements OnInit {
|
|||||||
|
|
||||||
isProductSelected = false;
|
isProductSelected = false;
|
||||||
introducerId: number | null = null;
|
introducerId: number | null = null;
|
||||||
|
introducerName: string | null = null;
|
||||||
|
introducerCif: string | null = null;
|
||||||
|
|
||||||
/** Recurring Deposits Account Template with product data */
|
/** Recurring Deposits Account Template with product data */
|
||||||
@Output() recurringDepositsAccountProductTemplate = new EventEmitter();
|
@Output() recurringDepositsAccountProductTemplate = new EventEmitter();
|
||||||
@@ -196,14 +198,18 @@ export class RecurringDepositsAccountDetailsStepComponent implements OnInit {
|
|||||||
/**
|
/**
|
||||||
* Returns recurring deposits account details form value.
|
* Returns recurring deposits account details form value.
|
||||||
*/
|
*/
|
||||||
onIntroducerChange(event: { clientId: number; displayName: string } | null): void {
|
onIntroducerChange(event: { clientId: number; displayName: string; cifNumber?: string } | null): void {
|
||||||
this.introducerId = event?.clientId ?? null;
|
this.introducerId = event?.clientId ?? null;
|
||||||
|
this.introducerName = event?.displayName ?? null;
|
||||||
|
this.introducerCif = event?.cifNumber ?? null;
|
||||||
}
|
}
|
||||||
|
|
||||||
get recurringDepositAccountDetails() {
|
get recurringDepositAccountDetails() {
|
||||||
const value = this.recurringDepositAccountDetailsForm.value;
|
const value = this.recurringDepositAccountDetailsForm.value;
|
||||||
if (this.introducerId) {
|
if (this.introducerId) {
|
||||||
value.introducerId = this.introducerId;
|
value.introducerId = this.introducerId;
|
||||||
|
value.introducerName = this.introducerName;
|
||||||
|
value.introducerCif = this.introducerCif;
|
||||||
}
|
}
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
|||||||
+39
-196
@@ -7,203 +7,46 @@
|
|||||||
-->
|
-->
|
||||||
|
|
||||||
<div class="layout-column gap-2px">
|
<div class="layout-column gap-2px">
|
||||||
<!-- ── Custom RD Interest Rate Chart (from m_rd_interest_rate_slab_history) ── -->
|
<!-- ── Tenure Calculator ───────────────────────────────────────── -->
|
||||||
@if (_activeRdVersion) {
|
@if (_activeRdVersion) {
|
||||||
<div class="rd-rate-header">
|
<div class="tenure-calc">
|
||||||
<strong>{{ _activeRdVersion.versionLabel }}</strong>
|
<div class="tenure-calc__header">
|
||||||
<span class="rd-rate-active-badge">Active</span>
|
<i class="fas fa-calculator"></i>
|
||||||
<span class="rd-rate-from">Effective from: {{ _activeRdVersion.effectiveFromDate }}</span>
|
<span>Tenure & Interest Calculator</span>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="tenure-calc__body">
|
||||||
<table class="mat-elevation-z1 rd-rate-table" mat-table [dataSource]="_activeRdVersion.slabs">
|
<div class="tenure-calc__input-row">
|
||||||
<ng-container matColumnDef="srNo">
|
<mat-form-field appearance="outline" class="tenure-calc__field">
|
||||||
<th mat-header-cell *matHeaderCellDef>Sr.</th>
|
<mat-label>Enter Tenure (Days)</mat-label>
|
||||||
<td mat-cell *matCellDef="let slab">{{ slab.srNo }}</td>
|
<input matInput type="number" [(ngModel)]="tenureDays" min="1" placeholder="e.g. 365" />
|
||||||
</ng-container>
|
<mat-hint>Enter the number of days for your RD</mat-hint>
|
||||||
<ng-container matColumnDef="description">
|
</mat-form-field>
|
||||||
<th mat-header-cell *matHeaderCellDef>Particular</th>
|
|
||||||
<td mat-cell *matCellDef="let slab">{{ slab.description }}</td>
|
|
||||||
</ng-container>
|
|
||||||
<ng-container matColumnDef="fromPeriod">
|
|
||||||
<th mat-header-cell *matHeaderCellDef>From</th>
|
|
||||||
<td mat-cell *matCellDef="let slab">{{ slab.fromPeriod }}</td>
|
|
||||||
</ng-container>
|
|
||||||
<ng-container matColumnDef="toPeriod">
|
|
||||||
<th mat-header-cell *matHeaderCellDef>To</th>
|
|
||||||
<td mat-cell *matCellDef="let slab">{{ slab.toPeriod ?? '—' }}</td>
|
|
||||||
</ng-container>
|
|
||||||
<ng-container matColumnDef="periodTypeLabel">
|
|
||||||
<th mat-header-cell *matHeaderCellDef>Period Type</th>
|
|
||||||
<td mat-cell *matCellDef="let slab">{{ slab.periodTypeLabel }}</td>
|
|
||||||
</ng-container>
|
|
||||||
<ng-container matColumnDef="annualInterestRate">
|
|
||||||
<th mat-header-cell *matHeaderCellDef>Annual Rate (%)</th>
|
|
||||||
<td mat-cell *matCellDef="let slab">
|
|
||||||
<strong>{{ slab.annualInterestRate | number: '1.2-2' }}</strong>
|
|
||||||
</td>
|
|
||||||
</ng-container>
|
|
||||||
<tr mat-header-row *matHeaderRowDef="rdSlabColumns"></tr>
|
|
||||||
<tr mat-row *matRowDef="let row; columns: rdSlabColumns"></tr>
|
|
||||||
</table>
|
|
||||||
}
|
|
||||||
|
|
||||||
<!-- ── Legacy chart (shown only when no custom rate chart available) ── -->
|
|
||||||
@if (!_activeRdVersion) {
|
|
||||||
<div class="flex-fill" *ngIf="recurringDepositsAccountProductTemplate?.accountChart?.name">
|
|
||||||
<span class="flex-40">{{ 'labels.inputs.name' | translate }}:</span>
|
|
||||||
<span class="flex-60">{{ recurringDepositsAccountProductTemplate?.accountChart?.name }}</span>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="flex-fill">
|
|
||||||
<span class="flex-40">{{ 'labels.inputs.Valid from Date' | translate }}:</span>
|
|
||||||
<span class="flex-60">{{ recurringDepositsAccountProductTemplate?.accountChart?.fromDate | dateFormat }}</span>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="flex-fill" *ngIf="recurringDepositsAccountProductTemplate?.accountChart?.endDate">
|
|
||||||
<span class="flex-40">{{ 'labels.inputs.End Date' | translate }}:</span>
|
|
||||||
<span class="flex-60">{{ recurringDepositsAccountProductTemplate?.accountChart?.endDate | dateFormat }}</span>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="flex-fill" *ngIf="recurringDepositsAccountProductTemplate?.accountChart?.description">
|
|
||||||
<span class="flex-40">{{ 'labels.inputs.Description' | translate }}:</span>
|
|
||||||
<span class="flex-60">{{ recurringDepositsAccountProductTemplate?.accountChart?.description }}</span>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="flex-fill">
|
|
||||||
<span class="flex-40">{{ 'labels.inputs.Primary Grouping by Amount' | translate }}:</span>
|
|
||||||
<span class="flex-60">{{
|
|
||||||
recurringDepositsAccountProductTemplate?.accountChart?.isPrimaryGroupingByAmount | yesNo
|
|
||||||
}}</span>
|
|
||||||
</div>
|
|
||||||
}
|
|
||||||
|
|
||||||
<table
|
|
||||||
class="mat-elevation-z1"
|
|
||||||
[class.hidden]="_activeRdVersion"
|
|
||||||
mat-table
|
|
||||||
[dataSource]="interestRateChartData"
|
|
||||||
#chartsTable
|
|
||||||
multiTemplateDataRows
|
|
||||||
>
|
|
||||||
<ng-container matColumnDef="period">
|
|
||||||
<th mat-header-cell *matHeaderCellDef>{{ 'labels.inputs.Period' | translate }}</th>
|
|
||||||
<td mat-cell *matCellDef="let chartSlab">
|
|
||||||
{{ chartSlab.fromPeriod }} - {{ chartSlab.toPeriod }} {{
|
|
||||||
chartSlab.periodType.value | translateKey: 'catalogs'
|
|
||||||
}}
|
|
||||||
</td>
|
|
||||||
</ng-container>
|
|
||||||
|
|
||||||
<ng-container matColumnDef="amountRange">
|
|
||||||
<th mat-header-cell *matHeaderCellDef>{{ 'labels.inputs.Amount Range' | translate }}</th>
|
|
||||||
<td mat-cell *matCellDef="let chartSlab">
|
|
||||||
{{ chartSlab.amountRangeFrom | formatNumber }} - {{ chartSlab.amountRangeTo | formatNumber }}
|
|
||||||
</td>
|
|
||||||
</ng-container>
|
|
||||||
|
|
||||||
<ng-container matColumnDef="interest">
|
|
||||||
<th mat-header-cell *matHeaderCellDef>{{ 'labels.inputs.Interest' | translate }}</th>
|
|
||||||
<td mat-cell *matCellDef="let chartSlab">{{ chartSlab.annualInterestRate | formatNumber }} %</td>
|
|
||||||
</ng-container>
|
|
||||||
|
|
||||||
<ng-container matColumnDef="description">
|
|
||||||
<th mat-header-cell *matHeaderCellDef>{{ 'labels.inputs.Description' | translate }}</th>
|
|
||||||
<td mat-cell *matCellDef="let chartSlab">{{ chartSlab.description }}</td>
|
|
||||||
</ng-container>
|
|
||||||
|
|
||||||
<ng-container matColumnDef="actions">
|
|
||||||
<th mat-header-cell *matHeaderCellDef>{{ 'labels.inputs.Actions' | translate }}</th>
|
|
||||||
<td mat-cell *matCellDef="let chartSlab; let chartSlabIndex = dataIndex">
|
|
||||||
<button
|
|
||||||
mat-button
|
|
||||||
color="primary"
|
|
||||||
(click)="expandChartSlabIndex = expandChartSlabIndex === chartSlabIndex ? null : chartSlabIndex"
|
|
||||||
>
|
|
||||||
<span *ngIf="expandChartSlabIndex !== chartSlabIndex">
|
|
||||||
<fa-icon icon="eye" class="m-r-10"></fa-icon>
|
|
||||||
{{ 'labels.buttons.View Incentives' | translate }}
|
|
||||||
</span>
|
|
||||||
<span *ngIf="expandChartSlabIndex === chartSlabIndex">
|
|
||||||
<fa-icon icon="eye-slash" class="m-r-10"></fa-icon>
|
|
||||||
{{ 'labels.buttons.Hide Incentives' | translate }}
|
|
||||||
</span>
|
|
||||||
</button>
|
|
||||||
</td>
|
|
||||||
</ng-container>
|
|
||||||
|
|
||||||
<ng-container matColumnDef="incentives">
|
|
||||||
<td
|
|
||||||
mat-cell
|
|
||||||
*matCellDef="let chartSlab; let chartSlabIndex = dataIndex"
|
|
||||||
[attr.colspan]="chartSlabsDisplayedColumns.length"
|
|
||||||
>
|
|
||||||
<div
|
|
||||||
class="incentives flex-fill layout-row flex-wrap"
|
|
||||||
[@expandChartSlab]="chartSlabIndex === expandChartSlabIndex ? 'expanded' : 'collapsed'"
|
|
||||||
>
|
|
||||||
<mat-card class="layout-row-wrap flex-fill">
|
|
||||||
<h4 class="m-b-10 flex-13">
|
|
||||||
{{ 'labels.heading.Incentives' | translate }}
|
|
||||||
</h4>
|
|
||||||
|
|
||||||
<table
|
|
||||||
class="mat-elevation-z1 flex-fill"
|
|
||||||
mat-table
|
|
||||||
[dataSource]="chartSlab.incentives"
|
|
||||||
*ngIf="chartSlab.incentives.length"
|
|
||||||
>
|
|
||||||
<ng-container matColumnDef="entityType">
|
|
||||||
<th mat-header-cell *matHeaderCellDef>{{ 'labels.inputs.Entity Type' | translate }}</th>
|
|
||||||
<td mat-cell *matCellDef="let incentive">
|
|
||||||
{{ incentive.entityType.value }}
|
|
||||||
</td>
|
|
||||||
</ng-container>
|
|
||||||
|
|
||||||
<ng-container matColumnDef="attributeName">
|
|
||||||
<th mat-header-cell *matHeaderCellDef>{{ 'labels.inputs.Attribute Name' | translate }}</th>
|
|
||||||
<td mat-cell *matCellDef="let incentive">
|
|
||||||
{{ incentive.attributeName.value }}
|
|
||||||
</td>
|
|
||||||
</ng-container>
|
|
||||||
|
|
||||||
<ng-container matColumnDef="conditionType">
|
|
||||||
<th mat-header-cell *matHeaderCellDef>{{ 'labels.inputs.Condition Type' | translate }}</th>
|
|
||||||
<td mat-cell *matCellDef="let incentive">
|
|
||||||
{{ incentive.conditionType.value | titlecase }}
|
|
||||||
</td>
|
|
||||||
</ng-container>
|
|
||||||
|
|
||||||
<ng-container matColumnDef="attributeValue">
|
|
||||||
<th mat-header-cell *matHeaderCellDef>{{ 'labels.inputs.Attribute Value' | translate }}</th>
|
|
||||||
<td mat-cell *matCellDef="let incentive" [ngSwitch]="incentive.attributeName">
|
|
||||||
{{ incentive.attributeValueDesc }}
|
|
||||||
</td>
|
|
||||||
</ng-container>
|
|
||||||
|
|
||||||
<ng-container matColumnDef="incentiveType">
|
|
||||||
<th mat-header-cell *matHeaderCellDef>{{ 'labels.inputs.Incentive Type' | translate }}</th>
|
|
||||||
<td mat-cell *matCellDef="let incentive">
|
|
||||||
{{ incentive.incentiveType.value }}
|
|
||||||
</td>
|
|
||||||
</ng-container>
|
|
||||||
|
|
||||||
<ng-container matColumnDef="amount">
|
|
||||||
<th mat-header-cell *matHeaderCellDef>{{ 'labels.inputs.Interest' | translate }}</th>
|
|
||||||
<td mat-cell *matCellDef="let incentive">
|
|
||||||
{{ incentive.amount | formatNumber }}
|
|
||||||
</td>
|
|
||||||
</ng-container>
|
|
||||||
|
|
||||||
<tr mat-header-row *matHeaderRowDef="incentivesDisplayedColumns"></tr>
|
|
||||||
<tr mat-row *matRowDef="let row; columns: incentivesDisplayedColumns"></tr>
|
|
||||||
</table>
|
|
||||||
</mat-card>
|
|
||||||
</div>
|
</div>
|
||||||
</td>
|
|
||||||
</ng-container>
|
|
||||||
|
|
||||||
<tr mat-header-row *matHeaderRowDef="chartSlabsDisplayedColumns"></tr>
|
@if (tenureDays && tenureDays > 0) {
|
||||||
<tr mat-row *matRowDef="let row; columns: chartSlabsDisplayedColumns"></tr>
|
@if (applicableSlab) {
|
||||||
<tr mat-row *matRowDef="let row; columns: chartSlabsIncentivesDisplayedColumns" class="incentives-row"></tr>
|
<div class="tenure-calc__result">
|
||||||
</table>
|
<div class="tenure-calc__result-row">
|
||||||
|
<span class="tenure-calc__result-label">Tenure</span>
|
||||||
|
<span class="tenure-calc__result-value">{{ tenureDays }} Days</span>
|
||||||
|
</div>
|
||||||
|
<div class="tenure-calc__result-row">
|
||||||
|
<span class="tenure-calc__result-label">Applicable Slab</span>
|
||||||
|
<span class="tenure-calc__result-value">{{ applicableSlab.description }}</span>
|
||||||
|
</div>
|
||||||
|
<div class="tenure-calc__result-row tenure-calc__result-row--highlight">
|
||||||
|
<span class="tenure-calc__result-label">Annual Interest Rate</span>
|
||||||
|
<span class="tenure-calc__result-rate">{{ applicableSlab.annualInterestRate | number: '1.2-2' }}%</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
} @else {
|
||||||
|
<div class="tenure-calc__no-match">
|
||||||
|
<i class="fas fa-exclamation-circle"></i>
|
||||||
|
No matching slab found for {{ tenureDays }} days
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
}
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
+99
@@ -6,6 +6,105 @@
|
|||||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
// ── Tenure Calculator ─────────────────────────────────────────────────────────
|
||||||
|
.tenure-calc {
|
||||||
|
border: 1px solid #e2e8f0;
|
||||||
|
border-radius: 10px;
|
||||||
|
overflow: hidden;
|
||||||
|
background: #fff;
|
||||||
|
box-shadow: 0 1px 4px rgb(0 0 0 / 5%);
|
||||||
|
margin-bottom: 1.25rem;
|
||||||
|
|
||||||
|
&__header {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 8px;
|
||||||
|
background: #f0f9ff;
|
||||||
|
border-bottom: 1px solid #bae6fd;
|
||||||
|
padding: 0.65rem 1rem;
|
||||||
|
font-size: 0.85rem;
|
||||||
|
font-weight: 700;
|
||||||
|
color: #0369a1;
|
||||||
|
text-transform: uppercase;
|
||||||
|
letter-spacing: 0.05em;
|
||||||
|
|
||||||
|
i {
|
||||||
|
font-size: 13px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&__body {
|
||||||
|
padding: 1rem 1.25rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
&__input-row {
|
||||||
|
display: flex;
|
||||||
|
align-items: flex-start;
|
||||||
|
gap: 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
&__field {
|
||||||
|
width: 260px;
|
||||||
|
}
|
||||||
|
|
||||||
|
&__result {
|
||||||
|
margin-top: 1rem;
|
||||||
|
border: 1px solid #e0f2fe;
|
||||||
|
border-radius: 8px;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
&__result-row {
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
align-items: center;
|
||||||
|
padding: 0.55rem 1rem;
|
||||||
|
border-bottom: 1px solid #f0f9ff;
|
||||||
|
font-size: 0.88rem;
|
||||||
|
|
||||||
|
&:last-child {
|
||||||
|
border-bottom: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
&--highlight {
|
||||||
|
background: #f0f9ff;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&__result-label {
|
||||||
|
color: #64748b;
|
||||||
|
font-weight: 500;
|
||||||
|
}
|
||||||
|
|
||||||
|
&__result-value {
|
||||||
|
color: #1e293b;
|
||||||
|
font-weight: 600;
|
||||||
|
}
|
||||||
|
|
||||||
|
&__result-rate {
|
||||||
|
font-size: 1.25rem;
|
||||||
|
font-weight: 800;
|
||||||
|
color: #0369a1;
|
||||||
|
}
|
||||||
|
|
||||||
|
&__no-match {
|
||||||
|
margin-top: 0.75rem;
|
||||||
|
padding: 0.6rem 1rem;
|
||||||
|
border-radius: 8px;
|
||||||
|
background: #fef2f2;
|
||||||
|
color: #dc2626;
|
||||||
|
font-size: 0.85rem;
|
||||||
|
font-weight: 600;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 6px;
|
||||||
|
|
||||||
|
i {
|
||||||
|
font-size: 13px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
.margin-t {
|
.margin-t {
|
||||||
margin-top: 2em;
|
margin-top: 2em;
|
||||||
}
|
}
|
||||||
|
|||||||
+19
-1
@@ -7,7 +7,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
/** Angular Imports */
|
/** Angular Imports */
|
||||||
import { Component, OnInit, Input, OnChanges, ViewChild } from '@angular/core';
|
import { Component, OnInit, Input, OnChanges, ViewChild, Output, EventEmitter } from '@angular/core';
|
||||||
import {
|
import {
|
||||||
MatTable,
|
MatTable,
|
||||||
MatColumnDef,
|
MatColumnDef,
|
||||||
@@ -28,6 +28,7 @@ import { DateFormatPipe } from '../../../../pipes/date-format.pipe';
|
|||||||
import { FormatNumberPipe } from '../../../../pipes/format-number.pipe';
|
import { FormatNumberPipe } from '../../../../pipes/format-number.pipe';
|
||||||
import { YesnoPipe } from '../../../../pipes/yesno.pipe';
|
import { YesnoPipe } from '../../../../pipes/yesno.pipe';
|
||||||
import { STANDALONE_SHARED_IMPORTS } from 'app/standalone-shared.module';
|
import { STANDALONE_SHARED_IMPORTS } from 'app/standalone-shared.module';
|
||||||
|
import { FormsModule } from '@angular/forms';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Recurring Deposits Account Interest Rate Chart Step
|
* Recurring Deposits Account Interest Rate Chart Step
|
||||||
@@ -45,6 +46,7 @@ import { STANDALONE_SHARED_IMPORTS } from 'app/standalone-shared.module';
|
|||||||
],
|
],
|
||||||
imports: [
|
imports: [
|
||||||
...STANDALONE_SHARED_IMPORTS,
|
...STANDALONE_SHARED_IMPORTS,
|
||||||
|
FormsModule,
|
||||||
MatTable,
|
MatTable,
|
||||||
MatColumnDef,
|
MatColumnDef,
|
||||||
MatHeaderCellDef,
|
MatHeaderCellDef,
|
||||||
@@ -114,10 +116,26 @@ export class RecurringDepositsAccountInterestRateChartStepComponent implements O
|
|||||||
/** Expand Chart Slab Index used in the view */
|
/** Expand Chart Slab Index used in the view */
|
||||||
expandChartSlabIndex: number;
|
expandChartSlabIndex: number;
|
||||||
|
|
||||||
|
/** Tenure entered by user (in days) */
|
||||||
|
tenureDays: number | null = null;
|
||||||
|
|
||||||
@ViewChild('chartsTable', { static: true }) chartsTableRef: MatTable<Element>;
|
@ViewChild('chartsTable', { static: true }) chartsTableRef: MatTable<Element>;
|
||||||
|
|
||||||
constructor() {}
|
constructor() {}
|
||||||
|
|
||||||
|
/** Find the matching slab for the entered tenure */
|
||||||
|
get applicableSlab(): any | null {
|
||||||
|
if (!this.tenureDays || !this._activeRdVersion?.slabs?.length) return null;
|
||||||
|
const days = this.tenureDays;
|
||||||
|
return (
|
||||||
|
this._activeRdVersion.slabs.find((s: any) => {
|
||||||
|
const from = s.fromPeriod ?? 0;
|
||||||
|
const to = s.toPeriod ?? Infinity;
|
||||||
|
return days >= from && days <= to;
|
||||||
|
}) ?? null
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
ngOnChanges() {
|
ngOnChanges() {
|
||||||
if (this.recurringDepositsAccountProductTemplate) {
|
if (this.recurringDepositsAccountProductTemplate) {
|
||||||
this.interestRateChartData = this.recurringDepositsAccountProductTemplate.accountChart?.chartSlabs ?? [];
|
this.interestRateChartData = this.recurringDepositsAccountProductTemplate.accountChart?.chartSlabs ?? [];
|
||||||
|
|||||||
+265
-137
@@ -7,9 +7,10 @@
|
|||||||
-->
|
-->
|
||||||
|
|
||||||
<div class="preview-wrapper">
|
<div class="preview-wrapper">
|
||||||
<!-- ===================== Details ===================== -->
|
<!-- ══ 1. Account Details ════════════════════════════════════════ -->
|
||||||
<div class="preview-section">
|
<div class="preview-section">
|
||||||
<div class="preview-section__header">
|
<div class="preview-section__header">
|
||||||
|
<i class="fas fa-info-circle preview-section__icon"></i>
|
||||||
<span class="preview-section__title">{{ 'labels.heading.Details' | translate }}</span>
|
<span class="preview-section__title">{{ 'labels.heading.Details' | translate }}</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="preview-body">
|
<div class="preview-body">
|
||||||
@@ -21,12 +22,10 @@
|
|||||||
| find: recurringDepositsAccountTemplate?.productOptions : 'id' : 'name'
|
| find: recurringDepositsAccountTemplate?.productOptions : 'id' : 'name'
|
||||||
}}</span>
|
}}</span>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="preview-field">
|
<div class="preview-field">
|
||||||
<span class="preview-label">{{ 'labels.inputs.Submitted On' | translate }}</span>
|
<span class="preview-label">{{ 'labels.inputs.Submitted On' | translate }}</span>
|
||||||
<span class="preview-value">{{ recurringDepositAccountData?.submittedOnDate | dateFormat }}</span>
|
<span class="preview-value">{{ recurringDepositAccountData?.submittedOnDate | dateFormat }}</span>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="preview-field">
|
<div class="preview-field">
|
||||||
<span class="preview-label">{{ 'labels.inputs.Field Officer' | translate }}</span>
|
<span class="preview-label">{{ 'labels.inputs.Field Officer' | translate }}</span>
|
||||||
<span class="preview-value">{{
|
<span class="preview-value">{{
|
||||||
@@ -34,18 +33,17 @@
|
|||||||
| find: recurringDepositsAccountProductTemplate?.fieldOfficerOptions : 'id' : 'displayName'
|
| find: recurringDepositsAccountProductTemplate?.fieldOfficerOptions : 'id' : 'displayName'
|
||||||
}}</span>
|
}}</span>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@if (recurringDepositAccountData?.externalId) {
|
@if (recurringDepositAccountData?.externalId) {
|
||||||
<div class="preview-field">
|
<div class="preview-field">
|
||||||
<span class="preview-label">{{ 'labels.inputs.External Id' | translate }}</span>
|
<span class="preview-label">{{ 'labels.inputs.External Id' | translate }}</span>
|
||||||
<span class="preview-value">{{ recurringDepositAccountData?.externalId }}</span>
|
<span class="preview-value">{{ recurringDepositAccountData.externalId }}</span>
|
||||||
</div>
|
</div>
|
||||||
}
|
}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- ===================== Product Classification ===================== -->
|
<!-- ══ 2. Product Classification ════════════════════════════════ -->
|
||||||
@if (
|
@if (
|
||||||
recurringDepositsAccountProductTemplate?.accountType ||
|
recurringDepositsAccountProductTemplate?.accountType ||
|
||||||
recurringDepositsAccountProductTemplate?.customerSegment ||
|
recurringDepositsAccountProductTemplate?.customerSegment ||
|
||||||
@@ -57,40 +55,42 @@
|
|||||||
) {
|
) {
|
||||||
<div class="preview-section">
|
<div class="preview-section">
|
||||||
<div class="preview-section__header">
|
<div class="preview-section__header">
|
||||||
|
<i class="fas fa-tags preview-section__icon"></i>
|
||||||
<span class="preview-section__title">Product Classification</span>
|
<span class="preview-section__title">Product Classification</span>
|
||||||
|
<span class="preview-section__badge">From Product</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="preview-body">
|
<div class="preview-body">
|
||||||
<div class="preview-grid preview-grid--three">
|
<div class="preview-grid preview-grid--three">
|
||||||
@if (recurringDepositsAccountProductTemplate?.accountType) {
|
@if (recurringDepositsAccountProductTemplate?.accountType) {
|
||||||
<div class="preview-field">
|
<div class="preview-field">
|
||||||
<span class="preview-label">Account Type</span>
|
<span class="preview-label">Account Type</span>
|
||||||
<span class="preview-value">{{ recurringDepositsAccountProductTemplate?.accountType }}</span>
|
<span class="preview-value">{{ recurringDepositsAccountProductTemplate.accountType }}</span>
|
||||||
</div>
|
</div>
|
||||||
}
|
}
|
||||||
@if (recurringDepositsAccountProductTemplate?.customerSegment) {
|
@if (recurringDepositsAccountProductTemplate?.customerSegment) {
|
||||||
<div class="preview-field">
|
<div class="preview-field">
|
||||||
<span class="preview-label">Customer Segment</span>
|
<span class="preview-label">Customer Segment</span>
|
||||||
<span class="preview-value">{{ recurringDepositsAccountProductTemplate?.customerSegment }}</span>
|
<span class="preview-value">{{ recurringDepositsAccountProductTemplate.customerSegment }}</span>
|
||||||
</div>
|
</div>
|
||||||
}
|
}
|
||||||
@if (recurringDepositsAccountProductTemplate?.productCode) {
|
@if (recurringDepositsAccountProductTemplate?.productCode) {
|
||||||
<div class="preview-field">
|
<div class="preview-field">
|
||||||
<span class="preview-label">Product Code</span>
|
<span class="preview-label">Product Code</span>
|
||||||
<span class="preview-value">{{ recurringDepositsAccountProductTemplate?.productCode }}</span>
|
<span class="preview-value preview-mono">{{ recurringDepositsAccountProductTemplate.productCode }}</span>
|
||||||
</div>
|
</div>
|
||||||
}
|
}
|
||||||
@if (recurringDepositsAccountProductTemplate?.effectiveDate) {
|
@if (recurringDepositsAccountProductTemplate?.effectiveDate) {
|
||||||
<div class="preview-field">
|
<div class="preview-field">
|
||||||
<span class="preview-label">Effective Date</span>
|
<span class="preview-label">Effective Date</span>
|
||||||
<span class="preview-value">{{
|
<span class="preview-value">{{
|
||||||
recurringDepositsAccountProductTemplate?.effectiveDate | dateFormat
|
recurringDepositsAccountProductTemplate.effectiveDate | dateFormat
|
||||||
}}</span>
|
}}</span>
|
||||||
</div>
|
</div>
|
||||||
}
|
}
|
||||||
@if (recurringDepositsAccountProductTemplate?.endDate) {
|
@if (recurringDepositsAccountProductTemplate?.endDate) {
|
||||||
<div class="preview-field">
|
<div class="preview-field">
|
||||||
<span class="preview-label">End Date</span>
|
<span class="preview-label">End Date</span>
|
||||||
<span class="preview-value">{{ recurringDepositsAccountProductTemplate?.endDate | dateFormat }}</span>
|
<span class="preview-value">{{ recurringDepositsAccountProductTemplate.endDate | dateFormat }}</span>
|
||||||
</div>
|
</div>
|
||||||
}
|
}
|
||||||
@if (
|
@if (
|
||||||
@@ -101,9 +101,9 @@
|
|||||||
<span class="preview-label">Introducer Required</span>
|
<span class="preview-label">Introducer Required</span>
|
||||||
<span
|
<span
|
||||||
class="preview-value preview-badge"
|
class="preview-value preview-badge"
|
||||||
[class.preview-badge--yes]="recurringDepositsAccountProductTemplate?.introducerRequired"
|
[class.preview-badge--yes]="recurringDepositsAccountProductTemplate.introducerRequired"
|
||||||
>
|
>
|
||||||
{{ recurringDepositsAccountProductTemplate?.introducerRequired | yesNo }}
|
{{ recurringDepositsAccountProductTemplate.introducerRequired | yesNo }}
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
}
|
}
|
||||||
@@ -115,9 +115,9 @@
|
|||||||
<span class="preview-label">Share Linking Enabled</span>
|
<span class="preview-label">Share Linking Enabled</span>
|
||||||
<span
|
<span
|
||||||
class="preview-value preview-badge"
|
class="preview-value preview-badge"
|
||||||
[class.preview-badge--yes]="recurringDepositsAccountProductTemplate?.shareLinkingEnabled"
|
[class.preview-badge--yes]="recurringDepositsAccountProductTemplate.shareLinkingEnabled"
|
||||||
>
|
>
|
||||||
{{ recurringDepositsAccountProductTemplate?.shareLinkingEnabled | yesNo }}
|
{{ recurringDepositsAccountProductTemplate.shareLinkingEnabled | yesNo }}
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
}
|
}
|
||||||
@@ -126,32 +126,54 @@
|
|||||||
</div>
|
</div>
|
||||||
}
|
}
|
||||||
|
|
||||||
<!-- ===================== Currency ===================== -->
|
<!-- ══ 3. Introducer Details (if selected) ══════════════════════ -->
|
||||||
|
@if (recurringDepositAccountData?.introducerId) {
|
||||||
|
<div class="preview-section">
|
||||||
|
<div class="preview-section__header">
|
||||||
|
<i class="fas fa-user-tie preview-section__icon"></i>
|
||||||
|
<span class="preview-section__title">Introducer Details</span>
|
||||||
|
</div>
|
||||||
|
<div class="preview-body">
|
||||||
|
<div class="preview-grid preview-grid--three">
|
||||||
|
<div class="preview-field">
|
||||||
|
<span class="preview-label">Name</span>
|
||||||
|
<span class="preview-value">{{ recurringDepositAccountData?.introducerName || '—' }}</span>
|
||||||
|
</div>
|
||||||
|
@if (recurringDepositAccountData?.introducerCif) {
|
||||||
|
<div class="preview-field">
|
||||||
|
<span class="preview-label">CIF No</span>
|
||||||
|
<span class="preview-value preview-mono">{{ recurringDepositAccountData.introducerCif }}</span>
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
<div class="preview-field">
|
||||||
|
<span class="preview-label">Client ID</span>
|
||||||
|
<span class="preview-value preview-mono">{{ recurringDepositAccountData.introducerId }}</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
|
||||||
|
<!-- ══ 4. Currency & Account Flags ══════════════════════════════ -->
|
||||||
<div class="preview-section">
|
<div class="preview-section">
|
||||||
<div class="preview-section__header">
|
<div class="preview-section__header">
|
||||||
|
<i class="fas fa-coins preview-section__icon"></i>
|
||||||
<span class="preview-section__title">{{ 'labels.heading.Currency' | translate }}</span>
|
<span class="preview-section__title">{{ 'labels.heading.Currency' | translate }}</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="preview-body">
|
<div class="preview-body">
|
||||||
<div class="preview-grid preview-grid--three">
|
<div class="preview-grid preview-grid--three">
|
||||||
<div class="preview-field">
|
<div class="preview-field">
|
||||||
<span class="preview-label">{{ 'labels.inputs.Currency' | translate }}</span>
|
<span class="preview-label">{{ 'labels.inputs.Currency' | translate }}</span>
|
||||||
<span class="preview-value">{{
|
<span class="preview-value">{{ currencyName }}</span>
|
||||||
recurringDepositsAccountProductTemplate?.currency?.code ||
|
|
||||||
recurringDepositsAccountProductTemplate?.currency?.name ||
|
|
||||||
'—'
|
|
||||||
}}</span>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="preview-field">
|
<div class="preview-field">
|
||||||
<span class="preview-label">{{ 'labels.inputs.Decimal Places' | translate }}</span>
|
<span class="preview-label">{{ 'labels.inputs.Decimal Places' | translate }}</span>
|
||||||
<span class="preview-value">{{ recurringDepositsAccountProductTemplate?.currency?.decimalPlaces }}</span>
|
<span class="preview-value">{{ decimalPlaces }}</span>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="preview-field">
|
<div class="preview-field">
|
||||||
<span class="preview-label">{{ 'labels.inputs.Currency In Multiples Of' | translate }}</span>
|
<span class="preview-label">{{ 'labels.inputs.Currency In Multiples Of' | translate }}</span>
|
||||||
<span class="preview-value">{{ recurringDepositsAccountProductTemplate?.currency?.inMultiplesOf }}</span>
|
<span class="preview-value">{{ inMultiplesOf }}</span>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@if (recurringDepositsAccountProductTemplate?.withHoldTax) {
|
@if (recurringDepositsAccountProductTemplate?.withHoldTax) {
|
||||||
<div class="preview-field">
|
<div class="preview-field">
|
||||||
<span class="preview-label">{{ 'labels.inputs.Is Withhold Tax Applicable' | translate }}</span>
|
<span class="preview-label">{{ 'labels.inputs.Is Withhold Tax Applicable' | translate }}</span>
|
||||||
@@ -163,14 +185,30 @@
|
|||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
}
|
}
|
||||||
|
|
||||||
@if (recurringDepositAccountData?.withHoldTax && recurringDepositsAccountProductTemplate?.taxGroup?.name) {
|
@if (recurringDepositAccountData?.withHoldTax && recurringDepositsAccountProductTemplate?.taxGroup?.name) {
|
||||||
<div class="preview-field">
|
<div class="preview-field">
|
||||||
<span class="preview-label">{{ 'labels.inputs.Tax Group' | translate }}</span>
|
<span class="preview-label">{{ 'labels.inputs.Tax Group' | translate }}</span>
|
||||||
<span class="preview-value">{{ recurringDepositsAccountProductTemplate?.taxGroup?.name }}</span>
|
<span class="preview-value">{{ recurringDepositsAccountProductTemplate.taxGroup.name }}</span>
|
||||||
</div>
|
</div>
|
||||||
}
|
}
|
||||||
|
<div class="preview-field">
|
||||||
|
<span class="preview-label">Balance Swap Option</span>
|
||||||
|
<span class="preview-value preview-badge" [class.preview-badge--yes]="rdCurrencyFlags?.balanceSwapOption">
|
||||||
|
{{ rdCurrencyFlags?.balanceSwapOption | yesNo }}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
<div class="preview-field">
|
||||||
|
<span class="preview-label">MSME</span>
|
||||||
|
<span class="preview-value preview-badge" [class.preview-badge--yes]="rdCurrencyFlags?.msme">
|
||||||
|
{{ rdCurrencyFlags?.msme | yesNo }}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
<div class="preview-field">
|
||||||
|
<span class="preview-label">Auto Debit Facility</span>
|
||||||
|
<span class="preview-value preview-badge" [class.preview-badge--yes]="rdCurrencyFlags?.autoDebitFacility">
|
||||||
|
{{ rdCurrencyFlags?.autoDebitFacility | yesNo }}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
@if (
|
@if (
|
||||||
recurringDepositsAccountProductTemplate?.dormancyAlert !== undefined &&
|
recurringDepositsAccountProductTemplate?.dormancyAlert !== undefined &&
|
||||||
recurringDepositsAccountProductTemplate?.dormancyAlert !== null
|
recurringDepositsAccountProductTemplate?.dormancyAlert !== null
|
||||||
@@ -179,43 +217,12 @@
|
|||||||
<span class="preview-label">Dormancy Alert</span>
|
<span class="preview-label">Dormancy Alert</span>
|
||||||
<span
|
<span
|
||||||
class="preview-value preview-badge"
|
class="preview-value preview-badge"
|
||||||
[class.preview-badge--yes]="recurringDepositsAccountProductTemplate?.dormancyAlert"
|
[class.preview-badge--yes]="recurringDepositsAccountProductTemplate.dormancyAlert"
|
||||||
>
|
>
|
||||||
{{ recurringDepositsAccountProductTemplate?.dormancyAlert | yesNo }}
|
{{ recurringDepositsAccountProductTemplate.dormancyAlert | yesNo }}
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
}
|
}
|
||||||
|
|
||||||
@if (
|
|
||||||
recurringDepositsAccountProductTemplate?.balanceSwapOption !== undefined &&
|
|
||||||
recurringDepositsAccountProductTemplate?.balanceSwapOption !== null
|
|
||||||
) {
|
|
||||||
<div class="preview-field">
|
|
||||||
<span class="preview-label">Balance Swap Option</span>
|
|
||||||
<span
|
|
||||||
class="preview-value preview-badge"
|
|
||||||
[class.preview-badge--yes]="recurringDepositsAccountProductTemplate?.balanceSwapOption"
|
|
||||||
>
|
|
||||||
{{ recurringDepositsAccountProductTemplate?.balanceSwapOption | yesNo }}
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
}
|
|
||||||
|
|
||||||
@if (
|
|
||||||
recurringDepositsAccountProductTemplate?.msme !== undefined &&
|
|
||||||
recurringDepositsAccountProductTemplate?.msme !== null
|
|
||||||
) {
|
|
||||||
<div class="preview-field">
|
|
||||||
<span class="preview-label">MSME</span>
|
|
||||||
<span
|
|
||||||
class="preview-value preview-badge"
|
|
||||||
[class.preview-badge--yes]="recurringDepositsAccountProductTemplate?.msme"
|
|
||||||
>
|
|
||||||
{{ recurringDepositsAccountProductTemplate?.msme | yesNo }}
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
}
|
|
||||||
|
|
||||||
@if (
|
@if (
|
||||||
recurringDepositsAccountProductTemplate?.nominationFacility !== undefined &&
|
recurringDepositsAccountProductTemplate?.nominationFacility !== undefined &&
|
||||||
recurringDepositsAccountProductTemplate?.nominationFacility !== null
|
recurringDepositsAccountProductTemplate?.nominationFacility !== null
|
||||||
@@ -224,24 +231,9 @@
|
|||||||
<span class="preview-label">Nomination Facility</span>
|
<span class="preview-label">Nomination Facility</span>
|
||||||
<span
|
<span
|
||||||
class="preview-value preview-badge"
|
class="preview-value preview-badge"
|
||||||
[class.preview-badge--yes]="recurringDepositsAccountProductTemplate?.nominationFacility"
|
[class.preview-badge--yes]="recurringDepositsAccountProductTemplate.nominationFacility"
|
||||||
>
|
>
|
||||||
{{ recurringDepositsAccountProductTemplate?.nominationFacility | yesNo }}
|
{{ recurringDepositsAccountProductTemplate.nominationFacility | yesNo }}
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
}
|
|
||||||
|
|
||||||
@if (
|
|
||||||
recurringDepositsAccountProductTemplate?.autoDebitFacility !== undefined &&
|
|
||||||
recurringDepositsAccountProductTemplate?.autoDebitFacility !== null
|
|
||||||
) {
|
|
||||||
<div class="preview-field">
|
|
||||||
<span class="preview-label">Auto Debit Facility</span>
|
|
||||||
<span
|
|
||||||
class="preview-value preview-badge"
|
|
||||||
[class.preview-badge--yes]="recurringDepositsAccountProductTemplate?.autoDebitFacility"
|
|
||||||
>
|
|
||||||
{{ recurringDepositsAccountProductTemplate?.autoDebitFacility | yesNo }}
|
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
}
|
}
|
||||||
@@ -249,93 +241,235 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- ===================== Interest Rate Chart ===================== -->
|
<!-- ══ 5. Dormancy Monitoring ════════════════════════════════════ -->
|
||||||
|
@if (
|
||||||
|
recurringDepositsAccountProductTemplate?.dormancyAlert ||
|
||||||
|
recurringDepositsAccountProductTemplate?.isDormancyTrackingActiveFromProduct
|
||||||
|
) {
|
||||||
|
<div class="preview-section">
|
||||||
|
<div class="preview-section__header">
|
||||||
|
<i class="fas fa-moon preview-section__icon"></i>
|
||||||
|
<span class="preview-section__title">Dormancy Monitoring</span>
|
||||||
|
<span
|
||||||
|
class="preview-section__badge"
|
||||||
|
[class.preview-section__badge--active]="
|
||||||
|
recurringDepositsAccountProductTemplate?.isDormancyTrackingActiveFromProduct
|
||||||
|
"
|
||||||
|
>
|
||||||
|
{{ recurringDepositsAccountProductTemplate?.isDormancyTrackingActiveFromProduct ? 'Active' : 'Inactive' }}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
<div class="preview-body">
|
||||||
|
<div class="preview-dormancy-timeline">
|
||||||
|
<div class="preview-dorm-step">
|
||||||
|
<div class="preview-dorm-step__dot preview-dorm-step__dot--inactive"></div>
|
||||||
|
<div class="preview-dorm-step__body">
|
||||||
|
<span class="preview-dorm-step__label">Inactive</span>
|
||||||
|
<span class="preview-dorm-step__days">
|
||||||
|
@if (recurringDepositsAccountProductTemplate?.daysToInactiveFromProduct != null) {
|
||||||
|
After {{ recurringDepositsAccountProductTemplate.daysToInactiveFromProduct }} days of no transaction
|
||||||
|
} @else {
|
||||||
|
Not configured
|
||||||
|
}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="preview-dorm-connector"></div>
|
||||||
|
<div class="preview-dorm-step">
|
||||||
|
<div class="preview-dorm-step__dot preview-dorm-step__dot--dormant"></div>
|
||||||
|
<div class="preview-dorm-step__body">
|
||||||
|
<span class="preview-dorm-step__label">Dormant</span>
|
||||||
|
<span class="preview-dorm-step__days">
|
||||||
|
@if (recurringDepositsAccountProductTemplate?.daysToDormancyFromProduct != null) {
|
||||||
|
{{ recurringDepositsAccountProductTemplate.daysToDormancyFromProduct }} days after inactive
|
||||||
|
} @else {
|
||||||
|
Not configured
|
||||||
|
}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="preview-dorm-connector"></div>
|
||||||
|
<div class="preview-dorm-step">
|
||||||
|
<div class="preview-dorm-step__dot preview-dorm-step__dot--escheat"></div>
|
||||||
|
<div class="preview-dorm-step__body">
|
||||||
|
<span class="preview-dorm-step__label">Escheat</span>
|
||||||
|
<span class="preview-dorm-step__days">
|
||||||
|
@if (recurringDepositsAccountProductTemplate?.daysToEscheatFromProduct != null) {
|
||||||
|
{{ recurringDepositsAccountProductTemplate.daysToEscheatFromProduct }} days after dormant
|
||||||
|
} @else {
|
||||||
|
Not configured
|
||||||
|
}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="preview-dorm-flags">
|
||||||
|
<span
|
||||||
|
class="preview-dorm-flag"
|
||||||
|
[class.preview-dorm-flag--on]="recurringDepositsAccountProductTemplate?.dormancyAlert"
|
||||||
|
>
|
||||||
|
<i class="fas fa-bell"></i> Alert
|
||||||
|
{{ recurringDepositsAccountProductTemplate?.dormancyAlert ? 'Enabled' : 'Disabled' }}
|
||||||
|
</span>
|
||||||
|
<span
|
||||||
|
class="preview-dorm-flag"
|
||||||
|
[class.preview-dorm-flag--on]="recurringDepositsAccountProductTemplate?.isDormancyTrackingActiveFromProduct"
|
||||||
|
>
|
||||||
|
<i class="fas fa-eye"></i> Tracking
|
||||||
|
{{ recurringDepositsAccountProductTemplate?.isDormancyTrackingActiveFromProduct ? 'Active' : 'Inactive' }}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
|
||||||
|
<!-- ══ 6. Nominee Details (if filled) ═══════════════════════════ -->
|
||||||
|
@if (rdNominee) {
|
||||||
|
<div class="preview-section">
|
||||||
|
<div class="preview-section__header">
|
||||||
|
<i class="fas fa-user-shield preview-section__icon"></i>
|
||||||
|
<span class="preview-section__title">Nominee Details</span>
|
||||||
|
<span class="preview-section__badge">
|
||||||
|
{{ rdNominee?.mode === 'linked' ? 'Linked Client' : 'Manual Entry' }}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
<div class="preview-body">
|
||||||
|
<div class="preview-grid preview-grid--three">
|
||||||
|
<div class="preview-field">
|
||||||
|
<span class="preview-label">Name</span>
|
||||||
|
<span class="preview-value">{{ rdNominee?.fullName || rdNominee?.displayName || '—' }}</span>
|
||||||
|
</div>
|
||||||
|
@if (rdNominee?.cifNumber) {
|
||||||
|
<div class="preview-field">
|
||||||
|
<span class="preview-label">CIF No</span>
|
||||||
|
<span class="preview-value preview-mono">{{ rdNominee.cifNumber }}</span>
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
<div class="preview-field">
|
||||||
|
<span class="preview-label">Relationship</span>
|
||||||
|
<span class="preview-value">{{ rdNominee?.relationship || '—' }}</span>
|
||||||
|
</div>
|
||||||
|
<div class="preview-field">
|
||||||
|
<span class="preview-label">Share %</span>
|
||||||
|
<span class="preview-value">{{ rdNominee?.nomineeShare ?? '—' }}%</span>
|
||||||
|
</div>
|
||||||
|
@if (rdNominee?.dateOfBirth) {
|
||||||
|
<div class="preview-field">
|
||||||
|
<span class="preview-label">Date of Birth</span>
|
||||||
|
<span class="preview-value">{{ rdNominee?.dateOfBirth | dateFormat }}</span>
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
@if (rdNominee?.nationality) {
|
||||||
|
<div class="preview-field">
|
||||||
|
<span class="preview-label">Nationality</span>
|
||||||
|
<span class="preview-value">{{ rdNominee.nationality }}</span>
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
@if (rdNominee?.mobileNo) {
|
||||||
|
<div class="preview-field">
|
||||||
|
<span class="preview-label">Mobile No</span>
|
||||||
|
<span class="preview-value preview-mono">{{ rdNominee.mobileNo }}</span>
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
@if (rdNominee?.aadhaarNumber) {
|
||||||
|
<div class="preview-field">
|
||||||
|
<span class="preview-label">Aadhaar No</span>
|
||||||
|
<span class="preview-value preview-mono">{{ rdNominee.aadhaarNumber }}</span>
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
@if (rdNominee?.panNumber) {
|
||||||
|
<div class="preview-field">
|
||||||
|
<span class="preview-label">PAN No</span>
|
||||||
|
<span class="preview-value preview-mono">{{ rdNominee.panNumber }}</span>
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
@if (rdNominee?.guardianName) {
|
||||||
|
<div class="preview-field">
|
||||||
|
<span class="preview-label">Guardian Name</span>
|
||||||
|
<span class="preview-value">{{ rdNominee.guardianName }}</span>
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
@if (rdNominee?.guardianRelationship) {
|
||||||
|
<div class="preview-field">
|
||||||
|
<span class="preview-label">Guardian Relationship</span>
|
||||||
|
<span class="preview-value">{{ rdNominee.guardianRelationship }}</span>
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
@if (rdNominee?.remarks) {
|
||||||
|
<div class="preview-field">
|
||||||
|
<span class="preview-label">Remarks</span>
|
||||||
|
<span class="preview-value">{{ rdNominee.remarks }}</span>
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
|
||||||
|
<!-- ══ 7. Interest Rate (Tenure-based result) ════════════════════ -->
|
||||||
@if (_activeRdVersion || recurringDepositsAccountProductTemplate?.accountChart) {
|
@if (_activeRdVersion || recurringDepositsAccountProductTemplate?.accountChart) {
|
||||||
<div class="preview-section">
|
<div class="preview-section">
|
||||||
<div class="preview-section__header">
|
<div class="preview-section__header">
|
||||||
<span class="preview-section__title">{{ 'labels.inputs.Interest Rate Chart' | translate }}</span>
|
<i class="fas fa-chart-line preview-section__icon"></i>
|
||||||
|
<span class="preview-section__title">Interest Rate</span>
|
||||||
|
@if (_activeRdVersion) {
|
||||||
|
<span class="preview-section__badge">{{ _activeRdVersion.versionLabel }}</span>
|
||||||
|
}
|
||||||
</div>
|
</div>
|
||||||
<div class="preview-body">
|
<div class="preview-body">
|
||||||
@if (_activeRdVersion) {
|
@if (_activeRdVersion) {
|
||||||
<div class="preview-grid preview-grid--three">
|
@if (rdTenureDays && rdApplicableSlab) {
|
||||||
<div class="preview-field">
|
<div class="preview-tenure-result">
|
||||||
<span class="preview-label">Version</span>
|
<div class="preview-tenure-result__row">
|
||||||
<span class="preview-value">{{ _activeRdVersion.versionLabel }}</span>
|
<span class="preview-label">Tenure</span>
|
||||||
|
<span class="preview-value">{{ rdTenureDays }} Days</span>
|
||||||
|
</div>
|
||||||
|
<div class="preview-tenure-result__row">
|
||||||
|
<span class="preview-label">Applicable Slab</span>
|
||||||
|
<span class="preview-value">{{ rdApplicableSlab.description }}</span>
|
||||||
|
</div>
|
||||||
|
<div class="preview-tenure-result__row preview-tenure-result__row--highlight">
|
||||||
|
<span class="preview-label">Annual Interest Rate</span>
|
||||||
|
<span class="preview-tenure-result__rate"
|
||||||
|
>{{ rdApplicableSlab.annualInterestRate | formatNumber }}%</span
|
||||||
|
>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="preview-field">
|
} @else {
|
||||||
<span class="preview-label">Active</span>
|
<span class="preview-muted">No tenure entered — interest rate not calculated</span>
|
||||||
<span class="preview-value preview-badge preview-badge--yes">Yes</span>
|
}
|
||||||
</div>
|
|
||||||
<div class="preview-field">
|
|
||||||
<span class="preview-label">Effective From</span>
|
|
||||||
<span class="preview-value">{{ _activeRdVersion.effectiveFromDate }}</span>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<table class="mat-elevation-z1 irc-table preview-table" mat-table [dataSource]="_activeRdVersion.slabs">
|
|
||||||
<ng-container matColumnDef="srNo">
|
|
||||||
<th mat-header-cell *matHeaderCellDef>Sr.</th>
|
|
||||||
<td mat-cell *matCellDef="let slab">{{ slab.srNo }}</td>
|
|
||||||
</ng-container>
|
|
||||||
<ng-container matColumnDef="description">
|
|
||||||
<th mat-header-cell *matHeaderCellDef>Particular</th>
|
|
||||||
<td mat-cell *matCellDef="let slab">{{ slab.description }}</td>
|
|
||||||
</ng-container>
|
|
||||||
<ng-container matColumnDef="fromPeriod">
|
|
||||||
<th mat-header-cell *matHeaderCellDef>From</th>
|
|
||||||
<td mat-cell *matCellDef="let slab">{{ slab.fromPeriod }}</td>
|
|
||||||
</ng-container>
|
|
||||||
<ng-container matColumnDef="toPeriod">
|
|
||||||
<th mat-header-cell *matHeaderCellDef>To</th>
|
|
||||||
<td mat-cell *matCellDef="let slab">{{ slab.toPeriod ?? 'Unassigned' }}</td>
|
|
||||||
</ng-container>
|
|
||||||
<ng-container matColumnDef="periodTypeLabel">
|
|
||||||
<th mat-header-cell *matHeaderCellDef>Period Type</th>
|
|
||||||
<td mat-cell *matCellDef="let slab">{{ slab.periodTypeLabel }}</td>
|
|
||||||
</ng-container>
|
|
||||||
<ng-container matColumnDef="annualInterestRate">
|
|
||||||
<th mat-header-cell *matHeaderCellDef>Annual Rate (%)</th>
|
|
||||||
<td mat-cell *matCellDef="let slab">{{ slab.annualInterestRate | formatNumber }}</td>
|
|
||||||
</ng-container>
|
|
||||||
<tr mat-header-row *matHeaderRowDef="rdSlabColumns"></tr>
|
|
||||||
<tr mat-row *matRowDef="let row; columns: rdSlabColumns"></tr>
|
|
||||||
</table>
|
|
||||||
} @else {
|
} @else {
|
||||||
<div class="preview-grid preview-grid--three">
|
<div class="preview-grid preview-grid--three">
|
||||||
@if (recurringDepositsAccountProductTemplate?.accountChart?.name) {
|
@if (recurringDepositsAccountProductTemplate?.accountChart?.name) {
|
||||||
<div class="preview-field">
|
<div class="preview-field">
|
||||||
<span class="preview-label">{{ 'labels.inputs.name' | translate }}</span>
|
<span class="preview-label">{{ 'labels.inputs.name' | translate }}</span>
|
||||||
<span class="preview-value">{{ recurringDepositsAccountProductTemplate?.accountChart?.name }}</span>
|
<span class="preview-value">{{ recurringDepositsAccountProductTemplate.accountChart.name }}</span>
|
||||||
</div>
|
</div>
|
||||||
}
|
}
|
||||||
|
|
||||||
@if (recurringDepositsAccountProductTemplate?.accountChart?.fromDate) {
|
@if (recurringDepositsAccountProductTemplate?.accountChart?.fromDate) {
|
||||||
<div class="preview-field">
|
<div class="preview-field">
|
||||||
<span class="preview-label">{{ 'labels.inputs.Valid from Date' | translate }}</span>
|
<span class="preview-label">{{ 'labels.inputs.Valid from Date' | translate }}</span>
|
||||||
<span class="preview-value">{{
|
<span class="preview-value">{{
|
||||||
recurringDepositsAccountProductTemplate?.accountChart?.fromDate | dateFormat
|
recurringDepositsAccountProductTemplate.accountChart.fromDate | dateFormat
|
||||||
}}</span>
|
}}</span>
|
||||||
</div>
|
</div>
|
||||||
}
|
}
|
||||||
|
|
||||||
@if (recurringDepositsAccountProductTemplate?.accountChart?.endDate) {
|
@if (recurringDepositsAccountProductTemplate?.accountChart?.endDate) {
|
||||||
<div class="preview-field">
|
<div class="preview-field">
|
||||||
<span class="preview-label">{{ 'labels.inputs.End Date' | translate }}</span>
|
<span class="preview-label">{{ 'labels.inputs.End Date' | translate }}</span>
|
||||||
<span class="preview-value">{{
|
<span class="preview-value">{{
|
||||||
recurringDepositsAccountProductTemplate?.accountChart?.endDate | dateFormat
|
recurringDepositsAccountProductTemplate.accountChart.endDate | dateFormat
|
||||||
}}</span>
|
}}</span>
|
||||||
</div>
|
</div>
|
||||||
}
|
}
|
||||||
|
|
||||||
@if (recurringDepositsAccountProductTemplate?.accountChart?.description) {
|
@if (recurringDepositsAccountProductTemplate?.accountChart?.description) {
|
||||||
<div class="preview-field">
|
<div class="preview-field">
|
||||||
<span class="preview-label">{{ 'labels.inputs.Description' | translate }}</span>
|
<span class="preview-label">{{ 'labels.inputs.Description' | translate }}</span>
|
||||||
<span class="preview-value">{{
|
<span class="preview-value">{{
|
||||||
recurringDepositsAccountProductTemplate?.accountChart?.description
|
recurringDepositsAccountProductTemplate.accountChart.description
|
||||||
}}</span>
|
}}</span>
|
||||||
</div>
|
</div>
|
||||||
}
|
}
|
||||||
|
|
||||||
<div class="preview-field">
|
<div class="preview-field">
|
||||||
<span class="preview-label">{{ 'labels.inputs.Primary Grouping by Amount' | translate }}</span>
|
<span class="preview-label">{{ 'labels.inputs.Primary Grouping by Amount' | translate }}</span>
|
||||||
<span class="preview-value">{{
|
<span class="preview-value">{{
|
||||||
@@ -359,24 +493,20 @@
|
|||||||
}}
|
}}
|
||||||
</td>
|
</td>
|
||||||
</ng-container>
|
</ng-container>
|
||||||
|
|
||||||
<ng-container matColumnDef="amountRange">
|
<ng-container matColumnDef="amountRange">
|
||||||
<th mat-header-cell *matHeaderCellDef>{{ 'labels.inputs.Amount Range' | translate }}</th>
|
<th mat-header-cell *matHeaderCellDef>{{ 'labels.inputs.Amount Range' | translate }}</th>
|
||||||
<td mat-cell *matCellDef="let chartSlab">
|
<td mat-cell *matCellDef="let chartSlab">
|
||||||
{{ chartSlab.amountRangeFrom | formatNumber }} - {{ chartSlab.amountRangeTo | formatNumber }}
|
{{ chartSlab.amountRangeFrom | formatNumber }} - {{ chartSlab.amountRangeTo | formatNumber }}
|
||||||
</td>
|
</td>
|
||||||
</ng-container>
|
</ng-container>
|
||||||
|
|
||||||
<ng-container matColumnDef="interest">
|
<ng-container matColumnDef="interest">
|
||||||
<th mat-header-cell *matHeaderCellDef>{{ 'labels.inputs.Interest' | translate }}</th>
|
<th mat-header-cell *matHeaderCellDef>{{ 'labels.inputs.Interest' | translate }}</th>
|
||||||
<td mat-cell *matCellDef="let chartSlab">{{ chartSlab.annualInterestRate | formatNumber }} %</td>
|
<td mat-cell *matCellDef="let chartSlab">{{ chartSlab.annualInterestRate | formatNumber }} %</td>
|
||||||
</ng-container>
|
</ng-container>
|
||||||
|
|
||||||
<ng-container matColumnDef="description">
|
<ng-container matColumnDef="description">
|
||||||
<th mat-header-cell *matHeaderCellDef>{{ 'labels.inputs.Description' | translate }}</th>
|
<th mat-header-cell *matHeaderCellDef>{{ 'labels.inputs.Description' | translate }}</th>
|
||||||
<td mat-cell *matCellDef="let chartSlab">{{ chartSlab.description }}</td>
|
<td mat-cell *matCellDef="let chartSlab">{{ chartSlab.description }}</td>
|
||||||
</ng-container>
|
</ng-container>
|
||||||
|
|
||||||
<ng-container matColumnDef="actions">
|
<ng-container matColumnDef="actions">
|
||||||
<th mat-header-cell *matHeaderCellDef>{{ 'labels.inputs.Actions' | translate }}</th>
|
<th mat-header-cell *matHeaderCellDef>{{ 'labels.inputs.Actions' | translate }}</th>
|
||||||
<td mat-cell *matCellDef="let chartSlab; let chartSlabIndex = dataIndex">
|
<td mat-cell *matCellDef="let chartSlab; let chartSlabIndex = dataIndex">
|
||||||
@@ -396,7 +526,6 @@
|
|||||||
</button>
|
</button>
|
||||||
</td>
|
</td>
|
||||||
</ng-container>
|
</ng-container>
|
||||||
|
|
||||||
<ng-container matColumnDef="incentives">
|
<ng-container matColumnDef="incentives">
|
||||||
<td
|
<td
|
||||||
mat-cell
|
mat-cell
|
||||||
@@ -446,7 +575,6 @@
|
|||||||
</div>
|
</div>
|
||||||
</td>
|
</td>
|
||||||
</ng-container>
|
</ng-container>
|
||||||
|
|
||||||
<tr mat-header-row *matHeaderRowDef="chartSlabsDisplayedColumns"></tr>
|
<tr mat-header-row *matHeaderRowDef="chartSlabsDisplayedColumns"></tr>
|
||||||
<tr mat-row *matRowDef="let row; columns: chartSlabsDisplayedColumns"></tr>
|
<tr mat-row *matRowDef="let row; columns: chartSlabsDisplayedColumns"></tr>
|
||||||
<tr
|
<tr
|
||||||
|
|||||||
+193
@@ -23,18 +23,48 @@
|
|||||||
box-shadow: 0 1px 3px rgb(0 0 0 / 6%);
|
box-shadow: 0 1px 3px rgb(0 0 0 / 6%);
|
||||||
|
|
||||||
&__header {
|
&__header {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 8px;
|
||||||
background: #f5f5f5;
|
background: #f5f5f5;
|
||||||
border-bottom: 1px solid #e0e0e0;
|
border-bottom: 1px solid #e0e0e0;
|
||||||
padding: 0.6rem 1rem;
|
padding: 0.6rem 1rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
&__icon {
|
||||||
|
font-size: 13px;
|
||||||
|
color: #0ea5e9;
|
||||||
|
width: 16px;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
&__title {
|
&__title {
|
||||||
|
flex: 1;
|
||||||
font-size: 0.95rem;
|
font-size: 0.95rem;
|
||||||
font-weight: 600;
|
font-weight: 600;
|
||||||
color: #333;
|
color: #333;
|
||||||
text-transform: uppercase;
|
text-transform: uppercase;
|
||||||
letter-spacing: 0.04em;
|
letter-spacing: 0.04em;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
&__badge {
|
||||||
|
display: inline-flex;
|
||||||
|
align-items: center;
|
||||||
|
padding: 2px 10px;
|
||||||
|
border-radius: 999px;
|
||||||
|
font-size: 10px;
|
||||||
|
font-weight: 700;
|
||||||
|
background: #dbeafe;
|
||||||
|
color: #1d4ed8;
|
||||||
|
border: 1px solid #bfdbfe;
|
||||||
|
text-transform: uppercase;
|
||||||
|
|
||||||
|
&--active {
|
||||||
|
background: #dcfce7 !important;
|
||||||
|
color: #15803d !important;
|
||||||
|
border-color: #bbf7d0 !important;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// ── Body ─────────────────────────────────────────────────────────────────────
|
// ── Body ─────────────────────────────────────────────────────────────────────
|
||||||
@@ -146,6 +176,169 @@
|
|||||||
margin-top: 1em;
|
margin-top: 1em;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ── Preview Tenure Result Card ─────────────────────────────────────────────────
|
||||||
|
.preview-tenure-result {
|
||||||
|
border: 1px solid #e0f2fe;
|
||||||
|
border-radius: 10px;
|
||||||
|
overflow: hidden;
|
||||||
|
|
||||||
|
&__row {
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
align-items: center;
|
||||||
|
padding: 0.65rem 1rem;
|
||||||
|
border-bottom: 1px solid #f0f9ff;
|
||||||
|
|
||||||
|
&:last-child {
|
||||||
|
border-bottom: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
&--highlight {
|
||||||
|
background: #f0f9ff;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&__rate {
|
||||||
|
font-size: 1.5rem;
|
||||||
|
font-weight: 800;
|
||||||
|
color: #0369a1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ── Misc ──────────────────────────────────────────────────────────────────────
|
||||||
|
.preview-muted {
|
||||||
|
color: #94a3b8;
|
||||||
|
font-style: italic;
|
||||||
|
}
|
||||||
|
|
||||||
|
.preview-mono {
|
||||||
|
font-family: monospace;
|
||||||
|
font-size: 0.88rem;
|
||||||
|
color: #334155;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ── Dormancy timeline ─────────────────────────────────────────────────────────
|
||||||
|
.preview-dormancy-timeline {
|
||||||
|
display: flex;
|
||||||
|
align-items: flex-start;
|
||||||
|
margin-bottom: 14px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.preview-dorm-step {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
gap: 6px;
|
||||||
|
flex: 1;
|
||||||
|
|
||||||
|
&__dot {
|
||||||
|
width: 36px;
|
||||||
|
height: 36px;
|
||||||
|
border-radius: 50%;
|
||||||
|
border: 3px solid;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
flex-shrink: 0;
|
||||||
|
|
||||||
|
&--inactive {
|
||||||
|
border-color: #f59e0b;
|
||||||
|
background: #fffbeb;
|
||||||
|
|
||||||
|
&::after {
|
||||||
|
content: '';
|
||||||
|
width: 10px;
|
||||||
|
height: 10px;
|
||||||
|
border-radius: 50%;
|
||||||
|
background: #f59e0b;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&--dormant {
|
||||||
|
border-color: #ef4444;
|
||||||
|
background: #fef2f2;
|
||||||
|
|
||||||
|
&::after {
|
||||||
|
content: '';
|
||||||
|
width: 10px;
|
||||||
|
height: 10px;
|
||||||
|
border-radius: 50%;
|
||||||
|
background: #ef4444;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&--escheat {
|
||||||
|
border-color: #7c3aed;
|
||||||
|
background: #f5f3ff;
|
||||||
|
|
||||||
|
&::after {
|
||||||
|
content: '';
|
||||||
|
width: 10px;
|
||||||
|
height: 10px;
|
||||||
|
border-radius: 50%;
|
||||||
|
background: #7c3aed;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&__body {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
text-align: center;
|
||||||
|
gap: 2px;
|
||||||
|
}
|
||||||
|
|
||||||
|
&__label {
|
||||||
|
font-size: 12px;
|
||||||
|
font-weight: 700;
|
||||||
|
color: #1e293b;
|
||||||
|
}
|
||||||
|
|
||||||
|
&__days {
|
||||||
|
font-size: 10.5px;
|
||||||
|
color: #64748b;
|
||||||
|
line-height: 1.3;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.preview-dorm-connector {
|
||||||
|
flex: 0 0 40px;
|
||||||
|
height: 3px;
|
||||||
|
background: linear-gradient(90deg, #e2e8f0, #cbd5e1);
|
||||||
|
margin-top: 16px;
|
||||||
|
border-radius: 2px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.preview-dorm-flags {
|
||||||
|
display: flex;
|
||||||
|
gap: 10px;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
}
|
||||||
|
|
||||||
|
.preview-dorm-flag {
|
||||||
|
display: inline-flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 5px;
|
||||||
|
padding: 4px 12px;
|
||||||
|
border-radius: 20px;
|
||||||
|
font-size: 11.5px;
|
||||||
|
font-weight: 600;
|
||||||
|
background: #f1f5f9;
|
||||||
|
color: #94a3b8;
|
||||||
|
border: 1px solid #e2e8f0;
|
||||||
|
|
||||||
|
i {
|
||||||
|
font-size: 11px;
|
||||||
|
}
|
||||||
|
|
||||||
|
&--on {
|
||||||
|
background: #f0fdf4;
|
||||||
|
color: #15803d;
|
||||||
|
border-color: #bbf7d0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// ── Product feature flag rows (same style as details step) ────────────────────
|
// ── Product feature flag rows (same style as details step) ────────────────────
|
||||||
.preview-feature-list {
|
.preview-feature-list {
|
||||||
margin-top: 1rem;
|
margin-top: 1rem;
|
||||||
|
|||||||
+16
@@ -73,6 +73,10 @@ export class RecurringDepositsAccountPreviewStepComponent implements OnChanges {
|
|||||||
@Input() recurringDepositsAccountTemplate: any;
|
@Input() recurringDepositsAccountTemplate: any;
|
||||||
@Input() recurringDepositsAccountProductTemplate: any;
|
@Input() recurringDepositsAccountProductTemplate: any;
|
||||||
@Input() recurringDepositAccountData: any;
|
@Input() recurringDepositAccountData: any;
|
||||||
|
@Input() rdNominee: any = null;
|
||||||
|
@Input() rdCurrencyFlags: any = null;
|
||||||
|
@Input() rdTenureDays: number | null = null;
|
||||||
|
@Input() rdApplicableSlab: any = null;
|
||||||
@Input() set rdInterestRates(rates: any[]) {
|
@Input() set rdInterestRates(rates: any[]) {
|
||||||
this._rdInterestRates = rates || [];
|
this._rdInterestRates = rates || [];
|
||||||
this._activeRdVersion = this._rdInterestRates.find((v: any) => v.isActive) ?? this._rdInterestRates[0] ?? null;
|
this._activeRdVersion = this._rdInterestRates.find((v: any) => v.isActive) ?? this._rdInterestRates[0] ?? null;
|
||||||
@@ -80,6 +84,18 @@ export class RecurringDepositsAccountPreviewStepComponent implements OnChanges {
|
|||||||
/** Output the submit action */
|
/** Output the submit action */
|
||||||
@Output() submitEvent = new EventEmitter();
|
@Output() submitEvent = new EventEmitter();
|
||||||
|
|
||||||
|
get currencyName(): string {
|
||||||
|
return this.recurringDepositsAccountProductTemplate?.currency?.name || '—';
|
||||||
|
}
|
||||||
|
|
||||||
|
get decimalPlaces(): string | number {
|
||||||
|
return this.recurringDepositsAccountProductTemplate?.currency?.decimalPlaces ?? '—';
|
||||||
|
}
|
||||||
|
|
||||||
|
get inMultiplesOf(): string | number {
|
||||||
|
return this.recurringDepositsAccountProductTemplate?.currency?.inMultiplesOf ?? '—';
|
||||||
|
}
|
||||||
|
|
||||||
_rdInterestRates: any[] = [];
|
_rdInterestRates: any[] = [];
|
||||||
_activeRdVersion: any = null;
|
_activeRdVersion: any = null;
|
||||||
|
|
||||||
|
|||||||
@@ -92,6 +92,8 @@
|
|||||||
[savingsAccountTemplate]="savingsAccountTemplate"
|
[savingsAccountTemplate]="savingsAccountTemplate"
|
||||||
[savingsAccountTermsForm]="savingsAccountTermsForm"
|
[savingsAccountTermsForm]="savingsAccountTermsForm"
|
||||||
[savingsAccount]="savingsAccount"
|
[savingsAccount]="savingsAccount"
|
||||||
|
[savingsAccountDigital]="savingsAccountDigital"
|
||||||
|
[savingsAccountNominee]="savingsAccountNominee"
|
||||||
(submitEvent)="submit()"
|
(submitEvent)="submit()"
|
||||||
>
|
>
|
||||||
</mifosx-savings-account-preview-step>
|
</mifosx-savings-account-preview-step>
|
||||||
|
|||||||
@@ -15,6 +15,7 @@ import { FormGroup } from '@angular/forms';
|
|||||||
import { SavingsAccountDetailsStepComponent } from '../savings-account-stepper/savings-account-details-step/savings-account-details-step.component';
|
import { SavingsAccountDetailsStepComponent } from '../savings-account-stepper/savings-account-details-step/savings-account-details-step.component';
|
||||||
import { SavingsAccountCurrencyStepComponent } from '../savings-account-stepper/savings-account-currency-step/savings-account-currency-step.component';
|
import { SavingsAccountCurrencyStepComponent } from '../savings-account-stepper/savings-account-currency-step/savings-account-currency-step.component';
|
||||||
import { SavingsAccountDigitalStepComponent } from '../savings-account-stepper/savings-account-digital-step/savings-account-digital-step.component';
|
import { SavingsAccountDigitalStepComponent } from '../savings-account-stepper/savings-account-digital-step/savings-account-digital-step.component';
|
||||||
|
import { SavingsAccountSettingsStepComponent } from '../savings-account-stepper/savings-account-settings-step/savings-account-settings-step.component';
|
||||||
|
|
||||||
/** Custom Services */
|
/** Custom Services */
|
||||||
import { SavingsService } from '../savings.service';
|
import { SavingsService } from '../savings.service';
|
||||||
@@ -69,6 +70,12 @@ export class CreateSavingsAccountComponent {
|
|||||||
@ViewChild(SavingsAccountDetailsStepComponent, { static: true })
|
@ViewChild(SavingsAccountDetailsStepComponent, { static: true })
|
||||||
savingsAccountDetailsStep: SavingsAccountDetailsStepComponent;
|
savingsAccountDetailsStep: SavingsAccountDetailsStepComponent;
|
||||||
|
|
||||||
|
@ViewChild(SavingsAccountDigitalStepComponent)
|
||||||
|
savingsAccountDigitalStep: SavingsAccountDigitalStepComponent;
|
||||||
|
|
||||||
|
@ViewChild(SavingsAccountCurrencyStepComponent)
|
||||||
|
savingsAccountCurrencyStep: SavingsAccountCurrencyStepComponent;
|
||||||
|
|
||||||
constructor() {
|
constructor() {
|
||||||
this.route.data.subscribe((data: { savingsAccountTemplate: any }) => {
|
this.route.data.subscribe((data: { savingsAccountTemplate: any }) => {
|
||||||
this.savingsAccountTemplate = data.savingsAccountTemplate;
|
this.savingsAccountTemplate = data.savingsAccountTemplate;
|
||||||
@@ -94,6 +101,14 @@ export class CreateSavingsAccountComponent {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
get savingsAccountDigital() {
|
||||||
|
return this.savingsAccountDigitalStep?.savingsAccountDigital ?? null;
|
||||||
|
}
|
||||||
|
|
||||||
|
get savingsAccountNominee() {
|
||||||
|
return this.savingsAccountCurrencyStep?.nomineeData ?? null;
|
||||||
|
}
|
||||||
|
|
||||||
submit() {
|
submit() {
|
||||||
const locale = this.settingsService.language.code;
|
const locale = this.settingsService.language.code;
|
||||||
const dateFormat = this.settingsService.dateFormat;
|
const dateFormat = this.settingsService.dateFormat;
|
||||||
|
|||||||
+3
-3
@@ -35,8 +35,9 @@
|
|||||||
{{ savingsAccountProductTemplate?.dormancyAlert ? 'Yes' : 'No' }}
|
{{ savingsAccountProductTemplate?.dormancyAlert ? 'Yes' : 'No' }}
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
|
@if (savingsAccountProductTemplate?.dormancyAlert) {
|
||||||
<mifosx-dormancy-alert-panel [productTemplate]="savingsAccountProductTemplate"></mifosx-dormancy-alert-panel>
|
<mifosx-dormancy-alert-panel [productTemplate]="savingsAccountProductTemplate"></mifosx-dormancy-alert-panel>
|
||||||
|
}
|
||||||
|
|
||||||
<div class="sac-alert">
|
<div class="sac-alert">
|
||||||
<div class="sac-alert__content">
|
<div class="sac-alert__content">
|
||||||
@@ -47,7 +48,6 @@
|
|||||||
{{ savingsAccountProductTemplate?.nominationFacility ? 'Yes' : 'No' }}
|
{{ savingsAccountProductTemplate?.nominationFacility ? 'Yes' : 'No' }}
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@if (savingsAccountProductTemplate?.nominationFacility) {
|
@if (savingsAccountProductTemplate?.nominationFacility) {
|
||||||
<mifosx-nominee-form (nomineeChange)="onNomineeChange($event)"></mifosx-nominee-form>
|
<mifosx-nominee-form (nomineeChange)="onNomineeChange($event)"></mifosx-nominee-form>
|
||||||
}
|
}
|
||||||
|
|||||||
+7
-1
@@ -59,6 +59,8 @@ export class SavingsAccountDetailsStepComponent implements OnInit {
|
|||||||
|
|
||||||
savingsProductSelected = false;
|
savingsProductSelected = false;
|
||||||
introducerId: number | null = null;
|
introducerId: number | null = null;
|
||||||
|
introducerName: string | null = null;
|
||||||
|
introducerCif: string | null = null;
|
||||||
|
|
||||||
/** Savings Account Template with product data */
|
/** Savings Account Template with product data */
|
||||||
@Output() savingsAccountProductTemplate = new EventEmitter();
|
@Output() savingsAccountProductTemplate = new EventEmitter();
|
||||||
@@ -168,14 +170,18 @@ export class SavingsAccountDetailsStepComponent implements OnInit {
|
|||||||
/**
|
/**
|
||||||
* Returns savings account form value.
|
* Returns savings account form value.
|
||||||
*/
|
*/
|
||||||
onIntroducerChange(event: { clientId: number; displayName: string } | null): void {
|
onIntroducerChange(event: { clientId: number; displayName: string; cifNumber?: string } | null): void {
|
||||||
this.introducerId = event?.clientId ?? null;
|
this.introducerId = event?.clientId ?? null;
|
||||||
|
this.introducerName = event?.displayName ?? null;
|
||||||
|
this.introducerCif = event?.cifNumber ?? null;
|
||||||
}
|
}
|
||||||
|
|
||||||
get savingsAccountDetails() {
|
get savingsAccountDetails() {
|
||||||
const value = this.savingsAccountDetailsForm.getRawValue();
|
const value = this.savingsAccountDetailsForm.getRawValue();
|
||||||
if (this.introducerId) {
|
if (this.introducerId) {
|
||||||
value.introducerId = this.introducerId;
|
value.introducerId = this.introducerId;
|
||||||
|
value.introducerName = this.introducerName;
|
||||||
|
value.introducerCif = this.introducerCif;
|
||||||
}
|
}
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
|||||||
+269
-117
@@ -7,9 +7,11 @@
|
|||||||
-->
|
-->
|
||||||
|
|
||||||
<div class="preview-wrapper">
|
<div class="preview-wrapper">
|
||||||
|
<!-- ══ 1. Account Details ════════════════════════════════════════ -->
|
||||||
<div class="preview-section">
|
<div class="preview-section">
|
||||||
<div class="preview-section__header">
|
<div class="preview-section__header">
|
||||||
<span class="preview-section__title">{{ 'labels.heading.Details' | translate }}</span>
|
<i class="fas fa-info-circle preview-section__icon"></i>
|
||||||
|
<span class="preview-section__title">Account Details</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="preview-body">
|
<div class="preview-body">
|
||||||
<div class="preview-grid preview-grid--three">
|
<div class="preview-grid preview-grid--three">
|
||||||
@@ -37,25 +39,27 @@
|
|||||||
<mifosx-external-identifier externalId="{{ savingsAccount.externalId }}"></mifosx-external-identifier>
|
<mifosx-external-identifier externalId="{{ savingsAccount.externalId }}"></mifosx-external-identifier>
|
||||||
</span>
|
</span>
|
||||||
} @else {
|
} @else {
|
||||||
<span class="preview-value">{{ 'labels.inputs.Unassigned' | translate }}</span>
|
<span class="preview-value preview-muted">Unassigned</span>
|
||||||
}
|
}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<!-- ══ 2. Product Classification ════════════════════════════════ -->
|
||||||
@if (
|
@if (
|
||||||
savingsAccountProductTemplate?.accountType ||
|
savingsAccountProductTemplate?.accountType ||
|
||||||
savingsAccountProductTemplate?.customerSegment ||
|
savingsAccountProductTemplate?.customerSegment ||
|
||||||
savingsAccountProductTemplate?.productCode ||
|
savingsAccountProductTemplate?.productCode ||
|
||||||
|
savingsAccountProductTemplate?.previewAccountNo ||
|
||||||
savingsAccountProductTemplate?.effectiveDate ||
|
savingsAccountProductTemplate?.effectiveDate ||
|
||||||
savingsAccountProductTemplate?.endDate ||
|
savingsAccountProductTemplate?.endDate
|
||||||
savingsAccountProductTemplate?.introducerRequired !== undefined ||
|
|
||||||
savingsAccountProductTemplate?.shareLinkingEnabled !== undefined
|
|
||||||
) {
|
) {
|
||||||
<div class="preview-section">
|
<div class="preview-section">
|
||||||
<div class="preview-section__header">
|
<div class="preview-section__header">
|
||||||
|
<i class="fas fa-tags preview-section__icon"></i>
|
||||||
<span class="preview-section__title">Product Classification</span>
|
<span class="preview-section__title">Product Classification</span>
|
||||||
|
<span class="preview-section__badge">From Product</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="preview-body">
|
<div class="preview-body">
|
||||||
<div class="preview-grid preview-grid--three">
|
<div class="preview-grid preview-grid--three">
|
||||||
@@ -74,9 +78,15 @@
|
|||||||
@if (savingsAccountProductTemplate?.productCode) {
|
@if (savingsAccountProductTemplate?.productCode) {
|
||||||
<div class="preview-field">
|
<div class="preview-field">
|
||||||
<span class="preview-label">Product Code</span>
|
<span class="preview-label">Product Code</span>
|
||||||
<span class="preview-value">{{ savingsAccountProductTemplate?.productCode }}</span>
|
<span class="preview-value preview-mono">{{ savingsAccountProductTemplate?.productCode }}</span>
|
||||||
</div>
|
</div>
|
||||||
}
|
}
|
||||||
|
<div class="preview-field">
|
||||||
|
<span class="preview-label">Account No</span>
|
||||||
|
<span class="preview-value preview-mono">{{
|
||||||
|
savingsAccountProductTemplate?.previewAccountNo || savingsAccountTemplate?.accountNo || 'Auto-generated'
|
||||||
|
}}</span>
|
||||||
|
</div>
|
||||||
@if (savingsAccountProductTemplate?.effectiveDate) {
|
@if (savingsAccountProductTemplate?.effectiveDate) {
|
||||||
<div class="preview-field">
|
<div class="preview-field">
|
||||||
<span class="preview-label">Effective Date</span>
|
<span class="preview-label">Effective Date</span>
|
||||||
@@ -89,145 +99,285 @@
|
|||||||
<span class="preview-value">{{ savingsAccountProductTemplate?.endDate | dateFormat }}</span>
|
<span class="preview-value">{{ savingsAccountProductTemplate?.endDate | dateFormat }}</span>
|
||||||
</div>
|
</div>
|
||||||
}
|
}
|
||||||
@if (
|
<div class="preview-field">
|
||||||
savingsAccountProductTemplate?.introducerRequired !== undefined &&
|
<span class="preview-label">Introducer Required</span>
|
||||||
savingsAccountProductTemplate?.introducerRequired !== null
|
<span
|
||||||
) {
|
class="preview-value preview-badge"
|
||||||
<div class="preview-field">
|
[class.preview-badge--yes]="savingsAccountProductTemplate?.introducerRequired"
|
||||||
<span class="preview-label">Introducer Required</span>
|
>
|
||||||
<span
|
{{ savingsAccountProductTemplate?.introducerRequired | yesNo }}
|
||||||
class="preview-value preview-badge"
|
</span>
|
||||||
[class.preview-badge--yes]="savingsAccountProductTemplate?.introducerRequired"
|
</div>
|
||||||
>
|
<div class="preview-field">
|
||||||
{{ savingsAccountProductTemplate?.introducerRequired | yesNo }}
|
<span class="preview-label">Share Linking Enabled</span>
|
||||||
</span>
|
<span
|
||||||
</div>
|
class="preview-value preview-badge"
|
||||||
}
|
[class.preview-badge--yes]="savingsAccountProductTemplate?.shareLinkingEnabled"
|
||||||
@if (
|
>
|
||||||
savingsAccountProductTemplate?.shareLinkingEnabled !== undefined &&
|
{{ savingsAccountProductTemplate?.shareLinkingEnabled | yesNo }}
|
||||||
savingsAccountProductTemplate?.shareLinkingEnabled !== null
|
</span>
|
||||||
) {
|
</div>
|
||||||
<div class="preview-field">
|
|
||||||
<span class="preview-label">Share Linking Enabled</span>
|
|
||||||
<span
|
|
||||||
class="preview-value preview-badge"
|
|
||||||
[class.preview-badge--yes]="savingsAccountProductTemplate?.shareLinkingEnabled"
|
|
||||||
>
|
|
||||||
{{ savingsAccountProductTemplate?.shareLinkingEnabled | yesNo }}
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
}
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
}
|
}
|
||||||
|
|
||||||
|
<!-- ══ 3. Introducer Details (if selected) ══════════════════════ -->
|
||||||
|
@if (savingsAccount?.introducerId) {
|
||||||
|
<div class="preview-section">
|
||||||
|
<div class="preview-section__header">
|
||||||
|
<i class="fas fa-user-tie preview-section__icon"></i>
|
||||||
|
<span class="preview-section__title">Introducer Details</span>
|
||||||
|
</div>
|
||||||
|
<div class="preview-body">
|
||||||
|
<div class="preview-grid preview-grid--three">
|
||||||
|
<div class="preview-field">
|
||||||
|
<span class="preview-label">Name</span>
|
||||||
|
<span class="preview-value">{{ savingsAccount?.introducerName || '—' }}</span>
|
||||||
|
</div>
|
||||||
|
@if (savingsAccount?.introducerCif) {
|
||||||
|
<div class="preview-field">
|
||||||
|
<span class="preview-label">CIF No</span>
|
||||||
|
<span class="preview-value preview-mono">{{ savingsAccount.introducerCif }}</span>
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
<div class="preview-field">
|
||||||
|
<span class="preview-label">Client ID</span>
|
||||||
|
<span class="preview-value preview-mono">{{ savingsAccount.introducerId }}</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
|
||||||
|
<!-- ══ 4. Currency & Account Flags ══════════════════════════════ -->
|
||||||
<div class="preview-section">
|
<div class="preview-section">
|
||||||
<div class="preview-section__header">
|
<div class="preview-section__header">
|
||||||
<span class="preview-section__title">{{ 'labels.heading.Currency' | translate }}</span>
|
<i class="fas fa-coins preview-section__icon"></i>
|
||||||
|
<span class="preview-section__title">Currency & Account Flags</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="preview-body">
|
<div class="preview-body">
|
||||||
<div class="preview-grid preview-grid--three">
|
<div class="preview-grid preview-grid--three">
|
||||||
<div class="preview-field">
|
<div class="preview-field">
|
||||||
<span class="preview-label">{{ 'labels.inputs.Currency' | translate }}</span>
|
<span class="preview-label">Currency</span>
|
||||||
<span class="preview-value">{{ savingsAccountTermsForm?.get('currencyCode')?.value }}</span>
|
<span class="preview-value">{{ currencyName }}</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="preview-field">
|
<div class="preview-field">
|
||||||
<span class="preview-label">{{ 'labels.inputs.Decimal Places' | translate }}</span>
|
<span class="preview-label">Decimal Places</span>
|
||||||
<span class="preview-value">{{ savingsAccountProductTemplate?.currency?.decimalPlaces }}</span>
|
<span class="preview-value">{{ decimalPlaces }}</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="preview-field">
|
<div class="preview-field">
|
||||||
<span class="preview-label">{{ 'labels.inputs.Currency In Multiples Of' | translate }}</span>
|
<span class="preview-label">Currency In Multiples Of</span>
|
||||||
<span class="preview-value">{{ savingsAccountProductTemplate?.currency?.inMultiplesOf }}</span>
|
<span class="preview-value">{{ inMultiplesOf }}</span>
|
||||||
|
</div>
|
||||||
|
<div class="preview-field">
|
||||||
|
<span class="preview-label">Dormancy Alert</span>
|
||||||
|
<span
|
||||||
|
class="preview-value preview-badge"
|
||||||
|
[class.preview-badge--yes]="savingsAccountProductTemplate?.dormancyAlert"
|
||||||
|
>
|
||||||
|
{{ savingsAccountProductTemplate?.dormancyAlert | yesNo }}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
<div class="preview-field">
|
||||||
|
<span class="preview-label">Nomination Facility</span>
|
||||||
|
<span
|
||||||
|
class="preview-value preview-badge"
|
||||||
|
[class.preview-badge--yes]="savingsAccountProductTemplate?.nominationFacility"
|
||||||
|
>
|
||||||
|
{{ savingsAccountProductTemplate?.nominationFacility | yesNo }}
|
||||||
|
</span>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@if (
|
|
||||||
savingsAccountProductTemplate?.dormancyAlert !== undefined &&
|
|
||||||
savingsAccountProductTemplate?.dormancyAlert !== null
|
|
||||||
) {
|
|
||||||
<div class="preview-field">
|
|
||||||
<span class="preview-label">Dormancy Alert</span>
|
|
||||||
<span
|
|
||||||
class="preview-value preview-badge"
|
|
||||||
[class.preview-badge--yes]="savingsAccountProductTemplate?.dormancyAlert"
|
|
||||||
>
|
|
||||||
{{ savingsAccountProductTemplate?.dormancyAlert | yesNo }}
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
}
|
|
||||||
|
|
||||||
@if (
|
|
||||||
savingsAccountProductTemplate?.balanceSwapOption !== undefined &&
|
|
||||||
savingsAccountProductTemplate?.balanceSwapOption !== null
|
|
||||||
) {
|
|
||||||
<div class="preview-field">
|
|
||||||
<span class="preview-label">Balance Swap Option</span>
|
|
||||||
<span
|
|
||||||
class="preview-value preview-badge"
|
|
||||||
[class.preview-badge--yes]="savingsAccountProductTemplate?.balanceSwapOption"
|
|
||||||
>
|
|
||||||
{{ savingsAccountProductTemplate?.balanceSwapOption | yesNo }}
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
}
|
|
||||||
|
|
||||||
@if (savingsAccountProductTemplate?.msme !== undefined && savingsAccountProductTemplate?.msme !== null) {
|
|
||||||
<div class="preview-field">
|
|
||||||
<span class="preview-label">MSME</span>
|
|
||||||
<span class="preview-value preview-badge" [class.preview-badge--yes]="savingsAccountProductTemplate?.msme">
|
|
||||||
{{ savingsAccountProductTemplate?.msme | yesNo }}
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
}
|
|
||||||
|
|
||||||
@if (
|
|
||||||
savingsAccountProductTemplate?.nominationFacility !== undefined &&
|
|
||||||
savingsAccountProductTemplate?.nominationFacility !== null
|
|
||||||
) {
|
|
||||||
<div class="preview-field">
|
|
||||||
<span class="preview-label">Nomination Facility</span>
|
|
||||||
<span
|
|
||||||
class="preview-value preview-badge"
|
|
||||||
[class.preview-badge--yes]="savingsAccountProductTemplate?.nominationFacility"
|
|
||||||
>
|
|
||||||
{{ savingsAccountProductTemplate?.nominationFacility | yesNo }}
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
}
|
|
||||||
|
|
||||||
@if (
|
|
||||||
savingsAccountProductTemplate?.autoDebitFacility !== undefined &&
|
|
||||||
savingsAccountProductTemplate?.autoDebitFacility !== null
|
|
||||||
) {
|
|
||||||
<div class="preview-field">
|
|
||||||
<span class="preview-label">Auto Debit Facility</span>
|
|
||||||
<span
|
|
||||||
class="preview-value preview-badge"
|
|
||||||
[class.preview-badge--yes]="savingsAccountProductTemplate?.autoDebitFacility"
|
|
||||||
>
|
|
||||||
{{ savingsAccountProductTemplate?.autoDebitFacility | yesNo }}
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
}
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@if (hasDigitalSection) {
|
<!-- ══ 5. Dormancy Monitoring ════════════════════════════════════ -->
|
||||||
|
@if (
|
||||||
|
savingsAccountProductTemplate?.dormancyAlert || savingsAccountProductTemplate?.isDormancyTrackingActiveFromProduct
|
||||||
|
) {
|
||||||
<div class="preview-section">
|
<div class="preview-section">
|
||||||
<div class="preview-section__header">
|
<div class="preview-section__header">
|
||||||
<span class="preview-section__title">Digital</span>
|
<i class="fas fa-moon preview-section__icon"></i>
|
||||||
|
<span class="preview-section__title">Dormancy Monitoring</span>
|
||||||
|
<span
|
||||||
|
class="preview-section__badge"
|
||||||
|
[class.preview-section__badge--active]="savingsAccountProductTemplate?.isDormancyTrackingActiveFromProduct"
|
||||||
|
>
|
||||||
|
{{ savingsAccountProductTemplate?.isDormancyTrackingActiveFromProduct ? 'Active' : 'Inactive' }}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
<div class="preview-body">
|
||||||
|
<div class="preview-dormancy-timeline">
|
||||||
|
<div class="preview-dorm-step">
|
||||||
|
<div class="preview-dorm-step__dot preview-dorm-step__dot--inactive"></div>
|
||||||
|
<div class="preview-dorm-step__body">
|
||||||
|
<span class="preview-dorm-step__label">Inactive</span>
|
||||||
|
<span class="preview-dorm-step__days">
|
||||||
|
@if (savingsAccountProductTemplate?.daysToInactiveFromProduct != null) {
|
||||||
|
After {{ savingsAccountProductTemplate.daysToInactiveFromProduct }} days of no transaction
|
||||||
|
} @else {
|
||||||
|
Not configured
|
||||||
|
}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="preview-dorm-connector"></div>
|
||||||
|
<div class="preview-dorm-step">
|
||||||
|
<div class="preview-dorm-step__dot preview-dorm-step__dot--dormant"></div>
|
||||||
|
<div class="preview-dorm-step__body">
|
||||||
|
<span class="preview-dorm-step__label">Dormant</span>
|
||||||
|
<span class="preview-dorm-step__days">
|
||||||
|
@if (savingsAccountProductTemplate?.daysToDormancyFromProduct != null) {
|
||||||
|
{{ savingsAccountProductTemplate.daysToDormancyFromProduct }} days after inactive
|
||||||
|
} @else {
|
||||||
|
Not configured
|
||||||
|
}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="preview-dorm-connector"></div>
|
||||||
|
<div class="preview-dorm-step">
|
||||||
|
<div class="preview-dorm-step__dot preview-dorm-step__dot--escheat"></div>
|
||||||
|
<div class="preview-dorm-step__body">
|
||||||
|
<span class="preview-dorm-step__label">Escheat</span>
|
||||||
|
<span class="preview-dorm-step__days">
|
||||||
|
@if (savingsAccountProductTemplate?.daysToEscheatFromProduct != null) {
|
||||||
|
{{ savingsAccountProductTemplate.daysToEscheatFromProduct }} days after dormant
|
||||||
|
} @else {
|
||||||
|
Not configured
|
||||||
|
}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="preview-dorm-flags">
|
||||||
|
<span class="preview-dorm-flag" [class.preview-dorm-flag--on]="savingsAccountProductTemplate?.dormancyAlert">
|
||||||
|
<i class="fas fa-bell"></i> Alert
|
||||||
|
{{ savingsAccountProductTemplate?.dormancyAlert ? 'Enabled' : 'Disabled' }}
|
||||||
|
</span>
|
||||||
|
<span
|
||||||
|
class="preview-dorm-flag"
|
||||||
|
[class.preview-dorm-flag--on]="savingsAccountProductTemplate?.isDormancyTrackingActiveFromProduct"
|
||||||
|
>
|
||||||
|
<i class="fas fa-eye"></i> Tracking
|
||||||
|
{{ savingsAccountProductTemplate?.isDormancyTrackingActiveFromProduct ? 'Active' : 'Inactive' }}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
|
||||||
|
<!-- ══ 7. Nominee Details (if filled) ═══════════════════════════ -->
|
||||||
|
@if (savingsAccountNominee) {
|
||||||
|
<div class="preview-section">
|
||||||
|
<div class="preview-section__header">
|
||||||
|
<i class="fas fa-user-shield preview-section__icon"></i>
|
||||||
|
<span class="preview-section__title">Nominee Details</span>
|
||||||
|
<span class="preview-section__badge">
|
||||||
|
{{ savingsAccountNominee?.mode === 'linked' ? 'Linked Client' : 'Manual Entry' }}
|
||||||
|
</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="preview-body">
|
<div class="preview-body">
|
||||||
<div class="preview-grid preview-grid--three">
|
<div class="preview-grid preview-grid--three">
|
||||||
@for (facility of digitalFacilityLabels; track facility.key) {
|
<!-- Name: fullName for manual, displayName for linked -->
|
||||||
|
<div class="preview-field">
|
||||||
|
<span class="preview-label">Name</span>
|
||||||
|
<span class="preview-value">{{
|
||||||
|
savingsAccountNominee?.fullName || savingsAccountNominee?.displayName || '—'
|
||||||
|
}}</span>
|
||||||
|
</div>
|
||||||
|
@if (savingsAccountNominee?.cifNumber) {
|
||||||
<div class="preview-field">
|
<div class="preview-field">
|
||||||
<span class="preview-label">{{ facility.label }}</span>
|
<span class="preview-label">CIF No</span>
|
||||||
|
<span class="preview-value preview-mono">{{ savingsAccountNominee.cifNumber }}</span>
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
<div class="preview-field">
|
||||||
|
<span class="preview-label">Relationship</span>
|
||||||
|
<span class="preview-value">{{ savingsAccountNominee?.relationship || '—' }}</span>
|
||||||
|
</div>
|
||||||
|
<div class="preview-field">
|
||||||
|
<span class="preview-label">Share %</span>
|
||||||
|
<span class="preview-value">{{ savingsAccountNominee?.nomineeShare ?? '—' }}%</span>
|
||||||
|
</div>
|
||||||
|
@if (savingsAccountNominee?.dateOfBirth) {
|
||||||
|
<div class="preview-field">
|
||||||
|
<span class="preview-label">Date of Birth</span>
|
||||||
|
<span class="preview-value">{{ savingsAccountNominee?.dateOfBirth | dateFormat }}</span>
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
@if (savingsAccountNominee?.nationality) {
|
||||||
|
<div class="preview-field">
|
||||||
|
<span class="preview-label">Nationality</span>
|
||||||
|
<span class="preview-value">{{ savingsAccountNominee?.nationality }}</span>
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
@if (savingsAccountNominee?.mobileNo) {
|
||||||
|
<div class="preview-field">
|
||||||
|
<span class="preview-label">Mobile No</span>
|
||||||
|
<span class="preview-value preview-mono">{{ savingsAccountNominee?.mobileNo }}</span>
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
@if (savingsAccountNominee?.aadhaarNumber) {
|
||||||
|
<div class="preview-field">
|
||||||
|
<span class="preview-label">Aadhaar No</span>
|
||||||
|
<span class="preview-value preview-mono">{{ savingsAccountNominee?.aadhaarNumber }}</span>
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
@if (savingsAccountNominee?.panNumber) {
|
||||||
|
<div class="preview-field">
|
||||||
|
<span class="preview-label">PAN No</span>
|
||||||
|
<span class="preview-value preview-mono">{{ savingsAccountNominee?.panNumber }}</span>
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
@if (savingsAccountNominee?.isDependent) {
|
||||||
|
<div class="preview-field">
|
||||||
|
<span class="preview-label">Dependent</span>
|
||||||
|
<span class="preview-value preview-badge preview-badge--warn">Yes</span>
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
@if (savingsAccountNominee?.guardianName) {
|
||||||
|
<div class="preview-field">
|
||||||
|
<span class="preview-label">Guardian Name</span>
|
||||||
|
<span class="preview-value">{{ savingsAccountNominee?.guardianName }}</span>
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
@if (savingsAccountNominee?.guardianRelationship) {
|
||||||
|
<div class="preview-field">
|
||||||
|
<span class="preview-label">Guardian Relationship</span>
|
||||||
|
<span class="preview-value">{{ savingsAccountNominee?.guardianRelationship }}</span>
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
@if (savingsAccountNominee?.remarks) {
|
||||||
|
<div class="preview-field">
|
||||||
|
<span class="preview-label">Remarks</span>
|
||||||
|
<span class="preview-value">{{ savingsAccountNominee?.remarks }}</span>
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
|
||||||
|
<!-- ══ 5. Digital Facilities ════════════════════════════════════ -->
|
||||||
|
@if (hasDigitalSection) {
|
||||||
|
<div class="preview-section">
|
||||||
|
<div class="preview-section__header">
|
||||||
|
<i class="fas fa-mobile-alt preview-section__icon"></i>
|
||||||
|
<span class="preview-section__title">Digital Facilities</span>
|
||||||
|
<span class="preview-section__badge preview-section__badge--digital">User Configured</span>
|
||||||
|
</div>
|
||||||
|
<div class="preview-body">
|
||||||
|
<div class="preview-digital-grid">
|
||||||
|
@for (facility of digitalFacilityLabels; track facility.key) {
|
||||||
|
<div class="preview-digital-card" [class.preview-digital-card--on]="digitalFacilityConfig?.[facility.key]">
|
||||||
|
<span class="preview-digital-label">{{ facility.label }}</span>
|
||||||
<span
|
<span
|
||||||
class="preview-value preview-badge"
|
class="preview-digital-status"
|
||||||
[class.preview-badge--yes]="digitalPreview?.accountFacilityConfig?.[facility.key]"
|
[class.preview-digital-status--on]="digitalFacilityConfig?.[facility.key]"
|
||||||
>
|
>
|
||||||
{{ digitalPreview?.accountFacilityConfig?.[facility.key] | yesNo }}
|
{{ digitalFacilityConfig?.[facility.key] ? 'Enabled' : 'Disabled' }}
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
}
|
}
|
||||||
@@ -236,9 +386,11 @@
|
|||||||
</div>
|
</div>
|
||||||
}
|
}
|
||||||
|
|
||||||
|
<!-- ══ 6. Client Members (GSIM) ═════════════════════════════════ -->
|
||||||
@if (activeClientMembers) {
|
@if (activeClientMembers) {
|
||||||
<div class="preview-section">
|
<div class="preview-section">
|
||||||
<div class="preview-section__header">
|
<div class="preview-section__header">
|
||||||
|
<i class="fas fa-users preview-section__icon"></i>
|
||||||
<span class="preview-section__title">{{ 'labels.heading.Client Members' | translate }}</span>
|
<span class="preview-section__title">{{ 'labels.heading.Client Members' | translate }}</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="preview-body">
|
<div class="preview-body">
|
||||||
|
|||||||
+247
-24
@@ -9,29 +9,59 @@
|
|||||||
.preview-wrapper {
|
.preview-wrapper {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
gap: 1.25rem;
|
gap: 1rem;
|
||||||
padding: 0.5rem 0;
|
padding: 0.5rem 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.preview-section {
|
.preview-section {
|
||||||
border: 1px solid #e0e0e0;
|
border: 1px solid #e2e8f0;
|
||||||
border-radius: 8px;
|
border-radius: 10px;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
background: #fff;
|
background: #fff;
|
||||||
box-shadow: 0 1px 3px rgb(0 0 0 / 6%);
|
box-shadow: 0 1px 4px rgb(0 0 0 / 5%);
|
||||||
|
|
||||||
&__header {
|
&__header {
|
||||||
background: #f5f5f5;
|
display: flex;
|
||||||
border-bottom: 1px solid #e0e0e0;
|
align-items: center;
|
||||||
|
gap: 8px;
|
||||||
|
background: #f8fafc;
|
||||||
|
border-bottom: 1px solid #e2e8f0;
|
||||||
padding: 0.6rem 1rem;
|
padding: 0.6rem 1rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
&__icon {
|
||||||
|
font-size: 13px;
|
||||||
|
color: #0ea5e9;
|
||||||
|
width: 16px;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
&__title {
|
&__title {
|
||||||
font-size: 0.95rem;
|
font-size: 0.82rem;
|
||||||
font-weight: 600;
|
font-weight: 700;
|
||||||
color: #333;
|
color: #1e293b;
|
||||||
text-transform: uppercase;
|
text-transform: uppercase;
|
||||||
letter-spacing: 0.04em;
|
letter-spacing: 0.06em;
|
||||||
|
flex: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
&__badge {
|
||||||
|
display: inline-flex;
|
||||||
|
align-items: center;
|
||||||
|
padding: 2px 10px;
|
||||||
|
border-radius: 999px;
|
||||||
|
font-size: 10px;
|
||||||
|
font-weight: 700;
|
||||||
|
background: #dbeafe;
|
||||||
|
color: #1d4ed8;
|
||||||
|
border: 1px solid #bfdbfe;
|
||||||
|
text-transform: uppercase;
|
||||||
|
|
||||||
|
&--digital {
|
||||||
|
background: #fef3c7;
|
||||||
|
color: #92400e;
|
||||||
|
border-color: #fde68a;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -41,7 +71,7 @@
|
|||||||
|
|
||||||
.preview-grid {
|
.preview-grid {
|
||||||
display: grid;
|
display: grid;
|
||||||
gap: 0.75rem 1.5rem;
|
gap: 0.85rem 1.5rem;
|
||||||
|
|
||||||
&--three {
|
&--three {
|
||||||
grid-template-columns: repeat(3, 1fr);
|
grid-template-columns: repeat(3, 1fr);
|
||||||
@@ -59,36 +89,229 @@
|
|||||||
.preview-field {
|
.preview-field {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
gap: 0.15rem;
|
gap: 0.2rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
.preview-label {
|
.preview-label {
|
||||||
font-size: 0.72rem;
|
font-size: 0.68rem;
|
||||||
color: #888;
|
color: #94a3b8;
|
||||||
font-weight: 500;
|
font-weight: 600;
|
||||||
text-transform: uppercase;
|
text-transform: uppercase;
|
||||||
letter-spacing: 0.04em;
|
letter-spacing: 0.05em;
|
||||||
}
|
}
|
||||||
|
|
||||||
.preview-value {
|
.preview-value {
|
||||||
font-size: 0.92rem;
|
font-size: 0.9rem;
|
||||||
color: #222;
|
color: #1e293b;
|
||||||
font-weight: 500;
|
font-weight: 500;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.preview-muted {
|
||||||
|
color: #94a3b8;
|
||||||
|
font-style: italic;
|
||||||
|
}
|
||||||
|
|
||||||
|
.preview-mono {
|
||||||
|
font-family: monospace;
|
||||||
|
font-size: 0.88rem;
|
||||||
|
color: #334155;
|
||||||
|
}
|
||||||
|
|
||||||
.preview-badge {
|
.preview-badge {
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
padding: 0.1rem 0.55rem;
|
padding: 0.15rem 0.6rem;
|
||||||
border-radius: 12px;
|
border-radius: 12px;
|
||||||
font-size: 0.78rem;
|
font-size: 0.75rem;
|
||||||
font-weight: 600;
|
font-weight: 600;
|
||||||
background: #ffebee;
|
background: #fef2f2;
|
||||||
color: #c62828;
|
color: #dc2626;
|
||||||
width: fit-content;
|
width: fit-content;
|
||||||
|
|
||||||
&--yes {
|
&--yes {
|
||||||
background: #e8f5e9;
|
background: #f0fdf4;
|
||||||
color: #2e7d32;
|
color: #15803d;
|
||||||
|
}
|
||||||
|
|
||||||
|
&--warn {
|
||||||
|
background: #fef3c7;
|
||||||
|
color: #92400e;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Digital facilities grid
|
||||||
|
.preview-digital-grid {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: repeat(4, 1fr);
|
||||||
|
gap: 8px;
|
||||||
|
|
||||||
|
@media (width <= 900px) {
|
||||||
|
grid-template-columns: repeat(3, 1fr);
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (width <= 600px) {
|
||||||
|
grid-template-columns: repeat(2, 1fr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.preview-digital-card {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 4px;
|
||||||
|
padding: 10px 12px;
|
||||||
|
border: 1.5px solid #e2e8f0;
|
||||||
|
border-radius: 8px;
|
||||||
|
background: #f8fafc;
|
||||||
|
transition: all 0.12s;
|
||||||
|
|
||||||
|
&--on {
|
||||||
|
border-color: #86efac;
|
||||||
|
background: #f0fdf4;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.preview-digital-label {
|
||||||
|
font-size: 11px;
|
||||||
|
font-weight: 600;
|
||||||
|
color: #475569;
|
||||||
|
}
|
||||||
|
|
||||||
|
.preview-digital-status {
|
||||||
|
font-size: 11px;
|
||||||
|
font-weight: 700;
|
||||||
|
color: #dc2626;
|
||||||
|
|
||||||
|
&--on {
|
||||||
|
color: #15803d;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Section badge variants
|
||||||
|
.preview-section__badge--active {
|
||||||
|
background: #dcfce7 !important;
|
||||||
|
color: #15803d !important;
|
||||||
|
border-color: #bbf7d0 !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ── Dormancy Monitoring ───────────────────────────────────────────
|
||||||
|
.preview-dormancy-timeline {
|
||||||
|
display: flex;
|
||||||
|
align-items: flex-start;
|
||||||
|
gap: 0;
|
||||||
|
margin-bottom: 14px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.preview-dorm-step {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
gap: 6px;
|
||||||
|
flex: 1;
|
||||||
|
|
||||||
|
&__dot {
|
||||||
|
width: 36px;
|
||||||
|
height: 36px;
|
||||||
|
border-radius: 50%;
|
||||||
|
border: 3px solid;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
flex-shrink: 0;
|
||||||
|
|
||||||
|
&--inactive {
|
||||||
|
border-color: #f59e0b;
|
||||||
|
background: #fffbeb;
|
||||||
|
|
||||||
|
&::after {
|
||||||
|
content: '';
|
||||||
|
width: 10px;
|
||||||
|
height: 10px;
|
||||||
|
border-radius: 50%;
|
||||||
|
background: #f59e0b;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&--dormant {
|
||||||
|
border-color: #ef4444;
|
||||||
|
background: #fef2f2;
|
||||||
|
|
||||||
|
&::after {
|
||||||
|
content: '';
|
||||||
|
width: 10px;
|
||||||
|
height: 10px;
|
||||||
|
border-radius: 50%;
|
||||||
|
background: #ef4444;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&--escheat {
|
||||||
|
border-color: #7c3aed;
|
||||||
|
background: #f5f3ff;
|
||||||
|
|
||||||
|
&::after {
|
||||||
|
content: '';
|
||||||
|
width: 10px;
|
||||||
|
height: 10px;
|
||||||
|
border-radius: 50%;
|
||||||
|
background: #7c3aed;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&__body {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
text-align: center;
|
||||||
|
gap: 2px;
|
||||||
|
}
|
||||||
|
|
||||||
|
&__label {
|
||||||
|
font-size: 12px;
|
||||||
|
font-weight: 700;
|
||||||
|
color: #1e293b;
|
||||||
|
}
|
||||||
|
|
||||||
|
&__days {
|
||||||
|
font-size: 10.5px;
|
||||||
|
color: #64748b;
|
||||||
|
line-height: 1.3;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.preview-dorm-connector {
|
||||||
|
flex: 0 0 40px;
|
||||||
|
height: 3px;
|
||||||
|
background: linear-gradient(90deg, #e2e8f0, #cbd5e1);
|
||||||
|
margin-top: 16px;
|
||||||
|
border-radius: 2px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.preview-dorm-flags {
|
||||||
|
display: flex;
|
||||||
|
gap: 10px;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
}
|
||||||
|
|
||||||
|
.preview-dorm-flag {
|
||||||
|
display: inline-flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 5px;
|
||||||
|
padding: 4px 12px;
|
||||||
|
border-radius: 20px;
|
||||||
|
font-size: 11.5px;
|
||||||
|
font-weight: 600;
|
||||||
|
background: #f1f5f9;
|
||||||
|
color: #94a3b8;
|
||||||
|
border: 1px solid #e2e8f0;
|
||||||
|
|
||||||
|
i {
|
||||||
|
font-size: 11px;
|
||||||
|
}
|
||||||
|
|
||||||
|
&--on {
|
||||||
|
background: #f0fdf4;
|
||||||
|
color: #15803d;
|
||||||
|
border-color: #bbf7d0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+28
-6
@@ -88,6 +88,10 @@ export class SavingsAccountPreviewStepComponent implements OnChanges {
|
|||||||
@Input() savingsAccountTermsForm: any;
|
@Input() savingsAccountTermsForm: any;
|
||||||
/** Savings Account */
|
/** Savings Account */
|
||||||
@Input() savingsAccount: any;
|
@Input() savingsAccount: any;
|
||||||
|
/** Digital facilities — user-modified values from digital step */
|
||||||
|
@Input() savingsAccountDigital: any;
|
||||||
|
/** Nominee data from currency step */
|
||||||
|
@Input() savingsAccountNominee: any;
|
||||||
/** active Client Members in case of GSIM Account */
|
/** active Client Members in case of GSIM Account */
|
||||||
@Input() activeClientMembers?: any;
|
@Input() activeClientMembers?: any;
|
||||||
|
|
||||||
@@ -118,15 +122,33 @@ export class SavingsAccountPreviewStepComponent implements OnChanges {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
get digitalPreview(): any {
|
/** Returns user-modified digital config (from digital step), falling back to product template */
|
||||||
return this.savingsAccountProductTemplate || {};
|
get digitalFacilityConfig(): any {
|
||||||
|
return (
|
||||||
|
this.savingsAccountDigital?.accountFacilityConfig ??
|
||||||
|
this.savingsAccountProductTemplate?.accountFacilityConfig ??
|
||||||
|
null
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
get hasDigitalSection(): boolean {
|
get hasDigitalSection(): boolean {
|
||||||
return !!(
|
return !!this.digitalFacilityConfig;
|
||||||
this.digitalPreview?.accountFacilityConfig ||
|
}
|
||||||
this.digitalPreview?.accountFacilityLimits?.length ||
|
|
||||||
this.digitalPreview?.depositLimitKyc
|
/** Currency info from product template */
|
||||||
|
get currencyName(): string {
|
||||||
|
return (
|
||||||
|
this.savingsAccountProductTemplate?.currency?.name ||
|
||||||
|
this.savingsAccountTermsForm?.get?.('currencyCode')?.value ||
|
||||||
|
'—'
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
get decimalPlaces(): string | number {
|
||||||
|
return this.savingsAccountProductTemplate?.currency?.decimalPlaces ?? '—';
|
||||||
|
}
|
||||||
|
|
||||||
|
get inMultiplesOf(): string | number {
|
||||||
|
return this.savingsAccountProductTemplate?.currency?.inMultiplesOf ?? '—';
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -31,7 +31,7 @@ export class IntroducerSearchComponent {
|
|||||||
private clientsService = inject(ClientsService);
|
private clientsService = inject(ClientsService);
|
||||||
private sanitizer = inject(DomSanitizer);
|
private sanitizer = inject(DomSanitizer);
|
||||||
|
|
||||||
@Output() introducerChange = new EventEmitter<{ clientId: number; displayName: string } | null>();
|
@Output() introducerChange = new EventEmitter<{ clientId: number; displayName: string; cifNumber?: string } | null>();
|
||||||
|
|
||||||
entryMode: 'linked' = 'linked';
|
entryMode: 'linked' = 'linked';
|
||||||
searchText = '';
|
searchText = '';
|
||||||
@@ -81,7 +81,11 @@ export class IntroducerSearchComponent {
|
|||||||
this.linkedProfileImage = null;
|
this.linkedProfileImage = null;
|
||||||
this.linkedKycStatus = null;
|
this.linkedKycStatus = null;
|
||||||
this.fetchLinkedClientData(client.id);
|
this.fetchLinkedClientData(client.id);
|
||||||
this.introducerChange.emit({ clientId: client.id, displayName: client.displayName });
|
this.introducerChange.emit({
|
||||||
|
clientId: client.id,
|
||||||
|
displayName: client.displayName,
|
||||||
|
cifNumber: client.cifNumber || client.accountNumber || ''
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
removeClient(): void {
|
removeClient(): void {
|
||||||
|
|||||||
@@ -36,6 +36,7 @@ export interface NomineeData {
|
|||||||
// Linked client fields
|
// Linked client fields
|
||||||
clientId?: number;
|
clientId?: number;
|
||||||
displayName?: string;
|
displayName?: string;
|
||||||
|
cifNumber?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
const RELATIONSHIPS = [
|
const RELATIONSHIPS = [
|
||||||
@@ -98,6 +99,7 @@ export class NomineeFormComponent implements OnInit {
|
|||||||
clientDob = '';
|
clientDob = '';
|
||||||
clientAadhaar = '';
|
clientAadhaar = '';
|
||||||
clientPan = '';
|
clientPan = '';
|
||||||
|
clientCifNumber = '';
|
||||||
linkedRelationship = '';
|
linkedRelationship = '';
|
||||||
linkedShare = 100;
|
linkedShare = 100;
|
||||||
|
|
||||||
@@ -177,7 +179,12 @@ export class NomineeFormComponent implements OnInit {
|
|||||||
this.searchResults = [];
|
this.searchResults = [];
|
||||||
this.searchText = '';
|
this.searchText = '';
|
||||||
this.fetchLinkedClientData(client.id);
|
this.fetchLinkedClientData(client.id);
|
||||||
this.nomineeChange.emit({ mode: 'linked', clientId: client.id, displayName: client.displayName });
|
this.nomineeChange.emit({
|
||||||
|
mode: 'linked',
|
||||||
|
clientId: client.id,
|
||||||
|
displayName: client.displayName,
|
||||||
|
cifNumber: client.accountNo || client.cifNumber || ''
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
removeLinked(): void {
|
removeLinked(): void {
|
||||||
@@ -191,6 +198,7 @@ export class NomineeFormComponent implements OnInit {
|
|||||||
mode: 'linked',
|
mode: 'linked',
|
||||||
clientId: this.selectedClient.id,
|
clientId: this.selectedClient.id,
|
||||||
displayName: this.selectedClient.displayName,
|
displayName: this.selectedClient.displayName,
|
||||||
|
cifNumber: this.selectedClient.accountNo || this.selectedClient.cifNumber || '',
|
||||||
relationship: rel,
|
relationship: rel,
|
||||||
nomineeShare: this.linkedShare
|
nomineeShare: this.linkedShare
|
||||||
});
|
});
|
||||||
@@ -204,6 +212,7 @@ export class NomineeFormComponent implements OnInit {
|
|||||||
this.clientDob = '';
|
this.clientDob = '';
|
||||||
this.clientAadhaar = '';
|
this.clientAadhaar = '';
|
||||||
this.clientPan = '';
|
this.clientPan = '';
|
||||||
|
this.clientCifNumber = '';
|
||||||
this.searchText = '';
|
this.searchText = '';
|
||||||
this.searchResults = [];
|
this.searchResults = [];
|
||||||
this.linkedRelationship = '';
|
this.linkedRelationship = '';
|
||||||
|
|||||||
@@ -5,12 +5,13 @@
|
|||||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
// IMPORTANT: THIS FILE IS AUTO GENERATED! DO NOT MANUALLY EDIT OR CHECKIN!
|
// IMPORTANT: THIS FILE IS AUTO GENERATED! DO NOT MANUALLY EDIT OR CHECKIN!
|
||||||
/* tslint:disable */
|
/* tslint:disable */
|
||||||
export default {
|
export default {
|
||||||
'mifos_x': {
|
'mifos_x': {
|
||||||
'version': '260425',
|
'version': '260427',
|
||||||
'hash': 'fbaec185'
|
'hash': '5fb25edc'
|
||||||
},
|
},
|
||||||
'allow_switching_backend_instance': true
|
'allow_switching_backend_instance': true
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -957,3 +957,51 @@ mat-card {
|
|||||||
border-radius: 16px !important;
|
border-radius: 16px !important;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* ─── Add Beneficiary Dialog Panel ─── */
|
||||||
|
.abd-dialog-panel {
|
||||||
|
.mat-mdc-dialog-container {
|
||||||
|
padding: 0;
|
||||||
|
border-radius: 14px;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mat-mdc-dialog-surface {
|
||||||
|
padding: 0 !important;
|
||||||
|
border-radius: 14px !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mat-mdc-dialog-content {
|
||||||
|
padding: 0 20px !important;
|
||||||
|
max-height: 72vh;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mat-mdc-dialog-actions {
|
||||||
|
padding: 0 !important;
|
||||||
|
margin: 0 !important;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ─── Add Related Client Dialog Panel ─── */
|
||||||
|
.arc-dialog-panel {
|
||||||
|
.mat-mdc-dialog-container {
|
||||||
|
padding: 0;
|
||||||
|
border-radius: 14px;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mat-mdc-dialog-surface {
|
||||||
|
padding: 0 !important;
|
||||||
|
border-radius: 14px !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mat-mdc-dialog-content {
|
||||||
|
padding: 0 20px !important;
|
||||||
|
max-height: 70vh;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mat-mdc-dialog-actions {
|
||||||
|
padding: 0 !important;
|
||||||
|
margin: 0 !important;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user