feat: Nexora grouped action menu for Current Account, FD, and RD views
- Non-individual clients: hide Nomination Facility & Nominees in create flow, skip nominee validation on submit, hide Nominees tab in account view - Current Account view: replace flat kebab menu with Nexora grouped menu (Transact / Restrict / Interest / Admin / Danger zone), scrollable body, pinned header, colour-coded icons; add kindOf/iconOf/hasKind helpers - Fixed Deposit view: same grouped menu using shared cur-action-menu styles - Recurring Deposit view: same grouped menu with permission directives - main.scss: add cur-action-menu / cur-menu global styles with MDC flex fix for Material 20 (.mat-mdc-menu-item-text) Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Sonnet 4.6
parent
38c4a7d9e9
commit
547cfd581e
@@ -60,6 +60,7 @@
|
|||||||
<mifosx-current-account-currency-step
|
<mifosx-current-account-currency-step
|
||||||
[currentAccountProductTemplate]="currentAccountProductTemplate"
|
[currentAccountProductTemplate]="currentAccountProductTemplate"
|
||||||
[primaryClientId]="currentAccountTemplate?.clientId ?? null"
|
[primaryClientId]="currentAccountTemplate?.clientId ?? null"
|
||||||
|
[isNonIndividualClient]="currentAccountDetailsStep.isNonIndividualClient"
|
||||||
></mifosx-current-account-currency-step>
|
></mifosx-current-account-currency-step>
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -143,6 +143,7 @@ export class CreateCurrentAccountComponent {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (
|
if (
|
||||||
|
!this.currentAccountDetailsStep.isNonIndividualClient &&
|
||||||
this.currentAccountProductTemplate?.nominationFacility &&
|
this.currentAccountProductTemplate?.nominationFacility &&
|
||||||
(this.currentAccountCurrencyStep?.nominees ?? []).length === 0
|
(this.currentAccountCurrencyStep?.nominees ?? []).length === 0
|
||||||
) {
|
) {
|
||||||
|
|||||||
+11
-9
@@ -63,16 +63,18 @@
|
|||||||
<mifosx-dormancy-alert-panel [productTemplate]="currentAccountProductTemplate"></mifosx-dormancy-alert-panel>
|
<mifosx-dormancy-alert-panel [productTemplate]="currentAccountProductTemplate"></mifosx-dormancy-alert-panel>
|
||||||
}
|
}
|
||||||
|
|
||||||
<div class="sac-alert">
|
@if (!isNonIndividualClient) {
|
||||||
<div class="sac-alert__content">
|
<div class="sac-alert">
|
||||||
<h4>Nomination Facility</h4>
|
<div class="sac-alert__content">
|
||||||
<p>Allow account holders to designate individuals to receive funds in the event of account holder's death.</p>
|
<h4>Nomination Facility</h4>
|
||||||
|
<p>Allow account holders to designate individuals to receive funds in the event of account holder's death.</p>
|
||||||
|
</div>
|
||||||
|
<span class="sac-badge" [class.sac-badge--yes]="currentAccountProductTemplate?.nominationFacility">
|
||||||
|
{{ currentAccountProductTemplate?.nominationFacility ? 'Yes' : 'No' }}
|
||||||
|
</span>
|
||||||
</div>
|
</div>
|
||||||
<span class="sac-badge" [class.sac-badge--yes]="currentAccountProductTemplate?.nominationFacility">
|
}
|
||||||
{{ currentAccountProductTemplate?.nominationFacility ? 'Yes' : 'No' }}
|
@if (!isNonIndividualClient && currentAccountProductTemplate?.nominationFacility) {
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
@if (currentAccountProductTemplate?.nominationFacility) {
|
|
||||||
<div class="nom-section">
|
<div class="nom-section">
|
||||||
<div class="nom-header">
|
<div class="nom-header">
|
||||||
<div class="nom-header__left"><i class="fas fa-user-friends"></i><span>Nominees</span></div>
|
<div class="nom-header__left"><i class="fas fa-user-friends"></i><span>Nominees</span></div>
|
||||||
|
|||||||
+1
@@ -28,6 +28,7 @@ import { FormsModule } from '@angular/forms';
|
|||||||
export class CurrentAccountCurrencyStepComponent implements OnChanges {
|
export class CurrentAccountCurrencyStepComponent implements OnChanges {
|
||||||
@Input() currentAccountProductTemplate: any;
|
@Input() currentAccountProductTemplate: any;
|
||||||
@Input() primaryClientId: number | null = null;
|
@Input() primaryClientId: number | null = null;
|
||||||
|
@Input() isNonIndividualClient = false;
|
||||||
@ViewChild(NomineeFormComponent) nomineeFormComp: NomineeFormComponent;
|
@ViewChild(NomineeFormComponent) nomineeFormComp: NomineeFormComponent;
|
||||||
|
|
||||||
nominees: any[] = [];
|
nominees: any[] = [];
|
||||||
|
|||||||
+188
-31
@@ -91,28 +91,183 @@
|
|||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<mat-menu #accountMenu="matMenu">
|
<mat-menu #accountMenu="matMenu" class="cur-action-menu" xPosition="before">
|
||||||
@for (item of buttonConfig.singleButtons; track item) {
|
<div class="cur-menu" (click)="$event.stopPropagation()">
|
||||||
<button mat-menu-item *mifosxHasPermission="item.taskPermissionName" (click)="doAction(item.name)">
|
<header class="cur-menu__head">
|
||||||
<mat-icon matListIcon>
|
<fa-icon icon="bolt" class="cur-menu__head-ico"></fa-icon>
|
||||||
<fa-icon icon="{{ item.icon }}" size="sm"></fa-icon>
|
<div>
|
||||||
</mat-icon>
|
<div class="cur-menu__head-title">Account Actions</div>
|
||||||
<span> {{ 'labels.menus.' + item.name | translate }} </span>
|
<div class="cur-menu__head-sub">Manage deposits, blocks, interest & more</div>
|
||||||
</button>
|
</div>
|
||||||
}
|
</header>
|
||||||
|
|
||||||
@if (buttonConfig.options && !currentAccountData.subStatus.block) {
|
<div class="cur-menu__body">
|
||||||
<button mat-menu-item [matMenuTriggerFor]="More">{{ 'labels.menus.More' | translate }}</button>
|
<!-- Transact: singleButtons + options of kind 'transact' -->
|
||||||
<mat-menu #More="matMenu">
|
@if (hasKind('transact')) {
|
||||||
@for (option of buttonConfig.options; track option) {
|
<div class="cur-menu__group">
|
||||||
<span>
|
<div class="cur-menu__group-title">Transact</div>
|
||||||
<button mat-menu-item *mifosxHasPermission="option.taskPermissionName" (click)="doAction(option.name)">
|
@for (item of buttonConfig.singleButtons; track item.name) {
|
||||||
{{ 'labels.menus.' + option.name | translate }}
|
@if (kindOf(item.name) === 'transact') {
|
||||||
</button>
|
<button
|
||||||
</span>
|
mat-menu-item
|
||||||
|
class="cur-menu__item cur-menu__item--transact"
|
||||||
|
*mifosxHasPermission="item.taskPermissionName"
|
||||||
|
(click)="doAction(item.name)"
|
||||||
|
>
|
||||||
|
<span class="cur-menu__ico"><fa-icon [icon]="iconOf(item.name, item.icon)"></fa-icon></span>
|
||||||
|
<span class="cur-menu__label">{{ 'labels.menus.' + item.name | translate }}</span>
|
||||||
|
</button>
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@for (option of buttonConfig.options; track option.name) {
|
||||||
|
@if (kindOf(option.name) === 'transact') {
|
||||||
|
<button
|
||||||
|
mat-menu-item
|
||||||
|
class="cur-menu__item cur-menu__item--transact"
|
||||||
|
*mifosxHasPermission="option.taskPermissionName"
|
||||||
|
(click)="doAction(option.name)"
|
||||||
|
>
|
||||||
|
<span class="cur-menu__ico"><fa-icon [icon]="iconOf(option.name)"></fa-icon></span>
|
||||||
|
<span class="cur-menu__label">{{ 'labels.menus.' + option.name | translate }}</span>
|
||||||
|
</button>
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</div>
|
||||||
}
|
}
|
||||||
</mat-menu>
|
|
||||||
}
|
<!-- Restrict: singleButtons + options of kind 'block' -->
|
||||||
|
@if (hasKind('block')) {
|
||||||
|
<div class="cur-menu__group">
|
||||||
|
<div class="cur-menu__group-title">Restrict</div>
|
||||||
|
@for (item of buttonConfig.singleButtons; track item.name) {
|
||||||
|
@if (kindOf(item.name) === 'block') {
|
||||||
|
<button
|
||||||
|
mat-menu-item
|
||||||
|
class="cur-menu__item cur-menu__item--block"
|
||||||
|
*mifosxHasPermission="item.taskPermissionName"
|
||||||
|
(click)="doAction(item.name)"
|
||||||
|
>
|
||||||
|
<span class="cur-menu__ico"><fa-icon [icon]="iconOf(item.name, item.icon)"></fa-icon></span>
|
||||||
|
<span class="cur-menu__label">{{ 'labels.menus.' + item.name | translate }}</span>
|
||||||
|
</button>
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@for (option of buttonConfig.options; track option.name) {
|
||||||
|
@if (kindOf(option.name) === 'block') {
|
||||||
|
<button
|
||||||
|
mat-menu-item
|
||||||
|
class="cur-menu__item cur-menu__item--block"
|
||||||
|
*mifosxHasPermission="option.taskPermissionName"
|
||||||
|
(click)="doAction(option.name)"
|
||||||
|
>
|
||||||
|
<span class="cur-menu__ico"><fa-icon [icon]="iconOf(option.name)"></fa-icon></span>
|
||||||
|
<span class="cur-menu__label">{{ 'labels.menus.' + option.name | translate }}</span>
|
||||||
|
</button>
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
|
||||||
|
<!-- Interest: singleButtons + options of kind 'interest' -->
|
||||||
|
@if (hasKind('interest')) {
|
||||||
|
<div class="cur-menu__group">
|
||||||
|
<div class="cur-menu__group-title">Interest</div>
|
||||||
|
@for (item of buttonConfig.singleButtons; track item.name) {
|
||||||
|
@if (kindOf(item.name) === 'interest') {
|
||||||
|
<button
|
||||||
|
mat-menu-item
|
||||||
|
class="cur-menu__item cur-menu__item--interest"
|
||||||
|
*mifosxHasPermission="item.taskPermissionName"
|
||||||
|
(click)="doAction(item.name)"
|
||||||
|
>
|
||||||
|
<span class="cur-menu__ico"><fa-icon [icon]="iconOf(item.name, item.icon)"></fa-icon></span>
|
||||||
|
<span class="cur-menu__label">{{ 'labels.menus.' + item.name | translate }}</span>
|
||||||
|
</button>
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@for (option of buttonConfig.options; track option.name) {
|
||||||
|
@if (kindOf(option.name) === 'interest') {
|
||||||
|
<button
|
||||||
|
mat-menu-item
|
||||||
|
class="cur-menu__item cur-menu__item--interest"
|
||||||
|
*mifosxHasPermission="option.taskPermissionName"
|
||||||
|
(click)="doAction(option.name)"
|
||||||
|
>
|
||||||
|
<span class="cur-menu__ico"><fa-icon [icon]="iconOf(option.name)"></fa-icon></span>
|
||||||
|
<span class="cur-menu__label">{{ 'labels.menus.' + option.name | translate }}</span>
|
||||||
|
</button>
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
|
||||||
|
<!-- Admin: singleButtons + options of kind 'admin', hidden only when blocked -->
|
||||||
|
@if (hasKind('admin') && !currentAccountData.subStatus.block) {
|
||||||
|
<div class="cur-menu__group">
|
||||||
|
<div class="cur-menu__group-title">Admin</div>
|
||||||
|
@for (item of buttonConfig.singleButtons; track item.name) {
|
||||||
|
@if (kindOf(item.name) === 'admin') {
|
||||||
|
<button
|
||||||
|
mat-menu-item
|
||||||
|
class="cur-menu__item cur-menu__item--admin"
|
||||||
|
*mifosxHasPermission="item.taskPermissionName"
|
||||||
|
(click)="doAction(item.name)"
|
||||||
|
>
|
||||||
|
<span class="cur-menu__ico"><fa-icon [icon]="iconOf(item.name, item.icon)"></fa-icon></span>
|
||||||
|
<span class="cur-menu__label">{{ 'labels.menus.' + item.name | translate }}</span>
|
||||||
|
</button>
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@for (option of buttonConfig.options; track option.name) {
|
||||||
|
@if (kindOf(option.name) === 'admin') {
|
||||||
|
<button
|
||||||
|
mat-menu-item
|
||||||
|
class="cur-menu__item cur-menu__item--admin"
|
||||||
|
*mifosxHasPermission="option.taskPermissionName"
|
||||||
|
(click)="doAction(option.name)"
|
||||||
|
>
|
||||||
|
<span class="cur-menu__ico"><fa-icon [icon]="iconOf(option.name)"></fa-icon></span>
|
||||||
|
<span class="cur-menu__label">{{ 'labels.menus.' + option.name | translate }}</span>
|
||||||
|
</button>
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
|
||||||
|
<!-- Danger zone: singleButtons + options of kind 'danger' -->
|
||||||
|
@if (hasKind('danger')) {
|
||||||
|
<div class="cur-menu__group cur-menu__group--danger">
|
||||||
|
<div class="cur-menu__group-title">Danger zone</div>
|
||||||
|
@for (item of buttonConfig.singleButtons; track item.name) {
|
||||||
|
@if (kindOf(item.name) === 'danger') {
|
||||||
|
<button
|
||||||
|
mat-menu-item
|
||||||
|
class="cur-menu__item cur-menu__item--danger"
|
||||||
|
*mifosxHasPermission="item.taskPermissionName"
|
||||||
|
(click)="doAction(item.name)"
|
||||||
|
>
|
||||||
|
<span class="cur-menu__ico"><fa-icon [icon]="iconOf(item.name, item.icon)"></fa-icon></span>
|
||||||
|
<span class="cur-menu__label">{{ 'labels.menus.' + item.name | translate }}</span>
|
||||||
|
</button>
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@for (option of buttonConfig.options; track option.name) {
|
||||||
|
@if (kindOf(option.name) === 'danger') {
|
||||||
|
<button
|
||||||
|
mat-menu-item
|
||||||
|
class="cur-menu__item cur-menu__item--danger"
|
||||||
|
*mifosxHasPermission="option.taskPermissionName"
|
||||||
|
(click)="doAction(option.name)"
|
||||||
|
>
|
||||||
|
<span class="cur-menu__ico"><fa-icon [icon]="iconOf(option.name)"></fa-icon></span>
|
||||||
|
<span class="cur-menu__label">{{ 'labels.menus.' + option.name | translate }}</span>
|
||||||
|
</button>
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</mat-menu>
|
</mat-menu>
|
||||||
</header>
|
</header>
|
||||||
|
|
||||||
@@ -201,17 +356,19 @@
|
|||||||
</a>
|
</a>
|
||||||
}
|
}
|
||||||
</ng-container>
|
</ng-container>
|
||||||
<a
|
@if (!isNonIndividualClient) {
|
||||||
mat-tab-link
|
<a
|
||||||
class="cur-tab"
|
mat-tab-link
|
||||||
[routerLink]="['./nominees']"
|
class="cur-tab"
|
||||||
routerLinkActive
|
[routerLink]="['./nominees']"
|
||||||
#nominees="routerLinkActive"
|
routerLinkActive
|
||||||
[active]="nominees.isActive"
|
#nominees="routerLinkActive"
|
||||||
>
|
[active]="nominees.isActive"
|
||||||
<fa-icon icon="user-shield" class="cur-tab__ic"></fa-icon>
|
>
|
||||||
<span>Nominees</span>
|
<fa-icon icon="user-shield" class="cur-tab__ic"></fa-icon>
|
||||||
</a>
|
<span>Nominees</span>
|
||||||
|
</a>
|
||||||
|
}
|
||||||
@for (currentAccountDatatable of currentAccountDatatables; track currentAccountDatatable) {
|
@for (currentAccountDatatable of currentAccountDatatables; track currentAccountDatatable) {
|
||||||
<a
|
<a
|
||||||
mat-tab-link
|
mat-tab-link
|
||||||
|
|||||||
@@ -20,6 +20,7 @@ import { ToggleWithholdTaxDialogComponent } from './custom-dialogs/toggle-withho
|
|||||||
/** Custom Buttons Configuration */
|
/** Custom Buttons Configuration */
|
||||||
import { CurrentAccountButtonsConfiguration } from './current-accounts-buttons.config';
|
import { CurrentAccountButtonsConfiguration } from './current-accounts-buttons.config';
|
||||||
import { CurrentAccountsService } from '../current-accounts.service';
|
import { CurrentAccountsService } from '../current-accounts.service';
|
||||||
|
import { ClientsService } from 'app/clients/clients.service';
|
||||||
import { ConfirmationDialogComponent } from 'app/shared/confirmation-dialog/confirmation-dialog.component';
|
import { ConfirmationDialogComponent } from 'app/shared/confirmation-dialog/confirmation-dialog.component';
|
||||||
import { Currency } from 'app/shared/models/general.model';
|
import { Currency } from 'app/shared/models/general.model';
|
||||||
import { TranslateService } from '@ngx-translate/core';
|
import { TranslateService } from '@ngx-translate/core';
|
||||||
@@ -40,7 +41,6 @@ import { LongTextComponent } from '../../shared/long-text/long-text.component';
|
|||||||
import { AccountNumberComponent } from '../../shared/account-number/account-number.component';
|
import { AccountNumberComponent } from '../../shared/account-number/account-number.component';
|
||||||
import { MatIconButton } from '@angular/material/button';
|
import { MatIconButton } from '@angular/material/button';
|
||||||
import { MatMenuTrigger, MatMenu, MatMenuItem } from '@angular/material/menu';
|
import { MatMenuTrigger, MatMenu, MatMenuItem } from '@angular/material/menu';
|
||||||
import { MatIcon } from '@angular/material/icon';
|
|
||||||
import { FaIconComponent } from '@fortawesome/angular-fontawesome';
|
import { FaIconComponent } from '@fortawesome/angular-fontawesome';
|
||||||
import { MatTabNav, MatTabLink, MatTabNavPanel } from '@angular/material/tabs';
|
import { MatTabNav, MatTabLink, MatTabNavPanel } from '@angular/material/tabs';
|
||||||
import { StatusLookupPipe } from '../../pipes/status-lookup.pipe';
|
import { StatusLookupPipe } from '../../pipes/status-lookup.pipe';
|
||||||
@@ -65,7 +65,6 @@ import { STANDALONE_SHARED_IMPORTS } from 'app/standalone-shared.module';
|
|||||||
AccountNumberComponent,
|
AccountNumberComponent,
|
||||||
MatIconButton,
|
MatIconButton,
|
||||||
MatMenuTrigger,
|
MatMenuTrigger,
|
||||||
MatIcon,
|
|
||||||
FaIconComponent,
|
FaIconComponent,
|
||||||
MatMenu,
|
MatMenu,
|
||||||
MatMenuItem,
|
MatMenuItem,
|
||||||
@@ -82,6 +81,7 @@ export class CurrentAccountViewComponent implements OnInit {
|
|||||||
private route = inject(ActivatedRoute);
|
private route = inject(ActivatedRoute);
|
||||||
private router = inject(Router);
|
private router = inject(Router);
|
||||||
private currentAccountsService = inject(CurrentAccountsService);
|
private currentAccountsService = inject(CurrentAccountsService);
|
||||||
|
private clientsService = inject(ClientsService);
|
||||||
private translateService = inject(TranslateService);
|
private translateService = inject(TranslateService);
|
||||||
dialog = inject(MatDialog);
|
dialog = inject(MatDialog);
|
||||||
|
|
||||||
@@ -95,8 +95,87 @@ export class CurrentAccountViewComponent implements OnInit {
|
|||||||
entityType: string;
|
entityType: string;
|
||||||
|
|
||||||
isActive = false;
|
isActive = false;
|
||||||
|
isNonIndividualClient = false;
|
||||||
currency: Currency;
|
currency: Currency;
|
||||||
|
|
||||||
|
private readonly ACTION_KIND: Record<string, 'transact' | 'block' | 'interest' | 'admin' | 'danger'> = {
|
||||||
|
Deposit: 'transact',
|
||||||
|
Withdrawal: 'transact',
|
||||||
|
'Hold Amount': 'transact',
|
||||||
|
'Transfer Funds': 'transact',
|
||||||
|
'Interbank Transfer': 'transact',
|
||||||
|
'Block Deposit': 'block',
|
||||||
|
'Unblock Deposit': 'block',
|
||||||
|
'Block Withdrawal': 'block',
|
||||||
|
'Unblock Withdrawal': 'block',
|
||||||
|
'Block Account': 'block',
|
||||||
|
'Unblock Account': 'block',
|
||||||
|
'Calculate Interest': 'interest',
|
||||||
|
'Post Interest': 'interest',
|
||||||
|
'Post Interest As On': 'interest',
|
||||||
|
'Enable Withhold Tax': 'interest',
|
||||||
|
'Disable Withhold Tax': 'interest',
|
||||||
|
'Add Charge': 'admin',
|
||||||
|
'Apply Annual Fees': 'admin',
|
||||||
|
'Modify Application': 'admin',
|
||||||
|
'Assign Staff': 'admin',
|
||||||
|
'Unassign Staff': 'admin',
|
||||||
|
Approve: 'admin',
|
||||||
|
Activate: 'admin',
|
||||||
|
'Undo Approval': 'admin',
|
||||||
|
Close: 'danger',
|
||||||
|
Reject: 'danger',
|
||||||
|
Delete: 'danger',
|
||||||
|
'Withdrawn by Client': 'danger'
|
||||||
|
};
|
||||||
|
|
||||||
|
private readonly ACTION_ICON: Record<string, string> = {
|
||||||
|
Deposit: 'arrow-down',
|
||||||
|
Withdrawal: 'arrow-up',
|
||||||
|
'Hold Amount': 'pause',
|
||||||
|
'Transfer Funds': 'exchange-alt',
|
||||||
|
'Interbank Transfer': 'random',
|
||||||
|
'Block Deposit': 'lock',
|
||||||
|
'Unblock Deposit': 'lock-open',
|
||||||
|
'Block Withdrawal': 'lock',
|
||||||
|
'Unblock Withdrawal': 'lock-open',
|
||||||
|
'Block Account': 'lock',
|
||||||
|
'Unblock Account': 'lock-open',
|
||||||
|
'Calculate Interest': 'calculator',
|
||||||
|
'Post Interest': 'percentage',
|
||||||
|
'Post Interest As On': 'calendar-day',
|
||||||
|
'Enable Withhold Tax': 'percentage',
|
||||||
|
'Disable Withhold Tax': 'percentage',
|
||||||
|
'Add Charge': 'plus-circle',
|
||||||
|
'Apply Annual Fees': 'receipt',
|
||||||
|
'Modify Application': 'edit',
|
||||||
|
'Assign Staff': 'user-plus',
|
||||||
|
'Unassign Staff': 'user-slash',
|
||||||
|
Approve: 'check-circle',
|
||||||
|
Activate: 'check',
|
||||||
|
'Undo Approval': 'undo',
|
||||||
|
Close: 'times-circle',
|
||||||
|
Reject: 'ban',
|
||||||
|
Delete: 'trash',
|
||||||
|
'Withdrawn by Client': 'user-slash'
|
||||||
|
};
|
||||||
|
|
||||||
|
kindOf(name: string): 'transact' | 'block' | 'interest' | 'admin' | 'danger' {
|
||||||
|
return this.ACTION_KIND[name] ?? 'admin';
|
||||||
|
}
|
||||||
|
|
||||||
|
iconOf(name: string, fallback?: string): string {
|
||||||
|
return this.ACTION_ICON[name] ?? fallback ?? 'circle';
|
||||||
|
}
|
||||||
|
|
||||||
|
hasKind(kind: 'transact' | 'block' | 'interest' | 'admin' | 'danger'): boolean {
|
||||||
|
const all = [
|
||||||
|
...(this.buttonConfig?.singleButtons ?? []),
|
||||||
|
...(this.buttonConfig?.options ?? [])
|
||||||
|
];
|
||||||
|
return all.some((item) => this.kindOf(item.name) === kind);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Fetches current account data from `resolve`
|
* Fetches current account data from `resolve`
|
||||||
* @param {ActivatedRoute} route Activated Route
|
* @param {ActivatedRoute} route Activated Route
|
||||||
@@ -120,6 +199,11 @@ export class CurrentAccountViewComponent implements OnInit {
|
|||||||
|
|
||||||
ngOnInit() {
|
ngOnInit() {
|
||||||
this.setConditionalButtons();
|
this.setConditionalButtons();
|
||||||
|
if (this.currentAccountData.clientId) {
|
||||||
|
this.clientsService.getClientData(String(this.currentAccountData.clientId)).subscribe((client: any) => {
|
||||||
|
this.isNonIndividualClient = client?.legalForm?.id === 2;
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
+95
-15
@@ -81,22 +81,102 @@
|
|||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<mat-menu #accountMenu="matMenu">
|
<mat-menu #accountMenu="matMenu" class="cur-action-menu" xPosition="before">
|
||||||
@for (button of buttonConfig.singleButtons; track button) {
|
<div class="cur-menu" (click)="$event.stopPropagation()">
|
||||||
<button mat-menu-item (click)="doAction(button.name)">
|
<header class="cur-menu__head">
|
||||||
<span>{{ button.name | translateKey: 'menus' }}</span>
|
<fa-icon icon="bolt" class="cur-menu__head-ico"></fa-icon>
|
||||||
</button>
|
<div>
|
||||||
}
|
<div class="cur-menu__head-title">Account Actions</div>
|
||||||
@if (buttonConfig.options.length) {
|
<div class="cur-menu__head-sub">Manage deposits, interest & more</div>
|
||||||
<button mat-menu-item [matMenuTriggerFor]="More">{{ 'More' | translateKey: 'menus' }}</button>
|
</div>
|
||||||
<mat-menu #More="matMenu">
|
</header>
|
||||||
@for (option of buttonConfig.options; track option) {
|
<div class="cur-menu__body">
|
||||||
<span>
|
@if (hasKind('transact')) {
|
||||||
<button mat-menu-item (click)="doAction(option.name)">{{ option.name | translateKey: 'menus' }}</button>
|
<div class="cur-menu__group">
|
||||||
</span>
|
<div class="cur-menu__group-title">Transact</div>
|
||||||
|
@for (item of buttonConfig.singleButtons; track item.name) {
|
||||||
|
@if (kindOf(item.name) === 'transact') {
|
||||||
|
<button mat-menu-item class="cur-menu__item cur-menu__item--transact" (click)="doAction(item.name)">
|
||||||
|
<span class="cur-menu__ico"><fa-icon [icon]="iconOf(item.name, item.icon)"></fa-icon></span>
|
||||||
|
<span class="cur-menu__label">{{ item.name | translateKey: 'menus' }}</span>
|
||||||
|
</button>
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@for (option of buttonConfig.options; track option.name) {
|
||||||
|
@if (kindOf(option.name) === 'transact') {
|
||||||
|
<button mat-menu-item class="cur-menu__item cur-menu__item--transact" (click)="doAction(option.name)">
|
||||||
|
<span class="cur-menu__ico"><fa-icon [icon]="iconOf(option.name)"></fa-icon></span>
|
||||||
|
<span class="cur-menu__label">{{ option.name | translateKey: 'menus' }}</span>
|
||||||
|
</button>
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</div>
|
||||||
}
|
}
|
||||||
</mat-menu>
|
@if (hasKind('interest')) {
|
||||||
}
|
<div class="cur-menu__group">
|
||||||
|
<div class="cur-menu__group-title">Interest</div>
|
||||||
|
@for (item of buttonConfig.singleButtons; track item.name) {
|
||||||
|
@if (kindOf(item.name) === 'interest') {
|
||||||
|
<button mat-menu-item class="cur-menu__item cur-menu__item--interest" (click)="doAction(item.name)">
|
||||||
|
<span class="cur-menu__ico"><fa-icon [icon]="iconOf(item.name, item.icon)"></fa-icon></span>
|
||||||
|
<span class="cur-menu__label">{{ item.name | translateKey: 'menus' }}</span>
|
||||||
|
</button>
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@for (option of buttonConfig.options; track option.name) {
|
||||||
|
@if (kindOf(option.name) === 'interest') {
|
||||||
|
<button mat-menu-item class="cur-menu__item cur-menu__item--interest" (click)="doAction(option.name)">
|
||||||
|
<span class="cur-menu__ico"><fa-icon [icon]="iconOf(option.name)"></fa-icon></span>
|
||||||
|
<span class="cur-menu__label">{{ option.name | translateKey: 'menus' }}</span>
|
||||||
|
</button>
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
@if (hasKind('admin')) {
|
||||||
|
<div class="cur-menu__group">
|
||||||
|
<div class="cur-menu__group-title">Admin</div>
|
||||||
|
@for (item of buttonConfig.singleButtons; track item.name) {
|
||||||
|
@if (kindOf(item.name) === 'admin') {
|
||||||
|
<button mat-menu-item class="cur-menu__item cur-menu__item--admin" (click)="doAction(item.name)">
|
||||||
|
<span class="cur-menu__ico"><fa-icon [icon]="iconOf(item.name, item.icon)"></fa-icon></span>
|
||||||
|
<span class="cur-menu__label">{{ item.name | translateKey: 'menus' }}</span>
|
||||||
|
</button>
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@for (option of buttonConfig.options; track option.name) {
|
||||||
|
@if (kindOf(option.name) === 'admin') {
|
||||||
|
<button mat-menu-item class="cur-menu__item cur-menu__item--admin" (click)="doAction(option.name)">
|
||||||
|
<span class="cur-menu__ico"><fa-icon [icon]="iconOf(option.name)"></fa-icon></span>
|
||||||
|
<span class="cur-menu__label">{{ option.name | translateKey: 'menus' }}</span>
|
||||||
|
</button>
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
@if (hasKind('danger')) {
|
||||||
|
<div class="cur-menu__group cur-menu__group--danger">
|
||||||
|
<div class="cur-menu__group-title">Danger zone</div>
|
||||||
|
@for (item of buttonConfig.singleButtons; track item.name) {
|
||||||
|
@if (kindOf(item.name) === 'danger') {
|
||||||
|
<button mat-menu-item class="cur-menu__item cur-menu__item--danger" (click)="doAction(item.name)">
|
||||||
|
<span class="cur-menu__ico"><fa-icon [icon]="iconOf(item.name, item.icon)"></fa-icon></span>
|
||||||
|
<span class="cur-menu__label">{{ item.name | translateKey: 'menus' }}</span>
|
||||||
|
</button>
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@for (option of buttonConfig.options; track option.name) {
|
||||||
|
@if (kindOf(option.name) === 'danger') {
|
||||||
|
<button mat-menu-item class="cur-menu__item cur-menu__item--danger" (click)="doAction(option.name)">
|
||||||
|
<span class="cur-menu__ico"><fa-icon [icon]="iconOf(option.name)"></fa-icon></span>
|
||||||
|
<span class="cur-menu__label">{{ option.name | translateKey: 'menus' }}</span>
|
||||||
|
</button>
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</mat-menu>
|
</mat-menu>
|
||||||
</header>
|
</header>
|
||||||
|
|
||||||
|
|||||||
+60
-2
@@ -30,7 +30,6 @@ import { AccountNumberComponent } from '../../../shared/account-number/account-n
|
|||||||
import { LongTextComponent } from '../../../shared/long-text/long-text.component';
|
import { LongTextComponent } from '../../../shared/long-text/long-text.component';
|
||||||
import { MatIconButton } from '@angular/material/button';
|
import { MatIconButton } from '@angular/material/button';
|
||||||
import { MatMenuTrigger, MatMenu, MatMenuItem } from '@angular/material/menu';
|
import { MatMenuTrigger, MatMenu, MatMenuItem } from '@angular/material/menu';
|
||||||
import { MatIcon } from '@angular/material/icon';
|
|
||||||
import { FaIconComponent } from '@fortawesome/angular-fontawesome';
|
import { FaIconComponent } from '@fortawesome/angular-fontawesome';
|
||||||
import { MatTabNav, MatTabLink, MatTabNavPanel } from '@angular/material/tabs';
|
import { MatTabNav, MatTabLink, MatTabNavPanel } from '@angular/material/tabs';
|
||||||
import { StatusLookupPipe } from '../../../pipes/status-lookup.pipe';
|
import { StatusLookupPipe } from '../../../pipes/status-lookup.pipe';
|
||||||
@@ -51,7 +50,6 @@ import { STANDALONE_SHARED_IMPORTS } from 'app/standalone-shared.module';
|
|||||||
AccountNumberComponent,
|
AccountNumberComponent,
|
||||||
MatIconButton,
|
MatIconButton,
|
||||||
MatMenuTrigger,
|
MatMenuTrigger,
|
||||||
MatIcon,
|
|
||||||
FaIconComponent,
|
FaIconComponent,
|
||||||
MatMenu,
|
MatMenu,
|
||||||
MatMenuItem,
|
MatMenuItem,
|
||||||
@@ -82,6 +80,66 @@ export class FixedDepositAccountViewComponent implements OnInit {
|
|||||||
currency: Currency;
|
currency: Currency;
|
||||||
showTransactions = false;
|
showTransactions = false;
|
||||||
|
|
||||||
|
private readonly ACTION_KIND: Record<string, 'transact' | 'block' | 'interest' | 'admin' | 'danger'> = {
|
||||||
|
Deposit: 'transact',
|
||||||
|
Withdrawal: 'transact',
|
||||||
|
'Transfer Funds': 'transact',
|
||||||
|
'Calculate Interest': 'interest',
|
||||||
|
'Post Interest': 'interest',
|
||||||
|
'Enable Withhold Tax': 'interest',
|
||||||
|
'Disable Withhold Tax': 'interest',
|
||||||
|
'Premature Close': 'danger',
|
||||||
|
'Undo Activation': 'admin',
|
||||||
|
Close: 'danger',
|
||||||
|
'Modify Application': 'admin',
|
||||||
|
Approve: 'admin',
|
||||||
|
'Undo Approval': 'admin',
|
||||||
|
Activate: 'admin',
|
||||||
|
'Add Charge': 'admin',
|
||||||
|
'Apply Annual Fees': 'admin',
|
||||||
|
Reject: 'danger',
|
||||||
|
'Withdrawn by Client': 'danger',
|
||||||
|
Delete: 'danger'
|
||||||
|
};
|
||||||
|
|
||||||
|
private readonly ACTION_ICON: Record<string, string> = {
|
||||||
|
Deposit: 'arrow-down',
|
||||||
|
Withdrawal: 'arrow-up',
|
||||||
|
'Transfer Funds': 'exchange-alt',
|
||||||
|
'Calculate Interest': 'calculator',
|
||||||
|
'Post Interest': 'percentage',
|
||||||
|
'Enable Withhold Tax': 'percentage',
|
||||||
|
'Disable Withhold Tax': 'percentage',
|
||||||
|
'Premature Close': 'times-circle',
|
||||||
|
'Undo Activation': 'undo',
|
||||||
|
Close: 'times-circle',
|
||||||
|
'Modify Application': 'edit',
|
||||||
|
Approve: 'check-circle',
|
||||||
|
'Undo Approval': 'undo',
|
||||||
|
Activate: 'check',
|
||||||
|
'Add Charge': 'plus-circle',
|
||||||
|
'Apply Annual Fees': 'receipt',
|
||||||
|
Reject: 'ban',
|
||||||
|
'Withdrawn by Client': 'user-slash',
|
||||||
|
Delete: 'trash'
|
||||||
|
};
|
||||||
|
|
||||||
|
kindOf(name: string): 'transact' | 'block' | 'interest' | 'admin' | 'danger' {
|
||||||
|
return this.ACTION_KIND[name] ?? 'admin';
|
||||||
|
}
|
||||||
|
|
||||||
|
iconOf(name: string, fallback?: string): string {
|
||||||
|
return this.ACTION_ICON[name] ?? fallback ?? 'circle';
|
||||||
|
}
|
||||||
|
|
||||||
|
hasKind(kind: 'transact' | 'block' | 'interest' | 'admin' | 'danger'): boolean {
|
||||||
|
const all = [
|
||||||
|
...(this.buttonConfig?.singleButtons ?? []),
|
||||||
|
...(this.buttonConfig?.options ?? [])
|
||||||
|
];
|
||||||
|
return all.some((item) => this.kindOf(item.name) === kind);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Fetches fixed deposits account data from `resolve`
|
* Fetches fixed deposits account data from `resolve`
|
||||||
* @param {ActivatedRoute} route Activated Route
|
* @param {ActivatedRoute} route Activated Route
|
||||||
|
|||||||
+135
-17
@@ -89,24 +89,142 @@
|
|||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<mat-menu #accountMenu="matMenu">
|
<mat-menu #accountMenu="matMenu" class="cur-action-menu" xPosition="before">
|
||||||
@for (item of buttonConfig.singleButtons; track item) {
|
<div class="cur-menu" (click)="$event.stopPropagation()">
|
||||||
<button mat-menu-item *mifosxHasPermission="item.taskPermissionName" (click)="doAction(item.name)">
|
<header class="cur-menu__head">
|
||||||
<span>{{ 'labels.menus.' + item.name | translate }}</span>
|
<fa-icon icon="bolt" class="cur-menu__head-ico"></fa-icon>
|
||||||
</button>
|
<div>
|
||||||
}
|
<div class="cur-menu__head-title">Account Actions</div>
|
||||||
@if (buttonConfig.options.length) {
|
<div class="cur-menu__head-sub">Manage deposits, interest & more</div>
|
||||||
<button mat-menu-item [matMenuTriggerFor]="More">{{ 'labels.menus.More' | translate }}</button>
|
</div>
|
||||||
<mat-menu #More="matMenu">
|
</header>
|
||||||
@for (option of buttonConfig.options; track option) {
|
<div class="cur-menu__body">
|
||||||
<span>
|
@if (hasKind('transact')) {
|
||||||
<button mat-menu-item *mifosxHasPermission="option.taskPermissionName" (click)="doAction(option.name)">
|
<div class="cur-menu__group">
|
||||||
{{ 'labels.menus.' + option.name | translate }}
|
<div class="cur-menu__group-title">Transact</div>
|
||||||
</button>
|
@for (item of buttonConfig.singleButtons; track item.name) {
|
||||||
</span>
|
@if (kindOf(item.name) === 'transact') {
|
||||||
|
<button
|
||||||
|
mat-menu-item
|
||||||
|
class="cur-menu__item cur-menu__item--transact"
|
||||||
|
*mifosxHasPermission="item.taskPermissionName"
|
||||||
|
(click)="doAction(item.name)"
|
||||||
|
>
|
||||||
|
<span class="cur-menu__ico"><fa-icon [icon]="iconOf(item.name, item.icon)"></fa-icon></span>
|
||||||
|
<span class="cur-menu__label">{{ 'labels.menus.' + item.name | translate }}</span>
|
||||||
|
</button>
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@for (option of buttonConfig.options; track option.name) {
|
||||||
|
@if (kindOf(option.name) === 'transact') {
|
||||||
|
<button
|
||||||
|
mat-menu-item
|
||||||
|
class="cur-menu__item cur-menu__item--transact"
|
||||||
|
*mifosxHasPermission="option.taskPermissionName"
|
||||||
|
(click)="doAction(option.name)"
|
||||||
|
>
|
||||||
|
<span class="cur-menu__ico"><fa-icon [icon]="iconOf(option.name)"></fa-icon></span>
|
||||||
|
<span class="cur-menu__label">{{ 'labels.menus.' + option.name | translate }}</span>
|
||||||
|
</button>
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</div>
|
||||||
}
|
}
|
||||||
</mat-menu>
|
@if (hasKind('interest')) {
|
||||||
}
|
<div class="cur-menu__group">
|
||||||
|
<div class="cur-menu__group-title">Interest</div>
|
||||||
|
@for (item of buttonConfig.singleButtons; track item.name) {
|
||||||
|
@if (kindOf(item.name) === 'interest') {
|
||||||
|
<button
|
||||||
|
mat-menu-item
|
||||||
|
class="cur-menu__item cur-menu__item--interest"
|
||||||
|
*mifosxHasPermission="item.taskPermissionName"
|
||||||
|
(click)="doAction(item.name)"
|
||||||
|
>
|
||||||
|
<span class="cur-menu__ico"><fa-icon [icon]="iconOf(item.name, item.icon)"></fa-icon></span>
|
||||||
|
<span class="cur-menu__label">{{ 'labels.menus.' + item.name | translate }}</span>
|
||||||
|
</button>
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@for (option of buttonConfig.options; track option.name) {
|
||||||
|
@if (kindOf(option.name) === 'interest') {
|
||||||
|
<button
|
||||||
|
mat-menu-item
|
||||||
|
class="cur-menu__item cur-menu__item--interest"
|
||||||
|
*mifosxHasPermission="option.taskPermissionName"
|
||||||
|
(click)="doAction(option.name)"
|
||||||
|
>
|
||||||
|
<span class="cur-menu__ico"><fa-icon [icon]="iconOf(option.name)"></fa-icon></span>
|
||||||
|
<span class="cur-menu__label">{{ 'labels.menus.' + option.name | translate }}</span>
|
||||||
|
</button>
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
@if (hasKind('admin')) {
|
||||||
|
<div class="cur-menu__group">
|
||||||
|
<div class="cur-menu__group-title">Admin</div>
|
||||||
|
@for (item of buttonConfig.singleButtons; track item.name) {
|
||||||
|
@if (kindOf(item.name) === 'admin') {
|
||||||
|
<button
|
||||||
|
mat-menu-item
|
||||||
|
class="cur-menu__item cur-menu__item--admin"
|
||||||
|
*mifosxHasPermission="item.taskPermissionName"
|
||||||
|
(click)="doAction(item.name)"
|
||||||
|
>
|
||||||
|
<span class="cur-menu__ico"><fa-icon [icon]="iconOf(item.name, item.icon)"></fa-icon></span>
|
||||||
|
<span class="cur-menu__label">{{ 'labels.menus.' + item.name | translate }}</span>
|
||||||
|
</button>
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@for (option of buttonConfig.options; track option.name) {
|
||||||
|
@if (kindOf(option.name) === 'admin') {
|
||||||
|
<button
|
||||||
|
mat-menu-item
|
||||||
|
class="cur-menu__item cur-menu__item--admin"
|
||||||
|
*mifosxHasPermission="option.taskPermissionName"
|
||||||
|
(click)="doAction(option.name)"
|
||||||
|
>
|
||||||
|
<span class="cur-menu__ico"><fa-icon [icon]="iconOf(option.name)"></fa-icon></span>
|
||||||
|
<span class="cur-menu__label">{{ 'labels.menus.' + option.name | translate }}</span>
|
||||||
|
</button>
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
@if (hasKind('danger')) {
|
||||||
|
<div class="cur-menu__group cur-menu__group--danger">
|
||||||
|
<div class="cur-menu__group-title">Danger zone</div>
|
||||||
|
@for (item of buttonConfig.singleButtons; track item.name) {
|
||||||
|
@if (kindOf(item.name) === 'danger') {
|
||||||
|
<button
|
||||||
|
mat-menu-item
|
||||||
|
class="cur-menu__item cur-menu__item--danger"
|
||||||
|
*mifosxHasPermission="item.taskPermissionName"
|
||||||
|
(click)="doAction(item.name)"
|
||||||
|
>
|
||||||
|
<span class="cur-menu__ico"><fa-icon [icon]="iconOf(item.name, item.icon)"></fa-icon></span>
|
||||||
|
<span class="cur-menu__label">{{ 'labels.menus.' + item.name | translate }}</span>
|
||||||
|
</button>
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@for (option of buttonConfig.options; track option.name) {
|
||||||
|
@if (kindOf(option.name) === 'danger') {
|
||||||
|
<button
|
||||||
|
mat-menu-item
|
||||||
|
class="cur-menu__item cur-menu__item--danger"
|
||||||
|
*mifosxHasPermission="option.taskPermissionName"
|
||||||
|
(click)="doAction(option.name)"
|
||||||
|
>
|
||||||
|
<span class="cur-menu__ico"><fa-icon [icon]="iconOf(option.name)"></fa-icon></span>
|
||||||
|
<span class="cur-menu__label">{{ 'labels.menus.' + option.name | translate }}</span>
|
||||||
|
</button>
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</mat-menu>
|
</mat-menu>
|
||||||
</header>
|
</header>
|
||||||
|
|
||||||
|
|||||||
+60
-2
@@ -29,7 +29,6 @@ import { AccountNumberComponent } from '../../../shared/account-number/account-n
|
|||||||
import { LongTextComponent } from '../../../shared/long-text/long-text.component';
|
import { LongTextComponent } from '../../../shared/long-text/long-text.component';
|
||||||
import { MatIconButton } from '@angular/material/button';
|
import { MatIconButton } from '@angular/material/button';
|
||||||
import { MatMenuTrigger, MatMenu, MatMenuItem } from '@angular/material/menu';
|
import { MatMenuTrigger, MatMenu, MatMenuItem } from '@angular/material/menu';
|
||||||
import { MatIcon } from '@angular/material/icon';
|
|
||||||
import { FaIconComponent } from '@fortawesome/angular-fontawesome';
|
import { FaIconComponent } from '@fortawesome/angular-fontawesome';
|
||||||
import { MatTabNav, MatTabLink, MatTabNavPanel } from '@angular/material/tabs';
|
import { MatTabNav, MatTabLink, MatTabNavPanel } from '@angular/material/tabs';
|
||||||
import { StatusLookupPipe } from '../../../pipes/status-lookup.pipe';
|
import { StatusLookupPipe } from '../../../pipes/status-lookup.pipe';
|
||||||
@@ -50,7 +49,6 @@ import { STANDALONE_SHARED_IMPORTS } from 'app/standalone-shared.module';
|
|||||||
AccountNumberComponent,
|
AccountNumberComponent,
|
||||||
MatIconButton,
|
MatIconButton,
|
||||||
MatMenuTrigger,
|
MatMenuTrigger,
|
||||||
MatIcon,
|
|
||||||
FaIconComponent,
|
FaIconComponent,
|
||||||
MatMenu,
|
MatMenu,
|
||||||
MatMenuItem,
|
MatMenuItem,
|
||||||
@@ -85,6 +83,66 @@ export class RecurringDepositsAccountViewComponent implements OnInit {
|
|||||||
entityType: string;
|
entityType: string;
|
||||||
currency: Currency;
|
currency: Currency;
|
||||||
showTransactions = false;
|
showTransactions = false;
|
||||||
|
|
||||||
|
private readonly ACTION_KIND: Record<string, 'transact' | 'block' | 'interest' | 'admin' | 'danger'> = {
|
||||||
|
Deposit: 'transact',
|
||||||
|
Withdrawal: 'transact',
|
||||||
|
'Transfer Funds': 'transact',
|
||||||
|
'Calculate Interest': 'interest',
|
||||||
|
'Post Interest': 'interest',
|
||||||
|
'Enable Withhold Tax': 'interest',
|
||||||
|
'Disable Withhold Tax': 'interest',
|
||||||
|
'Premature Close': 'danger',
|
||||||
|
'Undo Activation': 'admin',
|
||||||
|
Close: 'danger',
|
||||||
|
'Modify Application': 'admin',
|
||||||
|
Approve: 'admin',
|
||||||
|
'Undo Approval': 'admin',
|
||||||
|
Activate: 'admin',
|
||||||
|
'Add Charge': 'admin',
|
||||||
|
'Apply Annual Fees': 'admin',
|
||||||
|
Reject: 'danger',
|
||||||
|
'Withdrawn by Client': 'danger',
|
||||||
|
Delete: 'danger'
|
||||||
|
};
|
||||||
|
|
||||||
|
private readonly ACTION_ICON: Record<string, string> = {
|
||||||
|
Deposit: 'arrow-down',
|
||||||
|
Withdrawal: 'arrow-up',
|
||||||
|
'Transfer Funds': 'exchange-alt',
|
||||||
|
'Calculate Interest': 'calculator',
|
||||||
|
'Post Interest': 'percentage',
|
||||||
|
'Enable Withhold Tax': 'percentage',
|
||||||
|
'Disable Withhold Tax': 'percentage',
|
||||||
|
'Premature Close': 'times-circle',
|
||||||
|
'Undo Activation': 'undo',
|
||||||
|
Close: 'times-circle',
|
||||||
|
'Modify Application': 'edit',
|
||||||
|
Approve: 'check-circle',
|
||||||
|
'Undo Approval': 'undo',
|
||||||
|
Activate: 'check',
|
||||||
|
'Add Charge': 'plus-circle',
|
||||||
|
'Apply Annual Fees': 'receipt',
|
||||||
|
Reject: 'ban',
|
||||||
|
'Withdrawn by Client': 'user-slash',
|
||||||
|
Delete: 'trash'
|
||||||
|
};
|
||||||
|
|
||||||
|
kindOf(name: string): 'transact' | 'block' | 'interest' | 'admin' | 'danger' {
|
||||||
|
return this.ACTION_KIND[name] ?? 'admin';
|
||||||
|
}
|
||||||
|
|
||||||
|
iconOf(name: string, fallback?: string): string {
|
||||||
|
return this.ACTION_ICON[name] ?? fallback ?? 'circle';
|
||||||
|
}
|
||||||
|
|
||||||
|
hasKind(kind: 'transact' | 'block' | 'interest' | 'admin' | 'danger'): boolean {
|
||||||
|
const all = [
|
||||||
|
...(this.buttonConfig?.singleButtons ?? []),
|
||||||
|
...(this.buttonConfig?.options ?? [])
|
||||||
|
];
|
||||||
|
return all.some((item) => this.kindOf(item.name) === kind);
|
||||||
|
}
|
||||||
/**
|
/**
|
||||||
* Fetches recurringDeposits account data from `resolve`
|
* Fetches recurringDeposits account data from `resolve`
|
||||||
* @param {ActivatedRoute} route Activated Route
|
* @param {ActivatedRoute} route Activated Route
|
||||||
|
|||||||
+200
@@ -1177,6 +1177,16 @@ mat-card {
|
|||||||
min-width: 0;
|
min-width: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.sav-menu__item.mat-mdc-menu-item .mat-mdc-menu-item-text,
|
||||||
|
.sav-menu__item.mat-mdc-menu-item .mdc-list-item__primary-text,
|
||||||
|
.sav-menu__item.mat-mdc-menu-item .mdc-list-item__content {
|
||||||
|
display: flex !important;
|
||||||
|
flex-direction: row !important;
|
||||||
|
align-items: center !important;
|
||||||
|
gap: 10px !important;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
/* Hover lift on the icon */
|
/* Hover lift on the icon */
|
||||||
.sav-menu__item:hover .sav-menu__ico {
|
.sav-menu__item:hover .sav-menu__ico {
|
||||||
transform: scale(1.06);
|
transform: scale(1.06);
|
||||||
@@ -1216,6 +1226,196 @@ mat-card {
|
|||||||
background: #fef2f2 !important;
|
background: #fef2f2 !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* ─── Current Account action menu (mirrors sav-action-menu styling) ─────── */
|
||||||
|
.cur-action-menu.mat-mdc-menu-panel {
|
||||||
|
min-width: 280px !important;
|
||||||
|
max-width: 320px !important;
|
||||||
|
border-radius: 14px !important;
|
||||||
|
box-shadow:
|
||||||
|
0 8px 30px -6px rgb(15 23 42 / 22%),
|
||||||
|
0 0 0 1px rgb(15 23 42 / 6%) !important;
|
||||||
|
border: none !important;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
.cur-action-menu .mat-mdc-menu-content {
|
||||||
|
padding: 0 !important;
|
||||||
|
overflow: hidden !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.cur-menu {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
font-family: Inter, 'DM Sans', Roboto, sans-serif;
|
||||||
|
max-height: 440px;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
.cur-menu__body {
|
||||||
|
overflow-y: auto;
|
||||||
|
scrollbar-width: thin;
|
||||||
|
scrollbar-color: #cbd5e1 transparent;
|
||||||
|
}
|
||||||
|
|
||||||
|
.cur-menu__body::-webkit-scrollbar {
|
||||||
|
width: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.cur-menu__body::-webkit-scrollbar-track {
|
||||||
|
background: transparent;
|
||||||
|
}
|
||||||
|
|
||||||
|
.cur-menu__body::-webkit-scrollbar-thumb {
|
||||||
|
background: #cbd5e1;
|
||||||
|
border-radius: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.cur-menu__head {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 10px;
|
||||||
|
padding: 12px 14px;
|
||||||
|
background: linear-gradient(135deg, #1e3a8a 0%, #1e40af 45%, #4338ca 100%);
|
||||||
|
color: #fff;
|
||||||
|
}
|
||||||
|
|
||||||
|
.cur-menu__head-ico {
|
||||||
|
width: 28px;
|
||||||
|
height: 28px;
|
||||||
|
border-radius: 8px;
|
||||||
|
background: rgb(255 255 255 / 18%);
|
||||||
|
border: 1px solid rgb(255 255 255 / 28%);
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
font-size: 12px;
|
||||||
|
flex-shrink: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.cur-menu__head-title {
|
||||||
|
font-size: 13px;
|
||||||
|
font-weight: 800;
|
||||||
|
letter-spacing: 0.01em;
|
||||||
|
line-height: 1.1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.cur-menu__head-sub {
|
||||||
|
margin-top: 1px;
|
||||||
|
font-size: 10.5px;
|
||||||
|
color: rgb(255 255 255 / 78%);
|
||||||
|
}
|
||||||
|
|
||||||
|
.cur-menu__group {
|
||||||
|
padding: 6px 0;
|
||||||
|
|
||||||
|
& + & {
|
||||||
|
border-top: 1px solid #f1f5f9;
|
||||||
|
}
|
||||||
|
|
||||||
|
&--danger {
|
||||||
|
background: #fff8f8;
|
||||||
|
|
||||||
|
& + & {
|
||||||
|
border-top-color: #fee2e2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.cur-menu__group-title {
|
||||||
|
font-size: 9.5px;
|
||||||
|
font-weight: 800;
|
||||||
|
text-transform: uppercase;
|
||||||
|
letter-spacing: 0.08em;
|
||||||
|
color: #94a3b8;
|
||||||
|
padding: 4px 14px 2px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.cur-menu__item.mat-mdc-menu-item {
|
||||||
|
display: flex !important;
|
||||||
|
align-items: center;
|
||||||
|
gap: 10px;
|
||||||
|
min-height: 38px !important;
|
||||||
|
padding: 5px 14px !important;
|
||||||
|
font-size: 13px !important;
|
||||||
|
font-weight: 600;
|
||||||
|
color: #1e293b;
|
||||||
|
transition:
|
||||||
|
background 0.12s ease,
|
||||||
|
color 0.12s ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
.cur-menu__ico {
|
||||||
|
width: 26px;
|
||||||
|
height: 26px;
|
||||||
|
border-radius: 7px;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
font-size: 11px;
|
||||||
|
flex-shrink: 0;
|
||||||
|
background: #f1f5f9;
|
||||||
|
color: #64748b;
|
||||||
|
transition:
|
||||||
|
transform 0.12s ease,
|
||||||
|
background 0.12s ease,
|
||||||
|
color 0.12s ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
.cur-menu__label {
|
||||||
|
flex: 1 1 auto;
|
||||||
|
min-width: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Material 20 wraps projected content in .mat-mdc-menu-item-text — make it
|
||||||
|
flex so the icon square and label sit side-by-side instead of stacking. */
|
||||||
|
.cur-menu__item.mat-mdc-menu-item .mat-mdc-menu-item-text,
|
||||||
|
.cur-menu__item.mat-mdc-menu-item .mdc-list-item__primary-text,
|
||||||
|
.cur-menu__item.mat-mdc-menu-item .mdc-list-item__content {
|
||||||
|
display: flex !important;
|
||||||
|
flex-direction: row !important;
|
||||||
|
align-items: center !important;
|
||||||
|
gap: 10px !important;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.cur-menu__item:hover .cur-menu__ico {
|
||||||
|
transform: scale(1.06);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Variant tints */
|
||||||
|
.cur-menu__item--transact .cur-menu__ico {
|
||||||
|
background: #ecfdf5;
|
||||||
|
color: #047857;
|
||||||
|
}
|
||||||
|
|
||||||
|
.cur-menu__item--block .cur-menu__ico {
|
||||||
|
background: #fff7ed;
|
||||||
|
color: #c2410c;
|
||||||
|
}
|
||||||
|
|
||||||
|
.cur-menu__item--interest .cur-menu__ico {
|
||||||
|
background: #eff6ff;
|
||||||
|
color: #1d4ed8;
|
||||||
|
}
|
||||||
|
|
||||||
|
.cur-menu__item--admin .cur-menu__ico {
|
||||||
|
background: #f5f3ff;
|
||||||
|
color: #6d28d9;
|
||||||
|
}
|
||||||
|
|
||||||
|
.cur-menu__item--danger.mat-mdc-menu-item {
|
||||||
|
color: #991b1b !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.cur-menu__item--danger .cur-menu__ico {
|
||||||
|
background: #fee2e2;
|
||||||
|
color: #b91c1c;
|
||||||
|
}
|
||||||
|
|
||||||
|
.cur-menu__item--danger:hover {
|
||||||
|
background: #fef2f2 !important;
|
||||||
|
}
|
||||||
|
|
||||||
/* ─── Identity-Verify Dialog Panel ───
|
/* ─── Identity-Verify Dialog Panel ───
|
||||||
Strip Material's default surface padding so the teal gradient header
|
Strip Material's default surface padding so the teal gradient header
|
||||||
on the Withdraw "Verify Customer Identity" pop-up reaches edge-to-edge
|
on the Withdraw "Verify Customer Identity" pop-up reaches edge-to-edge
|
||||||
|
|||||||
Reference in New Issue
Block a user