feat: add current accounts list module with redesigned UI

- New accounts module with list, routing, and service
- Redesigned accounts-list UI with modern card layout, status badges, and action buttons
- Fixed totalRecords formatting (removed formatNumber pipe from integer count)
- Register accounts module in app.module and shell navigation

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Jaanu423
2026-05-21 11:19:30 +05:30
co-authored by Claude Sonnet 4.6
parent 43bab670a0
commit 45d4397b0e
8 changed files with 1125 additions and 4 deletions
@@ -0,0 +1,163 @@
<!--
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/.
-->
<div class="acl-page">
<!-- Header -->
<div class="acl-header" [ngClass]="config.accentClass">
<div class="acl-header__left">
<div class="acl-header__icon-wrap">
<fa-icon [icon]="config.icon"></fa-icon>
</div>
<div>
<h2 class="acl-header__title">{{ config.label }}</h2>
<span class="acl-header__subtitle">
@if (!isLoading) {
{{ totalRecords }} total records
} @else {
Loading...
}
</span>
</div>
</div>
</div>
<!-- Toolbar -->
<div class="acl-toolbar">
<div class="acl-search-field">
<fa-icon icon="search" class="acl-search-field__icon"></fa-icon>
<input
[formControl]="searchControl"
class="acl-search-field__input"
[placeholder]="searchType === 'accountNo' ? 'Search by account number...' : 'Search by client name...'"
/>
@if (searchControl.value) {
<button class="acl-search-field__clear" (click)="clearSearch()" matTooltip="Clear">
<fa-icon icon="times"></fa-icon>
</button>
}
</div>
<button
class="acl-toggle-btn"
(click)="toggleSearchType()"
[matTooltip]="'Switch to ' + (searchType === 'accountNo' ? 'client name' : 'account number') + ' search'"
>
<fa-icon icon="exchange-alt"></fa-icon>
{{ searchType === 'accountNo' ? 'Acct No' : 'Client' }}
</button>
<button class="acl-refresh-btn" (click)="loadAccounts()" matTooltip="Refresh">
<fa-icon icon="sync-alt"></fa-icon>
</button>
</div>
<!-- Table Card -->
<div class="acl-table-card">
@if (isLoading) {
<div class="acl-loading">
<mat-spinner diameter="36"></mat-spinner>
<span>Loading accounts...</span>
</div>
}
@if (!isLoading && dataSource.data.length === 0) {
<div class="acl-empty">
<fa-icon icon="inbox" size="2x" class="acl-empty__icon"></fa-icon>
<p>No accounts found</p>
</div>
}
@if (!isLoading && dataSource.data.length > 0) {
<div class="acl-table-wrapper">
<table mat-table [dataSource]="dataSource" matSort (matSortChange)="onSortChange($event)" class="acl-table">
<!-- Account No -->
<ng-container matColumnDef="accountNo">
<th mat-header-cell *matHeaderCellDef mat-sort-header class="acl-th">Account No</th>
<td mat-cell *matCellDef="let row" class="acl-td">
<span class="acl-acct-no">{{ row.accountNo }}</span>
</td>
</ng-container>
<!-- Type -->
<ng-container matColumnDef="depositType">
<th mat-header-cell *matHeaderCellDef class="acl-th acl-th--center">Type</th>
<td mat-cell *matCellDef="let row" class="acl-td acl-td--center">
<span class="acl-dtype-badge" [ngClass]="getDepositTypeBadgeClass(row)">
{{ getDepositTypeLabel(row) }}
</span>
</td>
</ng-container>
<!-- Client -->
<ng-container matColumnDef="clientName">
<th mat-header-cell *matHeaderCellDef mat-sort-header class="acl-th">Client</th>
<td mat-cell *matCellDef="let row" class="acl-td">
<span class="acl-client-name">{{ row.clientName }}</span>
</td>
</ng-container>
<!-- Product -->
<ng-container matColumnDef="productName">
<th mat-header-cell *matHeaderCellDef mat-sort-header class="acl-th">Product</th>
<td mat-cell *matCellDef="let row" class="acl-td">
<span class="acl-product">{{ row.savingsProductName || row.depositProductName || row.productName }}</span>
</td>
</ng-container>
<!-- Balance -->
<ng-container matColumnDef="balance">
<th mat-header-cell *matHeaderCellDef class="acl-th acl-th--right">Balance</th>
<td mat-cell *matCellDef="let row" class="acl-td acl-td--right">
<span class="acl-balance">{{ getCurrencySymbol(row) }} {{ getBalance(row) | formatNumber }}</span>
</td>
</ng-container>
<!-- Status -->
<ng-container matColumnDef="status">
<th mat-header-cell *matHeaderCellDef class="acl-th acl-th--center">Status</th>
<td mat-cell *matCellDef="let row" class="acl-td acl-td--center">
<span class="acl-status-badge" [ngClass]="getStatusClass(row)">
{{ getStatusLabel(row) }}
</span>
</td>
</ng-container>
<!-- Actions -->
<ng-container matColumnDef="actions">
<th mat-header-cell *matHeaderCellDef class="acl-th acl-th--center">Actions</th>
<td mat-cell *matCellDef="let row" class="acl-td acl-td--center">
<button
class="acl-view-btn"
(click)="$event.stopPropagation(); viewAccount(row)"
matTooltip="View Account"
>
<fa-icon icon="eye"></fa-icon>
</button>
</td>
</ng-container>
<tr mat-header-row *matHeaderRowDef="displayedColumns" class="acl-header-row"></tr>
<tr
mat-row
*matRowDef="let row; columns: displayedColumns"
class="acl-data-row"
(click)="viewAccount(row)"
></tr>
</table>
</div>
<mat-paginator
[length]="totalRecords"
[pageSize]="pageSize"
[pageIndex]="pageIndex"
[pageSizeOptions]="[10, 20, 50, 100]"
(page)="onPageChange($event)"
class="acl-paginator"
showFirstLastButtons
></mat-paginator>
}
</div>
</div>