feat: dynamic denomination breakdown in deposit forms + savings menu scroller
Deposit forms (Current/Savings/FD/RD) now load cash denominations from the Denomination Master instead of a hardcoded list: - active + discontinued denominations fetched via /denominationmaster - discontinued rows hidden by default behind a "Show discontinued" toggle, rendered faded and disabled (cannot be counted) when revealed - rows sorted by value descending; redesigned as a Denom/Qty/Amount table with circular coin chips and per-row amount (faded at zero) Also: savings account-actions menu now scrolls (max-height + grouped sections mirror the current-account menu) and renders all action items. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 4.7
parent
918a90368c
commit
89e17f561f
@@ -104,155 +104,172 @@
|
||||
</div>
|
||||
</header>
|
||||
|
||||
<!-- Cash movement (Deposit / Withdrawal / Hold Amount) -->
|
||||
<div class="sav-menu__group">
|
||||
<div class="sav-menu__group-title">Transact</div>
|
||||
@for (item of buttonConfig.singleButtons; track item.name) {
|
||||
@if (kindOf(item.name) === 'transact') {
|
||||
<button
|
||||
mat-menu-item
|
||||
class="sav-menu__item sav-menu__item--transact"
|
||||
*mifosxHasPermission="item.taskPermissionName"
|
||||
(click)="doAction(item.name)"
|
||||
>
|
||||
<span class="sav-menu__ico">
|
||||
<fa-icon [icon]="iconOf(item.name, item.icon)"></fa-icon>
|
||||
</span>
|
||||
<span class="sav-menu__label">{{ 'labels.menus.' + item.name | translate }}</span>
|
||||
</button>
|
||||
}
|
||||
<div class="sav-menu__body">
|
||||
<!-- Transact: singleButtons + options of kind 'transact' -->
|
||||
@if (hasKind('transact')) {
|
||||
<div class="sav-menu__group">
|
||||
<div class="sav-menu__group-title">Transact</div>
|
||||
@for (item of buttonConfig.singleButtons; track item.name) {
|
||||
@if (kindOf(item.name) === 'transact') {
|
||||
<button
|
||||
mat-menu-item
|
||||
class="sav-menu__item sav-menu__item--transact"
|
||||
*mifosxHasPermission="item.taskPermissionName"
|
||||
(click)="doAction(item.name)"
|
||||
>
|
||||
<span class="sav-menu__ico"><fa-icon [icon]="iconOf(item.name, item.icon)"></fa-icon></span>
|
||||
<span class="sav-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="sav-menu__item sav-menu__item--transact"
|
||||
*mifosxHasPermission="option.taskPermissionName"
|
||||
(click)="doAction(option.name)"
|
||||
>
|
||||
<span class="sav-menu__ico"><fa-icon [icon]="iconOf(option.name)"></fa-icon></span>
|
||||
<span class="sav-menu__label">{{ 'labels.menus.' + option.name | translate }}</span>
|
||||
</button>
|
||||
}
|
||||
}
|
||||
</div>
|
||||
}
|
||||
|
||||
<!-- Restrict: singleButtons + options of kind 'block' -->
|
||||
@if (hasKind('block')) {
|
||||
<div class="sav-menu__group">
|
||||
<div class="sav-menu__group-title">Restrict</div>
|
||||
@for (item of buttonConfig.singleButtons; track item.name) {
|
||||
@if (kindOf(item.name) === 'block') {
|
||||
<button
|
||||
mat-menu-item
|
||||
class="sav-menu__item sav-menu__item--block"
|
||||
*mifosxHasPermission="item.taskPermissionName"
|
||||
(click)="doAction(item.name)"
|
||||
>
|
||||
<span class="sav-menu__ico"><fa-icon [icon]="iconOf(item.name, item.icon)"></fa-icon></span>
|
||||
<span class="sav-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="sav-menu__item sav-menu__item--block"
|
||||
*mifosxHasPermission="option.taskPermissionName"
|
||||
(click)="doAction(option.name)"
|
||||
>
|
||||
<span class="sav-menu__ico"><fa-icon [icon]="iconOf(option.name)"></fa-icon></span>
|
||||
<span class="sav-menu__label">{{ 'labels.menus.' + option.name | translate }}</span>
|
||||
</button>
|
||||
}
|
||||
}
|
||||
</div>
|
||||
}
|
||||
|
||||
<!-- Interest: singleButtons + options of kind 'interest' -->
|
||||
@if (hasKind('interest')) {
|
||||
<div class="sav-menu__group">
|
||||
<div class="sav-menu__group-title">Interest</div>
|
||||
@for (item of buttonConfig.singleButtons; track item.name) {
|
||||
@if (kindOf(item.name) === 'interest') {
|
||||
<button
|
||||
mat-menu-item
|
||||
class="sav-menu__item sav-menu__item--interest"
|
||||
*mifosxHasPermission="item.taskPermissionName"
|
||||
(click)="doAction(item.name)"
|
||||
>
|
||||
<span class="sav-menu__ico"><fa-icon [icon]="iconOf(item.name, item.icon)"></fa-icon></span>
|
||||
<span class="sav-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="sav-menu__item sav-menu__item--interest"
|
||||
*mifosxHasPermission="option.taskPermissionName"
|
||||
(click)="doAction(option.name)"
|
||||
>
|
||||
<span class="sav-menu__ico"><fa-icon [icon]="iconOf(option.name)"></fa-icon></span>
|
||||
<span class="sav-menu__label">{{ 'labels.menus.' + option.name | translate }}</span>
|
||||
</button>
|
||||
}
|
||||
}
|
||||
</div>
|
||||
}
|
||||
|
||||
<!-- Admin: singleButtons + options of kind 'admin', hidden when blocked -->
|
||||
@if (hasKind('admin') && !savingsAccountData.subStatus.block) {
|
||||
<div class="sav-menu__group">
|
||||
<div class="sav-menu__group-title">Admin</div>
|
||||
@for (item of buttonConfig.singleButtons; track item.name) {
|
||||
@if (kindOf(item.name) === 'admin') {
|
||||
<button
|
||||
mat-menu-item
|
||||
class="sav-menu__item sav-menu__item--admin"
|
||||
*mifosxHasPermission="item.taskPermissionName"
|
||||
(click)="doAction(item.name)"
|
||||
>
|
||||
<span class="sav-menu__ico"><fa-icon [icon]="iconOf(item.name, item.icon)"></fa-icon></span>
|
||||
<span class="sav-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="sav-menu__item sav-menu__item--admin"
|
||||
*mifosxHasPermission="option.taskPermissionName"
|
||||
(click)="doAction(option.name)"
|
||||
>
|
||||
<span class="sav-menu__ico"><fa-icon [icon]="iconOf(option.name)"></fa-icon></span>
|
||||
<span class="sav-menu__label">{{ 'labels.menus.' + option.name | translate }}</span>
|
||||
</button>
|
||||
}
|
||||
}
|
||||
</div>
|
||||
}
|
||||
|
||||
<!-- Danger zone: singleButtons + options of kind 'danger' -->
|
||||
@if (hasKind('danger')) {
|
||||
<div class="sav-menu__group sav-menu__group--danger">
|
||||
<div class="sav-menu__group-title">Danger zone</div>
|
||||
@for (item of buttonConfig.singleButtons; track item.name) {
|
||||
@if (kindOf(item.name) === 'danger') {
|
||||
<button
|
||||
mat-menu-item
|
||||
class="sav-menu__item sav-menu__item--danger"
|
||||
*mifosxHasPermission="item.taskPermissionName"
|
||||
(click)="doAction(item.name)"
|
||||
>
|
||||
<span class="sav-menu__ico"><fa-icon [icon]="iconOf(item.name, item.icon)"></fa-icon></span>
|
||||
<span class="sav-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="sav-menu__item sav-menu__item--danger"
|
||||
*mifosxHasPermission="option.taskPermissionName"
|
||||
(click)="doAction(option.name)"
|
||||
>
|
||||
<span class="sav-menu__ico"><fa-icon [icon]="iconOf(option.name)"></fa-icon></span>
|
||||
<span class="sav-menu__label">{{ 'labels.menus.' + option.name | translate }}</span>
|
||||
</button>
|
||||
}
|
||||
}
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
|
||||
<!-- Restrictions (Block / Unblock variants) -->
|
||||
<div class="sav-menu__group">
|
||||
<div class="sav-menu__group-title">Restrict</div>
|
||||
@for (item of buttonConfig.singleButtons; track item.name) {
|
||||
@if (kindOf(item.name) === 'block') {
|
||||
<button
|
||||
mat-menu-item
|
||||
class="sav-menu__item sav-menu__item--block"
|
||||
*mifosxHasPermission="item.taskPermissionName"
|
||||
(click)="doAction(item.name)"
|
||||
>
|
||||
<span class="sav-menu__ico">
|
||||
<fa-icon [icon]="iconOf(item.name, item.icon)"></fa-icon>
|
||||
</span>
|
||||
<span class="sav-menu__label">{{ 'labels.menus.' + item.name | translate }}</span>
|
||||
</button>
|
||||
}
|
||||
}
|
||||
</div>
|
||||
|
||||
<!-- Interest -->
|
||||
<div class="sav-menu__group">
|
||||
<div class="sav-menu__group-title">Interest</div>
|
||||
@for (item of buttonConfig.singleButtons; track item.name) {
|
||||
@if (kindOf(item.name) === 'interest') {
|
||||
<button
|
||||
mat-menu-item
|
||||
class="sav-menu__item sav-menu__item--interest"
|
||||
*mifosxHasPermission="item.taskPermissionName"
|
||||
(click)="doAction(item.name)"
|
||||
>
|
||||
<span class="sav-menu__ico">
|
||||
<fa-icon [icon]="iconOf(item.name, item.icon)"></fa-icon>
|
||||
</span>
|
||||
<span class="sav-menu__label">{{ 'labels.menus.' + item.name | translate }}</span>
|
||||
</button>
|
||||
}
|
||||
}
|
||||
</div>
|
||||
|
||||
<!-- Admin (approval/staff/charges) — drawn from BOTH primary
|
||||
buttons and the historical "More" options. -->
|
||||
@if (buttonConfig.options && !savingsAccountData.subStatus.block) {
|
||||
<div class="sav-menu__group">
|
||||
<div class="sav-menu__group-title">Admin</div>
|
||||
@for (item of buttonConfig.singleButtons; track item.name) {
|
||||
@if (kindOf(item.name) === 'admin') {
|
||||
<button
|
||||
mat-menu-item
|
||||
class="sav-menu__item sav-menu__item--admin"
|
||||
*mifosxHasPermission="item.taskPermissionName"
|
||||
(click)="doAction(item.name)"
|
||||
>
|
||||
<span class="sav-menu__ico">
|
||||
<fa-icon [icon]="iconOf(item.name, item.icon)"></fa-icon>
|
||||
</span>
|
||||
<span class="sav-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="sav-menu__item sav-menu__item--admin"
|
||||
*mifosxHasPermission="option.taskPermissionName"
|
||||
(click)="doAction(option.name)"
|
||||
>
|
||||
<span class="sav-menu__ico">
|
||||
<fa-icon [icon]="iconOf(option.name)"></fa-icon>
|
||||
</span>
|
||||
<span class="sav-menu__label">{{ 'labels.menus.' + option.name | translate }}</span>
|
||||
</button>
|
||||
}
|
||||
}
|
||||
@for (option of buttonConfig.options; track option.name) {
|
||||
@if (kindOf(option.name) === 'interest') {
|
||||
<button
|
||||
mat-menu-item
|
||||
class="sav-menu__item sav-menu__item--interest"
|
||||
*mifosxHasPermission="option.taskPermissionName"
|
||||
(click)="doAction(option.name)"
|
||||
>
|
||||
<span class="sav-menu__ico">
|
||||
<fa-icon [icon]="iconOf(option.name)"></fa-icon>
|
||||
</span>
|
||||
<span class="sav-menu__label">{{ 'labels.menus.' + option.name | translate }}</span>
|
||||
</button>
|
||||
}
|
||||
}
|
||||
@for (option of buttonConfig.options; track option.name) {
|
||||
@if (kindOf(option.name) === 'transact') {
|
||||
<button
|
||||
mat-menu-item
|
||||
class="sav-menu__item sav-menu__item--transact"
|
||||
*mifosxHasPermission="option.taskPermissionName"
|
||||
(click)="doAction(option.name)"
|
||||
>
|
||||
<span class="sav-menu__ico">
|
||||
<fa-icon [icon]="iconOf(option.name)"></fa-icon>
|
||||
</span>
|
||||
<span class="sav-menu__label">{{ 'labels.menus.' + option.name | translate }}</span>
|
||||
</button>
|
||||
}
|
||||
}
|
||||
</div>
|
||||
}
|
||||
|
||||
<!-- Danger (Close / Reject / Delete) -->
|
||||
@if (buttonConfig.options && !savingsAccountData.subStatus.block) {
|
||||
<div class="sav-menu__group sav-menu__group--danger">
|
||||
<div class="sav-menu__group-title">Danger zone</div>
|
||||
@for (option of buttonConfig.options; track option.name) {
|
||||
@if (kindOf(option.name) === 'danger') {
|
||||
<button
|
||||
mat-menu-item
|
||||
class="sav-menu__item sav-menu__item--danger"
|
||||
*mifosxHasPermission="option.taskPermissionName"
|
||||
(click)="doAction(option.name)"
|
||||
>
|
||||
<span class="sav-menu__ico">
|
||||
<fa-icon [icon]="iconOf(option.name)"></fa-icon>
|
||||
</span>
|
||||
<span class="sav-menu__label">{{ 'labels.menus.' + option.name | translate }}</span>
|
||||
</button>
|
||||
}
|
||||
}
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
</mat-menu>
|
||||
</header>
|
||||
|
||||
@@ -170,6 +170,14 @@ export class SavingsAccountViewComponent implements OnInit {
|
||||
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 savings account data from `resolve`
|
||||
* @param {ActivatedRoute} route Activated Route
|
||||
|
||||
Reference in New Issue
Block a user