feat: Nexora UI upgrade for Current Account, FD, and RD account views

- Current Account: hero header with navy gradient, pill tabs, Nexora card layout for general tab, txn-tab/chg-tab table styles, bank statement passbook
- Fixed Deposits: fd-* prefixed hero header, KPI tiles, pill tab nav, nx-card general tab layout, txn-tab transactions, chg-tab charges
- Recurring Deposits: rd-* prefixed hero header with three KPI tiles, pill tab nav, nx-card general tab layout, txn-tab transactions, chg-tab charges
- Fix: removed broken FA4-format icon references from action menu buttons

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Jaanu423
2026-05-25 11:02:15 +05:30
co-authored by Claude Sonnet 4.6
parent ad6f629c3f
commit b7d009b22a
30 changed files with 4149 additions and 2090 deletions
@@ -6,25 +6,22 @@
file, You can obtain one at http://mozilla.org/MPL/2.0/. file, You can obtain one at http://mozilla.org/MPL/2.0/.
--> -->
<div class="tab-container mat-typography"> <div class="chg-tab">
<div class="layout-row align-start"> <div class="chg-tab__card">
<div class="m-b-10"> <div class="chg-tab__toolbar">
<h3>{{ 'labels.inputs.Charges' | translate }}</h3> <h3 class="chg-tab__title">{{ 'labels.inputs.Charges' | translate }}</h3>
</div> <span class="chg-tab__spacer"></span>
@if (this.chargesData) { @if (this.chargesData) {
<div class="action-button m-b-20"> <button mat-flat-button class="chg-tab__toggle" (click)="toggleCharges()">
<button mat-raised-button color="primary" (click)="toggleCharges()">
{{ {{
showInactiveCharges showInactiveCharges
? viewAllChargeButtons('View Active Charges') ? viewAllChargeButtons('View Active Charges')
: viewAllChargeButtons('View Inactive Charges') : viewAllChargeButtons('View Inactive Charges')
}} }}
</button> </button>
</div>
} }
</div> </div>
<div class="mat-elevation-z1 m-b-25">
<table mat-table #chargesTable [dataSource]="dataSource"> <table mat-table #chargesTable [dataSource]="dataSource">
<ng-container matColumnDef="name"> <ng-container matColumnDef="name">
<th mat-header-cell *matHeaderCellDef>{{ 'labels.inputs.Name' | translate }}</th> <th mat-header-cell *matHeaderCellDef>{{ 'labels.inputs.Name' | translate }}</th>
@@ -6,30 +6,107 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. * file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/ */
.tab-container { $navy: #0d1b2a;
padding: 1%; $slate: #475569;
margin: 1%; $muted: #64748b;
$border: #e2e8f0;
$soft: #f8fafc;
$blue: #1e40af;
h3 { .chg-tab {
margin: 1% auto; width: 100%;
} }
.action-button { .chg-tab__card {
margin-left: auto; background: #fff;
border: 1px solid $border;
border-radius: 14px;
box-shadow: 0 1px 3px rgb(15 23 42 / 4%);
overflow: hidden;
}
.chg-tab__toolbar {
display: flex;
align-items: center;
gap: 14px;
padding: 12px 18px;
background: $soft;
border-bottom: 1px solid $border;
}
.chg-tab__title {
margin: 0;
font-size: 14px;
font-weight: 700;
color: $navy;
letter-spacing: 0.01em;
}
.chg-tab__spacer {
flex: 1;
}
.chg-tab__toggle {
height: 34px !important;
border-radius: 8px !important;
font-weight: 600 !important;
font-size: 13px !important;
padding: 0 14px !important;
background: linear-gradient(135deg, #1e88e5 0%, $blue 100%) !important;
color: #fff !important;
} }
table { table {
width: 100%; width: 100%;
.account-action-button {
min-width: 26px;
padding: 0 6px;
margin: 4px;
line-height: 25px;
} }
.select-row:hover { ::ng-deep .chg-tab__card {
.mat-mdc-header-row {
background: $soft;
}
.mat-mdc-header-cell {
font-size: 11.5px;
font-weight: 800;
color: $slate;
text-transform: uppercase;
letter-spacing: 0.06em;
padding: 12px 14px;
border-bottom: 1px solid $border;
}
.mat-mdc-cell {
font-size: 13px;
color: $navy;
padding: 11px 14px;
border-bottom: 1px solid #f1f5f9;
}
.mat-mdc-row:hover {
background: #f8fafc;
cursor: pointer; cursor: pointer;
} }
/* Right-align monetary columns. */
.mat-column-due,
.mat-column-paid,
.mat-column-waived,
.mat-column-outstanding {
text-align: right;
font-variant-numeric: tabular-nums;
}
.mat-column-actions {
text-align: center;
width: 140px;
.account-action-button {
min-width: 30px !important;
padding: 0 8px !important;
margin: 0 3px !important;
height: 30px !important;
line-height: 30px !important;
border-radius: 7px !important;
}
} }
} }
@@ -6,115 +6,90 @@
file, You can obtain one at http://mozilla.org/MPL/2.0/. file, You can obtain one at http://mozilla.org/MPL/2.0/.
--> -->
<mat-card class="account-card"> <div class="cur-view">
<mat-card-header class="header layout-column"> <!-- ─── Gradient hero header ─────────────────────────────────────── -->
<mat-card-title-group class="header-title-group"> <header class="cur-hero">
<div class="profile-image-container"> <div class="cur-hero__left">
<div> <div class="cur-hero__avatar">
<img <fa-icon icon="university"></fa-icon>
mat-card-md-image
class="profile-image"
matTooltip="{{ 'tooltips.Current Account' | translate }}"
[src]="'assets/images/current_account_placeholder.png'"
/>
</div>
</div> </div>
<div class="mat-typography account-card-title"> <div class="cur-hero__info">
<mat-card-title class="layout-row layout-lt-md-column"> <!-- Status pill -->
<div class="flex-60"> <div class="cur-hero__status-row">
<h3>
@if (!currentAccountData.subStatus.block) { @if (!currentAccountData.subStatus.block) {
<i <span
class="fa fa-stop" class="cur-status-pill"
[ngClass]="currentAccountData.status.code | statusLookup" [ngClass]="currentAccountData.status.code | statusLookup"
[matTooltip]="currentAccountData.status.value" [matTooltip]="currentAccountData.status.value"
></i> >
} <span class="cur-status-pill__dot"></span>
@if (currentAccountData.subStatus.block) { {{ currentAccountData.status.value }}
<i </span>
class="fa fa-stop" } @else {
<span
class="cur-status-pill cur-status-pill--warn"
[ngClass]="currentAccountData.subStatus.value | statusLookup" [ngClass]="currentAccountData.subStatus.value | statusLookup"
[matTooltip]="currentAccountData.subStatus.value" [matTooltip]="currentAccountData.subStatus.value"
></i> >
<span class="cur-status-pill__dot"></span>
{{ currentAccountData.subStatus.value }}
</span>
} }
</h3> </div>
<!-- Product Name Row -->
<span class="product-row"> <h2 class="cur-hero__title">
<span class="m-r-5">{{ 'labels.inputs.Current Account Product' | translate }} :</span>
<span class="m-r-5">
<mifosx-long-text textValue="{{ currentAccountData.currentAccountProductName }}"></mifosx-long-text> <mifosx-long-text textValue="{{ currentAccountData.currentAccountProductName }}"></mifosx-long-text>
</span> </h2>
</span>
<!-- Account Number Row --> <div class="cur-hero__meta">
<span class="account-number-row"> <span class="cur-hero__meta-item">
<span class="m-r-5">{{ 'labels.inputs.Account Number' | translate }} :</span> <span class="cur-hero__meta-label">{{ 'labels.inputs.Account Number' | translate }}</span>
<span class="m-r-5">
<mifosx-account-number <mifosx-account-number
accountNo="{{ currentAccountData.accountNo }}" accountNo="{{ currentAccountData.accountNo }}"
display="left" display="left"
></mifosx-account-number> ></mifosx-account-number>
</span> </span>
<span class="cur-hero__meta-item">
<span class="cur-hero__meta-label">
{{ 'labels.text.' + entityType | translate }} {{ 'labels.inputs.name' | translate }}
</span> </span>
<!-- External ID Row --> <span class="cur-hero__meta-value">
@if (currentAccountData.externalId) {
<span class="external-id-row">
<span class="m-r-5">{{ 'labels.inputs.External Id' | translate }} :</span>
<span>{{ currentAccountData.externalId }}</span>
</span>
}
<span class="account-overview">
{{ 'labels.text.' + entityType | translate }} {{ 'labels.inputs.name' | translate }}:
{{ currentAccountData.clientName || currentAccountData.groupName }} {{ currentAccountData.clientName || currentAccountData.groupName }}
@if (currentAccountData.clientAccountNo) { @if (currentAccountData.clientAccountNo) {
<span class="m-l-10">
<mifosx-account-number accountNo="{{ currentAccountData.clientAccountNo }}"></mifosx-account-number> <mifosx-account-number accountNo="{{ currentAccountData.clientAccountNo }}"></mifosx-account-number>
</span>
} }
</span> </span>
</span>
</div>
</div>
</div> </div>
<!-- Balance KPI strip -->
@if (!currentAccountData.status.rejected && !currentAccountData.status.submittedAndPendingApproval) { @if (!currentAccountData.status.rejected && !currentAccountData.status.submittedAndPendingApproval) {
<div class="flex-30"> <div class="cur-hero__kpis">
<h3>{{ 'labels.heading.Account Overview' | translate }}</h3> <div class="cur-kpi">
<table class="account-overview"> <span class="cur-kpi__label">{{ 'labels.inputs.Current Balance' | translate }}</span>
<tbody> <span class="cur-kpi__value">
<tr> {{ currentAccountData.summary.accountBalance | currency: currency.code : 'symbol-narrow' : '1.2-2' }}
<td>{{ 'labels.inputs.Current Balance' | translate }}</td> </span>
<td class="r-amount"> </div>
{{ <div class="cur-kpi cur-kpi--available">
currentAccountData.summary.accountBalance | currency: currency.code : 'symbol-narrow' : '1.2-2' <span class="cur-kpi__label">{{ 'labels.inputs.Available Balance' | translate }}</span>
}} <span class="cur-kpi__value">
</td> {{ currentAccountData.summary.availableBalance | currency: currency.code : 'symbol-narrow' : '1.2-2' }}
</tr> </span>
<tr> </div>
<td>{{ 'labels.inputs.Available Balance' | translate }}</td>
<td class="r-amount">
{{
currentAccountData.summary.availableBalance
| currency: currency.code : 'symbol-narrow' : '1.2-2'
}}
</td>
</tr>
</tbody>
</table>
</div> </div>
} }
<div class="flex-5"> <!-- Action menu (kebab) -->
<button <div class="cur-hero__actions">
mat-icon-button <button mat-icon-button [matMenuTriggerFor]="accountMenu" aria-label="Account actions" yPosition="below">
[matMenuTriggerFor]="accountMenu" <fa-icon icon="ellipsis-v"></fa-icon>
aria-label="Loan account actions"
yPosition="below"
>
<mat-icon matListIcon class="actions-menu">
<fa-icon icon="bars" size="sm"></fa-icon>
</mat-icon>
</button> </button>
</div> </div>
</mat-card-title>
</div>
<mat-menu #accountMenu="matMenu"> <mat-menu #accountMenu="matMenu">
@for (item of buttonConfig.singleButtons; track item) { @for (item of buttonConfig.singleButtons; track item) {
@@ -139,106 +114,124 @@
</mat-menu> </mat-menu>
} }
</mat-menu> </mat-menu>
</mat-card-title-group> </header>
</mat-card-header>
<mat-card-content class="content"> <!-- ─── Pill-style tab navigation ─────────────────────────────────── -->
@if (isActive) { @if (isActive) {
<nav mat-tab-nav-bar class="navigation-tabs" [tabPanel]="tabPanel"> <nav mat-tab-nav-bar class="cur-tabs" [tabPanel]="tabPanel">
<a <a
mat-tab-link mat-tab-link
class="cur-tab"
[routerLink]="['./general']" [routerLink]="['./general']"
routerLinkActive routerLinkActive
#general="routerLinkActive" #general="routerLinkActive"
[active]="general.isActive" [active]="general.isActive"
> >
{{ 'labels.inputs.General' | translate }} <fa-icon icon="info-circle" class="cur-tab__ic"></fa-icon>
<span>{{ 'labels.inputs.General' | translate }}</span>
</a> </a>
<a <a
mat-tab-link mat-tab-link
class="cur-tab"
[routerLink]="['./transactions']" [routerLink]="['./transactions']"
routerLinkActive routerLinkActive
#transactions="routerLinkActive" #transactions="routerLinkActive"
[active]="transactions.isActive" [active]="transactions.isActive"
> >
{{ 'labels.inputs.Transactions' | translate }} <fa-icon icon="exchange-alt" class="cur-tab__ic"></fa-icon>
<span>{{ 'labels.inputs.Transactions' | translate }}</span>
</a> </a>
<a <a
mat-tab-link mat-tab-link
class="cur-tab"
[routerLink]="['./passbook']" [routerLink]="['./passbook']"
routerLinkActive routerLinkActive
#passbook="routerLinkActive" #passbook="routerLinkActive"
[active]="passbook.isActive" [active]="passbook.isActive"
> >
{{ 'labels.inputs.Passbook' | translate }} <fa-icon icon="book" class="cur-tab__ic"></fa-icon>
<span>{{ 'labels.inputs.Passbook' | translate }}</span>
</a> </a>
<a <a
mat-tab-link mat-tab-link
class="cur-tab"
[routerLink]="['./charges']" [routerLink]="['./charges']"
routerLinkActive routerLinkActive
#charges="routerLinkActive" #charges="routerLinkActive"
[active]="charges.isActive" [active]="charges.isActive"
> >
{{ 'labels.inputs.Charges' | translate }} <fa-icon icon="receipt" class="cur-tab__ic"></fa-icon>
<span>{{ 'labels.inputs.Charges' | translate }}</span>
</a> </a>
<a <a
mat-tab-link mat-tab-link
class="cur-tab"
[routerLink]="['./documents']" [routerLink]="['./documents']"
routerLinkActive routerLinkActive
#currentAccountDocuments="routerLinkActive" #currentAccountDocuments="routerLinkActive"
[active]="currentAccountDocuments.isActive" [active]="currentAccountDocuments.isActive"
> >
{{ 'labels.inputs.Documents' | translate }} <fa-icon icon="folder-open" class="cur-tab__ic"></fa-icon>
<span>{{ 'labels.inputs.Documents' | translate }}</span>
</a> </a>
<a <a
mat-tab-link mat-tab-link
class="cur-tab"
*mifosxHasPermission="'READ_CURRENTACCOUNTNOTE'" *mifosxHasPermission="'READ_CURRENTACCOUNTNOTE'"
[routerLink]="['./notes']" [routerLink]="['./notes']"
routerLinkActive routerLinkActive
#notes="routerLinkActive" #notes="routerLinkActive"
[active]="notes.isActive" [active]="notes.isActive"
> >
{{ 'labels.inputs.Notes' | translate }} <fa-icon icon="sticky-note" class="cur-tab__ic"></fa-icon>
<span>{{ 'labels.inputs.Notes' | translate }}</span>
</a> </a>
<ng-container *mifosxHasPermission="'READ_CURRENTACCOUNTCHARGE'"> <ng-container *mifosxHasPermission="'READ_CURRENTACCOUNTCHARGE'">
@if (currentAccountData.clientId) { @if (currentAccountData.clientId) {
<a <a
mat-tab-link mat-tab-link
class="cur-tab"
[routerLink]="['./standing-instructions']" [routerLink]="['./standing-instructions']"
routerLinkActive routerLinkActive
#standingInstructions="routerLinkActive" #standingInstructions="routerLinkActive"
[active]="standingInstructions.isActive" [active]="standingInstructions.isActive"
> >
{{ 'labels.inputs.Standing Instructions' | translate }} <fa-icon icon="calendar-check" class="cur-tab__ic"></fa-icon>
<span>{{ 'labels.inputs.Standing Instructions' | translate }}</span>
</a> </a>
} }
</ng-container> </ng-container>
<a <a
mat-tab-link mat-tab-link
class="cur-tab"
[routerLink]="['./nominees']" [routerLink]="['./nominees']"
routerLinkActive routerLinkActive
#nominees="routerLinkActive" #nominees="routerLinkActive"
[active]="nominees.isActive" [active]="nominees.isActive"
> >
Nominees <fa-icon icon="user-shield" class="cur-tab__ic"></fa-icon>
<span>Nominees</span>
</a> </a>
@for (currentAccountDatatable of currentAccountDatatables; track currentAccountDatatable) { @for (currentAccountDatatable of currentAccountDatatables; track currentAccountDatatable) {
<a <a
mat-tab-link mat-tab-link
class="cur-tab"
*mifosxHasPermission="'READ_' + currentAccountDatatable.registeredTableName" *mifosxHasPermission="'READ_' + currentAccountDatatable.registeredTableName"
[routerLink]="['./datatables', currentAccountDatatable.registeredTableName]" [routerLink]="['./datatables', currentAccountDatatable.registeredTableName]"
routerLinkActive routerLinkActive
#datatable="routerLinkActive" #datatable="routerLinkActive"
[active]="datatable.isActive" [active]="datatable.isActive"
> >
{{ currentAccountDatatable.registeredTableName }} <fa-icon icon="table" class="cur-tab__ic"></fa-icon>
<span>{{ currentAccountDatatable.registeredTableName }}</span>
</a> </a>
} }
</nav> </nav>
} }
<mat-tab-nav-panel #tabPanel> <mat-tab-nav-panel #tabPanel>
<div class="cur-body">
<router-outlet></router-outlet> <router-outlet></router-outlet>
</div>
</mat-tab-nav-panel> </mat-tab-nav-panel>
</mat-card-content> </div>
</mat-card>
@@ -6,12 +6,390 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. * file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/ */
mat-card-title { $navy: #0d1b2a;
display: flex; $blue: #1e88e5;
$blue-d: #1e40af;
$border: #e2e8f0;
.cur-view {
max-width: 1440px;
margin: 0 auto;
padding: 12px 20px 22px;
} }
.product-row, /* ─── Gradient hero header ──────────────────────────────────────────── */
.account-number-row, .cur-hero {
.external-id-row { position: relative;
display: block; display: grid;
grid-template-columns: minmax(0, 1fr) auto auto;
align-items: stretch;
gap: 14px;
padding: 12px 18px;
border-radius: 12px;
color: #fff;
background: linear-gradient(135deg, #1e3a8a 0%, #1e40af 45%, #4338ca 100%);
box-shadow: 0 6px 18px -10px rgb(15 23 42 / 35%);
overflow: hidden;
&::before {
content: '';
position: absolute;
inset: 0;
background: radial-gradient(circle at top right, rgb(255 255 255 / 12%) 0%, transparent 55%);
pointer-events: none;
}
&__left {
display: flex;
align-items: center;
gap: 12px;
min-width: 0;
position: relative;
z-index: 1;
}
&__avatar {
width: 40px;
height: 40px;
border-radius: 10px;
background: linear-gradient(135deg, rgb(255 255 255 / 22%) 0%, rgb(255 255 255 / 10%) 100%);
border: 1px solid rgb(255 255 255 / 28%);
display: flex;
align-items: center;
justify-content: center;
color: #fff;
font-size: 16px;
flex-shrink: 0;
box-shadow: 0 3px 10px -3px rgb(0 0 0 / 25%);
}
&__info {
display: flex;
flex-direction: column;
gap: 3px;
min-width: 0;
}
&__status-row {
display: flex;
align-items: center;
gap: 6px;
}
&__title {
margin: 0;
font-size: 15px;
font-weight: 800;
letter-spacing: 0.01em;
color: #fff;
line-height: 1.15;
::ng-deep mifosx-long-text {
color: #fff;
}
}
&__meta {
display: flex;
flex-wrap: wrap;
gap: 2px 18px;
margin-top: 1px;
}
&__meta-item {
display: inline-flex;
align-items: center;
gap: 6px;
font-size: 12px;
color: rgb(255 255 255 / 90%);
}
&__meta-label {
font-size: 10px;
text-transform: uppercase;
letter-spacing: 0.07em;
color: rgb(255 255 255 / 60%);
font-weight: 600;
}
&__meta-value {
font-weight: 600;
color: #fff;
}
&__kpis {
display: flex;
gap: 8px;
align-items: stretch;
position: relative;
z-index: 1;
}
&__actions {
display: flex;
align-items: center;
position: relative;
z-index: 1;
button {
width: 32px !important;
height: 32px !important;
min-width: 32px !important;
padding: 0 !important;
border-radius: 50% !important;
color: #fff !important;
background: rgb(255 255 255 / 10%) !important;
border: 1px solid rgb(255 255 255 / 22%) !important;
display: inline-flex !important;
align-items: center;
justify-content: center;
line-height: 1;
transition:
background 0.15s ease,
border-color 0.15s ease,
transform 0.12s ease;
::ng-deep fa-icon {
font-size: 14px;
line-height: 1;
display: inline-flex;
align-items: center;
justify-content: center;
}
::ng-deep .mat-mdc-button-persistent-ripple,
::ng-deep .mat-mdc-button-touch-target {
border-radius: 50% !important;
}
}
button:hover {
background: rgb(255 255 255 / 22%) !important;
border-color: rgb(255 255 255 / 38%) !important;
}
button:active {
transform: scale(0.94);
}
}
}
/* Balance KPI tiles */
.cur-kpi {
display: flex;
flex-direction: column;
justify-content: center;
min-width: 130px;
padding: 7px 14px;
border-radius: 9px;
background: rgb(255 255 255 / 14%);
border: 1px solid rgb(255 255 255 / 22%);
backdrop-filter: blur(8px);
&__label {
font-size: 9.5px;
text-transform: uppercase;
letter-spacing: 0.07em;
font-weight: 700;
color: rgb(255 255 255 / 75%);
}
&__value {
margin-top: 2px;
font-size: 15px;
font-weight: 800;
color: #fff;
font-variant-numeric: tabular-nums;
letter-spacing: -0.01em;
}
&--available {
background: rgb(16 185 129 / 22%);
border-color: rgb(16 185 129 / 35%);
}
}
/* Status pill */
.cur-status-pill {
display: inline-flex;
align-items: center;
gap: 5px;
height: 18px;
padding: 0 8px;
border-radius: 999px;
background: rgb(16 185 129 / 24%);
border: 1px solid rgb(16 185 129 / 40%);
font-size: 10px;
font-weight: 700;
text-transform: uppercase;
letter-spacing: 0.06em;
color: #d1fae5;
&__dot {
width: 5px;
height: 5px;
border-radius: 50%;
background: #10b981;
box-shadow: 0 0 0 2px rgb(16 185 129 / 30%);
}
&--warn {
background: rgb(245 158 11 / 24%);
border-color: rgb(245 158 11 / 40%);
color: #fef3c7;
.cur-status-pill__dot {
background: #f59e0b;
box-shadow: 0 0 0 3px rgb(245 158 11 / 30%);
}
}
&.statussubmitted,
&.statuspending {
background: rgb(245 158 11 / 24%);
border-color: rgb(245 158 11 / 40%);
color: #fef3c7;
.cur-status-pill__dot {
background: #f59e0b;
}
}
&.statusclosed,
&.statusrejected,
&.statuswithdrawn {
background: rgb(239 68 68 / 24%);
border-color: rgb(239 68 68 / 40%);
color: #fee2e2;
.cur-status-pill__dot {
background: #ef4444;
}
}
}
/* ─── Pill-style tab navigation ─────────────────────────────────────── */
.cur-tabs {
margin-top: 18px;
background: #fff;
border: 1px solid $border;
border-radius: 14px;
padding: 6px;
box-shadow: 0 1px 3px rgb(15 23 42 / 4%);
overflow: hidden;
::ng-deep {
.mat-mdc-tab-link-container {
border-bottom: none !important;
}
.mat-mdc-tab-links {
gap: 4px;
flex-wrap: wrap;
}
.mdc-tab-indicator__content--underline,
.mat-mdc-tab-header-pagination-controls-enabled .mdc-tab-indicator__content--underline {
display: none !important;
}
}
}
.cur-tab {
display: inline-flex !important;
align-items: center;
gap: 8px;
height: 38px !important;
min-width: 0 !important;
padding: 0 16px !important;
border-radius: 10px !important;
font-family: Inter, 'DM Sans', Roboto, sans-serif !important;
font-size: 13px !important;
font-weight: 600 !important;
letter-spacing: 0.01em !important;
color: #64748b !important;
background: transparent !important;
transition: all 0.15s ease;
white-space: nowrap;
border: 1px solid transparent !important;
opacity: 1 !important;
&__ic {
font-size: 12px;
color: inherit;
}
&:hover:not(.mdc-tab--active) {
background: #f1f5f9 !important;
color: $navy !important;
}
&.mdc-tab--active,
&.mat-mdc-tab-link-active {
background: linear-gradient(135deg, $blue 0%, $blue-d 100%) !important;
color: #fff !important;
box-shadow: 0 2px 6px -1px rgb(30 64 175 / 35%);
border-color: $blue-d !important;
::ng-deep .mdc-tab__text-label,
::ng-deep .mat-mdc-tab-link-content,
::ng-deep span,
.cur-tab__ic {
color: #fff !important;
opacity: 1 !important;
}
}
}
.cur-body {
margin-top: 16px;
}
/* ─── Responsive ────────────────────────────────────────────────────── */
@media (width <= 1100px) {
.cur-hero {
grid-template-columns: 1fr;
&__kpis {
width: 100%;
flex-wrap: wrap;
}
&__actions {
position: absolute;
top: 18px;
right: 18px;
}
}
.cur-kpi {
flex: 1 1 auto;
min-width: 0;
}
}
@media (width <= 700px) {
.cur-view {
padding: 12px;
}
.cur-hero {
padding: 18px;
&__title {
font-size: 18px;
}
&__avatar {
width: 52px;
height: 52px;
font-size: 22px;
border-radius: 12px;
}
}
.cur-tab {
padding: 0 12px !important;
font-size: 12px !important;
}
} }
@@ -13,355 +13,390 @@
} }
@if (!isLoading) { @if (!isLoading) {
<div class="current-account-tables layout-row gap-2percent"> <div class="gt-grid">
<div class="flex-49 layout-column gap-4percent"> <!-- ─── LEFT COLUMN ──────────────────────────────────────────── -->
<div class="gt-col">
<!-- Current Account Details -->
<section class="nx-card">
<header class="nx-card__head">
<fa-icon icon="info-circle" class="nx-card__ico"></fa-icon>
<h3 class="nx-card__title">{{ 'labels.heading.Current Account Details' | translate }}</h3>
</header>
<div class="nx-card__body">
@if (!currentAccountData.status.rejected && !currentAccountData.status.submittedAndPendingApproval) { @if (!currentAccountData.status.rejected && !currentAccountData.status.submittedAndPendingApproval) {
<div> <div class="nx-row">
<h4 class="table-headers">{{ 'labels.heading.Current Account Details' | translate }}</h4> <span class="nx-row__label">{{ 'labels.inputs.External Id' | translate }}</span>
<table> <span class="nx-row__value">
<tbody>
<tr>
<td>{{ 'labels.inputs.External Id' | translate }}</td>
@if (currentAccountData.externalId) { @if (currentAccountData.externalId) {
<td>
<mifosx-external-identifier <mifosx-external-identifier
externalId="{{ currentAccountData.externalId }}" externalId="{{ currentAccountData.externalId }}"
></mifosx-external-identifier> ></mifosx-external-identifier>
</td> } @else {
{{ 'labels.inputs.Not Provided' | translate }}
} }
@if (!currentAccountData.externalId) { </span>
<td>{{ 'labels.inputs.Not Provided' | translate }}</td> </div>
} <div class="nx-row">
</tr> <span class="nx-row__label">{{ 'labels.inputs.Activated On' | translate }}</span>
<tr> <span class="nx-row__value">
<td>{{ 'labels.inputs.Activated On' | translate }}</td>
<td>
{{ {{
currentAccountData.timeline.activatedOnDate currentAccountData.timeline.activatedOnDate
? (currentAccountData.timeline.activatedOnDate | dateFormat) ? (currentAccountData.timeline.activatedOnDate | dateFormat)
: 'Not Activated' : 'Not Activated'
}} }}
</td> </span>
</tr> </div>
<tr> <div class="nx-row">
<td>{{ 'labels.inputs.Field Officer' | translate }}</td> <span class="nx-row__label">{{ 'labels.inputs.Field Officer' | translate }}</span>
<td>{{ currentAccountData.fieldOfficerName ? currentAccountData.fieldOfficerName : 'Unassigned' }}</td> <span class="nx-row__value">
</tr> {{ currentAccountData.fieldOfficerName ? currentAccountData.fieldOfficerName : 'Unassigned' }}
<tr> </span>
<td>{{ 'labels.inputs.Currency' | translate }}</td> </div>
<td>{{ currentAccountData.currency.name }} [{{ currentAccountData.currency.code }}]</td> <div class="nx-row">
</tr> <span class="nx-row__label">{{ 'labels.inputs.Currency' | translate }}</span>
<tr> <span class="nx-row__value">
<td>{{ 'labels.inputs.Nominal Interest Rate' | translate }}</td> {{ currentAccountData.currency.name }}
<td class="r-amount"> <span class="nx-mono">[{{ currentAccountData.currency.code }}]</span>
</span>
</div>
<div class="nx-row">
<span class="nx-row__label">{{ 'labels.inputs.Nominal Interest Rate' | translate }}</span>
<span class="nx-row__value nx-row__value--amount">
@if (currentAccountData.nominalAnnualInterestRate) { @if (currentAccountData.nominalAnnualInterestRate) {
<span>{{ currentAccountData.nominalAnnualInterestRate | formatNumber }} %</span> {{ currentAccountData.nominalAnnualInterestRate | formatNumber }} %
} @else {
0 %
} }
@if (!currentAccountData.nominalAnnualInterestRate) { </span>
<span>0 %</span>
}
</td>
</tr>
</tbody>
</table>
</div> </div>
} @else { } @else {
<div> <div class="nx-row">
<h4 class="table-headers">{{ 'labels.heading.Current Account Details' | translate }}</h4> <span class="nx-row__label">{{ 'labels.inputs.Field Officer' | translate }}</span>
<table> <span class="nx-row__value">
<tbody> {{ currentAccountData.fieldOfficerName ? currentAccountData.fieldOfficerName : 'Unassigned' }}
<tr> </span>
<td>{{ 'labels.inputs.Field Officer' | translate }}</td> </div>
<td>{{ currentAccountData.fieldOfficerName ? currentAccountData.fieldOfficerName : 'Unassigned' }}</td> <div class="nx-row">
</tr> <span class="nx-row__label">{{ 'labels.inputs.Balance' | translate }}</span>
<tr> <span class="nx-row__value nx-row__value--amount">
<td>{{ 'labels.inputs.Balance' | translate }}</td>
<td class="r-amount">
{{ currentAccountData.summary.accountBalance | currency: currency.code : 'symbol-narrow' : '1.2-2' }} {{ currentAccountData.summary.accountBalance | currency: currency.code : 'symbol-narrow' : '1.2-2' }}
</td> </span>
</tr>
</tbody>
</table>
</div> </div>
} }
</div>
</section>
<!-- Performance History -->
@if (!currentAccountData.status.rejected && !currentAccountData.status.submittedAndPendingApproval) { @if (!currentAccountData.status.rejected && !currentAccountData.status.submittedAndPendingApproval) {
<div> <section class="nx-card">
<h4 class="table-headers">{{ 'labels.heading.Performance History' | translate }}</h4> <header class="nx-card__head">
<table> <fa-icon icon="chart-line" class="nx-card__ico"></fa-icon>
<tbody> <h3 class="nx-card__title">{{ 'labels.heading.Performance History' | translate }}</h3>
</header>
<div class="nx-card__body">
@if (currentAccountData.summary.totalDeposits) { @if (currentAccountData.summary.totalDeposits) {
<tr> <div class="nx-row">
<td>{{ 'labels.inputs.Total Deposits' | translate }}</td> <span class="nx-row__label">{{ 'labels.inputs.Total Deposits' | translate }}</span>
<td class="r-amount"> <span class="nx-row__value nx-row__value--amount nx-row__value--positive">
{{ currentAccountData.summary.totalDeposits | currency: currency.code : 'symbol-narrow' : '1.2-2' }} {{ currentAccountData.summary.totalDeposits | currency: currency.code : 'symbol-narrow' : '1.2-2' }}
</td> </span>
</tr>
}
@if (currentAccountData.summary.totalInterestEarned >= 0) {
<tr>
<td>{{ 'labels.inputs.Total Interest Earned' | translate }}</td>
<td class="r-amount">
{{
currentAccountData.summary.totalInterestEarned
| currency: currency.code : 'symbol-narrow' : '1.2-2'
}}
</td>
</tr>
}
</tbody>
</table>
</div> </div>
} }
</div>
@if (isActive) {
<div class="flex-49">
<h4 class="table-headers">{{ 'labels.heading.Account Summary' | translate }}</h4>
<table>
<tbody>
@if (currentAccountData.summary.totalWithdrawals) {
<tr>
<td>{{ 'labels.inputs.Total Withdrawls' | translate }}</td>
<td class="r-amount">
{{
currentAccountData.summary.totalWithdrawals | currency: currency.code : 'symbol-narrow' : '1.2-2'
}}
</td>
</tr>
}
@if (currentAccountData.summary.totalWithdrawalFees) {
<tr>
<td>{{ 'labels.inputs.Withdrawals Fees' | translate }}</td>
<td class="r-amount">
{{
currentAccountData.summary.totalWithdrawalFees | currency: currency.code : 'symbol-narrow' : '1.2-2'
}}
</td>
</tr>
}
@if (currentAccountData.summary.totalAnnualFees) {
<tr>
<td>{{ 'labels.inputs.Annual Fees' | translate }}</td>
<td class="r-amount">
{{ currentAccountData.summary.totalAnnualFees | currency: currency.code : 'symbol-narrow' : '1.2-2' }}
</td>
</tr>
}
@if (currentAccountData.summary.totalInterestEarned >= 0) { @if (currentAccountData.summary.totalInterestEarned >= 0) {
<tr> <div class="nx-row">
<td>{{ 'labels.inputs.Interest Earned' | translate }}</td> <span class="nx-row__label">{{ 'labels.inputs.Total Interest Earned' | translate }}</span>
<td class="r-amount"> <span class="nx-row__value nx-row__value--amount">
{{ {{
currentAccountData.summary.totalInterestEarned | currency: currency.code : 'symbol-narrow' : '1.2-2' currentAccountData.summary.totalInterestEarned | currency: currency.code : 'symbol-narrow' : '1.2-2'
}} }}
</td> </span>
</tr> </div>
}
@if (!currentAccountData.summary.totalDeposits && !(currentAccountData.summary.totalInterestEarned >= 0)) {
<div class="nx-empty">
<fa-icon icon="inbox" class="nx-empty__ico"></fa-icon>
<span>No activity yet.</span>
</div>
}
</div>
</section>
}
</div>
<!-- ─── RIGHT COLUMN ─────────────────────────────────────────── -->
<div class="gt-col">
@if (isActive) {
<section class="nx-card">
<header class="nx-card__head">
<fa-icon icon="file-invoice" class="nx-card__ico"></fa-icon>
<h3 class="nx-card__title">{{ 'labels.heading.Account Summary' | translate }}</h3>
</header>
<div class="nx-card__body">
@if (currentAccountData.summary.totalWithdrawals) {
<div class="nx-row">
<span class="nx-row__label">{{ 'labels.inputs.Total Withdrawls' | translate }}</span>
<span class="nx-row__value nx-row__value--amount nx-row__value--negative">
{{
currentAccountData.summary.totalWithdrawals | currency: currency.code : 'symbol-narrow' : '1.2-2'
}}
</span>
</div>
}
@if (currentAccountData.summary.totalWithdrawalFees) {
<div class="nx-row">
<span class="nx-row__label">{{ 'labels.inputs.Withdrawals Fees' | translate }}</span>
<span class="nx-row__value nx-row__value--amount">
{{
currentAccountData.summary.totalWithdrawalFees | currency: currency.code : 'symbol-narrow' : '1.2-2'
}}
</span>
</div>
}
@if (currentAccountData.summary.totalAnnualFees) {
<div class="nx-row">
<span class="nx-row__label">{{ 'labels.inputs.Annual Fees' | translate }}</span>
<span class="nx-row__value nx-row__value--amount">
{{ currentAccountData.summary.totalAnnualFees | currency: currency.code : 'symbol-narrow' : '1.2-2' }}
</span>
</div>
}
@if (currentAccountData.summary.totalInterestEarned >= 0) {
<div class="nx-row">
<span class="nx-row__label">{{ 'labels.inputs.Interest Earned' | translate }}</span>
<span class="nx-row__value nx-row__value--amount">
{{
currentAccountData.summary.totalInterestEarned | currency: currency.code : 'symbol-narrow' : '1.2-2'
}}
</span>
</div>
} }
@if (currentAccountData.summary.totalInterestPosted) { @if (currentAccountData.summary.totalInterestPosted) {
<tr> <div class="nx-row">
<td>{{ 'labels.inputs.Interest Posted' | translate }}</td> <span class="nx-row__label">{{ 'labels.inputs.Interest Posted' | translate }}</span>
<td class="r-amount"> <span class="nx-row__value nx-row__value--amount">
{{ {{
currentAccountData.summary.totalInterestPosted | currency: currency.code : 'symbol-narrow' : '1.2-2' currentAccountData.summary.totalInterestPosted | currency: currency.code : 'symbol-narrow' : '1.2-2'
}} }}
</td> </span>
</tr> </div>
} }
@if (currentAccountData.summary.interestNotPosted >= 0) { @if (currentAccountData.summary.interestNotPosted >= 0) {
<tr> <div class="nx-row">
<td>{{ 'labels.inputs.Interest Earned Not Posted' | translate }}</td> <span class="nx-row__label">{{ 'labels.inputs.Interest Earned Not Posted' | translate }}</span>
<td class="r-amount"> <span class="nx-row__value nx-row__value--amount">
{{ {{
currentAccountData.summary.interestNotPosted | currency: currency.code : 'symbol-narrow' : '1.2-2' currentAccountData.summary.interestNotPosted | currency: currency.code : 'symbol-narrow' : '1.2-2'
}} }}
</td> </span>
</tr> </div>
} }
@if (currentAccountData.summary.totalOverdraftInterestDerived) { @if (currentAccountData.summary.totalOverdraftInterestDerived) {
<tr> <div class="nx-row">
<td>{{ 'labels.inputs.Interest On Overdraft' | translate }}</td> <span class="nx-row__label">{{ 'labels.inputs.Interest On Overdraft' | translate }}</span>
<td class="r-amount"> <span class="nx-row__value nx-row__value--amount">
{{ {{
currentAccountData.summary.totalOverdraftInterestDerived currentAccountData.summary.totalOverdraftInterestDerived
| currency: currency.code : 'symbol-narrow' : '1.2-2' | currency: currency.code : 'symbol-narrow' : '1.2-2'
}} }}
</td> </span>
</tr> </div>
} }
@if (currentAccountData.summary.interestNotPosted < 0) { @if (currentAccountData.summary.interestNotPosted < 0) {
<tr> <div class="nx-row">
<td>{{ 'labels.inputs.Overdraft Interest Not Posted' | translate }}</td> <span class="nx-row__label">{{ 'labels.inputs.Overdraft Interest Not Posted' | translate }}</span>
<td class="r-amount"> <span class="nx-row__value nx-row__value--amount">
{{ {{
currentAccountData.summary.interestNotPosted | currency: currency.code : 'symbol-narrow' : '1.2-2' currentAccountData.summary.interestNotPosted | currency: currency.code : 'symbol-narrow' : '1.2-2'
}} }}
</td> </span>
</tr> </div>
} }
@if (currentAccountData.nominalAnnualInterestRate) { @if (currentAccountData.nominalAnnualInterestRate) {
<tr> <div class="nx-row">
<td>{{ 'labels.inputs.Nominal Interest Rate' | translate }}</td> <span class="nx-row__label">{{ 'labels.inputs.Nominal Interest Rate' | translate }}</span>
<td class="r-amount">{{ currentAccountData.nominalAnnualInterestRate | formatNumber }} %</td> <span class="nx-row__value nx-row__value--amount">
</tr> {{ currentAccountData.nominalAnnualInterestRate | formatNumber }} %
</span>
</div>
} }
<tr> <div class="nx-row">
<td>{{ 'labels.inputs.Interest Compounding Period' | translate }}</td> <span class="nx-row__label">{{ 'labels.inputs.Interest Compounding Period' | translate }}</span>
<td>{{ currentAccountData.interestCompoundingPeriodType.value | translateKey: 'catalogs' }}</td> <span class="nx-row__value">
</tr> {{ currentAccountData.interestCompoundingPeriodType.value | translateKey: 'catalogs' }}
<tr> </span>
<td>{{ 'labels.inputs.Interest Posting Period' | translate }}</td> </div>
<td>{{ currentAccountData.interestPostingPeriodType.value | translateKey: 'catalogs' }}</td> <div class="nx-row">
</tr> <span class="nx-row__label">{{ 'labels.inputs.Interest Posting Period' | translate }}</span>
<tr> <span class="nx-row__value">
<td>{{ 'labels.inputs.Interest Calculated Using' | translate }}</td> {{ currentAccountData.interestPostingPeriodType.value | translateKey: 'catalogs' }}
<td>{{ currentAccountData.interestCalculationType.value | translateKey: 'catalogs' }}</td> </span>
</tr> </div>
<tr> <div class="nx-row">
<td>{{ 'labels.inputs.Days in Year' | translate }}</td> <span class="nx-row__label">{{ 'labels.inputs.Interest Calculated Using' | translate }}</span>
<td>{{ currentAccountData.interestCalculationDaysInYearType.value | translateKey: 'catalogs' }}</td> <span class="nx-row__value">
</tr> {{ currentAccountData.interestCalculationType.value | translateKey: 'catalogs' }}
</span>
</div>
<div class="nx-row">
<span class="nx-row__label">{{ 'labels.inputs.Days in Year' | translate }}</span>
<span class="nx-row__value">
{{ currentAccountData.interestCalculationDaysInYearType.value | translateKey: 'catalogs' }}
</span>
</div>
@if (currentAccountData.withdrawalFee) { @if (currentAccountData.withdrawalFee) {
<tr> <div class="nx-row">
<td>{{ 'labels.inputs.Withdrawal Fee' | translate }}</td> <span class="nx-row__label">{{ 'labels.inputs.Withdrawal Fee' | translate }}</span>
<td class="r-amount"> <span class="nx-row__value nx-row__value--amount">
{{ currentAccountData.withdrawalFee.amount | currency: currency.code : 'symbol-narrow' : '1.2-2' }} {{ currentAccountData.withdrawalFee.amount | currency: currency.code : 'symbol-narrow' : '1.2-2' }}
</td> </span>
</tr> </div>
} }
@if (currentAccountData.lastActiveTransactionDate) { @if (currentAccountData.lastActiveTransactionDate) {
<tr> <div class="nx-row">
<td>{{ 'labels.inputs.Last Active Transaction Date' | translate }}</td> <span class="nx-row__label">{{ 'labels.inputs.Last Active Transaction Date' | translate }}</span>
<td>{{ currentAccountData.lastActiveTransactionDate | dateFormat }}</td> <span class="nx-row__value">{{ currentAccountData.lastActiveTransactionDate | dateFormat }}</span>
</tr> </div>
} }
@if (!(currentAccountData.subStatus.id === 0)) { @if (!(currentAccountData.subStatus.id === 0)) {
<tr> <div class="nx-row">
<td>{{ 'labels.inputs.Substatus' | translate }}</td> <span class="nx-row__label">{{ 'labels.inputs.Substatus' | translate }}</span>
<td>{{ currentAccountData.subStatus.value }}</td> <span class="nx-row__value">{{ currentAccountData.subStatus.value }}</span>
</tr> </div>
} }
@if (currentAccountData.daysToInactive) { @if (currentAccountData.daysToInactive) {
<tr> <div class="nx-row">
<td>{{ 'labels.inputs.Days to Inactive' | translate }}</td> <span class="nx-row__label">{{ 'labels.inputs.Days to Inactive' | translate }}</span>
<td>{{ currentAccountData.daysToInactive }}</td> <span class="nx-row__value">{{ currentAccountData.daysToInactive }}</span>
</tr> </div>
} }
@if (currentAccountData.daysToDormancy) { @if (currentAccountData.daysToDormancy) {
<tr> <div class="nx-row">
<td>{{ 'labels.inputs.Days to Dormancy' | translate }}</td> <span class="nx-row__label">{{ 'labels.inputs.Days to Dormancy' | translate }}</span>
<td>{{ currentAccountData.daysToDormancy }}</td> <span class="nx-row__value">{{ currentAccountData.daysToDormancy }}</span>
</tr> </div>
} }
@if (currentAccountData.daysToEscheat) { @if (currentAccountData.daysToEscheat) {
<tr> <div class="nx-row">
<td>{{ 'labels.inputs.Days to Escheat' | translate }}</td> <span class="nx-row__label">{{ 'labels.inputs.Days to Escheat' | translate }}</span>
<td>{{ currentAccountData.daysToEscheat }}</td> <span class="nx-row__value">{{ currentAccountData.daysToEscheat }}</span>
</tr> </div>
} }
@if (currentAccountData.annualFee) { @if (currentAccountData.annualFee) {
<tr> <div class="nx-row">
<td>{{ 'labels.inputs.Annual Fee' | translate }}</td> <span class="nx-row__label">{{ 'labels.inputs.Annual Fee' | translate }}</span>
<td class="r-amount"> <span class="nx-row__value nx-row__value--amount">
{{ currentAccountData.annualFee.amount | currency: currency.code : 'symbol-narrow' : '1.2-2' }} {{ currentAccountData.annualFee.amount | currency: currency.code : 'symbol-narrow' : '1.2-2' }}
</td> </span>
</tr> </div>
} }
@if (currentAccountData.allowOverdraft) { @if (currentAccountData.allowOverdraft) {
<tr> <div class="nx-row">
<td>{{ 'labels.inputs.Overdraft Limit' | translate }}</td> <span class="nx-row__label">{{ 'labels.inputs.Overdraft Limit' | translate }}</span>
<td class="r-amount"> <span class="nx-row__value nx-row__value--amount">
{{ currentAccountData.overdraftLimit | currency: currency.code : 'symbol-narrow' : '1.2-2' }} {{ currentAccountData.overdraftLimit | currency: currency.code : 'symbol-narrow' : '1.2-2' }}
</td> </span>
</tr> </div>
} }
@if (currentAccountData.allowOverdraft) { @if (currentAccountData.allowOverdraft) {
<tr> <div class="nx-row">
<td>{{ 'labels.inputs.Minimum Overdraft Required for Interest Calculation' | translate }}</td> <span class="nx-row__label">
<td> {{ 'labels.inputs.Minimum Overdraft Required for Interest Calculation' | translate }}
</span>
<span class="nx-row__value">
{{ {{
currentAccountData.minOverdraftForInterestCalculation currentAccountData.minOverdraftForInterestCalculation
| currency: currency.code : 'symbol-narrow' : '1.2-2' | currency: currency.code : 'symbol-narrow' : '1.2-2'
}} }}
</td> </span>
</tr> </div>
} }
@if (currentAccountData.minBalanceForInterestCalculation) { @if (currentAccountData.minBalanceForInterestCalculation) {
<tr> <div class="nx-row">
<td>{{ 'labels.inputs.Min Balance Required for Interest Calculation' | translate }}</td> <span class="nx-row__label">
<td>{{ currentAccountData.minBalanceForInterestCalculation | formatNumber }}</td> {{ 'labels.inputs.Min Balance Required for Interest Calculation' | translate }}
</tr> </span>
<span class="nx-row__value">
{{ currentAccountData.minBalanceForInterestCalculation | formatNumber }}
</span>
</div>
} }
@if (currentAccountData.minRequiredBalance) { @if (currentAccountData.minRequiredBalance) {
<tr> <div class="nx-row">
<td>{{ 'labels.inputs.Minimum Required Balance' | translate }}</td> <span class="nx-row__label">{{ 'labels.inputs.Minimum Required Balance' | translate }}</span>
<td>{{ currentAccountData.minRequiredBalance | formatNumber }}</td> <span class="nx-row__value">{{ currentAccountData.minRequiredBalance | formatNumber }}</span>
</tr> </div>
} }
@if (currentAccountData.enforceMinRequiredBalance) { @if (currentAccountData.enforceMinRequiredBalance) {
<tr> <div class="nx-row">
<td>{{ 'labels.inputs.Enforce Minimum Required Balance' | translate }}</td> <span class="nx-row__label">{{ 'labels.inputs.Enforce Minimum Required Balance' | translate }}</span>
<td>{{ currentAccountData.enforceMinRequiredBalance | yesNo }}</td> <span class="nx-row__value">{{ currentAccountData.enforceMinRequiredBalance | yesNo }}</span>
</tr> </div>
} }
@if (currentAccountData.summary.lastInterestCalculationDate) { @if (currentAccountData.summary.lastInterestCalculationDate) {
<tr> <div class="nx-row">
<td>{{ 'labels.inputs.Interest Recalculation Date' | translate }}</td> <span class="nx-row__label">{{ 'labels.inputs.Interest Recalculation Date' | translate }}</span>
<td>{{ currentAccountData.summary.lastInterestCalculationDate | dateFormat }}</td> <span class="nx-row__value">
</tr> {{ currentAccountData.summary.lastInterestCalculationDate | dateFormat }}
</span>
</div>
} }
@if (currentAccountData.onHoldFunds) { @if (currentAccountData.onHoldFunds) {
<tr> <div class="nx-row">
<td>{{ 'labels.inputs.On Hold Funds' | translate }}</td> <span class="nx-row__label">{{ 'labels.inputs.On Hold Funds' | translate }}</span>
<td> <span class="nx-row__value nx-row__value--amount">
<a *mifosxHasPermission="'READ_CURRENTACCOUNT'">{{ <a *mifosxHasPermission="'READ_CURRENTACCOUNT'">
currentAccountData.onHoldFunds | currency: currency.code : 'symbol-narrow' : '1.2-2' {{ currentAccountData.onHoldFunds | currency: currency.code : 'symbol-narrow' : '1.2-2' }}
}}</a> </a>
</td> </span>
</tr> </div>
} }
@if (currentAccountData.withHoldTax) { @if (currentAccountData.withHoldTax) {
<tr> <div class="nx-row">
<td>{{ 'labels.inputs.Withhold Tax Group' | translate }}</td> <span class="nx-row__label">{{ 'labels.inputs.Withhold Tax Group' | translate }}</span>
<td>{{ currentAccountData.taxGroup.name }}</td> <span class="nx-row__value">{{ currentAccountData.taxGroup.name }}</span>
</tr>
}
</tbody>
</table>
</div> </div>
}
</div>
</section>
} @else { } @else {
<div class="flex-49"> <section class="nx-card">
<h4 class="table-headers">{{ 'labels.heading.Account Summary' | translate }}</h4> <header class="nx-card__head">
<table> <fa-icon icon="file-invoice" class="nx-card__ico"></fa-icon>
<tbody> <h3 class="nx-card__title">{{ 'labels.heading.Account Summary' | translate }}</h3>
<tr> </header>
<td>{{ 'labels.inputs.External Id' | translate }}</td> <div class="nx-card__body">
<div class="nx-row">
<span class="nx-row__label">{{ 'labels.inputs.External Id' | translate }}</span>
<span class="nx-row__value">
@if (currentAccountData.externalId) { @if (currentAccountData.externalId) {
<td>
<mifosx-external-identifier <mifosx-external-identifier
externalId="{{ currentAccountData.externalId }}" externalId="{{ currentAccountData.externalId }}"
></mifosx-external-identifier> ></mifosx-external-identifier>
</td> } @else {
{{ 'labels.inputs.Not Provided' | translate }}
} }
@if (!currentAccountData.externalId) { </span>
<td>{{ 'labels.inputs.Not Provided' | translate }}</td> </div>
} <div class="nx-row">
</tr> <span class="nx-row__label">{{ 'labels.inputs.Activated On' | translate }}</span>
<tr> <span class="nx-row__value">
<td>{{ 'labels.inputs.Activated On' | translate }}</td>
<td>
{{ {{
currentAccountData.timeline.activatedOnDate currentAccountData.timeline.activatedOnDate
? (currentAccountData.timeline.activatedOnDate | dateFormat) ? (currentAccountData.timeline.activatedOnDate | dateFormat)
: 'Not Activated' : 'Not Activated'
}} }}
</td> </span>
</tr>
<tr>
<td>{{ 'labels.inputs.Currency' | translate }}</td>
<td>{{ currentAccountData.currency.name }} [{{ currentAccountData.currency.code }}]</td>
</tr>
</tbody>
</table>
</div> </div>
<div class="nx-row">
<span class="nx-row__label">{{ 'labels.inputs.Currency' | translate }}</span>
<span class="nx-row__value">
{{ currentAccountData.currency.name }}
<span class="nx-mono">[{{ currentAccountData.currency.code }}]</span>
</span>
</div>
</div>
</section>
} }
</div> </div>
</div>
} }
@@ -6,9 +6,15 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. * file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/ */
$navy: #0d1b2a;
$slate: #475569;
$muted: #64748b;
$border: #e2e8f0;
$soft: #f8fafc;
/* ─── Loader keyframes ──────────────────────────────────────────────── */
$bar: 160px; $bar: 160px;
$foo: $bar * 8; $foo: $bar * 8;
$color: #e2e4ec;
.loader { .loader {
margin-bottom: 39px; margin-bottom: 39px;
@@ -79,164 +85,136 @@ $color: #e2e4ec;
} }
} }
.general-tab-container { /* ─── Two-column grid ───────────────────────────────────────────────── */
padding: 16px 20px; .gt-grid {
width: 100%; display: grid;
box-sizing: border-box; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
position: relative; gap: 16px;
background-color: var(--background-color, #f8f9fa);
color: var(--text-color, #333);
transition:
background-color 0.3s ease,
color 0.3s ease;
.page-header { @media (width <= 1024px) {
margin-bottom: 24px; grid-template-columns: 1fr;
padding: 16px 0;
position: relative;
border-bottom: 1px solid var(--border-color, #e9ecef);
.header-title {
font-size: 1.75rem;
font-weight: 600;
margin: 0 0 8px;
line-height: 1.2;
color: var(--primary-color, #007bff);
position: relative;
}
.header-subtitle {
font-size: 0.95rem;
margin: 0;
line-height: 1.4;
color: var(--text-secondary, #6c757d);
position: relative;
} }
} }
.content-wrapper { .gt-col {
position: relative;
width: 100%;
}
.account-info-card {
background: var(--card-background, #fff);
border-radius: 8px;
box-shadow: 0 2px 4px rgb(0 0 0 / 10%);
overflow: hidden;
position: relative;
width: 100%;
max-width: 600px;
transition:
box-shadow 0.3s ease,
background-color 0.3s ease;
.card-header {
padding: 16px 20px;
background: var(--card-header-bg, #f8f9fa);
border-bottom: 1px solid var(--border-color, #e9ecef);
position: relative;
h3 {
margin: 0;
font-size: 1.1rem;
font-weight: 600;
line-height: 1.3;
color: var(--text-color, #333);
}
}
.card-content {
padding: 20px;
position: relative;
.info-row {
display: flex; display: flex;
justify-content: space-between; flex-direction: column;
align-items: baseline; gap: 16px;
padding: 10px 0; min-width: 0;
border-bottom: 1px solid var(--border-light, #f1f3f4); }
position: relative;
min-height: 24px; /* ─── Nexora section card ───────────────────────────────────────────── */
.nx-card {
background: #fff;
border: 1px solid $border;
border-radius: 14px;
box-shadow: 0 1px 3px rgb(15 23 42 / 4%);
overflow: hidden;
&__head {
display: flex;
align-items: center;
gap: 10px;
padding: 12px 18px;
background: $soft;
border-bottom: 1px solid $border;
}
&__ico {
width: 26px;
height: 26px;
display: inline-flex;
align-items: center;
justify-content: center;
border-radius: 8px;
background: linear-gradient(135deg, #3b82f6 0%, #1e40af 100%);
color: #fff;
font-size: 12px;
}
&__title {
margin: 0;
font-size: 13.5px;
font-weight: 700;
color: $navy;
letter-spacing: 0.01em;
}
&__body {
padding: 4px 18px 10px;
}
}
/* ─── Key/Value row ─────────────────────────────────────────────────── */
.nx-row {
display: grid;
grid-template-columns: minmax(0, 1fr) auto;
gap: 12px;
align-items: center;
min-height: 38px;
padding: 8px 0;
border-bottom: 1px dashed #eef2f7;
font-size: 13px;
&:last-child { &:last-child {
border-bottom: none; border-bottom: none;
} }
.label { &__label {
color: $slate;
font-weight: 500; font-weight: 500;
color: var(--text-secondary, #6c757d);
flex: 0 0 auto;
margin-right: 16px;
white-space: nowrap;
line-height: 1.4;
} }
.value { &__value {
color: $navy;
font-weight: 600; font-weight: 600;
color: var(--text-color, #333);
text-align: right; text-align: right;
flex: 1 1 auto; word-break: break-word;
line-height: 1.4;
&.currency { &--amount {
color: var(--success-color, #28a745); font-variant-numeric: tabular-nums;
font-size: 1.05rem; font-weight: 700;
}
} }
&--positive {
color: #047857;
} }
&--negative {
color: #b91c1c;
} }
} }
} }
// Dark mode styles .nx-muted {
[data-theme='dark'] .general-tab-container, color: $muted;
.dark-theme .general-tab-container { font-weight: 500;
--background-color: #1a1a1a; font-style: italic;
--text-color: #e9ecef;
--text-secondary: #adb5bd;
--primary-color: #4dabf7;
--card-background: #2d3748;
--card-header-bg: #374151;
--border-color: #4a5568;
--border-light: #2d3748;
--success-color: #68d391;
} }
// Responsive adjustments for mobile .nx-mono {
@media (width <= 768px) { font-family: 'JetBrains Mono', 'Courier New', monospace;
.general-tab-container { font-size: 12.5px;
padding: 12px 16px; color: $muted;
margin-left: 4px;
.page-header {
margin-bottom: 20px;
padding: 12px 0;
.header-title {
font-size: 1.5rem;
} }
.header-subtitle { /* ─── Empty state inside a card ─────────────────────────────────────── */
font-size: 0.9rem; .nx-empty {
} display: flex;
flex-direction: column;
align-items: center;
gap: 8px;
padding: 24px 16px;
color: $muted;
&__ico {
font-size: 28px;
color: #cbd5e1;
} }
.account-info-card { span {
.card-header { font-size: 13px;
padding: 14px 16px; font-weight: 500;
}
.card-content {
padding: 16px;
.info-row {
padding: 8px 0;
.label {
margin-right: 12px;
}
}
}
}
} }
} }
@@ -7,8 +7,8 @@
--> -->
<div class="passbook-container"> <div class="passbook-container">
<!-- Date Range Filter --> <!-- Filter Bar -->
<div class="passbook-filter-bar"> <div class="passbook-filter-bar no-print">
<form [formGroup]="dateRangeForm" class="passbook-filter-form"> <form [formGroup]="dateRangeForm" class="passbook-filter-form">
<mat-form-field appearance="outline" class="passbook-date-field" (click)="fromDatePicker.open()"> <mat-form-field appearance="outline" class="passbook-date-field" (click)="fromDatePicker.open()">
<mat-label>{{ 'labels.inputs.From Date' | translate }}</mat-label> <mat-label>{{ 'labels.inputs.From Date' | translate }}</mat-label>
@@ -45,105 +45,152 @@
</form> </form>
</div> </div>
<!-- Passbook Preview (Printable Content) --> <!-- Bank Statement -->
<div class="passbook-preview" #passbookContent> <div class="statement-wrapper" #passbookContent>
<div class="passbook-header"> <!-- Bank Header -->
<h2>{{ 'labels.heading.Current Account Passbook' | translate }}</h2> <div class="bank-header">
<h3>{{ productName }}</h3> <div class="bank-logo-area">
<div class="bank-logo-circle">
<mat-icon>account_balance</mat-icon>
</div> </div>
<div class="bank-name-block">
<!-- Account Info --> <div class="bank-title">LincPay Co-operative Bank Ltd.</div>
<div class="passbook-info-grid"> <div class="bank-subtitle">Current Account Statement</div>
<div class="passbook-info-item">
<div class="label">{{ 'labels.inputs.Account Number' | translate }}</div>
<div class="value">{{ accountNo }}</div>
</div> </div>
<div class="passbook-info-item">
<div class="label">{{ 'labels.inputs.Account Holder' | translate }}</div>
<div class="value">{{ clientName }}</div>
</div> </div>
<div class="passbook-info-item"> <div class="statement-label">
<div class="label">{{ 'labels.inputs.Current Account Product' | translate }}</div> <div class="stmt-label-text">STATEMENT OF ACCOUNT</div>
<div class="value">{{ productName }}</div> <div class="stmt-period">As on: {{ maxDate | dateFormat }}</div>
</div>
<div class="passbook-info-item">
<div class="label">{{ 'labels.inputs.Opening Date' | translate }}</div>
<div class="value">{{ activatedOnDate | dateFormat }}</div>
</div>
<div class="passbook-info-item">
<div class="label">{{ 'labels.inputs.Status' | translate }}</div>
<div class="value">{{ status }}</div>
</div>
<div class="passbook-info-item">
<div class="label">{{ 'labels.inputs.Interest Rate' | translate }}</div>
<div class="value">{{ interestRate }}%</div>
</div> </div>
</div> </div>
<!-- Balance Summary --> <!-- Account Details -->
<div class="passbook-balance-row"> <div class="account-details-band">
<div class="balance-item"> <div class="account-details-grid">
<span>{{ 'labels.inputs.Current Balance' | translate }}: </span> <div class="detail-block">
<b>{{ accountBalance | currency: currency?.code : 'symbol-narrow' : '1.2-2' }}</b> <div class="detail-label">Account Holder</div>
<div class="detail-value bold">{{ clientName | uppercase }}</div>
</div> </div>
<div class="balance-item"> <div class="detail-block">
<span>{{ 'labels.inputs.Available Balance' | translate }}: </span> <div class="detail-label">Account Number</div>
<b>{{ availableBalance | currency: currency?.code : 'symbol-narrow' : '1.2-2' }}</b> <div class="detail-value mono bold">{{ accountNo }}</div>
</div>
<div class="detail-block">
<div class="detail-label">Product</div>
<div class="detail-value">{{ productName }}</div>
</div>
<div class="detail-block">
<div class="detail-label">Account Opening Date</div>
<div class="detail-value">{{ activatedOnDate | dateFormat }}</div>
</div>
<div class="detail-block">
<div class="detail-label">Status</div>
<div class="detail-value status-badge" [class.active]="status === 'Active'">{{ status }}</div>
</div>
<div class="detail-block">
<div class="detail-label">Interest Rate (p.a.)</div>
<div class="detail-value">{{ interestRate }}%</div>
</div>
</div>
</div>
<!-- Balance Summary Strip -->
<div class="balance-summary-strip">
<div class="balance-box">
<div class="balance-box-label">Current Balance</div>
<div class="balance-box-value">{{ accountBalance | currency: currency?.code : 'symbol-narrow' : '1.2-2' }}</div>
</div>
<div class="balance-divider"></div>
<div class="balance-box">
<div class="balance-box-label">Available Balance</div>
<div class="balance-box-value">
{{ availableBalance | currency: currency?.code : 'symbol-narrow' : '1.2-2' }}
</div>
</div>
<div class="balance-divider"></div>
<div class="balance-box">
<div class="balance-box-label">Total Transactions</div>
<div class="balance-box-value">{{ filteredTransactions.length }}</div>
</div> </div>
</div> </div>
<!-- Transactions Table --> <!-- Transactions Table -->
@if (filteredTransactions.length > 0) { @if (filteredTransactions.length > 0) {
<table> <table class="statement-table">
<thead> <thead>
<tr> <tr>
<th>#</th> <th class="col-sr">#</th>
<th>{{ 'labels.inputs.Date' | translate }}</th> <th class="col-date">Date</th>
<th>{{ 'labels.inputs.Description' | translate }}</th> <th class="col-desc">Description</th>
<th class="text-right">{{ 'labels.inputs.Debit' | translate }}</th> <th class="col-ref">Ref No.</th>
<th class="text-right">{{ 'labels.inputs.Credit' | translate }}</th> <th class="col-amount text-right">Debit (Dr)</th>
<th class="text-right">{{ 'labels.inputs.Balance' | translate }}</th> <th class="col-amount text-right">Credit (Cr)</th>
<th class="col-balance text-right">Balance (&#8377;)</th>
</tr> </tr>
</thead> </thead>
<tbody> <tbody>
@for (txn of filteredTransactions; track txn.id; let i = $index) { @for (txn of filteredTransactions; track txn.id; let i = $index) {
<tr [class.reversed]="txn.reversed"> <tr
<td>{{ i + 1 }}</td> [class.reversed-row]="txn.reversed"
<td>{{ txn.date | dateFormat }}</td> [class.debit-row]="isDebit(txn.transactionType) && !txn.reversed"
<td>{{ txn.transactionType.value }}</td> [class.credit-row]="!isDebit(txn.transactionType) && !txn.reversed"
<td class="text-right"> >
<td class="col-sr text-center">{{ i + 1 }}</td>
<td class="col-date">{{ txn.date | dateFormat }}</td>
<td class="col-desc">
<span class="txn-desc">{{ txn.transactionType.value }}</span>
@if (txn.reversed) {
<span class="reversed-badge">REVERSED</span>
}
</td>
<td class="col-ref text-muted mono">{{ txn.id }}</td>
<td class="col-amount text-right debit-amount">
@if (isDebit(txn.transactionType)) { @if (isDebit(txn.transactionType)) {
{{ txn.amount | currency: currency?.code : 'symbol-narrow' : '1.2-2' }} {{ txn.amount | currency: currency?.code : 'symbol-narrow' : '1.2-2' }}
} }
</td> </td>
<td class="text-right"> <td class="col-amount text-right credit-amount">
@if (!isDebit(txn.transactionType)) { @if (!isDebit(txn.transactionType)) {
{{ txn.amount | currency: currency?.code : 'symbol-narrow' : '1.2-2' }} {{ txn.amount | currency: currency?.code : 'symbol-narrow' : '1.2-2' }}
} }
</td> </td>
<td class="text-right"> <td class="col-balance text-right balance-amount">
{{ txn.runningBalance | currency: currency?.code : 'symbol-narrow' : '1.2-2' }} {{ txn.runningBalance | currency: currency?.code : 'symbol-narrow' : '1.2-2' }}
</td> </td>
</tr> </tr>
} }
</tbody> </tbody>
<tfoot>
<tr class="total-row">
<td colspan="4" class="text-right total-label">Closing Balance</td>
<td class="text-right total-label"></td>
<td class="text-right total-label"></td>
<td class="text-right closing-balance">
{{ accountBalance | currency: currency?.code : 'symbol-narrow' : '1.2-2' }}
</td>
</tr>
</tfoot>
</table> </table>
} @else { } @else {
<div class="passbook-no-data"> <div class="no-data-block">
<mat-icon>info_outline</mat-icon> <mat-icon>inbox</mat-icon>
<span>{{ <p>
{{
isFiltered isFiltered
? ('labels.text.No transactions found for the selected date range.' | translate) ? ('labels.text.No transactions found for the selected date range.' | translate)
: 'No transactions found.' : 'No transactions found.'
}}</span> }}
</p>
</div> </div>
} }
<!-- Footer --> <!-- Statement Footer -->
<div class="passbook-footer"> <div class="statement-footer">
{{ 'labels.text.Generated on' | translate }}: {{ maxDate | dateFormat }} <div class="footer-note">
&nbsp;|&nbsp; This is a computer-generated statement and does not require a signature. For queries, contact your branch or
{{ 'labels.text.Total Transactions' | translate }}: {{ filteredTransactions.length }} call customer care.
</div>
<div class="footer-meta">Generated on: {{ maxDate | dateFormat }} &nbsp;|&nbsp; Account No: {{ accountNo }}</div>
</div> </div>
</div> </div>
</div> </div>
@@ -6,13 +6,31 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. * file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/ */
// ─── Variables ──────────────────────────────────────────────────────────────
$bank-primary: #1a3a6b; // deep navy (like SBI/PNB)
$bank-accent: #c8a951; // gold trim
$debit-color: #c0392b;
$credit-color: #1a7a3f;
$balance-color: #1a3a6b;
$border-color: #d0d7e3;
$row-alt: #f4f7fb;
$header-bg: #1a3a6b;
$header-text: #fff;
// ─── Container ──────────────────────────────────────────────────────────────
.passbook-container { .passbook-container {
padding: 16px; padding: 16px;
background: #eef1f7;
min-height: 100%;
} }
// Filter Bar // ─── Filter Bar ─────────────────────────────────────────────────────────────
.passbook-filter-bar { .passbook-filter-bar {
margin-bottom: 16px; margin-bottom: 16px;
background: #fff;
border-radius: 8px;
padding: 12px 16px;
border: 1px solid $border-color;
} }
.passbook-filter-form { .passbook-filter-form {
@@ -30,147 +48,388 @@
flex: 1; flex: 1;
} }
// Passbook Preview // ─── Statement Wrapper ───────────────────────────────────────────────────────
.passbook-preview { .statement-wrapper {
border: 1px solid #e0e0e0;
border-radius: 8px;
padding: 24px;
background: #fff; background: #fff;
border: 1px solid $border-color;
border-radius: 8px;
overflow: hidden;
box-shadow: 0 2px 12px rgb(0 0 0 / 8%);
font-family: 'Segoe UI', Arial, sans-serif;
} }
.passbook-header { // ─── Bank Header ─────────────────────────────────────────────────────────────
text-align: center; .bank-header {
margin-bottom: 20px; background: $bank-primary;
border-bottom: 2px solid #1976d2; padding: 18px 24px;
padding-bottom: 12px; display: flex;
justify-content: space-between;
h2 { align-items: center;
color: #1976d2; border-bottom: 4px solid $bank-accent;
font-size: 20px;
margin: 0 0 4px;
font-weight: 600;
} }
h3 { .bank-logo-area {
font-size: 14px; display: flex;
font-weight: 400; align-items: center;
color: #666; gap: 14px;
margin: 0; }
.bank-logo-circle {
width: 52px;
height: 52px;
border-radius: 50%;
background: $bank-accent;
display: flex;
align-items: center;
justify-content: center;
mat-icon {
color: $bank-primary;
font-size: 28px;
width: 28px;
height: 28px;
} }
} }
.passbook-info-grid { .bank-name-block {
display: grid; .bank-title {
grid-template-columns: repeat(3, 1fr); color: #fff;
gap: 12px 20px; font-size: 18px;
margin-bottom: 16px; font-weight: 700;
padding: 12px; letter-spacing: 0.3px;
background: #f5f5f5;
border-radius: 6px;
} }
.passbook-info-item { .bank-subtitle {
.label { color: $bank-accent;
font-size: 10px; font-size: 11px;
font-weight: 600; font-weight: 500;
color: #888; letter-spacing: 1.5px;
text-transform: uppercase; text-transform: uppercase;
letter-spacing: 0.5px;
}
.value {
font-size: 13px;
color: #333;
margin-top: 2px; margin-top: 2px;
} }
} }
.passbook-balance-row { .statement-label {
text-align: right;
.stmt-label-text {
color: $bank-accent;
font-size: 13px;
font-weight: 700;
letter-spacing: 2px;
text-transform: uppercase;
}
.stmt-period {
color: rgb(255 255 255 / 75%);
font-size: 11px;
margin-top: 4px;
}
}
// ─── Account Details Band ────────────────────────────────────────────────────
.account-details-band {
background: #f0f3f9;
border-bottom: 1px solid $border-color;
padding: 14px 24px;
}
.account-details-grid {
display: grid;
grid-template-columns: repeat(3, 1fr);
gap: 12px 24px;
}
.detail-block {
.detail-label {
font-size: 9px;
font-weight: 700;
color: #7a8aaa;
text-transform: uppercase;
letter-spacing: 0.8px;
margin-bottom: 3px;
}
.detail-value {
font-size: 13px;
color: #222;
&.bold {
font-weight: 600;
}
&.mono {
font-family: 'Courier New', monospace;
letter-spacing: 1px;
}
&.status-badge {
display: inline-block;
padding: 1px 8px;
border-radius: 10px;
font-size: 11px;
font-weight: 600;
background: #eee;
color: #555;
&.active {
background: #d4edda;
color: #155724;
}
}
}
}
// ─── Balance Summary Strip ───────────────────────────────────────────────────
.balance-summary-strip {
display: flex; display: flex;
justify-content: space-between; align-items: stretch;
margin-bottom: 16px; background: $bank-primary;
padding: 10px 14px; padding: 0;
background: #e3f2fd;
border-radius: 6px;
font-size: 14px;
.balance-item {
b {
color: #1976d2;
} }
.balance-box {
flex: 1;
padding: 12px 20px;
text-align: center;
.balance-box-label {
font-size: 10px;
font-weight: 600;
color: rgb(255 255 255 / 65%);
text-transform: uppercase;
letter-spacing: 1px;
margin-bottom: 4px;
}
.balance-box-value {
font-size: 16px;
font-weight: 700;
color: $bank-accent;
} }
} }
// Transactions Table .balance-divider {
table { width: 1px;
background: rgb(255 255 255 / 15%);
margin: 8px 0;
}
// ─── Transactions Table ───────────────────────────────────────────────────────
.statement-table {
width: 100%; width: 100%;
border-collapse: collapse; border-collapse: collapse;
font-size: 13px; font-size: 12.5px;
th { thead tr {
background: #1976d2; background: #e8edf5;
color: #fff; border-top: 1px solid $border-color;
padding: 8px 10px; border-bottom: 2px solid $bank-primary;
text-align: left;
font-weight: 600;
font-size: 12px;
} }
thead th {
padding: 9px 10px;
font-size: 11px;
font-weight: 700;
color: $bank-primary;
text-transform: uppercase;
letter-spacing: 0.4px;
white-space: nowrap;
}
tbody tr {
border-bottom: 1px solid #e8ecf3;
transition: background 0.1s;
&:nth-child(even) {
background: $row-alt;
}
&:hover {
background: #dce6f5;
}
&.reversed-row {
opacity: 0.5;
text-decoration: line-through;
}
}
tbody td {
padding: 7px 10px;
vertical-align: middle;
color: #333;
}
tfoot .total-row {
background: #e8edf5;
border-top: 2px solid $bank-primary;
td { td {
padding: 6px 10px; padding: 9px 10px;
border-bottom: 1px solid #e0e0e0; }
}
} }
tr:nth-child(even) { // ─── Column widths ────────────────────────────────────────────────────────────
background: #fafafa; .col-sr {
width: 38px;
} }
tr:hover { .col-date {
background: #f0f0f0; width: 110px;
white-space: nowrap;
} }
.reversed { .col-desc {
text-decoration: line-through; min-width: 160px;
color: #999;
} }
.col-ref {
width: 80px;
}
.col-amount {
width: 110px;
}
.col-balance {
width: 120px;
}
// ─── Amount colors ────────────────────────────────────────────────────────────
.debit-amount {
color: $debit-color;
font-weight: 500;
}
.credit-amount {
color: $credit-color;
font-weight: 500;
}
.balance-amount {
color: $balance-color;
font-weight: 600;
font-family: 'Courier New', monospace;
}
.total-label {
font-size: 12px;
font-weight: 700;
color: $bank-primary;
text-transform: uppercase;
letter-spacing: 0.5px;
}
.closing-balance {
font-size: 14px;
font-weight: 700;
color: $bank-primary;
font-family: 'Courier New', monospace;
}
// ─── Badges & misc ────────────────────────────────────────────────────────────
.txn-desc {
font-weight: 500;
}
.reversed-badge {
display: inline-block;
margin-left: 8px;
font-size: 9px;
font-weight: 700;
color: #fff;
background: #e74c3c;
padding: 1px 5px;
border-radius: 3px;
letter-spacing: 0.5px;
} }
.text-right { .text-right {
text-align: right; text-align: right;
} }
.passbook-no-data { .text-center {
text-align: center;
}
.text-muted {
color: #999;
}
.mono {
font-family: 'Courier New', monospace;
font-size: 11px;
}
// ─── No Data ──────────────────────────────────────────────────────────────────
.no-data-block {
display: flex; display: flex;
flex-direction: column;
align-items: center; align-items: center;
justify-content: center; justify-content: center;
gap: 8px; padding: 48px;
padding: 32px; color: #aaa;
color: #888;
font-size: 14px;
mat-icon { mat-icon {
color: #bbb; font-size: 48px;
width: 48px;
height: 48px;
margin-bottom: 12px;
}
p {
font-size: 14px;
margin: 0;
} }
} }
.passbook-footer { // ─── Statement Footer ─────────────────────────────────────────────────────────
margin-top: 16px; .statement-footer {
font-size: 11px; background: #f0f3f9;
color: #999; border-top: 1px solid $border-color;
padding: 12px 24px;
text-align: center; text-align: center;
border-top: 1px solid #e0e0e0;
padding-top: 10px; .footer-note {
font-size: 10px;
color: #888;
margin-bottom: 4px;
font-style: italic;
} }
// Responsive .footer-meta {
font-size: 10px;
color: #aaa;
letter-spacing: 0.3px;
}
}
// ─── Responsive ───────────────────────────────────────────────────────────────
@media (width <= 768px) { @media (width <= 768px) {
.passbook-info-grid { .account-details-grid {
grid-template-columns: 1fr 1fr; grid-template-columns: 1fr 1fr;
} }
.passbook-balance-row { .bank-header {
flex-direction: column; flex-direction: column;
gap: 8px; gap: 12px;
align-items: flex-start;
}
.statement-label {
text-align: left;
}
.balance-summary-strip {
flex-direction: column;
}
.balance-divider {
width: auto;
height: 1px;
margin: 0 20px;
} }
.passbook-filter-form { .passbook-filter-form {
@@ -188,19 +447,35 @@ table {
} }
@media (width <= 480px) { @media (width <= 480px) {
.passbook-info-grid { .account-details-grid {
grid-template-columns: 1fr; grid-template-columns: 1fr;
} }
} }
// Print-specific styles // ─── Print ────────────────────────────────────────────────────────────────────
@media print { @media print {
.passbook-filter-bar { .no-print {
display: none !important; display: none !important;
} }
.passbook-preview { .passbook-container {
border: none; background: #fff;
padding: 0; padding: 0;
} }
.statement-wrapper {
border: none;
box-shadow: none;
border-radius: 0;
}
.bank-header {
-webkit-print-color-adjust: exact;
print-color-adjust: exact;
}
.balance-summary-strip {
-webkit-print-color-adjust: exact;
print-color-adjust: exact;
}
} }
@@ -6,23 +6,22 @@
file, You can obtain one at http://mozilla.org/MPL/2.0/. file, You can obtain one at http://mozilla.org/MPL/2.0/.
--> -->
<div class="container"> <div class="txn-tab">
<div class="mat-elevation-z1 m-b-25" [hidden]="!accountWithTransactions"> <div class="txn-tab__card" [hidden]="!accountWithTransactions">
<div class="layout-row align-end">
@if (checkStatus()) { @if (checkStatus()) {
<div class="action-button m-b-20 layout-row gap-20px"> <div class="txn-tab__toolbar">
<mat-checkbox [formControl]="hideReversedParam" (click)="hideReversed()" class="accruals"> <mat-checkbox [formControl]="hideReversedParam" (click)="hideReversed()" class="txn-tab__check">
{{ 'labels.inputs.Hide Reversed' | translate }}</mat-checkbox {{ 'labels.inputs.Hide Reversed' | translate }}
> </mat-checkbox>
<mat-checkbox [formControl]="hideAccrualsParam" (click)="hideAccruals()" class="accruals"> <mat-checkbox [formControl]="hideAccrualsParam" (click)="hideAccruals()" class="txn-tab__check">
{{ 'labels.inputs.Hide Accruals' | translate }}</mat-checkbox {{ 'labels.inputs.Hide Accruals' | translate }}
> </mat-checkbox>
<button mat-raised-button color="primary" [routerLink]="['export']"> <span class="txn-tab__spacer"></span>
<button mat-flat-button class="txn-tab__export" [routerLink]="['export']">
{{ 'labels.buttons.Export' | translate }} {{ 'labels.buttons.Export' | translate }}
</button> </button>
</div> </div>
} }
</div>
<table mat-table [dataSource]="dataSource" matSort> <table mat-table [dataSource]="dataSource" matSort>
<ng-container matColumnDef="row"> <ng-container matColumnDef="row">
@@ -176,10 +175,11 @@
<mat-paginator [pageSize]="50" [pageSizeOptions]="[50, 100, 200]" showFirstLastButtons></mat-paginator> <mat-paginator [pageSize]="50" [pageSizeOptions]="[50, 100, 200]" showFirstLastButtons></mat-paginator>
</div> </div>
<div class="alert" [hidden]="accountWithTransactions"> <div class="txn-tab__empty" [hidden]="accountWithTransactions">
<div class="message"> <fa-icon icon="inbox" class="txn-tab__empty-ico"></fa-icon>
<i class="fa fa-exclamation-circle alert-check"></i> <div class="txn-tab__empty-title">
{{ 'labels.text.No transaction was found' | translate }} {{ 'labels.text.No transaction was found' | translate }}
</div> </div>
<div class="txn-tab__empty-sub">Posted transactions will appear here.</div>
</div> </div>
</div> </div>
@@ -6,37 +6,151 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. * file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/ */
@use 'assets/styles/helper'; $navy: #0d1b2a;
$slate: #475569;
$muted: #64748b;
$border: #e2e8f0;
$soft: #f8fafc;
$blue: #1e40af;
.tab-container { .txn-tab {
padding: 1%; width: 100%;
margin: 1%;
h3 {
margin: 1% auto;
} }
.action-button { .txn-tab__card {
margin-left: auto; background: #fff;
border: 1px solid $border;
border-radius: 14px;
box-shadow: 0 1px 3px rgb(15 23 42 / 4%);
overflow: hidden;
} }
/* ─── Toolbar ─────────────────────────────────────────────────────── */
.txn-tab__toolbar {
display: flex;
align-items: center;
gap: 18px;
padding: 12px 18px;
background: $soft;
border-bottom: 1px solid $border;
flex-wrap: wrap;
}
.txn-tab__check {
font-size: 13px;
color: $slate;
font-weight: 500;
}
.txn-tab__spacer {
flex: 1;
}
.txn-tab__export {
height: 36px !important;
border-radius: 8px !important;
font-weight: 600 !important;
font-size: 13px !important;
padding: 0 16px !important;
background: linear-gradient(135deg, #1e88e5 0%, $blue 100%) !important;
color: #fff !important;
}
/* ─── Table ───────────────────────────────────────────────────────── */
table { table {
width: 100%; width: 100%;
.account-action-button {
min-width: 26px;
padding: 0 0 3px;
margin: 0 10%;
line-height: 25px;
.accruals {
padding-top: 1%;
}
}
}
} }
.select-row:hover { ::ng-deep .txn-tab__card {
cursor: pointer; .mat-mdc-header-row {
background: $soft;
}
.mat-mdc-header-cell {
font-size: 11.5px;
font-weight: 800; font-weight: 800;
color: $slate;
text-transform: uppercase;
letter-spacing: 0.06em;
padding: 12px 14px;
border-bottom: 1px solid $border;
}
.mat-mdc-cell {
font-size: 13px;
color: $navy;
padding: 11px 14px;
border-bottom: 1px solid #f1f5f9;
}
.mat-mdc-row:hover {
background: #f8fafc;
cursor: pointer;
}
/* Tabular numerics on the money columns (Debit / Credit / Balance) +
right-align them. */
.mat-column-debit,
.mat-column-credit,
.mat-column-balance {
text-align: right;
font-variant-numeric: tabular-nums;
}
.mat-column-actions {
text-align: center;
width: 80px;
}
/* Compact paginator */
.mat-mdc-paginator {
border-top: 1px solid $border;
background: $soft;
min-height: 48px;
}
/* Row tint variants — strike-through reversed, dim accrual, blue transfer */
.strike td {
text-decoration: line-through;
color: $muted;
}
.accrual td {
color: $muted;
font-style: italic;
}
.transfer td {
color: #6d28d9;
}
}
/* ─── Empty state ─────────────────────────────────────────────────── */
.txn-tab__empty {
background: #fff;
border: 1px solid $border;
border-radius: 14px;
box-shadow: 0 1px 3px rgb(15 23 42 / 4%);
padding: 56px 24px;
text-align: center;
color: $muted;
}
.txn-tab__empty-ico {
font-size: 34px;
color: #cbd5e1;
margin-bottom: 8px;
}
.txn-tab__empty-title {
font-size: 14.5px;
font-weight: 700;
color: $slate;
margin-top: 6px;
}
.txn-tab__empty-sub {
font-size: 12.5px;
color: $muted;
margin-top: 2px;
} }
@@ -6,21 +6,18 @@
file, You can obtain one at http://mozilla.org/MPL/2.0/. file, You can obtain one at http://mozilla.org/MPL/2.0/.
--> -->
<div class="tab-container mat-typography"> <div class="chg-tab">
<div class="layout-row align-start"> <div class="chg-tab__card">
<div class="m-b-10"> <div class="chg-tab__toolbar">
<h3>{{ 'labels.heading.All Charges' | translate }}</h3> <h3 class="chg-tab__title">{{ 'labels.heading.All Charges' | translate }}</h3>
</div> <span class="chg-tab__spacer"></span>
@if (this.chargesData) { @if (this.chargesData) {
<div class="action-button m-b-20"> <button mat-flat-button class="chg-tab__toggle" (click)="toggleCharges()">
<button mat-raised-button color="primary" (click)="toggleCharges()">
{{ showInactiveCharges ? 'View Active Charges' : 'View Inactive Charges' }} {{ showInactiveCharges ? 'View Active Charges' : 'View Inactive Charges' }}
</button> </button>
</div>
} }
</div> </div>
<div class="mat-elevation-z1 m-b-25">
<table mat-table #chargesTable [dataSource]="dataSource"> <table mat-table #chargesTable [dataSource]="dataSource">
<ng-container matColumnDef="name"> <ng-container matColumnDef="name">
<th mat-header-cell *matHeaderCellDef>{{ 'labels.inputs.name' | translate }}</th> <th mat-header-cell *matHeaderCellDef>{{ 'labels.inputs.name' | translate }}</th>
@@ -6,26 +6,106 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. * file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/ */
.tab-container { $navy: #0d1b2a;
padding: 1%; $slate: #475569;
margin: 1%; $muted: #64748b;
$border: #e2e8f0;
$soft: #f8fafc;
$blue: #1e40af;
h3 { .chg-tab {
margin: 1% auto; width: 100%;
} }
.action-button { .chg-tab__card {
margin-left: auto; background: #fff;
border: 1px solid $border;
border-radius: 14px;
box-shadow: 0 1px 3px rgb(15 23 42 / 4%);
overflow: hidden;
}
.chg-tab__toolbar {
display: flex;
align-items: center;
gap: 14px;
padding: 12px 18px;
background: $soft;
border-bottom: 1px solid $border;
}
.chg-tab__title {
margin: 0;
font-size: 14px;
font-weight: 700;
color: $navy;
letter-spacing: 0.01em;
}
.chg-tab__spacer {
flex: 1;
}
.chg-tab__toggle {
height: 34px !important;
border-radius: 8px !important;
font-weight: 600 !important;
font-size: 13px !important;
padding: 0 14px !important;
background: linear-gradient(135deg, #1e88e5 0%, $blue 100%) !important;
color: #fff !important;
} }
table { table {
width: 100%; width: 100%;
}
::ng-deep .chg-tab__card {
.mat-mdc-header-row {
background: $soft;
}
.mat-mdc-header-cell {
font-size: 11.5px;
font-weight: 800;
color: $slate;
text-transform: uppercase;
letter-spacing: 0.06em;
padding: 12px 14px;
border-bottom: 1px solid $border;
}
.mat-mdc-cell {
font-size: 13px;
color: $navy;
padding: 11px 14px;
border-bottom: 1px solid #f1f5f9;
}
.mat-mdc-row:hover {
background: #f8fafc;
cursor: pointer;
}
.mat-column-due,
.mat-column-paid,
.mat-column-waived,
.mat-column-outstanding {
text-align: right;
font-variant-numeric: tabular-nums;
}
.mat-column-actions {
text-align: center;
width: 140px;
.account-action-button { .account-action-button {
min-width: 26px; min-width: 30px !important;
padding: 0 6px; padding: 0 8px !important;
margin: 4px; margin: 0 3px !important;
line-height: 25px; height: 30px !important;
line-height: 30px !important;
border-radius: 7px !important;
} }
} }
} }
@@ -6,99 +6,87 @@
file, You can obtain one at http://mozilla.org/MPL/2.0/. file, You can obtain one at http://mozilla.org/MPL/2.0/.
--> -->
<mat-card class="account-card"> <div class="fd-view">
<mat-card-header class="header layout-column"> <!-- ─── Gradient hero header ─────────────────────────────────────── -->
<mat-card-title-group class="header-title-group"> <header class="fd-hero">
<div class="profile-image-container"> <div class="fd-hero__left">
<div> <div class="fd-hero__avatar">
<img <fa-icon icon="piggy-bank"></fa-icon>
mat-card-md-image
class="profile-image"
matTooltip="{{ 'tooltips.Fixed Deposits Account' | translate }}"
[src]="'assets/images/fd_account_placeholder.png'"
/>
</div>
</div> </div>
<div class="mat-typography account-card-title"> <div class="fd-hero__info">
<mat-card-title> <div class="fd-hero__status-row">
<div class="layout-row responsive-column"> <span
<div class="flex-60"> class="fd-status-pill"
<h3>
<i
class="fa fa-stop"
[ngClass]="fixedDepositsAccountData.status.code | statusLookup" [ngClass]="fixedDepositsAccountData.status.code | statusLookup"
[matTooltip]="fixedDepositsAccountData.status.value" [matTooltip]="fixedDepositsAccountData.status.value"
></i> >
{{ 'labels.inputs.Fixed Deposit Product' | translate }} : <span class="fd-status-pill__dot"></span>
{{ fixedDepositsAccountData.depositProductName }} {{ fixedDepositsAccountData.status.value }}
<mifosx-account-number accountNo="{{ fixedDepositsAccountData.accountNo }}"></mifosx-account-number> </span>
</h3> </div>
<span class="account-overview">
<span class="m-r-10">{{ 'labels.text.' + entityType | translate }} :</span> <h2 class="fd-hero__title">
<mifosx-long-text textValue="{{ fixedDepositsAccountData.depositProductName }}"></mifosx-long-text>
</h2>
<div class="fd-hero__meta">
<span class="fd-hero__meta-item">
<span class="fd-hero__meta-label">{{ 'labels.inputs.Account Number' | translate }}</span>
<mifosx-account-number
accountNo="{{ fixedDepositsAccountData.accountNo }}"
display="left"
></mifosx-account-number>
</span>
<span class="fd-hero__meta-item">
<span class="fd-hero__meta-label">
{{ 'labels.text.' + entityType | translate }} {{ 'labels.inputs.name' | translate }}
</span>
<span class="fd-hero__meta-value">
{{ fixedDepositsAccountData.clientName || fixedDepositsAccountData.groupName }} {{ fixedDepositsAccountData.clientName || fixedDepositsAccountData.groupName }}
@if (fixedDepositsAccountData.clientAccountNo) { @if (fixedDepositsAccountData.clientAccountNo) {
<span class="m-l-10">
<mifosx-account-number <mifosx-account-number
accountNo="{{ fixedDepositsAccountData.clientAccountNo }}" accountNo="{{ fixedDepositsAccountData.clientAccountNo }}"
></mifosx-account-number> ></mifosx-account-number>
</span>
} }
</span> </span>
</span>
</div>
</div>
</div> </div>
@if ( <!-- Balance KPI strip -->
!fixedDepositsAccountData.status.rejected && !fixedDepositsAccountData.status.submittedAndPendingApproval @if (!fixedDepositsAccountData.status.rejected && !fixedDepositsAccountData.status.submittedAndPendingApproval) {
) { <div class="fd-hero__kpis">
<div class="flex-30"> <div class="fd-kpi">
<h3 class="flex-100">{{ 'labels.heading.Account Overview' | translate }}</h3> <span class="fd-kpi__label">{{ 'labels.inputs.Current Balance' | translate }}</span>
<table class="account-overview flex-100"> <span class="fd-kpi__value">
<tbody> {{ fixedDepositsAccountData.summary.accountBalance | currency: currency.code : 'symbol-narrow' : '1.2-2' }}
<tr> </span>
<td class="flex-70">{{ 'labels.inputs.Current Balance' | translate }}</td> </div>
<td class="r-amount flex-30"> <div class="fd-kpi fd-kpi--deposit">
{{ <span class="fd-kpi__label">{{ 'labels.inputs.Deposit Amount' | translate }}</span>
fixedDepositsAccountData.summary.accountBalance <span class="fd-kpi__value">
| currency: currency.code : 'symbol-narrow' : '1.2-2' {{ fixedDepositsAccountData.depositAmount | currency: currency.code : 'symbol-narrow' : '1.2-2' }}
}} </span>
</td> </div>
</tr>
<tr>
<td class="flex-70">{{ 'labels.inputs.Deposit Amount' | translate }}</td>
<td class="r-amount flex-30">
{{
fixedDepositsAccountData.depositAmount | currency: currency.code : 'symbol-narrow' : '1.2-2'
}}
</td>
</tr>
</tbody>
</table>
</div> </div>
} }
<div class="flex-5"> <!-- Action menu (kebab) -->
<button <div class="fd-hero__actions">
mat-icon-button <button mat-icon-button [matMenuTriggerFor]="accountMenu" aria-label="Account actions" yPosition="below">
[matMenuTriggerFor]="accountMenu" <fa-icon icon="ellipsis-v"></fa-icon>
aria-label="Fixed Deposit account actions"
yPosition="below"
>
<mat-icon matListIcon class="actions-menu">
<fa-icon icon="bars" size="sm"></fa-icon>
</mat-icon>
</button> </button>
</div> </div>
</div>
</mat-card-title>
</div>
<mat-menu #accountMenu="matMenu"> <mat-menu #accountMenu="matMenu">
@for (button of buttonConfig.singleButtons; track button) { @for (button of buttonConfig.singleButtons; track button) {
<button mat-menu-item (click)="doAction(button.name)"> <button mat-menu-item (click)="doAction(button.name)">
<i ngClass="{{ button.icon }}"></i> {{ button.name | translateKey: 'menus' }} <span>{{ button.name | translateKey: 'menus' }}</span>
</button> </button>
} }
@if (buttonConfig.options.length) { @if (buttonConfig.options.length) {
<button mat-menu-item [matMenuTriggerFor]="More">{{ 'More' | translateKey: 'menus' }}</button> <button mat-menu-item [matMenuTriggerFor]="More">{{ 'More' | translateKey: 'menus' }}</button>
<mat-menu #More="matMenu"> <mat-menu #More="matMenu">
@@ -110,87 +98,99 @@
</mat-menu> </mat-menu>
} }
</mat-menu> </mat-menu>
</mat-card-title-group> </header>
</mat-card-header>
<mat-card-content class="content"> <!-- ─── Pill-style tab navigation ─────────────────────────────────── -->
<nav mat-tab-nav-bar class="navigation-tabs" [tabPanel]="tabPanel"> <nav mat-tab-nav-bar class="fd-tabs" [tabPanel]="tabPanel">
<a <a
mat-tab-link mat-tab-link
class="fd-tab"
[routerLink]="['./general']" [routerLink]="['./general']"
routerLinkActive routerLinkActive
#general="routerLinkActive" #general="routerLinkActive"
[active]="general.isActive" [active]="general.isActive"
> >
{{ 'labels.inputs.General' | translate }} <fa-icon icon="info-circle" class="fd-tab__ic"></fa-icon>
<span>{{ 'labels.inputs.General' | translate }}</span>
</a> </a>
<a <a
mat-tab-link mat-tab-link
class="fd-tab"
[routerLink]="['./interest-rate-chart']" [routerLink]="['./interest-rate-chart']"
routerLinkActive routerLinkActive
#IRC="routerLinkActive" #IRC="routerLinkActive"
[active]="IRC.isActive" [active]="IRC.isActive"
> >
{{ 'labels.inputs.Interest Rate Chart' | translate }} <fa-icon icon="chart-line" class="fd-tab__ic"></fa-icon>
<span>{{ 'labels.inputs.Interest Rate Chart' | translate }}</span>
</a> </a>
@if (showTransactions) { @if (showTransactions) {
<span>
<a <a
mat-tab-link mat-tab-link
class="fd-tab"
[routerLink]="['./transactions']" [routerLink]="['./transactions']"
routerLinkActive routerLinkActive
#transactions="routerLinkActive" #transactions="routerLinkActive"
[active]="transactions.isActive" [active]="transactions.isActive"
> >
{{ 'labels.inputs.Transactions' | translate }} <fa-icon icon="exchange-alt" class="fd-tab__ic"></fa-icon>
<span>{{ 'labels.inputs.Transactions' | translate }}</span>
</a> </a>
</span>
} }
<a <a
mat-tab-link mat-tab-link
class="fd-tab"
[routerLink]="['./charges']" [routerLink]="['./charges']"
routerLinkActive routerLinkActive
#charges="routerLinkActive" #charges="routerLinkActive"
[active]="charges.isActive" [active]="charges.isActive"
> >
{{ 'labels.inputs.Charges' | translate }} <fa-icon icon="receipt" class="fd-tab__ic"></fa-icon>
<span>{{ 'labels.inputs.Charges' | translate }}</span>
</a> </a>
@if (fixedDepositsAccountData.clientId) { @if (fixedDepositsAccountData.clientId) {
<a <a
mat-tab-link mat-tab-link
class="fd-tab"
[routerLink]="['./standing-instructions']" [routerLink]="['./standing-instructions']"
routerLinkActive routerLinkActive
#standingInstructions="routerLinkActive" #standingInstructions="routerLinkActive"
[active]="standingInstructions.isActive" [active]="standingInstructions.isActive"
> >
{{ 'labels.inputs.Standing Instructions' | translate }} <fa-icon icon="calendar-check" class="fd-tab__ic"></fa-icon>
<span>{{ 'labels.inputs.Standing Instructions' | translate }}</span>
</a> </a>
} }
<a <a
mat-tab-link mat-tab-link
class="fd-tab"
[routerLink]="['./nominees']" [routerLink]="['./nominees']"
routerLinkActive routerLinkActive
#nominees="routerLinkActive" #nominees="routerLinkActive"
[active]="nominees.isActive" [active]="nominees.isActive"
> >
Nominees <fa-icon icon="user-shield" class="fd-tab__ic"></fa-icon>
<span>Nominees</span>
</a> </a>
@for (savingsDatatable of savingsDatatables; track savingsDatatable) { @for (savingsDatatable of savingsDatatables; track savingsDatatable) {
<a <a
mat-tab-link mat-tab-link
class="fd-tab"
*mifosxHasPermission="'READ_' + savingsDatatable.registeredTableName" *mifosxHasPermission="'READ_' + savingsDatatable.registeredTableName"
[routerLink]="['./datatables', savingsDatatable.registeredTableName]" [routerLink]="['./datatables', savingsDatatable.registeredTableName]"
routerLinkActive routerLinkActive
#datatable="routerLinkActive" #datatable="routerLinkActive"
[active]="datatable.isActive" [active]="datatable.isActive"
> >
{{ savingsDatatable.registeredTableName }} <fa-icon icon="table" class="fd-tab__ic"></fa-icon>
<span>{{ savingsDatatable.registeredTableName }}</span>
</a> </a>
} }
</nav> </nav>
<mat-tab-nav-panel #tabPanel> <mat-tab-nav-panel #tabPanel>
<div class="fd-body">
<router-outlet></router-outlet> <router-outlet></router-outlet>
</div>
</mat-tab-nav-panel> </mat-tab-nav-panel>
</mat-card-content> </div>
</mat-card>
@@ -5,3 +5,381 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this * License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. * file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/ */
$navy: #0d1b2a;
$blue: #1e88e5;
$blue-d: #1e40af;
$border: #e2e8f0;
.fd-view {
max-width: 1440px;
margin: 0 auto;
padding: 12px 20px 22px;
}
/* ─── Gradient hero header ──────────────────────────────────────────── */
.fd-hero {
position: relative;
display: grid;
grid-template-columns: minmax(0, 1fr) auto auto;
align-items: stretch;
gap: 14px;
padding: 12px 18px;
border-radius: 12px;
color: #fff;
background: linear-gradient(135deg, #1e3a8a 0%, #1e40af 45%, #4338ca 100%);
box-shadow: 0 6px 18px -10px rgb(15 23 42 / 35%);
overflow: hidden;
&::before {
content: '';
position: absolute;
inset: 0;
background: radial-gradient(circle at top right, rgb(255 255 255 / 12%) 0%, transparent 55%);
pointer-events: none;
}
&__left {
display: flex;
align-items: center;
gap: 12px;
min-width: 0;
position: relative;
z-index: 1;
}
&__avatar {
width: 40px;
height: 40px;
border-radius: 10px;
background: linear-gradient(135deg, rgb(255 255 255 / 22%) 0%, rgb(255 255 255 / 10%) 100%);
border: 1px solid rgb(255 255 255 / 28%);
display: flex;
align-items: center;
justify-content: center;
color: #fff;
font-size: 16px;
flex-shrink: 0;
box-shadow: 0 3px 10px -3px rgb(0 0 0 / 25%);
}
&__info {
display: flex;
flex-direction: column;
gap: 3px;
min-width: 0;
}
&__status-row {
display: flex;
align-items: center;
gap: 6px;
}
&__title {
margin: 0;
font-size: 15px;
font-weight: 800;
letter-spacing: 0.01em;
color: #fff;
line-height: 1.15;
::ng-deep mifosx-long-text {
color: #fff;
}
}
&__meta {
display: flex;
flex-wrap: wrap;
gap: 2px 18px;
margin-top: 1px;
}
&__meta-item {
display: inline-flex;
align-items: center;
gap: 6px;
font-size: 12px;
color: rgb(255 255 255 / 90%);
}
&__meta-label {
font-size: 10px;
text-transform: uppercase;
letter-spacing: 0.07em;
color: rgb(255 255 255 / 60%);
font-weight: 600;
}
&__meta-value {
font-weight: 600;
color: #fff;
}
&__kpis {
display: flex;
gap: 8px;
align-items: stretch;
position: relative;
z-index: 1;
}
&__actions {
display: flex;
align-items: center;
position: relative;
z-index: 1;
button {
width: 32px !important;
height: 32px !important;
min-width: 32px !important;
padding: 0 !important;
border-radius: 50% !important;
color: #fff !important;
background: rgb(255 255 255 / 10%) !important;
border: 1px solid rgb(255 255 255 / 22%) !important;
display: inline-flex !important;
align-items: center;
justify-content: center;
line-height: 1;
transition:
background 0.15s ease,
border-color 0.15s ease,
transform 0.12s ease;
::ng-deep fa-icon {
font-size: 14px;
line-height: 1;
display: inline-flex;
align-items: center;
justify-content: center;
}
::ng-deep .mat-mdc-button-persistent-ripple,
::ng-deep .mat-mdc-button-touch-target {
border-radius: 50% !important;
}
}
button:hover {
background: rgb(255 255 255 / 22%) !important;
border-color: rgb(255 255 255 / 38%) !important;
}
button:active {
transform: scale(0.94);
}
}
}
/* KPI tiles */
.fd-kpi {
display: flex;
flex-direction: column;
justify-content: center;
min-width: 130px;
padding: 7px 14px;
border-radius: 9px;
background: rgb(255 255 255 / 14%);
border: 1px solid rgb(255 255 255 / 22%);
backdrop-filter: blur(8px);
&__label {
font-size: 9.5px;
text-transform: uppercase;
letter-spacing: 0.07em;
font-weight: 700;
color: rgb(255 255 255 / 75%);
}
&__value {
margin-top: 2px;
font-size: 15px;
font-weight: 800;
color: #fff;
font-variant-numeric: tabular-nums;
letter-spacing: -0.01em;
}
&--deposit {
background: rgb(245 158 11 / 22%);
border-color: rgb(245 158 11 / 35%);
}
}
/* Status pill */
.fd-status-pill {
display: inline-flex;
align-items: center;
gap: 5px;
height: 18px;
padding: 0 8px;
border-radius: 999px;
background: rgb(16 185 129 / 24%);
border: 1px solid rgb(16 185 129 / 40%);
font-size: 10px;
font-weight: 700;
text-transform: uppercase;
letter-spacing: 0.06em;
color: #d1fae5;
&__dot {
width: 5px;
height: 5px;
border-radius: 50%;
background: #10b981;
box-shadow: 0 0 0 2px rgb(16 185 129 / 30%);
}
&.statussubmitted,
&.statuspending {
background: rgb(245 158 11 / 24%);
border-color: rgb(245 158 11 / 40%);
color: #fef3c7;
.fd-status-pill__dot {
background: #f59e0b;
}
}
&.statusclosed,
&.statusrejected,
&.statuswithdrawn,
&.statusprematureclosed {
background: rgb(239 68 68 / 24%);
border-color: rgb(239 68 68 / 40%);
color: #fee2e2;
.fd-status-pill__dot {
background: #ef4444;
}
}
}
/* ─── Pill-style tab navigation ─────────────────────────────────────── */
.fd-tabs {
margin-top: 18px;
background: #fff;
border: 1px solid $border;
border-radius: 14px;
padding: 6px;
box-shadow: 0 1px 3px rgb(15 23 42 / 4%);
overflow: hidden;
::ng-deep {
.mat-mdc-tab-link-container {
border-bottom: none !important;
}
.mat-mdc-tab-links {
gap: 4px;
flex-wrap: wrap;
}
.mdc-tab-indicator__content--underline,
.mat-mdc-tab-header-pagination-controls-enabled .mdc-tab-indicator__content--underline {
display: none !important;
}
}
}
.fd-tab {
display: inline-flex !important;
align-items: center;
gap: 8px;
height: 38px !important;
min-width: 0 !important;
padding: 0 16px !important;
border-radius: 10px !important;
font-family: Inter, 'DM Sans', Roboto, sans-serif !important;
font-size: 13px !important;
font-weight: 600 !important;
letter-spacing: 0.01em !important;
color: #64748b !important;
background: transparent !important;
transition: all 0.15s ease;
white-space: nowrap;
border: 1px solid transparent !important;
opacity: 1 !important;
&__ic {
font-size: 12px;
color: inherit;
}
&:hover:not(.mdc-tab--active) {
background: #f1f5f9 !important;
color: $navy !important;
}
&.mdc-tab--active,
&.mat-mdc-tab-link-active {
background: linear-gradient(135deg, $blue 0%, $blue-d 100%) !important;
color: #fff !important;
box-shadow: 0 2px 6px -1px rgb(30 64 175 / 35%);
border-color: $blue-d !important;
::ng-deep .mdc-tab__text-label,
::ng-deep .mat-mdc-tab-link-content,
::ng-deep span,
.fd-tab__ic {
color: #fff !important;
opacity: 1 !important;
}
}
}
.fd-body {
margin-top: 16px;
}
/* ─── Responsive ────────────────────────────────────────────────────── */
@media (width <= 1100px) {
.fd-hero {
grid-template-columns: 1fr;
&__kpis {
width: 100%;
flex-wrap: wrap;
}
&__actions {
position: absolute;
top: 18px;
right: 18px;
}
}
.fd-kpi {
flex: 1 1 auto;
min-width: 0;
}
}
@media (width <= 700px) {
.fd-view {
padding: 12px;
}
.fd-hero {
padding: 18px;
&__title {
font-size: 18px;
}
&__avatar {
width: 52px;
height: 52px;
font-size: 22px;
border-radius: 12px;
}
}
.fd-tab {
padding: 0 12px !important;
font-size: 12px !important;
}
}
@@ -24,17 +24,10 @@ import { FixedDepositsButtonsConfiguration } from './fixed-deposits-buttons.conf
import { FixedDepositsService } from '../fixed-deposits.service'; import { FixedDepositsService } from '../fixed-deposits.service';
import { SavingsService } from 'app/savings/savings.service'; import { SavingsService } from 'app/savings/savings.service';
import { Currency } from 'app/shared/models/general.model'; import { Currency } from 'app/shared/models/general.model';
import {
MatCard,
MatCardHeader,
MatCardTitleGroup,
MatCardMdImage,
MatCardTitle,
MatCardContent
} from '@angular/material/card';
import { MatTooltip } from '@angular/material/tooltip'; import { MatTooltip } from '@angular/material/tooltip';
import { NgClass, CurrencyPipe } from '@angular/common'; import { NgClass, CurrencyPipe } from '@angular/common';
import { AccountNumberComponent } from '../../../shared/account-number/account-number.component'; import { AccountNumberComponent } from '../../../shared/account-number/account-number.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 { MatIcon } from '@angular/material/icon';
@@ -52,12 +45,9 @@ import { STANDALONE_SHARED_IMPORTS } from 'app/standalone-shared.module';
styleUrls: ['./fixed-deposit-account-view.component.scss'], styleUrls: ['./fixed-deposit-account-view.component.scss'],
imports: [ imports: [
...STANDALONE_SHARED_IMPORTS, ...STANDALONE_SHARED_IMPORTS,
MatCardHeader,
MatCardTitleGroup,
MatCardMdImage,
MatTooltip, MatTooltip,
MatCardTitle,
NgClass, NgClass,
LongTextComponent,
AccountNumberComponent, AccountNumberComponent,
MatIconButton, MatIconButton,
MatMenuTrigger, MatMenuTrigger,
@@ -6,196 +6,211 @@
file, You can obtain one at http://mozilla.org/MPL/2.0/. file, You can obtain one at http://mozilla.org/MPL/2.0/.
--> -->
<div class="fixed-deposits-account-tables layout-row gap-2percent"> <div class="gt-grid">
<div class="flex-49 layout-column gap-4percent"> <!-- ─── Left Column ──────────────────────────────────────────────── -->
<div> <div class="gt-col">
<h4 class="table-headers">{{ 'labels.heading.Fixed Deposit Details' | translate }}</h4> <!-- Fixed Deposit Details -->
<table> <div class="nx-card">
<tbody> <div class="nx-card__head">
<tr> <span class="nx-card__ico"><fa-icon icon="file-alt"></fa-icon></span>
<td>{{ 'labels.inputs.External Id' | translate }}</td> <h3 class="nx-card__title">{{ 'labels.heading.Fixed Deposit Details' | translate }}</h3>
<td> </div>
<div class="nx-card__body">
<div class="nx-row">
<span class="nx-row__label">{{ 'labels.inputs.External Id' | translate }}</span>
<span class="nx-row__value">
@if (fixedDepositsAccountData.externalId) { @if (fixedDepositsAccountData.externalId) {
<span>
<mifosx-external-identifier <mifosx-external-identifier
externalId="{{ fixedDepositsAccountData.externalId }}" externalId="{{ fixedDepositsAccountData.externalId }}"
completed="true" completed="true"
></mifosx-external-identifier> ></mifosx-external-identifier>
</span> } @else {
<span class="nx-muted">{{ 'labels.inputs.Not Available' | translate }}</span>
} }
@if (!fixedDepositsAccountData.externalId) {
<span>
{{ 'labels.inputs.Not Available' | translate }}
</span> </span>
} </div>
</td> <div class="nx-row">
</tr> <span class="nx-row__label">{{ 'labels.inputs.Activated On' | translate }}</span>
<tr> <span class="nx-row__value">
<td>{{ 'labels.inputs.Activated On' | translate }}</td>
<td>
{{ {{
fixedDepositsAccountData.timeline.activatedOnDate fixedDepositsAccountData.timeline.activatedOnDate
? (fixedDepositsAccountData.timeline.activatedOnDate | dateFormat) ? (fixedDepositsAccountData.timeline.activatedOnDate | dateFormat)
: ('labels.text.Not Activated' | translate) : ('labels.text.Not Activated' | translate)
}} }}
</td> </span>
</tr> </div>
@if (fixedDepositsAccountData.timeline.closedOnDate) { @if (fixedDepositsAccountData.timeline.closedOnDate) {
<tr> <div class="nx-row">
<td>{{ 'labels.inputs.Closed On' | translate }}</td> <span class="nx-row__label">{{ 'labels.inputs.Closed On' | translate }}</span>
<td>{{ fixedDepositsAccountData.timeline.closedOnDate | dateFormat }}</td> <span class="nx-row__value">{{ fixedDepositsAccountData.timeline.closedOnDate | dateFormat }}</span>
</tr> </div>
} }
<tr> <div class="nx-row">
<td>{{ 'labels.inputs.Field Officer' | translate }}</td> <span class="nx-row__label">{{ 'labels.inputs.Field Officer' | translate }}</span>
<td> <span class="nx-row__value">
{{ {{
fixedDepositsAccountData.fieldOfficerName fixedDepositsAccountData.fieldOfficerName
? fixedDepositsAccountData.fieldOfficerName ? fixedDepositsAccountData.fieldOfficerName
: ('Unassigned' | translateKey: 'inputs') : ('Unassigned' | translateKey: 'inputs')
}} }}
</td> </span>
</tr> </div>
<tr> <div class="nx-row">
<td>{{ 'labels.inputs.Maturity Date' | translate }}</td> <span class="nx-row__label">{{ 'labels.inputs.Maturity Date' | translate }}</span>
<td> <span class="nx-row__value">
{{ fixedDepositsAccountData.maturityDate ? (fixedDepositsAccountData.maturityDate | dateFormat) : 'N/A' }} {{ fixedDepositsAccountData.maturityDate ? (fixedDepositsAccountData.maturityDate | dateFormat) : 'N/A' }}
</td> </span>
</tr> </div>
<tr> <div class="nx-row">
<td>{{ 'labels.inputs.Deposit Period' | translate }}</td> <span class="nx-row__label">{{ 'labels.inputs.Deposit Period' | translate }}</span>
<td> <span class="nx-row__value">
{{ fixedDepositsAccountData.depositPeriod }}&nbsp;{{ {{ fixedDepositsAccountData.depositPeriod }}&nbsp;{{
fixedDepositsAccountData.depositPeriodFrequency.value | translateKey: 'catalogs' fixedDepositsAccountData.depositPeriodFrequency.value | translateKey: 'catalogs'
}} }}
</td> </span>
</tr> </div>
@if (fixedDepositsAccountData.withHoldTax) { @if (fixedDepositsAccountData.withHoldTax) {
<tr> <div class="nx-row">
<td>{{ 'labels.inputs.Tax Group' | translate }}</td> <span class="nx-row__label">{{ 'labels.inputs.Tax Group' | translate }}</span>
<td>{{ fixedDepositsAccountData.taxGroup.name }}</td> <span class="nx-row__value">{{ fixedDepositsAccountData.taxGroup.name }}</span>
</tr> </div>
} }
@if (fixedDepositsAccountData.onAccountClosure) { @if (fixedDepositsAccountData.onAccountClosure) {
<tr> <div class="nx-row">
<td>{{ 'labels.inputs.Maturity Instructions' | translate }}</td> <span class="nx-row__label">{{ 'labels.inputs.Maturity Instructions' | translate }}</span>
<td>{{ fixedDepositsAccountData.onAccountClosure.value | translateKey: 'catalogs' }}</td> <span class="nx-row__value">{{
</tr> fixedDepositsAccountData.onAccountClosure.value | translateKey: 'catalogs'
}}</span>
</div>
} }
</tbody> </div>
</table>
</div> </div>
<div> <!-- Interest Details -->
<h4 class="table-headers">{{ 'labels.heading.Interest Details' | translate }}</h4> <div class="nx-card">
<table> <div class="nx-card__head">
<tbody> <span class="nx-card__ico"><fa-icon icon="percentage"></fa-icon></span>
<tr> <h3 class="nx-card__title">{{ 'labels.heading.Interest Details' | translate }}</h3>
<td>{{ 'labels.inputs.Interest Rate' | translate }}</td> </div>
<td>{{ fixedDepositsAccountData.nominalAnnualInterestRate }} %</td> <div class="nx-card__body">
</tr> <div class="nx-row">
<tr> <span class="nx-row__label">{{ 'labels.inputs.Interest Rate' | translate }}</span>
<td>{{ 'labels.inputs.Interest Compounding Period' | translate }}</td> <span class="nx-row__value">{{ fixedDepositsAccountData.nominalAnnualInterestRate }} %</span>
<td>{{ fixedDepositsAccountData.interestCompoundingPeriodType.value | translateKey: 'catalogs' }}</td> </div>
</tr> <div class="nx-row">
<tr> <span class="nx-row__label">{{ 'labels.inputs.Interest Compounding Period' | translate }}</span>
<td>{{ 'labels.inputs.Interest Posting Period' | translate }}</td> <span class="nx-row__value">{{
<td>{{ fixedDepositsAccountData.interestPostingPeriodType.value | translateKey: 'catalogs' }}</td> fixedDepositsAccountData.interestCompoundingPeriodType.value | translateKey: 'catalogs'
</tr> }}</span>
<tr> </div>
<td>{{ 'labels.inputs.Interest Calculated Using' | translate }}</td> <div class="nx-row">
<td>{{ fixedDepositsAccountData.interestCalculationType.value | translateKey: 'catalogs' }}</td> <span class="nx-row__label">{{ 'labels.inputs.Interest Posting Period' | translate }}</span>
</tr> <span class="nx-row__value">{{
<tr> fixedDepositsAccountData.interestPostingPeriodType.value | translateKey: 'catalogs'
<td>{{ 'labels.inputs.No. of Days in Year' | translate }}</td> }}</span>
<td>{{ fixedDepositsAccountData.interestCalculationDaysInYearType.value | translateKey: 'catalogs' }}</td> </div>
</tr> <div class="nx-row">
<span class="nx-row__label">{{ 'labels.inputs.Interest Calculated Using' | translate }}</span>
<span class="nx-row__value">{{
fixedDepositsAccountData.interestCalculationType.value | translateKey: 'catalogs'
}}</span>
</div>
<div class="nx-row">
<span class="nx-row__label">{{ 'labels.inputs.No. of Days in Year' | translate }}</span>
<span class="nx-row__value">{{
fixedDepositsAccountData.interestCalculationDaysInYearType.value | translateKey: 'catalogs'
}}</span>
</div>
@if (fixedDepositsAccountData.preClosurePenalApplicable) { @if (fixedDepositsAccountData.preClosurePenalApplicable) {
<tr> <div class="nx-row">
<td>{{ 'labels.inputs.Pre-cloure Penal' | translate }}</td> <span class="nx-row__label">{{ 'labels.inputs.Pre-cloure Penal' | translate }}</span>
<td> <span class="nx-row__value">
{{ fixedDepositsAccountData.preClosurePenalInterest }} % on {{ fixedDepositsAccountData.preClosurePenalInterest }} % on
{{ fixedDepositsAccountData.preClosurePenalInterestOnType.value | translateKey: 'catalogs' }} {{ fixedDepositsAccountData.preClosurePenalInterestOnType.value | translateKey: 'catalogs' }}
</td> </span>
</tr> </div>
} }
</tbody> </div>
</table>
</div> </div>
</div> </div>
<div class="flex-49"> <!-- ─── Right Column ─────────────────────────────────────────────── -->
<div class="gt-col">
@if (!fixedDepositsAccountData.status.rejected && !fixedDepositsAccountData.status.submittedAndPendingApproval) { @if (!fixedDepositsAccountData.status.rejected && !fixedDepositsAccountData.status.submittedAndPendingApproval) {
<div> <!-- Performance History -->
<h4 class="table-headers">{{ 'labels.heading.Performance History' | translate }}</h4> <div class="nx-card">
<table> <div class="nx-card__head">
<tbody> <span class="nx-card__ico"><fa-icon icon="chart-bar"></fa-icon></span>
<tr> <h3 class="nx-card__title">{{ 'labels.heading.Performance History' | translate }}</h3>
<td>{{ 'labels.inputs.Principal Amount' | translate }}</td> </div>
<td class="r-amount"> <div class="nx-card__body">
<div class="nx-row">
<span class="nx-row__label">{{ 'labels.inputs.Principal Amount' | translate }}</span>
<span class="nx-row__value nx-row__value--amount">
{{ fixedDepositsAccountData.depositAmount | currency: currency.code : 'symbol-narrow' : '1.2-2' }} {{ fixedDepositsAccountData.depositAmount | currency: currency.code : 'symbol-narrow' : '1.2-2' }}
</td> </span>
</tr> </div>
<tr> <div class="nx-row">
<td>{{ 'labels.inputs.Maturity Amount' | translate }}</td> <span class="nx-row__label">{{ 'labels.inputs.Maturity Amount' | translate }}</span>
<td class="r-amount"> <span class="nx-row__value nx-row__value--amount nx-row__value--positive">
{{ fixedDepositsAccountData.maturityAmount | currency: currency.code : 'symbol-narrow' : '1.2-2' }} {{ fixedDepositsAccountData.maturityAmount | currency: currency.code : 'symbol-narrow' : '1.2-2' }}
</td> </span>
</tr> </div>
@if (fixedDepositsAccountData.summary.totalDeposits) { @if (fixedDepositsAccountData.summary.totalDeposits) {
<tr> <div class="nx-row">
<td>{{ 'labels.inputs.Total Deposits' | translate }}</td> <span class="nx-row__label">{{ 'labels.inputs.Total Deposits' | translate }}</span>
<td class="r-amount"> <span class="nx-row__value nx-row__value--amount">
{{ {{
fixedDepositsAccountData.summary.totalDeposits | currency: currency.code : 'symbol-narrow' : '1.2-2' fixedDepositsAccountData.summary.totalDeposits | currency: currency.code : 'symbol-narrow' : '1.2-2'
}} }}
</td> </span>
</tr> </div>
} }
@if (fixedDepositsAccountData.summary.totalWithdrawals) { @if (fixedDepositsAccountData.summary.totalWithdrawals) {
<tr> <div class="nx-row">
<td>{{ 'labels.inputs.Total Withdrawals' | translate }}</td> <span class="nx-row__label">{{ 'labels.inputs.Total Withdrawals' | translate }}</span>
<td class="r-amount"> <span class="nx-row__value nx-row__value--amount nx-row__value--negative">
{{ {{
fixedDepositsAccountData.summary.totalWithdrawals fixedDepositsAccountData.summary.totalWithdrawals
| currency: currency.code : 'symbol-narrow' : '1.2-2' | currency: currency.code : 'symbol-narrow' : '1.2-2'
}} }}
</td> </span>
</tr> </div>
} }
@if (fixedDepositsAccountData.summary.totalInterestEarned >= 0) { @if (fixedDepositsAccountData.summary.totalInterestEarned >= 0) {
<tr> <div class="nx-row">
<td>{{ 'labels.inputs.Total Interest Earned' | translate }}</td> <span class="nx-row__label">{{ 'labels.inputs.Total Interest Earned' | translate }}</span>
<td class="r-amount"> <span class="nx-row__value nx-row__value--amount nx-row__value--positive">
{{ {{
fixedDepositsAccountData.summary.totalInterestEarned fixedDepositsAccountData.summary.totalInterestEarned
| currency: currency.code : 'symbol-narrow' : '1.2-2' | currency: currency.code : 'symbol-narrow' : '1.2-2'
}} }}
</td> </span>
</tr> </div>
} }
</tbody> </div>
</table>
</div> </div>
} @else { } @else {
<div> <!-- Other Details (pending/rejected) -->
<h4 class="table-headers">{{ 'labels.heading.Other Details' | translate }}</h4> <div class="nx-card">
<table> <div class="nx-card__head">
<tbody> <span class="nx-card__ico"><fa-icon icon="info-circle"></fa-icon></span>
<tr> <h3 class="nx-card__title">{{ 'labels.heading.Other Details' | translate }}</h3>
<td>{{ 'labels.inputs.Principal Amount' | translate }}</td> </div>
<td class="r-amount"> <div class="nx-card__body">
<div class="nx-row">
<span class="nx-row__label">{{ 'labels.inputs.Principal Amount' | translate }}</span>
<span class="nx-row__value nx-row__value--amount">
{{ fixedDepositsAccountData.depositAmount | currency: currency.code : 'symbol-narrow' : '1.2-2' }} {{ fixedDepositsAccountData.depositAmount | currency: currency.code : 'symbol-narrow' : '1.2-2' }}
</td> </span>
</tr> </div>
<tr> <div class="nx-row">
<td>{{ 'labels.inputs.Maturity Amount' | translate }}</td> <span class="nx-row__label">{{ 'labels.inputs.Maturity Amount' | translate }}</span>
<td class="r-amount"> <span class="nx-row__value nx-row__value--amount">
{{ fixedDepositsAccountData.maturityAmount | currency: currency.code : 'symbol-narrow' : '1.2-2' }} {{ fixedDepositsAccountData.maturityAmount | currency: currency.code : 'symbol-narrow' : '1.2-2' }}
</td> </span>
</tr> </div>
</tbody> </div>
</table>
</div> </div>
} }
</div> </div>
@@ -6,6 +6,115 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. * file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/ */
.fixed-deposits-account-tables { $navy: #0d1b2a;
padding: 1%; $slate: #475569;
$muted: #64748b;
$border: #e2e8f0;
$soft: #f8fafc;
/* ─── Two-column grid ───────────────────────────────────────────────── */
.gt-grid {
display: grid;
grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
gap: 16px;
@media (width <= 1024px) {
grid-template-columns: 1fr;
}
}
.gt-col {
display: flex;
flex-direction: column;
gap: 16px;
min-width: 0;
}
/* ─── Nexora section card ───────────────────────────────────────────── */
.nx-card {
background: #fff;
border: 1px solid $border;
border-radius: 14px;
box-shadow: 0 1px 3px rgb(15 23 42 / 4%);
overflow: hidden;
&__head {
display: flex;
align-items: center;
gap: 10px;
padding: 12px 18px;
background: $soft;
border-bottom: 1px solid $border;
}
&__ico {
width: 26px;
height: 26px;
display: inline-flex;
align-items: center;
justify-content: center;
border-radius: 8px;
background: linear-gradient(135deg, #3b82f6 0%, #1e40af 100%);
color: #fff;
font-size: 12px;
}
&__title {
margin: 0;
font-size: 13.5px;
font-weight: 700;
color: $navy;
letter-spacing: 0.01em;
}
&__body {
padding: 4px 18px 10px;
}
}
/* ─── Key/Value row ─────────────────────────────────────────────────── */
.nx-row {
display: grid;
grid-template-columns: minmax(0, 1fr) auto;
gap: 12px;
align-items: center;
min-height: 38px;
padding: 8px 0;
border-bottom: 1px dashed #eef2f7;
font-size: 13px;
&:last-child {
border-bottom: none;
}
&__label {
color: $slate;
font-weight: 500;
}
&__value {
color: $navy;
font-weight: 600;
text-align: right;
word-break: break-word;
&--amount {
font-variant-numeric: tabular-nums;
font-weight: 700;
}
&--positive {
color: #047857;
}
&--negative {
color: #b91c1c;
}
}
}
.nx-muted {
color: $muted;
font-weight: 500;
font-style: italic;
} }
@@ -12,6 +12,7 @@ import { Currency } from 'app/shared/models/general.model';
import { CurrencyPipe } from '@angular/common'; import { CurrencyPipe } from '@angular/common';
import { ExternalIdentifierComponent } from '../../../../shared/external-identifier/external-identifier.component'; import { ExternalIdentifierComponent } from '../../../../shared/external-identifier/external-identifier.component';
import { DateFormatPipe } from '../../../../pipes/date-format.pipe'; import { DateFormatPipe } from '../../../../pipes/date-format.pipe';
import { FaIconComponent } from '@fortawesome/angular-fontawesome';
import { STANDALONE_SHARED_IMPORTS } from 'app/standalone-shared.module'; import { STANDALONE_SHARED_IMPORTS } from 'app/standalone-shared.module';
@Component({ @Component({
@@ -21,6 +22,7 @@ import { STANDALONE_SHARED_IMPORTS } from 'app/standalone-shared.module';
imports: [ imports: [
...STANDALONE_SHARED_IMPORTS, ...STANDALONE_SHARED_IMPORTS,
ExternalIdentifierComponent, ExternalIdentifierComponent,
FaIconComponent,
CurrencyPipe, CurrencyPipe,
DateFormatPipe DateFormatPipe
] ]
@@ -6,23 +6,19 @@
file, You can obtain one at http://mozilla.org/MPL/2.0/. file, You can obtain one at http://mozilla.org/MPL/2.0/.
--> -->
<div class="tab-container mat-typography"> <div class="txn-tab">
<div class="mat-elevation-z1 m-b-25"> <div class="txn-tab__card">
<div class="layout-row align-start">
<div class="m-b-20">
<h3>{{ 'labels.heading.All Transactions' | translate }}</h3>
</div>
@if (checkStatus()) { @if (checkStatus()) {
<div class="action-button m-b-20 layout-row gap-20px"> <div class="txn-tab__toolbar">
<mat-checkbox [formControl]="hideReversedParam" (click)="hideReversed()" class="accruals"> <mat-checkbox [formControl]="hideReversedParam" (click)="hideReversed()" class="txn-tab__check">
{{ 'labels.inputs.Hide Reversed' | translate }}</mat-checkbox {{ 'labels.inputs.Hide Reversed' | translate }}
> </mat-checkbox>
<mat-checkbox [formControl]="hideAccrualsParam" (click)="hideAccruals()" class="accruals"> <mat-checkbox [formControl]="hideAccrualsParam" (click)="hideAccruals()" class="txn-tab__check">
{{ 'labels.inputs.Hide Accruals' | translate }}</mat-checkbox {{ 'labels.inputs.Hide Accruals' | translate }}
> </mat-checkbox>
<span class="txn-tab__spacer"></span>
</div> </div>
} }
</div>
<table mat-table [dataSource]="dataSource"> <table mat-table [dataSource]="dataSource">
<ng-container matColumnDef="row"> <ng-container matColumnDef="row">
@@ -105,7 +101,7 @@
</ng-container> </ng-container>
<ng-container matColumnDef="actions"> <ng-container matColumnDef="actions">
<th mat-header-cell *matHeaderCellDef>{{ 'labels.inputs.Actions' | translate }}</th> <th mat-header-cell class="center" *matHeaderCellDef>{{ 'labels.inputs.Actions' | translate }}</th>
<td mat-cell class="center" *matCellDef="let transaction; let idx = index"> <td mat-cell class="center" *matCellDef="let transaction; let idx = index">
<button mat-icon-button [matMenuTriggerFor]="transactionMenu" aria-label="" class="action-button"> <button mat-icon-button [matMenuTriggerFor]="transactionMenu" aria-label="" class="action-button">
<mat-icon>more_vert</mat-icon> <mat-icon>more_vert</mat-icon>
@@ -6,48 +6,95 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. * file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/ */
@use 'assets/styles/helper'; $navy: #0d1b2a;
@use 'assets/styles/colours' as *; $slate: #475569;
$muted: #64748b;
$border: #e2e8f0;
$soft: #f8fafc;
$blue: #1e40af;
.tab-container { .txn-tab {
padding: 1%; width: 100%;
margin: 1%;
h3 {
margin: 1% auto;
} }
.action-button { .txn-tab__card {
margin-left: auto; background: #fff;
border: 1px solid $border;
border-radius: 14px;
box-shadow: 0 1px 3px rgb(15 23 42 / 4%);
overflow: hidden;
}
.txn-tab__toolbar {
display: flex;
align-items: center;
gap: 18px;
padding: 12px 18px;
background: $soft;
border-bottom: 1px solid $border;
flex-wrap: wrap;
}
.txn-tab__check {
font-size: 13px;
color: $slate;
font-weight: 500;
}
.txn-tab__spacer {
flex: 1;
} }
table { table {
width: 100%; width: 100%;
color: $black;
.account-action-button {
min-width: 26px;
padding: 0 0 3px;
margin: 0 2%;
line-height: 25px;
} }
.strike { ::ng-deep .txn-tab__card {
text-decoration: line-through; .mat-mdc-header-row {
color: $status-active-overdue; background: $soft;
} }
.linked { .mat-mdc-header-cell {
color: $status-approved; font-size: 11.5px;
}
.accrual {
color: $msg-default;
}
}
}
.select-row:hover {
cursor: pointer;
font-weight: 800; font-weight: 800;
color: $slate;
text-transform: uppercase;
letter-spacing: 0.06em;
padding: 12px 14px;
border-bottom: 1px solid $border;
}
.mat-mdc-cell {
font-size: 13px;
color: $navy;
padding: 11px 14px;
border-bottom: 1px solid #f1f5f9;
}
.mat-mdc-row:hover {
background: #f8fafc;
cursor: pointer;
}
.mat-column-debit,
.mat-column-credit,
.mat-column-balance {
text-align: right;
font-variant-numeric: tabular-nums;
}
.mat-column-actions {
text-align: center;
width: 80px;
}
.strike td {
text-decoration: line-through;
color: $muted;
}
.accrual td {
color: $muted;
font-style: italic;
}
} }
@@ -6,14 +6,13 @@
file, You can obtain one at http://mozilla.org/MPL/2.0/. file, You can obtain one at http://mozilla.org/MPL/2.0/.
--> -->
<div class="tab-container mat-typography"> <div class="chg-tab">
<div class="layout-row align-start"> <div class="chg-tab__card">
<div class="m-b-10"> <div class="chg-tab__toolbar">
<h3>{{ 'labels.heading.All Charges' | translate }}</h3> <h3 class="chg-tab__title">{{ 'labels.heading.All Charges' | translate }}</h3>
</div> <span class="chg-tab__spacer"></span>
</div> </div>
<div class="mat-elevation-z1 m-b-25">
<table mat-table #chargesTable [dataSource]="dataSource"> <table mat-table #chargesTable [dataSource]="dataSource">
<ng-container matColumnDef="name"> <ng-container matColumnDef="name">
<th mat-header-cell *matHeaderCellDef>{{ 'labels.inputs.name' | translate }}</th> <th mat-header-cell *matHeaderCellDef>{{ 'labels.inputs.name' | translate }}</th>
@@ -6,26 +6,96 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. * file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/ */
.tab-container { $navy: #0d1b2a;
padding: 1%; $slate: #475569;
margin: 1%; $muted: #64748b;
$border: #e2e8f0;
$soft: #f8fafc;
$blue: #1e40af;
h3 { .chg-tab {
margin: 1% auto; width: 100%;
} }
.action-button { .chg-tab__card {
margin-left: auto; background: #fff;
border: 1px solid $border;
border-radius: 14px;
box-shadow: 0 1px 3px rgb(15 23 42 / 4%);
overflow: hidden;
}
.chg-tab__toolbar {
display: flex;
align-items: center;
gap: 14px;
padding: 12px 18px;
background: $soft;
border-bottom: 1px solid $border;
}
.chg-tab__title {
margin: 0;
font-size: 14px;
font-weight: 700;
color: $navy;
letter-spacing: 0.01em;
}
.chg-tab__spacer {
flex: 1;
} }
table { table {
width: 100%; width: 100%;
}
::ng-deep .chg-tab__card {
.mat-mdc-header-row {
background: $soft;
}
.mat-mdc-header-cell {
font-size: 11.5px;
font-weight: 800;
color: $slate;
text-transform: uppercase;
letter-spacing: 0.06em;
padding: 12px 14px;
border-bottom: 1px solid $border;
}
.mat-mdc-cell {
font-size: 13px;
color: $navy;
padding: 11px 14px;
border-bottom: 1px solid #f1f5f9;
}
.mat-mdc-row:hover {
background: #f8fafc;
cursor: pointer;
}
.mat-column-due,
.mat-column-paid,
.mat-column-waived,
.mat-column-outstanding {
text-align: right;
font-variant-numeric: tabular-nums;
}
.mat-column-actions {
text-align: center;
width: 140px;
.account-action-button { .account-action-button {
min-width: 26px; min-width: 30px !important;
padding: 0 6px; padding: 0 8px !important;
margin: 4px; margin: 0 3px !important;
line-height: 25px; height: 30px !important;
line-height: 30px !important;
border-radius: 7px !important;
} }
} }
} }
@@ -6,503 +6,442 @@
file, You can obtain one at http://mozilla.org/MPL/2.0/. file, You can obtain one at http://mozilla.org/MPL/2.0/.
--> -->
<div class="recurring-deposits-account-tables layout-row gap-2percent"> <div class="gt-grid">
<!-- ─── Left Column ──────────────────────────────────────────────── -->
<div class="gt-col">
@if ( @if (
!recurringDepositsAccountData.status.rejected && !recurringDepositsAccountData.status.submittedAndPendingApproval !recurringDepositsAccountData.status.rejected && !recurringDepositsAccountData.status.submittedAndPendingApproval
) { ) {
<div class="flex-49"> <!-- ACTIVE: Account Details -->
<h4 class="table-headers">{{ 'labels.inputs.Account Details' | translate }}</h4> <div class="nx-card">
<table> <div class="nx-card__head">
<tbody> <span class="nx-card__ico"><fa-icon icon="file-alt"></fa-icon></span>
<tr> <h3 class="nx-card__title">{{ 'labels.inputs.Account Details' | translate }}</h3>
<td>{{ 'labels.inputs.External Id' | translate }}</td> </div>
<td> <div class="nx-card__body">
<div class="nx-row">
<span class="nx-row__label">{{ 'labels.inputs.External Id' | translate }}</span>
<span class="nx-row__value">
@if (recurringDepositsAccountData.externalId) { @if (recurringDepositsAccountData.externalId) {
<span>
<mifosx-external-identifier <mifosx-external-identifier
externalId="{{ recurringDepositsAccountData.externalId }}" externalId="{{ recurringDepositsAccountData.externalId }}"
completed="true" completed="true"
></mifosx-external-identifier> ></mifosx-external-identifier>
</span> } @else {
<span class="nx-muted">{{ 'labels.inputs.Not Available' | translate }}</span>
} }
@if (!recurringDepositsAccountData.externalId) {
<span>
{{ 'labels.inputs.Not Available' | translate }}
</span> </span>
} </div>
</td> <div class="nx-row">
</tr> <span class="nx-row__label">{{ 'labels.inputs.Field Officer' | translate }}</span>
<tr> <span class="nx-row__value">
<td>{{ 'labels.inputs.Field Officer' | translate }}</td> @if (recurringDepositsAccountData.fieldOfficerName) {
<td>
{{ recurringDepositsAccountData.fieldOfficerName }} {{ recurringDepositsAccountData.fieldOfficerName }}
@if (!recurringDepositsAccountData.fieldOfficerName) { } @else {
<span>{{ 'labels.inputs.Unassigned' | translate }}</span> <span class="nx-muted">{{ 'labels.inputs.Unassigned' | translate }}</span>
} }
</td> </span>
</tr> </div>
<tr> <div class="nx-row">
<td>{{ 'labels.inputs.Activation date' | translate }}</td> <span class="nx-row__label">{{ 'labels.inputs.Activation date' | translate }}</span>
<td>{{ recurringDepositsAccountData.timeline.activatedOnDate | dateFormat }}</td> <span class="nx-row__value">{{ recurringDepositsAccountData.timeline.activatedOnDate | dateFormat }}</span>
</tr> </div>
<tr> <div class="nx-row">
<td>{{ 'labels.inputs.Maturity Date' | translate }}</td> <span class="nx-row__label">{{ 'labels.inputs.Maturity Date' | translate }}</span>
<td> <span class="nx-row__value">{{ recurringDepositsAccountData.maturityDate | dateFormat }}</span>
<span>{{ recurringDepositsAccountData.maturityDate | dateFormat }}</span> </div>
</td>
</tr>
@if ( @if (
recurringDepositsAccountData.timeline.closedOnDate || recurringDepositsAccountData.summary.totalWitddrawals recurringDepositsAccountData.timeline.closedOnDate || recurringDepositsAccountData.summary.totalWitddrawals
) { ) {
<tr> <div class="nx-row">
@if (recurringDepositsAccountData.timeline.closedOnDate) { <span class="nx-row__label">{{ 'labels.inputs.Closed on Date' | translate }}</span>
<td> <span class="nx-row__value">{{ recurringDepositsAccountData.timeline.closedOnDate | dateFormat }}</span>
{{ 'labels.inputs.Closed on Date' | translate }} </div>
</td>
} }
<td> <div class="nx-row">
<span>{{ recurringDepositsAccountData.timeline.closedOnDate | dateFormat }}</span> <span class="nx-row__label">{{ 'labels.inputs.Deposit Frequency' | translate }}</span>
</td> <span class="nx-row__value">
</tr>
}
<tr></tr>
<tr>
<td>{{ 'labels.inputs.Deposit Frequency' | translate }}</td>
<td>
<span class="m-r-5">{{ recurringDepositsAccountData.recurringFrequency }}</span> <span class="m-r-5">{{ recurringDepositsAccountData.recurringFrequency }}</span>
{{ recurringDepositsAccountData.recurringFrequencyType.value | translateKey: 'catalogs' }} {{ recurringDepositsAccountData.recurringFrequencyType.value | translateKey: 'catalogs' }}
</td> </span>
</tr> </div>
@if (recurringDepositsAccountData.minBalanceForInterestCalculation) { @if (recurringDepositsAccountData.minBalanceForInterestCalculation) {
<tr> <div class="nx-row">
<td>{{ 'labels.inputs.Balance Required for Interest Calculation' | translate }}</td> <span class="nx-row__label">{{
<td> 'labels.inputs.Balance Required for Interest Calculation' | translate
<span>{{ recurringDepositsAccountData.minBalanceForInterestCalculation }}</span> }}</span>
</td> <span class="nx-row__value">{{ recurringDepositsAccountData.minBalanceForInterestCalculation }}</span>
</tr> </div>
} }
@if (recurringDepositsAccountData.witdHoldTax) { @if (recurringDepositsAccountData.witdHoldTax) {
<tr> <div class="nx-row">
<td>{{ 'labels.inputs.Witdhold Tax Group' | translate }}</td> <span class="nx-row__label">{{ 'labels.inputs.Witdhold Tax Group' | translate }}</span>
<td> <span class="nx-row__value">{{ recurringDepositsAccountData.taxGroup.name }}</span>
<span>{{ recurringDepositsAccountData.taxGroup.name }}</span>
</td>
</tr>
}
</tbody>
</table>
</div> </div>
} }
</div>
</div>
@if ( <!-- ACTIVE: Interest Details -->
!recurringDepositsAccountData.status.rejected && !recurringDepositsAccountData.status.submittedAndPendingApproval <div class="nx-card">
) { <div class="nx-card__head">
<div class="flex-49"> <span class="nx-card__ico"><fa-icon icon="percentage"></fa-icon></span>
<h4 class="table-headers">{{ 'labels.heading.Performance History' | translate }}</h4> <h3 class="nx-card__title">{{ 'labels.heading.Interest Details' | translate }}</h3>
<table> </div>
<tbody> <div class="nx-card__body">
<tr> <div class="nx-row">
<td>{{ 'labels.inputs.Principal Amount' | translate }}</td> <span class="nx-row__label">{{ 'labels.inputs.Interest Rate' | translate }}</span>
<td class="r-amount"> <span class="nx-row__value"
<span>{{ >{{ recurringDepositsAccountData.nominalAnnualInterestRate | formatNumber }} %</span
recurringDepositsAccountData.depositAmount | currency: currency.code : 'symbol-narrow' : '1.2-2' >
</div>
<div class="nx-row">
<span class="nx-row__label">{{ 'labels.inputs.Interest Compounding Period' | translate }}</span>
<span class="nx-row__value">{{
recurringDepositsAccountData.interestCompoundingPeriodType.value | translateKey: 'catalogs'
}}</span> }}</span>
</td> </div>
</tr> <div class="nx-row">
<tr> <span class="nx-row__label">{{ 'labels.inputs.Interest Posting Period' | translate }}</span>
<td>{{ 'labels.inputs.Maturity Amount' | translate }}</td> <span class="nx-row__value">{{
<td class="r-amount"> recurringDepositsAccountData.interestPostingPeriodType.value | translateKey: 'catalogs'
<span>{{
recurringDepositsAccountData.maturityAmount | currency: currency.code : 'symbol-narrow' : '1.2-2'
}}</span> }}</span>
</td> </div>
</tr> <div class="nx-row">
<tr> <span class="nx-row__label">{{ 'labels.inputs.Interest calculated using' | translate }}</span>
<td>{{ 'labels.inputs.Recurring Deposit Amount' | translate }}</td> <span class="nx-row__value">{{
<td class="r-amount"> recurringDepositsAccountData.interestCalculationType.value | translateKey: 'catalogs'
<span>{{
recurringDepositsAccountData?.mandatoryRecommendedDepositAmount
| currency: currency.code : 'symbol-narrow' : '1.2-2'
}}</span> }}</span>
</td> </div>
</tr> <div class="nx-row">
<tr> <span class="nx-row__label">{{ 'labels.inputs.Days in Year' | translate }}</span>
<td>{{ 'labels.inputs.Deposits till Date' | translate }}</td> <span class="nx-row__value">{{
<td class="r-amount"> recurringDepositsAccountData.interestCalculationDaysInYearType.value | translateKey: 'catalogs'
@if (recurringDepositsAccountData.summary.totalDeposits) {
<span>{{
recurringDepositsAccountData.summary.totalDeposits
| currency: currency.code : 'symbol-narrow' : '1.2-2'
}}</span> }}</span>
} </div>
@if (!recurringDepositsAccountData.summary.totalDeposits) { @if (recurringDepositsAccountData.preClosurePenalApplicable) {
<span>{{ 0 | currency: currency.code : 'symbol-narrow' : '1.2-2' }}</span> <div class="nx-row">
} <span class="nx-row__label">{{ 'labels.inputs.Pre-closure penal Interest (less)' | translate }}</span>
</td> <span class="nx-row__value">
</tr> {{ recurringDepositsAccountData.preClosurePenalInterest }} % on
<tr> {{ recurringDepositsAccountData.preClosurePenalInterestOnType.value | translateKey: 'catalogs' }}
<td>{{ 'labels.inputs.Withdrwals till Date' | translate }}</td> </span>
<td class="r-amount">
@if (recurringDepositsAccountData.summary.totalWithdrawals) {
<span>{{
recurringDepositsAccountData.summary.totalWithdrawals
| currency: currency.code : 'symbol-narrow' : '1.2-2'
}}</span>
}
@if (!recurringDepositsAccountData.summary.totalWithdrawals) {
<span>{{ 0 | currency: currency.code : 'symbol-narrow' : '1.2-2' }}</span>
}
</td>
</tr>
@if (recurringDepositsAccountData.summary.totalInterestEarned >= 0) {
<tr>
<td>{{ 'labels.inputs.Interest Earned' | translate }}</td>
<td class="r-amount">
<span>{{
recurringDepositsAccountData.summary.totalInterestEarned
| currency: currency.code : 'symbol-narrow' : '1.2-2'
}}</span>
</td>
</tr>
}
</tbody>
</table>
</div> </div>
} }
</div>
@if ( </div>
recurringDepositsAccountData.status.rejected || recurringDepositsAccountData.status.submittedAndPendingApproval } @else {
) { <!-- PENDING/REJECTED: Account Details -->
<div class="flex-49"> <div class="nx-card">
<table> <div class="nx-card__head">
<tbody> <span class="nx-card__ico"><fa-icon icon="file-alt"></fa-icon></span>
<tr> <h3 class="nx-card__title">{{ 'labels.inputs.Account Details' | translate }}</h3>
<td>{{ 'labels.inputs.External Id' | translate }}</td> </div>
<td> <div class="nx-card__body">
<div class="nx-row">
<span class="nx-row__label">{{ 'labels.inputs.External Id' | translate }}</span>
<span class="nx-row__value">
@if (recurringDepositsAccountData.externalId) { @if (recurringDepositsAccountData.externalId) {
<span>
<mifosx-external-identifier <mifosx-external-identifier
externalId="{{ recurringDepositsAccountData.externalId }}" externalId="{{ recurringDepositsAccountData.externalId }}"
completed="true" completed="true"
></mifosx-external-identifier> ></mifosx-external-identifier>
</span> } @else {
<span class="nx-muted">{{ 'labels.inputs.Not Available' | translate }}</span>
} }
@if (!recurringDepositsAccountData.externalId) {
<span>
{{ 'labels.inputs.Not Available' | translate }}
</span> </span>
} </div>
</td> <div class="nx-row">
</tr> <span class="nx-row__label">{{ 'labels.inputs.Date of Deposit' | translate }}</span>
<tr> <span class="nx-row__value">
<td>{{ 'labels.inputs.Date of Deposit' | translate }}</td>
<td>
@if (!recurringDepositsAccountData.expectedFirstDepositOnDate) { @if (!recurringDepositsAccountData.expectedFirstDepositOnDate) {
<span {{ recurringDepositsAccountData.timeline.activatedOnDate | dateFormat }}
>{{ recurringDepositsAccountData.timeline.activatedOnDate | dateFormat }}
@if (!recurringDepositsAccountData.timeline.activatedOnDate) { @if (!recurringDepositsAccountData.timeline.activatedOnDate) {
<span>{{ 'labels.inputs.Not Activated' | translate }}</span> <span class="nx-muted">{{ 'labels.inputs.Not Activated' | translate }}</span>
}
} @else {
{{ recurringDepositsAccountData.expectedFirstDepositOnDate | dateFormat }}
} }
</span> </span>
} </div>
@if (recurringDepositsAccountData.expectedFirstDepositOnDate) { <div class="nx-row">
<span <span class="nx-row__label">{{ 'labels.inputs.Period' | translate }}</span>
>{{ recurringDepositsAccountData.expectedFirstDepositOnDate | dateFormat }} <span class="nx-row__value">
@if (!recurringDepositsAccountData.expectedFirstDepositOnDate) { {{ recurringDepositsAccountData.depositPeriod }}&nbsp;{{
<span>{{ 'labels.inputs.Not Activated' | translate }}</span>
}
</span>
}
</td>
</tr>
<tr>
<td>{{ 'labels.inputs.Period' | translate }}</td>
<td>
<span
>{{ recurringDepositsAccountData.depositPeriod }}&nbsp;{{
recurringDepositsAccountData.depositPeriodFrequency.value recurringDepositsAccountData.depositPeriodFrequency.value
}}</span }}
> </span>
</td> </div>
</tr>
@if (recurringDepositsAccountData.maturityDate) { @if (recurringDepositsAccountData.maturityDate) {
<tr> <div class="nx-row">
<td>{{ 'labels.inputs.Maturity Date' | translate }}</td> <span class="nx-row__label">{{ 'labels.inputs.Maturity Date' | translate }}</span>
<td> <span class="nx-row__value">{{ recurringDepositsAccountData.maturityDate | dateFormat }}</span>
<span>{{ recurringDepositsAccountData.maturityDate | dateFormat }}</span> </div>
</td>
</tr>
} }
<tr> <div class="nx-row">
<td>{{ 'labels.inputs.Total Deposits' | translate }}</td> <span class="nx-row__label">{{ 'labels.inputs.Total Deposits' | translate }}</span>
<td class="r-amount"> <span class="nx-row__value nx-row__value--amount">
@if (recurringDepositsAccountData.summary.totalDeposits) { @if (recurringDepositsAccountData.summary.totalDeposits) {
<span>{{ {{
recurringDepositsAccountData.summary.totalDeposits recurringDepositsAccountData.summary.totalDeposits
| currency: currency.code : 'symbol-narrow' : '1.2-2' | currency: currency.code : 'symbol-narrow' : '1.2-2'
}}</span> }}
} @else {
{{ 0 | currency: currency.code : 'symbol-narrow' : '1.2-2' }}
} }
@if (!recurringDepositsAccountData.summary.totalDeposits) { </span>
<span>{{ 0 | currency: currency.code : 'symbol-narrow' : '1.2-2' }}</span> </div>
} <div class="nx-row">
</td> <span class="nx-row__label">{{ 'labels.inputs.Actual Available Balance' | translate }}</span>
</tr> <span class="nx-row__value nx-row__value--amount">
<tr>
<td>{{ 'labels.inputs.Actual Available Balance' | translate }}</td>
<td class="r-amount">
{{ {{
recurringDepositsAccountData.summary.accountBalance recurringDepositsAccountData.summary.accountBalance
| currency: currency.code : 'symbol-narrow' : '1.2-2' | currency: currency.code : 'symbol-narrow' : '1.2-2'
}} }}
</td> </span>
</tr> </div>
<tr> <div class="nx-row">
<td>{{ 'labels.inputs.Recurring Deposit Amount' | translate }}</td> <span class="nx-row__label">{{ 'labels.inputs.Recurring Deposit Amount' | translate }}</span>
<td class="r-amount"> <span class="nx-row__value nx-row__value--amount">
{{ {{
recurringDepositsAccountData.mandatoryRecommendedDepositAmount recurringDepositsAccountData.mandatoryRecommendedDepositAmount
| currency: currency.code : 'symbol-narrow' : '1.2-2' | currency: currency.code : 'symbol-narrow' : '1.2-2'
}} }}
</td> </span>
</tr> </div>
@if (recurringDepositsAccountData.summary.totalInterestEarned) { @if (recurringDepositsAccountData.summary.totalInterestEarned) {
<tr> <div class="nx-row">
<td>{{ 'labels.inputs.Interests Earned' | translate }}</td> <span class="nx-row__label">{{ 'labels.inputs.Interests Earned' | translate }}</span>
<td> <span class="nx-row__value nx-row__value--amount">
<span {{ recurringDepositsAccountData.currency.displaySymbol }}&nbsp;{{
>{{ recurringDepositsAccountData.currency.displaySymbol }}&nbsp;{{
recurringDepositsAccountData.summary.totalInterestEarned recurringDepositsAccountData.summary.totalInterestEarned
}}</span }}
> </span>
</td> </div>
</tr>
} }
@if (recurringDepositsAccountData.summary.totalWithdrawals) { @if (recurringDepositsAccountData.summary.totalWithdrawals) {
<tr> <div class="nx-row">
<td>{{ 'labels.inputs.Total Withdrawls' | translate }}</td> <span class="nx-row__label">{{ 'labels.inputs.Total Withdrawls' | translate }}</span>
<td class="r-amount"> <span class="nx-row__value nx-row__value--amount">
<span>{{ {{
recurringDepositsAccountData.summary.totalWithdrawals recurringDepositsAccountData.summary.totalWithdrawals
| currency: currency.code : 'symbol-narrow' : '1.2-2' | currency: currency.code : 'symbol-narrow' : '1.2-2'
}}</span> }}
</td> </span>
</tr> </div>
} }
@if (recurringDepositsAccountData.minBalanceForInterestCalculation) { @if (recurringDepositsAccountData.minBalanceForInterestCalculation) {
<tr> <div class="nx-row">
<td>{{ 'labels.inputs.Balance Required for Interest Calculation' | translate }}</td> <span class="nx-row__label">{{
<td class="r-amount"> 'labels.inputs.Balance Required for Interest Calculation' | translate
<span>{{ recurringDepositsAccountData.minBalanceForInterestCalculation | number }}</span> }}</span>
</td> <span class="nx-row__value">{{
</tr> recurringDepositsAccountData.minBalanceForInterestCalculation | number
} }}</span>
</tbody>
</table>
</div> </div>
} }
</div>
</div>
@if ( <!-- PENDING/REJECTED: Interest Details -->
recurringDepositsAccountData.status.rejected || recurringDepositsAccountData.status.submittedAndPendingApproval <div class="nx-card">
) { <div class="nx-card__head">
<div class="flex-49"> <span class="nx-card__ico"><fa-icon icon="percentage"></fa-icon></span>
<table> <h3 class="nx-card__title">{{ 'labels.heading.Interest Details' | translate }}</h3>
<tbody> </div>
<tr> <div class="nx-card__body">
<td>{{ 'labels.inputs.Principal Amount' | translate }}</td> <div class="nx-row">
<td class="r-amount"> <span class="nx-row__label">{{ 'labels.inputs.Interest Compounding Period' | translate }}</span>
@if (recurringDepositsAccountData.depositAmount) { <span class="nx-row__value">{{
<span>{{ recurringDepositsAccountData.interestCompoundingPeriodType.value | translateKey: 'catalogs'
recurringDepositsAccountData.depositAmount | currency: currency.code : 'symbol-narrow' : '1.2-2'
}}</span> }}</span>
} </div>
@if (!recurringDepositsAccountData.depositAmount) { <div class="nx-row">
<span>{{ 0 | currency: currency.code : 'symbol-narrow' : '1.2-2' }}</span> <span class="nx-row__label">{{ 'labels.inputs.Interest Posting Period' | translate }}</span>
} <span class="nx-row__value">{{
</td> recurringDepositsAccountData.interestPostingPeriodType.value | translateKey: 'catalogs'
</tr>
<tr>
<td>{{ 'labels.inputs.Rate of Interest' | translate }}</td>
<td class="r-amount">
<span>{{ recurringDepositsAccountData.nominalAnnualInterestRate | formatNumber }} %</span>
</td>
</tr>
@if (recurringDepositsAccountData.maturityDate) {
<tr>
<td>{{ 'labels.inputs.Maturity Amount' | translate }}</td>
<td class="r-amount">
<span>{{
recurringDepositsAccountData.maturityAmount | currency: currency.code : 'symbol-narrow' : '1.2-2'
}}</span> }}</span>
</td> </div>
</tr> <div class="nx-row">
} <span class="nx-row__label">{{ 'labels.inputs.Interest calculated using' | translate }}</span>
<tr> <span class="nx-row__value">{{
<td>{{ 'labels.inputs.Total Withdrawls' | translate }}</td> recurringDepositsAccountData.interestCalculationType.value | translateKey: 'catalogs'
<td class="r-amount">
@if (recurringDepositsAccountData.summary.totalWithdrawals) {
<span>{{
recurringDepositsAccountData.summary.totalWithdrawals
| currency: currency.code : 'symbol-narrow' : '1.2-2'
}}</span> }}</span>
} </div>
@if (!recurringDepositsAccountData.summary.totalWithdrawals) { <div class="nx-row">
<span>{{ 0 | currency: currency.code : 'symbol-narrow' : '1.2-2' }}</span> <span class="nx-row__label">{{ 'labels.inputs.Days in Year' | translate }}</span>
} <span class="nx-row__value">{{
</td> recurringDepositsAccountData.interestCalculationDaysInYearType.value | translateKey: 'catalogs'
</tr>
@if (recurringDepositsAccountData.timeline.closedOnDate) {
<tr>
<td>{{ 'labels.inputs.Closed on Date' | translate }}</td>
<td>
{{ recurringDepositsAccountData.timeline.closedOnDate | dateFormat }}
</td>
</tr>
}
<tr>
<td>{{ 'labels.inputs.Deposits Frequency' | translate }}</td>
<td>
{{ recurringDepositsAccountData.recurringFrequency }}&nbsp;{{
recurringDepositsAccountData.recurringFrequencyType.value | translateKey: 'catalogs'
}}
</td>
</tr>
@if (recurringDepositsAccountData.summary.totalInterestEarned) {
<tr>
<td>{{ 'labels.inputs.Interests Posted' | translate }}</td>
<td class="r-amount">
@if (recurringDepositsAccountData.summary.totalInterestPosted) {
<span>{{
recurringDepositsAccountData.summary.totalInterestPosted
| currency: currency.code : 'symbol-narrow' : '1.2-2'
}}</span> }}</span>
</div>
@if (recurringDepositsAccountData.preClosurePenalApplicable) {
<div class="nx-row">
<span class="nx-row__label">{{ 'labels.inputs.Pre-closure penal Interest (less)' | translate }}</span>
<span class="nx-row__value">
{{ recurringDepositsAccountData.preClosurePenalInterest }} % on
{{ recurringDepositsAccountData.preClosurePenalInterestOnType.value | translateKey: 'catalogs' }}
</span>
</div>
} }
@if (!recurringDepositsAccountData.summary.totalInterestPosted) { @if (recurringDepositsAccountData.witdHoldTax) {
<span>{{ 0 | currency: currency.code : 'symbol-narrow' : '1.2-2' }}</span> <div class="nx-row">
<span class="nx-row__label">{{ 'labels.inputs.Witdhold Tax Group' | translate }}</span>
<span class="nx-row__value">{{ recurringDepositsAccountData.taxGroup.name }}</span>
</div>
} }
</td> </div>
</tr>
}
</tbody>
</table>
</div> </div>
} }
</div> </div>
<div class="recurring-deposits-account-tables layout-row gap-2percent"> <!-- ─── Right Column ─────────────────────────────────────────────── -->
<div class="gt-col">
@if ( @if (
!recurringDepositsAccountData.status.rejected && !recurringDepositsAccountData.status.submittedAndPendingApproval !recurringDepositsAccountData.status.rejected && !recurringDepositsAccountData.status.submittedAndPendingApproval
) { ) {
<div class="flex-49"> <!-- ACTIVE: Performance History -->
<h4 class="table-headers">{{ 'labels.heading.Interest Details' | translate }}</h4> <div class="nx-card">
<table> <div class="nx-card__head">
<tbody> <span class="nx-card__ico"><fa-icon icon="chart-bar"></fa-icon></span>
<tr> <h3 class="nx-card__title">{{ 'labels.heading.Performance History' | translate }}</h3>
<td>{{ 'labels.inputs.Interest Rate' | translate }}</td> </div>
<td class="r-amount">{{ recurringDepositsAccountData.nominalAnnualInterestRate | formatNumber }} %</td> <div class="nx-card__body">
</tr> <div class="nx-row">
<tr> <span class="nx-row__label">{{ 'labels.inputs.Principal Amount' | translate }}</span>
<td>{{ 'labels.inputs.Interest Compounding Period' | translate }}</td> <span class="nx-row__value nx-row__value--amount">
<td> {{ recurringDepositsAccountData.depositAmount | currency: currency.code : 'symbol-narrow' : '1.2-2' }}
<span>{{ </span>
recurringDepositsAccountData.interestCompoundingPeriodType.value | translateKey: 'catalogs' </div>
}}</span> <div class="nx-row">
</td> <span class="nx-row__label">{{ 'labels.inputs.Maturity Amount' | translate }}</span>
</tr> <span class="nx-row__value nx-row__value--amount nx-row__value--positive">
<tr> {{ recurringDepositsAccountData.maturityAmount | currency: currency.code : 'symbol-narrow' : '1.2-2' }}
<td>{{ 'labels.inputs.Interest Posting Period' | translate }}</td> </span>
<td> </div>
<span>{{ recurringDepositsAccountData.interestPostingPeriodType.value | translateKey: 'catalogs' }}</span> <div class="nx-row">
</td> <span class="nx-row__label">{{ 'labels.inputs.Recurring Deposit Amount' | translate }}</span>
</tr> <span class="nx-row__value nx-row__value--amount">
<tr>
<td>{{ 'labels.inputs.Interest calculated using' | translate }}</td>
<td>
<span>{{ recurringDepositsAccountData.interestCalculationType.value | translateKey: 'catalogs' }}</span>
</td>
</tr>
<tr>
<td>{{ 'labels.inputs.Days in Year' | translate }}</td>
<td>
<span>{{
recurringDepositsAccountData.interestCalculationDaysInYearType.value | translateKey: 'catalogs'
}}</span>
</td>
</tr>
@if (recurringDepositsAccountData.preClosurePenalApplicable) {
<tr>
<td>{{ 'labels.inputs.Pre-closure penal Interest (less)' | translate }}</td>
<td>
<span
>{{ recurringDepositsAccountData.preClosurePenalInterest }} % on
{{ {{
recurringDepositsAccountData.preClosurePenalInterestOnType.value | translateKey: 'catalogs' recurringDepositsAccountData?.mandatoryRecommendedDepositAmount
}}</span | currency: currency.code : 'symbol-narrow' : '1.2-2'
> }}
</td> </span>
</tr>
}
</tbody>
</table>
</div> </div>
} <div class="nx-row">
<span class="nx-row__label">{{ 'labels.inputs.Deposits till Date' | translate }}</span>
@if ( <span class="nx-row__value nx-row__value--amount">
recurringDepositsAccountData.status.rejected || recurringDepositsAccountData.status.submittedAndPendingApproval @if (recurringDepositsAccountData.summary.totalDeposits) {
) {
<div class="flex-49">
<table>
<tbody>
<tr>
<td>{{ 'labels.inputs.Interest Compounding Period' | translate }}</td>
<td>
<span>{{
recurringDepositsAccountData.interestCompoundingPeriodType.value | translateKey: 'catalogs'
}}</span>
</td>
</tr>
<tr>
<td>{{ 'labels.inputs.Interest Posting Period' | translate }}</td>
<td>
<span>{{ recurringDepositsAccountData.interestPostingPeriodType.value | translateKey: 'catalogs' }}</span>
</td>
</tr>
<tr>
<td>{{ 'labels.inputs.Interest calculated using' | translate }}</td>
<td>
<span>{{ recurringDepositsAccountData.interestCalculationType.value | translateKey: 'catalogs' }}</span>
</td>
</tr>
<tr>
<td>{{ 'labels.inputs.Days in Year' | translate }}</td>
<td>
<span>{{
recurringDepositsAccountData.interestCalculationDaysInYearType.value | translateKey: 'catalogs'
}}</span>
</td>
</tr>
@if (recurringDepositsAccountData.preClosurePenalApplicable) {
<tr>
<td>{{ 'labels.inputs.Pre-closure penal Interest (less)' | translate }}</td>
<td>
<span
>{{ recurringDepositsAccountData.preClosurePenalInterest }} % on
{{ {{
recurringDepositsAccountData.preClosurePenalInterestOnType.value | translateKey: 'catalogs' recurringDepositsAccountData.summary.totalDeposits
}}</span | currency: currency.code : 'symbol-narrow' : '1.2-2'
}}
} @else {
{{ 0 | currency: currency.code : 'symbol-narrow' : '1.2-2' }}
}
</span>
</div>
<div class="nx-row">
<span class="nx-row__label">{{ 'labels.inputs.Withdrwals till Date' | translate }}</span>
<span class="nx-row__value nx-row__value--amount nx-row__value--negative">
@if (recurringDepositsAccountData.summary.totalWithdrawals) {
{{
recurringDepositsAccountData.summary.totalWithdrawals
| currency: currency.code : 'symbol-narrow' : '1.2-2'
}}
} @else {
{{ 0 | currency: currency.code : 'symbol-narrow' : '1.2-2' }}
}
</span>
</div>
@if (recurringDepositsAccountData.summary.totalInterestEarned >= 0) {
<div class="nx-row">
<span class="nx-row__label">{{ 'labels.inputs.Interest Earned' | translate }}</span>
<span class="nx-row__value nx-row__value--amount nx-row__value--positive">
{{
recurringDepositsAccountData.summary.totalInterestEarned
| currency: currency.code : 'symbol-narrow' : '1.2-2'
}}
</span>
</div>
}
</div>
</div>
} @else {
<!-- PENDING/REJECTED: Financial Summary -->
<div class="nx-card">
<div class="nx-card__head">
<span class="nx-card__ico"><fa-icon icon="info-circle"></fa-icon></span>
<h3 class="nx-card__title">{{ 'labels.heading.Other Details' | translate }}</h3>
</div>
<div class="nx-card__body">
<div class="nx-row">
<span class="nx-row__label">{{ 'labels.inputs.Principal Amount' | translate }}</span>
<span class="nx-row__value nx-row__value--amount">
@if (recurringDepositsAccountData.depositAmount) {
{{ recurringDepositsAccountData.depositAmount | currency: currency.code : 'symbol-narrow' : '1.2-2' }}
} @else {
{{ 0 | currency: currency.code : 'symbol-narrow' : '1.2-2' }}
}
</span>
</div>
<div class="nx-row">
<span class="nx-row__label">{{ 'labels.inputs.Rate of Interest' | translate }}</span>
<span class="nx-row__value"
>{{ recurringDepositsAccountData.nominalAnnualInterestRate | formatNumber }} %</span
> >
</td> </div>
</tr> @if (recurringDepositsAccountData.maturityDate) {
<div class="nx-row">
<span class="nx-row__label">{{ 'labels.inputs.Maturity Amount' | translate }}</span>
<span class="nx-row__value nx-row__value--amount">
{{ recurringDepositsAccountData.maturityAmount | currency: currency.code : 'symbol-narrow' : '1.2-2' }}
</span>
</div>
} }
@if (recurringDepositsAccountData.witdHoldTax) { <div class="nx-row">
<tr> <span class="nx-row__label">{{ 'labels.inputs.Total Withdrawls' | translate }}</span>
<td>{{ 'labels.inputs.Witdhold Tax Group' | translate }}</td> <span class="nx-row__value nx-row__value--amount">
<td> @if (recurringDepositsAccountData.summary.totalWithdrawals) {
<span>{{ recurringDepositsAccountData.taxGroup.name }}</span> {{
</td> recurringDepositsAccountData.summary.totalWithdrawals
</tr> | currency: currency.code : 'symbol-narrow' : '1.2-2'
}}
} @else {
{{ 0 | currency: currency.code : 'symbol-narrow' : '1.2-2' }}
} }
</tbody> </span>
</table> </div>
@if (recurringDepositsAccountData.timeline.closedOnDate) {
<div class="nx-row">
<span class="nx-row__label">{{ 'labels.inputs.Closed on Date' | translate }}</span>
<span class="nx-row__value">{{ recurringDepositsAccountData.timeline.closedOnDate | dateFormat }}</span>
</div>
}
<div class="nx-row">
<span class="nx-row__label">{{ 'labels.inputs.Deposits Frequency' | translate }}</span>
<span class="nx-row__value">
{{ recurringDepositsAccountData.recurringFrequency }}&nbsp;{{
recurringDepositsAccountData.recurringFrequencyType.value | translateKey: 'catalogs'
}}
</span>
</div>
@if (recurringDepositsAccountData.summary.totalInterestEarned) {
<div class="nx-row">
<span class="nx-row__label">{{ 'labels.inputs.Interests Posted' | translate }}</span>
<span class="nx-row__value nx-row__value--amount">
@if (recurringDepositsAccountData.summary.totalInterestPosted) {
{{
recurringDepositsAccountData.summary.totalInterestPosted
| currency: currency.code : 'symbol-narrow' : '1.2-2'
}}
} @else {
{{ 0 | currency: currency.code : 'symbol-narrow' : '1.2-2' }}
}
</span>
</div> </div>
} }
</div> </div>
</div>
}
</div>
</div>
@@ -6,6 +6,115 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. * file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/ */
.recurring-deposits-account-tables { $navy: #0d1b2a;
padding: 1%; $slate: #475569;
$muted: #64748b;
$border: #e2e8f0;
$soft: #f8fafc;
/* ─── Two-column grid ───────────────────────────────────────────────── */
.gt-grid {
display: grid;
grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
gap: 16px;
@media (width <= 1024px) {
grid-template-columns: 1fr;
}
}
.gt-col {
display: flex;
flex-direction: column;
gap: 16px;
min-width: 0;
}
/* ─── Nexora section card ───────────────────────────────────────────── */
.nx-card {
background: #fff;
border: 1px solid $border;
border-radius: 14px;
box-shadow: 0 1px 3px rgb(15 23 42 / 4%);
overflow: hidden;
&__head {
display: flex;
align-items: center;
gap: 10px;
padding: 12px 18px;
background: $soft;
border-bottom: 1px solid $border;
}
&__ico {
width: 26px;
height: 26px;
display: inline-flex;
align-items: center;
justify-content: center;
border-radius: 8px;
background: linear-gradient(135deg, #3b82f6 0%, #1e40af 100%);
color: #fff;
font-size: 12px;
}
&__title {
margin: 0;
font-size: 13.5px;
font-weight: 700;
color: $navy;
letter-spacing: 0.01em;
}
&__body {
padding: 4px 18px 10px;
}
}
/* ─── Key/Value row ─────────────────────────────────────────────────── */
.nx-row {
display: grid;
grid-template-columns: minmax(0, 1fr) auto;
gap: 12px;
align-items: center;
min-height: 38px;
padding: 8px 0;
border-bottom: 1px dashed #eef2f7;
font-size: 13px;
&:last-child {
border-bottom: none;
}
&__label {
color: $slate;
font-weight: 500;
}
&__value {
color: $navy;
font-weight: 600;
text-align: right;
word-break: break-word;
&--amount {
font-variant-numeric: tabular-nums;
font-weight: 700;
}
&--positive {
color: #047857;
}
&--negative {
color: #b91c1c;
}
}
}
.nx-muted {
color: $muted;
font-weight: 500;
font-style: italic;
} }
@@ -13,6 +13,7 @@ import { DecimalPipe, CurrencyPipe } from '@angular/common';
import { ExternalIdentifierComponent } from '../../../../shared/external-identifier/external-identifier.component'; import { ExternalIdentifierComponent } from '../../../../shared/external-identifier/external-identifier.component';
import { DateFormatPipe } from '../../../../pipes/date-format.pipe'; import { DateFormatPipe } from '../../../../pipes/date-format.pipe';
import { FormatNumberPipe } from '../../../../pipes/format-number.pipe'; import { FormatNumberPipe } from '../../../../pipes/format-number.pipe';
import { FaIconComponent } from '@fortawesome/angular-fontawesome';
import { STANDALONE_SHARED_IMPORTS } from 'app/standalone-shared.module'; import { STANDALONE_SHARED_IMPORTS } from 'app/standalone-shared.module';
@Component({ @Component({
@@ -22,6 +23,7 @@ import { STANDALONE_SHARED_IMPORTS } from 'app/standalone-shared.module';
imports: [ imports: [
...STANDALONE_SHARED_IMPORTS, ...STANDALONE_SHARED_IMPORTS,
ExternalIdentifierComponent, ExternalIdentifierComponent,
FaIconComponent,
DecimalPipe, DecimalPipe,
CurrencyPipe, CurrencyPipe,
DateFormatPipe, DateFormatPipe,
@@ -6,105 +6,95 @@
file, You can obtain one at http://mozilla.org/MPL/2.0/. file, You can obtain one at http://mozilla.org/MPL/2.0/.
--> -->
<mat-card class="account-card"> <div class="rd-view">
<mat-card-header class="header layout-column"> <!-- ─── Gradient hero header ─────────────────────────────────────── -->
<mat-card-title-group class="header-title-group"> <header class="rd-hero">
<div class="profile-image-container"> <div class="rd-hero__left">
<div> <div class="rd-hero__avatar">
<img <fa-icon icon="calendar-alt"></fa-icon>
mat-card-md-image
class="profile-image"
matTooltip="{{ 'tooltips.Recurring Deposits Account' | translate }}"
[src]="'assets/images/recurring-deposits_account_placeholder.png'"
/>
</div>
</div> </div>
<div class="mat-typography account-card-title"> <div class="rd-hero__info">
<mat-card-title> <div class="rd-hero__status-row">
<div class="layout-row responsive-column"> <span
<div class="flex-60"> class="rd-status-pill"
<h3>
<i
class="fa fa-stop"
[ngClass]="recurringDepositsAccountData.status.code | statusLookup" [ngClass]="recurringDepositsAccountData.status.code | statusLookup"
[matTooltip]="recurringDepositsAccountData.status.value" [matTooltip]="recurringDepositsAccountData.status.value"
></i> >
{{ 'labels.inputs.Recurring Deposit' | translate }} : <span class="rd-status-pill__dot"></span>
{{ recurringDepositsAccountData.depositProductName }} {{ recurringDepositsAccountData.status.value }}
<mifosx-account-number accountNo="{{ recurringDepositsAccountData.accountNo }}"></mifosx-account-number> </span>
</h3> </div>
<span class="account-overview">
{{ 'labels.text.' + entityType | translate }} {{ 'labels.inputs.name' | translate }}: <h2 class="rd-hero__title">
<mifosx-long-text textValue="{{ recurringDepositsAccountData.depositProductName }}"></mifosx-long-text>
</h2>
<div class="rd-hero__meta">
<span class="rd-hero__meta-item">
<span class="rd-hero__meta-label">{{ 'labels.inputs.Account Number' | translate }}</span>
<mifosx-account-number
accountNo="{{ recurringDepositsAccountData.accountNo }}"
display="left"
></mifosx-account-number>
</span>
<span class="rd-hero__meta-item">
<span class="rd-hero__meta-label">
{{ 'labels.text.' + entityType | translate }} {{ 'labels.inputs.name' | translate }}
</span>
<span class="rd-hero__meta-value">
{{ recurringDepositsAccountData.clientName || recurringDepositsAccountData.groupName }} {{ recurringDepositsAccountData.clientName || recurringDepositsAccountData.groupName }}
@if (recurringDepositsAccountData.clientAccountNo) { @if (recurringDepositsAccountData.clientAccountNo) {
<span class="m-l-10">
<mifosx-account-number <mifosx-account-number
accountNo="{{ recurringDepositsAccountData.clientAccountNo }}" accountNo="{{ recurringDepositsAccountData.clientAccountNo }}"
></mifosx-account-number> ></mifosx-account-number>
</span>
} }
</span> </span>
</span>
</div>
</div>
</div> </div>
<!-- Balance KPI strip -->
@if ( @if (
!recurringDepositsAccountData.status.rejected && !recurringDepositsAccountData.status.rejected && !recurringDepositsAccountData.status.submittedAndPendingApproval
!recurringDepositsAccountData.status.submittedAndPendingApproval
) { ) {
<div class="flex-30"> <div class="rd-hero__kpis">
<h3>{{ 'labels.heading.Account Overview' | translate }}</h3> <div class="rd-kpi">
<table class="account-overview"> <span class="rd-kpi__label">{{ 'labels.inputs.Current Balance' | translate }}</span>
<tbody> <span class="rd-kpi__value">
<tr>
<td>{{ 'labels.inputs.Current Balance' | translate }}</td>
<td class="r-amount">
{{ {{
recurringDepositsAccountData.summary.accountBalance recurringDepositsAccountData.summary.accountBalance | currency: currency.code : 'symbol-narrow' : '1.2-2'
| currency: currency.code : 'symbol-narrow' : '1.2-2'
}} }}
</td> </span>
</tr> </div>
<tr> <div class="rd-kpi rd-kpi--deposit">
<td>{{ 'labels.inputs.Deposit Amount' | translate }}</td> <span class="rd-kpi__label">{{ 'labels.inputs.Deposit Amount' | translate }}</span>
<td class="r-amount"> <span class="rd-kpi__value">
{{ {{ recurringDepositsAccountData.depositAmount | currency: currency.code : 'symbol-narrow' : '1.2-2' }}
recurringDepositsAccountData.depositAmount </span>
| currency: currency.code : 'symbol-narrow' : '1.2-2' </div>
}} <div class="rd-kpi rd-kpi--period">
</td> <span class="rd-kpi__label">{{ 'labels.inputs.Deposit Period' | translate }}</span>
</tr> <span class="rd-kpi__value">{{ recurringDepositsAccountData.depositPeriod | number }}</span>
<tr> </div>
<td>{{ 'labels.inputs.Deposit Period' | translate }}</td>
<td class="r-amount">{{ recurringDepositsAccountData.depositPeriod | number }}</td>
</tr>
</tbody>
</table>
</div> </div>
} }
<div class="flex-5"> <!-- Action menu (kebab) -->
<button <div class="rd-hero__actions">
mat-icon-button <button mat-icon-button [matMenuTriggerFor]="accountMenu" aria-label="Account actions" yPosition="below">
[matMenuTriggerFor]="accountMenu" <fa-icon icon="ellipsis-v"></fa-icon>
aria-label="Loan account actions"
yPosition="below"
>
<mat-icon matListIcon class="actions-menu">
<fa-icon icon="bars" size="sm"></fa-icon>
</mat-icon>
</button> </button>
</div> </div>
</div>
</mat-card-title>
</div>
<mat-menu #accountMenu="matMenu"> <mat-menu #accountMenu="matMenu">
@for (item of buttonConfig.singleButtons; track item) { @for (item of buttonConfig.singleButtons; track item) {
<button mat-menu-item *mifosxHasPermission="item.taskPermissionName" (click)="doAction(item.name)"> <button mat-menu-item *mifosxHasPermission="item.taskPermissionName" (click)="doAction(item.name)">
<i ngClass="{{ item.icon }}"></i> {{ 'labels.menus.' + item.name | translate }} <span>{{ 'labels.menus.' + item.name | translate }}</span>
</button> </button>
} }
@if (buttonConfig.options.length) { @if (buttonConfig.options.length) {
<button mat-menu-item [matMenuTriggerFor]="More">{{ 'labels.menus.More' | translate }}</button> <button mat-menu-item [matMenuTriggerFor]="More">{{ 'labels.menus.More' | translate }}</button>
<mat-menu #More="matMenu"> <mat-menu #More="matMenu">
@@ -118,84 +108,99 @@
</mat-menu> </mat-menu>
} }
</mat-menu> </mat-menu>
</mat-card-title-group> </header>
</mat-card-header>
<mat-card-content class="content"> <!-- ─── Pill-style tab navigation ─────────────────────────────────── -->
<nav mat-tab-nav-bar class="navigation-tabs" [tabPanel]="tabPanel"> <nav mat-tab-nav-bar class="rd-tabs" [tabPanel]="tabPanel">
<a <a
mat-tab-link mat-tab-link
class="rd-tab"
[routerLink]="['./general']" [routerLink]="['./general']"
routerLinkActive routerLinkActive
#general="routerLinkActive" #general="routerLinkActive"
[active]="general.isActive" [active]="general.isActive"
> >
{{ 'labels.inputs.General' | translate }} <fa-icon icon="info-circle" class="rd-tab__ic"></fa-icon>
<span>{{ 'labels.inputs.General' | translate }}</span>
</a> </a>
<a <a
mat-tab-link mat-tab-link
class="rd-tab"
[routerLink]="['./interest-rate-chart']" [routerLink]="['./interest-rate-chart']"
routerLinkActive routerLinkActive
#IRC="routerLinkActive" #IRC="routerLinkActive"
[active]="IRC.isActive" [active]="IRC.isActive"
> >
{{ 'labels.inputs.Interest Rate Chart' | translate }} <fa-icon icon="chart-line" class="rd-tab__ic"></fa-icon>
<span>{{ 'labels.inputs.Interest Rate Chart' | translate }}</span>
</a> </a>
@if (showTransactions) { @if (showTransactions) {
<a <a
mat-tab-link mat-tab-link
class="rd-tab"
[routerLink]="['./transactions']" [routerLink]="['./transactions']"
routerLinkActive routerLinkActive
#transactions="routerLinkActive" #transactions="routerLinkActive"
[active]="transactions.isActive" [active]="transactions.isActive"
> >
{{ 'labels.inputs.Transactions' | translate }} <fa-icon icon="exchange-alt" class="rd-tab__ic"></fa-icon>
<span>{{ 'labels.inputs.Transactions' | translate }}</span>
</a> </a>
} }
<a <a
mat-tab-link mat-tab-link
class="rd-tab"
[routerLink]="['./charges']" [routerLink]="['./charges']"
routerLinkActive routerLinkActive
#charges="routerLinkActive" #charges="routerLinkActive"
[active]="charges.isActive" [active]="charges.isActive"
> >
{{ 'labels.inputs.Charges' | translate }} <fa-icon icon="receipt" class="rd-tab__ic"></fa-icon>
<span>{{ 'labels.inputs.Charges' | translate }}</span>
</a> </a>
@if (recurringDepositsAccountData.clientId) { @if (recurringDepositsAccountData.clientId) {
<a <a
mat-tab-link mat-tab-link
class="rd-tab"
[routerLink]="['./standing-instructions-tab']" [routerLink]="['./standing-instructions-tab']"
routerLinkActive routerLinkActive
#standingInstructions="routerLinkActive" #standingInstructions="routerLinkActive"
[active]="standingInstructions.isActive" [active]="standingInstructions.isActive"
> >
{{ 'labels.inputs.Standing Instructions' | translate }} <fa-icon icon="calendar-check" class="rd-tab__ic"></fa-icon>
<span>{{ 'labels.inputs.Standing Instructions' | translate }}</span>
</a> </a>
} }
<a <a
mat-tab-link mat-tab-link
class="rd-tab"
[routerLink]="['./nominees']" [routerLink]="['./nominees']"
routerLinkActive routerLinkActive
#nominees="routerLinkActive" #nominees="routerLinkActive"
[active]="nominees.isActive" [active]="nominees.isActive"
> >
Nominees <fa-icon icon="user-shield" class="rd-tab__ic"></fa-icon>
<span>Nominees</span>
</a> </a>
@for (savingsDatatable of savingsDatatables; track savingsDatatable) { @for (savingsDatatable of savingsDatatables; track savingsDatatable) {
<a <a
mat-tab-link mat-tab-link
class="rd-tab"
*mifosxHasPermission="'READ_' + savingsDatatable.registeredTableName" *mifosxHasPermission="'READ_' + savingsDatatable.registeredTableName"
[routerLink]="['./datatables', savingsDatatable.registeredTableName]" [routerLink]="['./datatables', savingsDatatable.registeredTableName]"
routerLinkActive routerLinkActive
#datatable="routerLinkActive" #datatable="routerLinkActive"
[active]="datatable.isActive" [active]="datatable.isActive"
> >
{{ savingsDatatable.registeredTableName }} <fa-icon icon="table" class="rd-tab__ic"></fa-icon>
<span>{{ savingsDatatable.registeredTableName }}</span>
</a> </a>
} }
</nav> </nav>
<mat-tab-nav-panel #tabPanel> <mat-tab-nav-panel #tabPanel>
<div class="rd-body">
<router-outlet></router-outlet> <router-outlet></router-outlet>
</div>
</mat-tab-nav-panel> </mat-tab-nav-panel>
</mat-card-content> </div>
</mat-card>
@@ -5,3 +5,386 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this * License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. * file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/ */
$navy: #0d1b2a;
$blue: #1e88e5;
$blue-d: #1e40af;
$border: #e2e8f0;
.rd-view {
max-width: 1440px;
margin: 0 auto;
padding: 12px 20px 22px;
}
/* ─── Gradient hero header ──────────────────────────────────────────── */
.rd-hero {
position: relative;
display: grid;
grid-template-columns: minmax(0, 1fr) auto auto;
align-items: stretch;
gap: 14px;
padding: 12px 18px;
border-radius: 12px;
color: #fff;
background: linear-gradient(135deg, #1e3a8a 0%, #1e40af 45%, #4338ca 100%);
box-shadow: 0 6px 18px -10px rgb(15 23 42 / 35%);
overflow: hidden;
&::before {
content: '';
position: absolute;
inset: 0;
background: radial-gradient(circle at top right, rgb(255 255 255 / 12%) 0%, transparent 55%);
pointer-events: none;
}
&__left {
display: flex;
align-items: center;
gap: 12px;
min-width: 0;
position: relative;
z-index: 1;
}
&__avatar {
width: 40px;
height: 40px;
border-radius: 10px;
background: linear-gradient(135deg, rgb(255 255 255 / 22%) 0%, rgb(255 255 255 / 10%) 100%);
border: 1px solid rgb(255 255 255 / 28%);
display: flex;
align-items: center;
justify-content: center;
color: #fff;
font-size: 16px;
flex-shrink: 0;
box-shadow: 0 3px 10px -3px rgb(0 0 0 / 25%);
}
&__info {
display: flex;
flex-direction: column;
gap: 3px;
min-width: 0;
}
&__status-row {
display: flex;
align-items: center;
gap: 6px;
}
&__title {
margin: 0;
font-size: 15px;
font-weight: 800;
letter-spacing: 0.01em;
color: #fff;
line-height: 1.15;
::ng-deep mifosx-long-text {
color: #fff;
}
}
&__meta {
display: flex;
flex-wrap: wrap;
gap: 2px 18px;
margin-top: 1px;
}
&__meta-item {
display: inline-flex;
align-items: center;
gap: 6px;
font-size: 12px;
color: rgb(255 255 255 / 90%);
}
&__meta-label {
font-size: 10px;
text-transform: uppercase;
letter-spacing: 0.07em;
color: rgb(255 255 255 / 60%);
font-weight: 600;
}
&__meta-value {
font-weight: 600;
color: #fff;
}
&__kpis {
display: flex;
gap: 8px;
align-items: stretch;
position: relative;
z-index: 1;
}
&__actions {
display: flex;
align-items: center;
position: relative;
z-index: 1;
button {
width: 32px !important;
height: 32px !important;
min-width: 32px !important;
padding: 0 !important;
border-radius: 50% !important;
color: #fff !important;
background: rgb(255 255 255 / 10%) !important;
border: 1px solid rgb(255 255 255 / 22%) !important;
display: inline-flex !important;
align-items: center;
justify-content: center;
line-height: 1;
transition:
background 0.15s ease,
border-color 0.15s ease,
transform 0.12s ease;
::ng-deep fa-icon {
font-size: 14px;
line-height: 1;
display: inline-flex;
align-items: center;
justify-content: center;
}
::ng-deep .mat-mdc-button-persistent-ripple,
::ng-deep .mat-mdc-button-touch-target {
border-radius: 50% !important;
}
}
button:hover {
background: rgb(255 255 255 / 22%) !important;
border-color: rgb(255 255 255 / 38%) !important;
}
button:active {
transform: scale(0.94);
}
}
}
/* KPI tiles */
.rd-kpi {
display: flex;
flex-direction: column;
justify-content: center;
min-width: 110px;
padding: 7px 14px;
border-radius: 9px;
background: rgb(255 255 255 / 14%);
border: 1px solid rgb(255 255 255 / 22%);
backdrop-filter: blur(8px);
&__label {
font-size: 9.5px;
text-transform: uppercase;
letter-spacing: 0.07em;
font-weight: 700;
color: rgb(255 255 255 / 75%);
}
&__value {
margin-top: 2px;
font-size: 15px;
font-weight: 800;
color: #fff;
font-variant-numeric: tabular-nums;
letter-spacing: -0.01em;
}
&--deposit {
background: rgb(245 158 11 / 22%);
border-color: rgb(245 158 11 / 35%);
}
&--period {
background: rgb(139 92 246 / 22%);
border-color: rgb(139 92 246 / 35%);
}
}
/* Status pill */
.rd-status-pill {
display: inline-flex;
align-items: center;
gap: 5px;
height: 18px;
padding: 0 8px;
border-radius: 999px;
background: rgb(16 185 129 / 24%);
border: 1px solid rgb(16 185 129 / 40%);
font-size: 10px;
font-weight: 700;
text-transform: uppercase;
letter-spacing: 0.06em;
color: #d1fae5;
&__dot {
width: 5px;
height: 5px;
border-radius: 50%;
background: #10b981;
box-shadow: 0 0 0 2px rgb(16 185 129 / 30%);
}
&.statussubmitted,
&.statuspending {
background: rgb(245 158 11 / 24%);
border-color: rgb(245 158 11 / 40%);
color: #fef3c7;
.rd-status-pill__dot {
background: #f59e0b;
}
}
&.statusclosed,
&.statusrejected,
&.statuswithdrawn,
&.statusprematureclosed {
background: rgb(239 68 68 / 24%);
border-color: rgb(239 68 68 / 40%);
color: #fee2e2;
.rd-status-pill__dot {
background: #ef4444;
}
}
}
/* ─── Pill-style tab navigation ─────────────────────────────────────── */
.rd-tabs {
margin-top: 18px;
background: #fff;
border: 1px solid $border;
border-radius: 14px;
padding: 6px;
box-shadow: 0 1px 3px rgb(15 23 42 / 4%);
overflow: hidden;
::ng-deep {
.mat-mdc-tab-link-container {
border-bottom: none !important;
}
.mat-mdc-tab-links {
gap: 4px;
flex-wrap: wrap;
}
.mdc-tab-indicator__content--underline,
.mat-mdc-tab-header-pagination-controls-enabled .mdc-tab-indicator__content--underline {
display: none !important;
}
}
}
.rd-tab {
display: inline-flex !important;
align-items: center;
gap: 8px;
height: 38px !important;
min-width: 0 !important;
padding: 0 16px !important;
border-radius: 10px !important;
font-family: Inter, 'DM Sans', Roboto, sans-serif !important;
font-size: 13px !important;
font-weight: 600 !important;
letter-spacing: 0.01em !important;
color: #64748b !important;
background: transparent !important;
transition: all 0.15s ease;
white-space: nowrap;
border: 1px solid transparent !important;
opacity: 1 !important;
&__ic {
font-size: 12px;
color: inherit;
}
&:hover:not(.mdc-tab--active) {
background: #f1f5f9 !important;
color: $navy !important;
}
&.mdc-tab--active,
&.mat-mdc-tab-link-active {
background: linear-gradient(135deg, $blue 0%, $blue-d 100%) !important;
color: #fff !important;
box-shadow: 0 2px 6px -1px rgb(30 64 175 / 35%);
border-color: $blue-d !important;
::ng-deep .mdc-tab__text-label,
::ng-deep .mat-mdc-tab-link-content,
::ng-deep span,
.rd-tab__ic {
color: #fff !important;
opacity: 1 !important;
}
}
}
.rd-body {
margin-top: 16px;
}
/* ─── Responsive ────────────────────────────────────────────────────── */
@media (width <= 1100px) {
.rd-hero {
grid-template-columns: 1fr;
&__kpis {
width: 100%;
flex-wrap: wrap;
}
&__actions {
position: absolute;
top: 18px;
right: 18px;
}
}
.rd-kpi {
flex: 1 1 auto;
min-width: 0;
}
}
@media (width <= 700px) {
.rd-view {
padding: 12px;
}
.rd-hero {
padding: 18px;
&__title {
font-size: 18px;
}
&__avatar {
width: 52px;
height: 52px;
font-size: 22px;
border-radius: 12px;
}
}
.rd-tab {
padding: 0 12px !important;
font-size: 12px !important;
}
}
@@ -23,17 +23,10 @@ import { DeleteDialogComponent } from 'app/shared/delete-dialog/delete-dialog.co
import { RecurringDepositConfirmationDialogComponent } from './custom-dialogs/recurring-deposit-confirmation-dialog/recurring-deposit-confirmation-dialog.component'; import { RecurringDepositConfirmationDialogComponent } from './custom-dialogs/recurring-deposit-confirmation-dialog/recurring-deposit-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';
import {
MatCard,
MatCardHeader,
MatCardTitleGroup,
MatCardMdImage,
MatCardTitle,
MatCardContent
} from '@angular/material/card';
import { MatTooltip } from '@angular/material/tooltip'; import { MatTooltip } from '@angular/material/tooltip';
import { NgClass, DecimalPipe, CurrencyPipe } from '@angular/common'; import { NgClass, DecimalPipe, CurrencyPipe } from '@angular/common';
import { AccountNumberComponent } from '../../../shared/account-number/account-number.component'; import { AccountNumberComponent } from '../../../shared/account-number/account-number.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 { MatIcon } from '@angular/material/icon';
@@ -51,12 +44,9 @@ import { STANDALONE_SHARED_IMPORTS } from 'app/standalone-shared.module';
styleUrls: ['./recurring-deposits-account-view.component.scss'], styleUrls: ['./recurring-deposits-account-view.component.scss'],
imports: [ imports: [
...STANDALONE_SHARED_IMPORTS, ...STANDALONE_SHARED_IMPORTS,
MatCardHeader,
MatCardTitleGroup,
MatCardMdImage,
MatTooltip, MatTooltip,
MatCardTitle,
NgClass, NgClass,
LongTextComponent,
AccountNumberComponent, AccountNumberComponent,
MatIconButton, MatIconButton,
MatMenuTrigger, MatMenuTrigger,
@@ -6,23 +6,19 @@
file, You can obtain one at http://mozilla.org/MPL/2.0/. file, You can obtain one at http://mozilla.org/MPL/2.0/.
--> -->
<div class="tab-container mat-typography"> <div class="txn-tab">
<div class="mat-elevation-z1 m-b-25"> <div class="txn-tab__card">
<div class="layout-row align-start">
<div class="m-b-20">
<h3>{{ 'labels.heading.All Transactions' | translate }}</h3>
</div>
@if (checkStatus()) { @if (checkStatus()) {
<div class="action-button m-b-20 layout-row gap-20px"> <div class="txn-tab__toolbar">
<mat-checkbox [formControl]="hideReversedParam" (click)="hideReversed()" class="accruals"> <mat-checkbox [formControl]="hideReversedParam" (click)="hideReversed()" class="txn-tab__check">
{{ 'labels.inputs.Hide Reversed' | translate }}</mat-checkbox {{ 'labels.inputs.Hide Reversed' | translate }}
> </mat-checkbox>
<mat-checkbox [formControl]="hideAccrualsParam" (click)="hideAccruals()" class="accruals"> <mat-checkbox [formControl]="hideAccrualsParam" (click)="hideAccruals()" class="txn-tab__check">
{{ 'labels.inputs.Hide Accruals' | translate }}</mat-checkbox {{ 'labels.inputs.Hide Accruals' | translate }}
> </mat-checkbox>
<span class="txn-tab__spacer"></span>
</div> </div>
} }
</div>
<table mat-table [dataSource]="dataSource"> <table mat-table [dataSource]="dataSource">
<ng-container matColumnDef="row"> <ng-container matColumnDef="row">
@@ -6,37 +6,95 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. * file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/ */
@use 'assets/styles/helper'; $navy: #0d1b2a;
$slate: #475569;
$muted: #64748b;
$border: #e2e8f0;
$soft: #f8fafc;
$blue: #1e40af;
.tab-container { .txn-tab {
padding: 1%; width: 100%;
margin: 1%;
h3 {
margin: 1% auto;
} }
.action-button { .txn-tab__card {
margin-left: auto; background: #fff;
border: 1px solid $border;
border-radius: 14px;
box-shadow: 0 1px 3px rgb(15 23 42 / 4%);
overflow: hidden;
}
.txn-tab__toolbar {
display: flex;
align-items: center;
gap: 18px;
padding: 12px 18px;
background: $soft;
border-bottom: 1px solid $border;
flex-wrap: wrap;
}
.txn-tab__check {
font-size: 13px;
color: $slate;
font-weight: 500;
}
.txn-tab__spacer {
flex: 1;
} }
table { table {
width: 100%; width: 100%;
.account-action-button {
min-width: 26px;
padding: 0 0 3px;
margin: 0 10%;
line-height: 25px;
.accruals {
padding-top: 1%;
}
}
}
} }
.select-row:hover { ::ng-deep .txn-tab__card {
cursor: pointer; .mat-mdc-header-row {
background: $soft;
}
.mat-mdc-header-cell {
font-size: 11.5px;
font-weight: 800; font-weight: 800;
color: $slate;
text-transform: uppercase;
letter-spacing: 0.06em;
padding: 12px 14px;
border-bottom: 1px solid $border;
}
.mat-mdc-cell {
font-size: 13px;
color: $navy;
padding: 11px 14px;
border-bottom: 1px solid #f1f5f9;
}
.mat-mdc-row:hover {
background: #f8fafc;
cursor: pointer;
}
.mat-column-debit,
.mat-column-credit,
.mat-column-balance {
text-align: right;
font-variant-numeric: tabular-nums;
}
.mat-column-actions {
text-align: center;
width: 80px;
}
.strike td {
text-decoration: line-through;
color: $muted;
}
.accrual td {
color: $muted;
font-style: italic;
}
} }