diff --git a/src/app/accounts/accounts-list/accounts-list.component.html b/src/app/accounts/accounts-list/accounts-list.component.html new file mode 100644 index 000000000..c90880af5 --- /dev/null +++ b/src/app/accounts/accounts-list/accounts-list.component.html @@ -0,0 +1,163 @@ + + +
+ +
+
+
+ +
+
+

{{ config.label }}

+ + @if (!isLoading) { + {{ totalRecords }} total records + } @else { + Loading... + } + +
+
+
+ + +
+
+ + + @if (searchControl.value) { + + } +
+ + +
+ + +
+ @if (isLoading) { +
+ + Loading accounts... +
+ } + + @if (!isLoading && dataSource.data.length === 0) { +
+ +

No accounts found

+
+ } + + @if (!isLoading && dataSource.data.length > 0) { +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Account No + {{ row.accountNo }} + Type + + {{ getDepositTypeLabel(row) }} + + Client + {{ row.clientName }} + Product + {{ row.savingsProductName || row.depositProductName || row.productName }} + Balance + {{ getCurrencySymbol(row) }} {{ getBalance(row) | formatNumber }} + Status + + {{ getStatusLabel(row) }} + + Actions + +
+
+ + + } +
+
diff --git a/src/app/accounts/accounts-list/accounts-list.component.scss b/src/app/accounts/accounts-list/accounts-list.component.scss new file mode 100644 index 000000000..278974fce --- /dev/null +++ b/src/app/accounts/accounts-list/accounts-list.component.scss @@ -0,0 +1,482 @@ +/** + * 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 ─────────────────────────────────────────────────────────────────── +$radius-sm: 8px; +$radius-md: 12px; +$radius-lg: 16px; +$shadow-card: + 0 1px 3px rgb(0 0 0 / 6%), + 0 4px 16px rgb(0 0 0 / 6%); +$transition: 0.15s ease; + +// ─── Page ───────────────────────────────────────────────────────────────────── +.acl-page { + padding: 1.25rem 1.5rem; + display: flex; + flex-direction: column; + gap: 1rem; + max-width: 1440px; + margin: 0 auto; +} + +// ─── Header ─────────────────────────────────────────────────────────────────── +.acl-header { + display: flex; + align-items: center; + justify-content: space-between; + padding: 1.25rem 1.5rem; + border-radius: $radius-lg; + background: #fff; + box-shadow: $shadow-card; + position: relative; + overflow: hidden; + + &::before { + content: ''; + position: absolute; + inset: 0 auto 0 0; + width: 5px; + background: var(--accent-color, #1976d2); + border-radius: $radius-lg 0 0 $radius-lg; + } + + &__left { + display: flex; + align-items: center; + gap: 1rem; + } + + &__icon-wrap { + width: 48px; + height: 48px; + border-radius: $radius-md; + background: var(--accent-bg, #e3f2fd); + display: flex; + align-items: center; + justify-content: center; + font-size: 1.35rem; + color: var(--accent-color, #1976d2); + flex-shrink: 0; + } + + &__title { + margin: 0; + font-size: 1.1rem; + font-weight: 700; + color: #1a2332; + letter-spacing: -0.01em; + line-height: 1.3; + } + + &__subtitle { + font-size: 0.73rem; + color: #94a3b8; + margin-top: 3px; + display: block; + font-weight: 500; + } + + // ── Accent variants ──────────────────────────────────────────────────────── + &.accent--saving { + --accent-color: #1565c0; + --accent-bg: #dbeafe; + } + + &.accent--current { + --accent-color: #065f46; + --accent-bg: #d1fae5; + } + + &.accent--fd { + --accent-color: #6b21a8; + --accent-bg: #f3e8ff; + } + + &.accent--rd { + --accent-color: #c2410c; + --accent-bg: #ffedd5; + } +} + +// ─── Toolbar (Search + Actions) ─────────────────────────────────────────────── +.acl-toolbar { + display: flex; + align-items: center; + gap: 0.75rem; + padding: 0.75rem 1rem; + background: #fff; + border-radius: $radius-md; + box-shadow: $shadow-card; +} + +.acl-search-field { + flex: 1; + display: flex; + align-items: center; + gap: 0.6rem; + background: #f8fafc; + border: 1.5px solid #e2e8f0; + border-radius: $radius-sm; + padding: 0.45rem 0.9rem; + transition: + border-color $transition, + box-shadow $transition; + + &:focus-within { + border-color: #3b82f6; + box-shadow: 0 0 0 3px rgb(59 130 246 / 12%); + background: #fff; + } + + &__icon { + color: #94a3b8; + font-size: 0.8rem; + flex-shrink: 0; + } + + &__input { + flex: 1; + border: none; + background: transparent; + outline: none; + font-size: 0.83rem; + color: #1e293b; + + &::placeholder { + color: #cbd5e1; + } + } + + &__clear { + border: none; + background: transparent; + color: #cbd5e1; + cursor: pointer; + padding: 0; + font-size: 0.75rem; + line-height: 1; + transition: color $transition; + + &:hover { + color: #64748b; + } + } +} + +.acl-toggle-btn, +.acl-refresh-btn { + white-space: nowrap; + padding: 0.45rem 0.9rem; + border-radius: $radius-sm; + border: 1.5px solid #e2e8f0; + background: #f8fafc; + font-size: 0.78rem; + font-weight: 600; + color: #475569; + cursor: pointer; + display: inline-flex; + align-items: center; + gap: 0.35rem; + transition: + background $transition, + color $transition, + border-color $transition; + + &:hover { + background: #eff6ff; + color: #1d4ed8; + border-color: #bfdbfe; + } +} + +.acl-refresh-btn { + width: 38px; + height: 38px; + padding: 0; + justify-content: center; + flex-shrink: 0; +} + +// ─── Table Card ─────────────────────────────────────────────────────────────── +.acl-table-card { + background: #fff; + border-radius: $radius-lg; + box-shadow: $shadow-card; + border: 1px solid #f1f5f9; + overflow: hidden; + min-height: 280px; + position: relative; +} + +.acl-loading { + display: flex; + flex-direction: column; + align-items: center; + justify-content: center; + gap: 0.75rem; + padding: 4rem; + color: #94a3b8; + font-size: 0.83rem; + font-weight: 500; +} + +.acl-empty { + display: flex; + flex-direction: column; + align-items: center; + justify-content: center; + gap: 0.5rem; + padding: 4rem; + color: #cbd5e1; + + &__icon { + color: #e2e8f0; + } + + p { + font-size: 0.88rem; + font-weight: 500; + color: #94a3b8; + margin: 0; + } +} + +.acl-table-wrapper { + overflow-x: auto; +} + +// ─── Table ──────────────────────────────────────────────────────────────────── +.acl-table { + width: 100%; + + .acl-header-row { + background: #f8fafc; + border-bottom: 2px solid #e2e8f0; + } + + .acl-th { + font-size: 0.65rem; + font-weight: 700; + text-transform: uppercase; + letter-spacing: 0.07em; + color: #64748b; + padding: 0.75rem 1rem; + white-space: nowrap; + + &--right { + text-align: right !important; + } + + &--center { + text-align: center !important; + } + } + + .acl-data-row { + cursor: pointer; + border-bottom: 1px solid #f8fafc; + transition: background $transition; + + &:hover { + background: #f0f7ff !important; + + .acl-acct-no { + color: #1d4ed8; + background: #dbeafe; + } + } + + &:last-child { + border-bottom: none; + } + } + + .acl-td { + padding: 0.7rem 1rem; + font-size: 0.82rem; + vertical-align: middle; + + &--right { + text-align: right !important; + } + + &--center { + text-align: center !important; + } + } +} + +// ─── Cell Atoms ─────────────────────────────────────────────────────────────── +.acl-acct-no { + font-family: 'Courier New', monospace; + font-size: 0.77rem; + font-weight: 700; + color: #1565c0; + background: #eff6ff; + padding: 3px 10px; + border-radius: 20px; + white-space: nowrap; + transition: + background $transition, + color $transition; +} + +.acl-client-name { + font-weight: 600; + color: #1e293b; + font-size: 0.82rem; +} + +.acl-product { + font-size: 0.75rem; + color: #64748b; + background: #f1f5f9; + padding: 3px 9px; + border-radius: $radius-sm; + display: inline-block; + max-width: 160px; + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; + vertical-align: middle; + border: 1px solid #e2e8f0; +} + +.acl-balance { + font-weight: 700; + font-size: 0.88rem; + color: #15803d; + white-space: nowrap; + font-variant-numeric: tabular-nums; +} + +// ─── Deposit Type Badge ─────────────────────────────────────────────────────── +.acl-dtype-badge { + display: inline-flex; + align-items: center; + justify-content: center; + font-size: 0.62rem; + font-weight: 800; + padding: 3px 10px; + border-radius: 20px; + letter-spacing: 0.6px; + text-transform: uppercase; + + &.dtype--sb { + background: #dbeafe; + color: #1e40af; + border: 1px solid #bfdbfe; + } + + &.dtype--fd { + background: #f3e8ff; + color: #6b21a8; + border: 1px solid #e9d5ff; + } + + &.dtype--rd { + background: #ffedd5; + color: #c2410c; + border: 1px solid #fed7aa; + } + + &.dtype--ca { + background: #d1fae5; + color: #065f46; + border: 1px solid #a7f3d0; + } +} + +// ─── Status Badge ───────────────────────────────────────────────────────────── +.acl-status-badge { + display: inline-block; + font-size: 0.65rem; + font-weight: 700; + padding: 3px 10px; + border-radius: 20px; + text-transform: uppercase; + letter-spacing: 0.5px; + white-space: nowrap; + + &.status--submitted { + background: #fff7ed; + color: #c2410c; + border: 1px solid #fed7aa; + } + + &.status--approved { + background: #eff6ff; + color: #1d4ed8; + border: 1px solid #bfdbfe; + } + + &.status--active { + background: #f0fdf4; + color: #15803d; + border: 1px solid #bbf7d0; + } + + &.status--withdrawn { + background: #fdf2f8; + color: #86198f; + border: 1px solid #f0abfc; + } + + &.status--rejected { + background: #fff1f2; + color: #be123c; + border: 1px solid #fecdd3; + } + + &.status--closed { + background: #f8fafc; + color: #64748b; + border: 1px solid #e2e8f0; + } + + &.status--default { + background: #f8fafc; + color: #94a3b8; + border: 1px solid #e2e8f0; + } +} + +// ─── Action Button ──────────────────────────────────────────────────────────── +.acl-view-btn { + width: 32px; + height: 32px; + border-radius: $radius-sm; + border: 1.5px solid #e2e8f0; + background: #f8fafc; + color: #64748b; + cursor: pointer; + display: inline-flex; + align-items: center; + justify-content: center; + font-size: 0.78rem; + transition: + background $transition, + color $transition, + border-color $transition, + box-shadow $transition; + + &:hover { + background: #eff6ff; + color: #1d4ed8; + border-color: #bfdbfe; + box-shadow: 0 2px 8px rgb(29 78 216 / 15%); + } +} + +// ─── Paginator ──────────────────────────────────────────────────────────────── +.acl-paginator { + border-top: 1px solid #f1f5f9; + background: #fafbfe; + font-size: 0.8rem; +} diff --git a/src/app/accounts/accounts-list/accounts-list.component.ts b/src/app/accounts/accounts-list/accounts-list.component.ts new file mode 100644 index 000000000..2930757bf --- /dev/null +++ b/src/app/accounts/accounts-list/accounts-list.component.ts @@ -0,0 +1,327 @@ +/** + * 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, OnInit, OnDestroy, ViewChild, inject } from '@angular/core'; +import { ActivatedRoute, Router } from '@angular/router'; +import { FormControl, ReactiveFormsModule } from '@angular/forms'; +import { MatPaginator, PageEvent } from '@angular/material/paginator'; +import { MatSort, MatSortHeader, Sort } from '@angular/material/sort'; +import { + MatTableDataSource, + MatTable, + MatColumnDef, + MatHeaderCellDef, + MatHeaderCell, + MatCellDef, + MatCell, + MatHeaderRowDef, + MatHeaderRow, + MatRowDef, + MatRow +} from '@angular/material/table'; +import { Subject } from 'rxjs'; +import { debounceTime, distinctUntilChanged, takeUntil } from 'rxjs/operators'; +import { NgClass, NgIf } from '@angular/common'; +import { FaIconComponent } from '@fortawesome/angular-fontawesome'; +import { MatCardModule } from '@angular/material/card'; +import { MatTooltipModule } from '@angular/material/tooltip'; +import { MatProgressSpinnerModule } from '@angular/material/progress-spinner'; +import { MatButtonModule } from '@angular/material/button'; +import { FormatNumberPipe } from '../../pipes/format-number.pipe'; +import { STANDALONE_SHARED_IMPORTS } from 'app/standalone-shared.module'; +import { AccountsService } from '../accounts.service'; + +export type AccountType = 'savings' | 'current' | 'fixed-deposits' | 'recurring-deposits'; + +interface AccountConfig { + label: string; + icon: string; + color: string; + accentClass: string; +} + +@Component({ + selector: 'mifosx-accounts-list', + templateUrl: './accounts-list.component.html', + styleUrls: ['./accounts-list.component.scss'], + standalone: true, + imports: [ + ...STANDALONE_SHARED_IMPORTS, + ReactiveFormsModule, + FaIconComponent, + MatTable, + MatSort, + MatSortHeader, + MatColumnDef, + MatHeaderCellDef, + MatHeaderCell, + MatCellDef, + MatCell, + MatHeaderRowDef, + MatHeaderRow, + MatRowDef, + MatRow, + MatPaginator, + NgClass, + NgIf, + MatCardModule, + MatTooltipModule, + MatProgressSpinnerModule, + MatButtonModule, + FormatNumberPipe + ] +}) +export class AccountsListComponent implements OnInit, OnDestroy { + private route = inject(ActivatedRoute); + private router = inject(Router); + private accountsService = inject(AccountsService); + + private destroy$ = new Subject(); + + accountType: AccountType = 'savings'; + displayedColumns = [ + 'accountNo', + 'depositType', + 'clientName', + 'productName', + 'balance', + 'status', + 'actions' + ]; + dataSource = new MatTableDataSource([]); + + totalRecords = 0; + pageSize = 20; + pageIndex = 0; + isLoading = false; + + searchControl = new FormControl(''); + searchType: 'accountNo' | 'clientName' = 'accountNo'; + + @ViewChild(MatPaginator) paginator!: MatPaginator; + @ViewChild(MatSort) sort!: MatSort; + + readonly configs: Record = { + savings: { label: 'Savings Accounts', icon: 'piggy-bank', color: '#1976d2', accentClass: 'accent--saving' }, + current: { label: 'Current Accounts', icon: 'building', color: '#00796b', accentClass: 'accent--current' }, + 'fixed-deposits': { + label: 'Fixed Deposit Accounts', + icon: 'lock', + color: '#6a1b9a', + accentClass: 'accent--fd' + }, + 'recurring-deposits': { + label: 'Recurring Deposit Accounts', + icon: 'sync', + color: '#e65100', + accentClass: 'accent--rd' + } + }; + + get config(): AccountConfig { + return this.configs[this.accountType]; + } + + ngOnInit() { + this.route.data.pipe(takeUntil(this.destroy$)).subscribe((data) => { + this.accountType = data['accountType'] as AccountType; + this.pageIndex = 0; + this.searchControl.setValue('', { emitEvent: false }); + this.loadAccounts(); + }); + + this.searchControl.valueChanges + .pipe(debounceTime(300), distinctUntilChanged(), takeUntil(this.destroy$)) + .subscribe(() => { + this.pageIndex = 0; + this.loadAccounts(); + }); + } + + ngOnDestroy() { + this.destroy$.next(); + this.destroy$.complete(); + } + + loadAccounts() { + this.isLoading = true; + const search = (this.searchControl.value || '').trim(); + const params = { + offset: this.pageIndex * this.pageSize, + limit: this.pageSize, + accountNo: this.searchType === 'accountNo' ? search : undefined, + clientName: this.searchType === 'clientName' ? search : undefined + }; + + const obs$ = + this.accountType === 'savings' + ? this.accountsService.getSavingsAccounts(params) + : this.accountType === 'current' + ? this.accountsService.getCurrentAccounts(params) + : this.accountType === 'fixed-deposits' + ? this.accountsService.getFixedDepositAccounts(params) + : this.accountsService.getRecurringDepositAccounts(params); + + obs$.pipe(takeUntil(this.destroy$)).subscribe({ + next: (res) => { + let items: any[] = Array.isArray(res) ? res : (res?.pageItems ?? []); + + // Client-side deposit type filter (safety net until backend rebuild) + const depositTypeFilter = this.getDepositTypeId(); + if (depositTypeFilter !== null) { + items = items.filter((a: any) => a?.depositType?.id === depositTypeFilter); + } + + // Client-side search fallback (for when backend search isn't rebuilt yet) + const searchTerm = (this.searchControl.value || '').trim().toLowerCase(); + if (searchTerm) { + items = items.filter((a: any) => { + if (this.searchType === 'accountNo') { + return (a?.accountNo || '').toLowerCase().includes(searchTerm); + } + return (a?.clientName || '').toLowerCase().includes(searchTerm); + }); + } + + this.totalRecords = Array.isArray(res) ? items.length : (res?.totalFilteredRecords ?? items.length); + this.dataSource.data = items; + this.isLoading = false; + }, + error: () => { + this.isLoading = false; + } + }); + } + + onPageChange(event: PageEvent) { + this.pageIndex = event.pageIndex; + this.pageSize = event.pageSize; + this.loadAccounts(); + } + + onSortChange(sort: Sort) { + this.pageIndex = 0; + this.loadAccounts(); + } + + toggleSearchType() { + this.searchType = this.searchType === 'accountNo' ? 'clientName' : 'accountNo'; + if (this.searchControl.value) { + this.loadAccounts(); + } + } + + clearSearch() { + this.searchControl.setValue(''); + } + + getDepositTypeId(): number | null { + // Only filter on savings page — FD/RD endpoints already return correct type + return this.accountType === 'savings' ? 100 : null; + } + + getDepositTypeBadgeClass(_account: any): string { + switch (this.accountType) { + case 'savings': + return 'dtype--sb'; + case 'fixed-deposits': + return 'dtype--fd'; + case 'recurring-deposits': + return 'dtype--rd'; + default: + return 'dtype--ca'; + } + } + + getDepositTypeLabel(_account: any): string { + switch (this.accountType) { + case 'savings': + return 'SB'; + case 'fixed-deposits': + return 'FD'; + case 'recurring-deposits': + return 'RD'; + default: + return 'CA'; + } + } + + viewAccount(account: any) { + const id = account.id; + switch (this.accountType) { + case 'savings': + this.router.navigate([ + '/clients', + account.clientId, + 'savings-accounts', + id, + 'general' + ]); + break; + case 'current': + this.router.navigate([ + '/clients', + account.clientId, + 'current-accounts', + id, + 'general' + ]); + break; + case 'fixed-deposits': + this.router.navigate([ + '/clients', + account.clientId, + 'fixed-deposits-accounts', + id, + 'general' + ]); + break; + case 'recurring-deposits': + this.router.navigate([ + '/clients', + account.clientId, + 'recurring-deposits-accounts', + id, + 'general' + ]); + break; + } + } + + getBalance(account: any): number { + return account?.summary?.accountBalance ?? account?.accountBalance ?? 0; + } + + getCurrencySymbol(account: any): string { + return account?.currency?.displaySymbol || account?.currency?.code || '₹'; + } + + getStatusClass(account: any): string { + const id = account?.status?.id ?? account?.statusId; + switch (id) { + case 100: + return 'status--submitted'; + case 200: + return 'status--approved'; + case 300: + return 'status--active'; + case 400: + return 'status--withdrawn'; + case 500: + return 'status--rejected'; + case 600: + return 'status--closed'; + default: + return 'status--default'; + } + } + + getStatusLabel(account: any): string { + return account?.status?.value ?? account?.statusValue ?? 'Unknown'; + } +} diff --git a/src/app/accounts/accounts-routing.module.ts b/src/app/accounts/accounts-routing.module.ts new file mode 100644 index 000000000..3654ae7de --- /dev/null +++ b/src/app/accounts/accounts-routing.module.ts @@ -0,0 +1,54 @@ +/** + * 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 { NgModule } from '@angular/core'; +import { Routes, RouterModule } from '@angular/router'; + +import { Route } from '../core/route/route.service'; +import { AccountsListComponent } from './accounts-list/accounts-list.component'; + +const routes: Routes = [ + Route.withShell([ + { + path: 'accounts', + children: [ + { path: '', redirectTo: 'savings', pathMatch: 'full' }, + { + path: 'savings', + component: AccountsListComponent, + data: { accountType: 'savings', title: 'Savings Accounts', breadcrumb: 'Savings Accounts' } + }, + { + path: 'current', + component: AccountsListComponent, + data: { accountType: 'current', title: 'Current Accounts', breadcrumb: 'Current Accounts' } + }, + { + path: 'fixed-deposits', + component: AccountsListComponent, + data: { accountType: 'fixed-deposits', title: 'Fixed Deposit Accounts', breadcrumb: 'Fixed Deposit Accounts' } + }, + { + path: 'recurring-deposits', + component: AccountsListComponent, + data: { + accountType: 'recurring-deposits', + title: 'Recurring Deposit Accounts', + breadcrumb: 'Recurring Deposit Accounts' + } + } + ] + } + ]) +]; + +@NgModule({ + imports: [RouterModule.forChild(routes)], + exports: [RouterModule] +}) +export class AccountsRoutingModule {} diff --git a/src/app/accounts/accounts.module.ts b/src/app/accounts/accounts.module.ts new file mode 100644 index 000000000..780ca1e1c --- /dev/null +++ b/src/app/accounts/accounts.module.ts @@ -0,0 +1,19 @@ +/** + * 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 { NgModule } from '@angular/core'; +import { AccountsRoutingModule } from './accounts-routing.module'; +import { AccountsListComponent } from './accounts-list/accounts-list.component'; + +@NgModule({ + imports: [ + AccountsRoutingModule, + AccountsListComponent + ] +}) +export class AccountsModule {} diff --git a/src/app/accounts/accounts.service.ts b/src/app/accounts/accounts.service.ts new file mode 100644 index 000000000..d48f2b0e9 --- /dev/null +++ b/src/app/accounts/accounts.service.ts @@ -0,0 +1,70 @@ +/** + * 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 { Injectable, inject } from '@angular/core'; +import { HttpClient, HttpParams } from '@angular/common/http'; +import { Observable } from 'rxjs'; + +export interface AccountListParams { + offset?: number; + limit?: number; + accountNo?: string; + clientName?: string; + orderBy?: string; + sortOrder?: string; +} + +@Injectable({ providedIn: 'root' }) +export class AccountsService { + private http = inject(HttpClient); + + getSavingsAccounts(params: AccountListParams = {}): Observable { + let httpParams = new HttpParams() + .set('depositType', '100') + .set('offset', (params.offset ?? 0).toString()) + .set('limit', (params.limit ?? 20).toString()); + if (params.accountNo) httpParams = httpParams.set('accountNo', params.accountNo); + if (params.clientName) httpParams = httpParams.set('clientName', params.clientName); + if (params.orderBy) httpParams = httpParams.set('orderBy', params.orderBy); + if (params.sortOrder) httpParams = httpParams.set('sortOrder', params.sortOrder); + return this.http.get('/savingsaccounts', { params: httpParams }); + } + + getCurrentAccounts(params: AccountListParams = {}): Observable { + let httpParams = new HttpParams() + .set('offset', (params.offset ?? 0).toString()) + .set('limit', (params.limit ?? 20).toString()); + if (params.accountNo) httpParams = httpParams.set('accountNo', params.accountNo); + if (params.clientName) httpParams = httpParams.set('clientName', params.clientName); + return this.http.get('/currentaccounts', { params: httpParams }); + } + + getFixedDepositAccounts(params: AccountListParams = {}): Observable { + let httpParams = new HttpParams() + .set('paged', 'true') + .set('offset', (params.offset ?? 0).toString()) + .set('limit', (params.limit ?? 20).toString()); + if (params.accountNo) httpParams = httpParams.set('accountNo', params.accountNo); + if (params.clientName) httpParams = httpParams.set('clientName', params.clientName); + if (params.orderBy) httpParams = httpParams.set('orderBy', params.orderBy); + if (params.sortOrder) httpParams = httpParams.set('sortOrder', params.sortOrder); + return this.http.get('/fixeddepositaccounts', { params: httpParams }); + } + + getRecurringDepositAccounts(params: AccountListParams = {}): Observable { + let httpParams = new HttpParams() + .set('paged', 'true') + .set('offset', (params.offset ?? 0).toString()) + .set('limit', (params.limit ?? 20).toString()); + if (params.accountNo) httpParams = httpParams.set('accountNo', params.accountNo); + if (params.clientName) httpParams = httpParams.set('clientName', params.clientName); + if (params.orderBy) httpParams = httpParams.set('orderBy', params.orderBy); + if (params.sortOrder) httpParams = httpParams.set('sortOrder', params.sortOrder); + return this.http.get('/recurringdepositaccounts', { params: httpParams }); + } +} diff --git a/src/app/app.module.ts b/src/app/app.module.ts index 056c7f946..b42ed9907 100644 --- a/src/app/app.module.ts +++ b/src/app/app.module.ts @@ -63,6 +63,7 @@ import { FiuModule } from './fiu/fiu.module'; import { SftModule } from './sft/sft.module'; import { DigitalModule } from './digital/digital.module'; import { LetterMgmtModule } from './letter-mgmt/letter-mgmt.module'; +import { AccountsModule } from './accounts/accounts.module'; import { PortalModule } from '@angular/cdk/portal'; /** Main Routing Module */ @@ -162,6 +163,7 @@ export function HttpLoaderFactory(http: HttpClient) { SftModule, DigitalModule, LetterMgmtModule, + AccountsModule, AppRoutingModule, NotFoundComponent, CallbackComponent, diff --git a/src/app/core/shell/shell.component.html b/src/app/core/shell/shell.component.html index 2f313eca8..4987ca946 100644 --- a/src/app/core/shell/shell.component.html +++ b/src/app/core/shell/shell.component.html @@ -564,14 +564,18 @@
Accounts
- - - + - +