Files
cbsnexora/src/app/rd-dashboard/rd-dashboard.component.html
T

257 lines
12 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<!--
Copyright since 2025 Mifos Initiative
This Source Code Form is subject to the terms of the Mozilla Public
License, v. 2.0. If a copy of the MPL was not distributed with this
file, You can obtain one at http://mozilla.org/MPL/2.0/.
-->
<div class="rdd-container">
<!-- Header -->
<div class="rdd-header">
<div class="rdd-header__left">
<div class="rdd-header__icon">
<fa-icon icon="piggy-bank"></fa-icon>
</div>
<div>
<h2 class="rdd-header__title">RD Dashboard</h2>
<p class="rdd-header__sub">
All running Recurring Deposits as of <strong>{{ businessDate || '—' }}</strong> (business date). Click any
card to see those RDs in the list below.
</p>
</div>
</div>
<button class="rdd-btn rdd-btn--slim" (click)="load()" [disabled]="loading">
<fa-icon icon="sync-alt" [class.fa-spin]="loading"></fa-icon>
<span>{{ loading ? 'Loading...' : 'Reload' }}</span>
</button>
</div>
@if (errorMessage) {
<div class="rdd-alert">
<fa-icon icon="exclamation-triangle"></fa-icon>
<span>{{ errorMessage }}</span>
</div>
}
<!-- 1. Summary -->
<section class="rdd-section">
<h3 class="rdd-section__title">RD Book at a Glance</h3>
<div class="rdd-cards">
<button class="rdd-card rdd-card--success" [class.rdd-card--active]="stageFilter === 'REGULAR'" (click)="showStage('REGULAR')">
<span class="rdd-card__label"><fa-icon icon="chart-line"></fa-icon> Active RDs</span>
<span class="rdd-card__val">{{ summary.activeCount }}</span>
<span class="rdd-card__sub">Balance ₹{{ summary.activeBalance | number: '1.2-2' }}</span>
</button>
<button class="rdd-card rdd-card--info" [class.rdd-card--active]="stageFilter === 'MATURED'" (click)="showStage('MATURED')">
<span class="rdd-card__label"><fa-icon icon="calendar-check"></fa-icon> Matured – Close Pending</span>
<span class="rdd-card__val">{{ summary.maturedCount }}</span>
<span class="rdd-card__sub">To pay ₹{{ summary.maturedAmount | number: '1.2-2' }}</span>
</button>
<div class="rdd-card rdd-card--neutral rdd-card--static">
<span class="rdd-card__label"><fa-icon icon="check-circle"></fa-icon> Closed This Month</span>
<span class="rdd-card__val">{{ maturedClosedThisMonth + prematureClosedThisMonth }}</span>
<span class="rdd-card__sub">On maturity {{ maturedClosedThisMonth }} · Premature {{ prematureClosedThisMonth }}</span>
</div>
<div class="rdd-card rdd-card--neutral rdd-card--static">
<span class="rdd-card__label"><fa-icon icon="hand-holding-usd"></fa-icon> This Month's Installments</span>
<span class="rdd-card__val">{{ summary.collectionPercent }}%</span>
<div class="rdd-progress">
<div class="rdd-progress__bar" [style.width.%]="summary.collectionPercent"></div>
</div>
<span class="rdd-card__sub"
>Received ₹{{ summary.receivedThisMonth | number: '1.0-0' }} of ₹{{
summary.dueThisMonth | number: '1.0-0'
}}</span
>
</div>
<button class="rdd-card rdd-card--danger" [class.rdd-card--active]="extraFilter === 'overdue'" (click)="showExtra('overdue')">
<span class="rdd-card__label"><fa-icon icon="exclamation-circle"></fa-icon> Overdue RDs</span>
<span class="rdd-card__val">{{ summary.overdueCount }}</span>
<span class="rdd-card__sub">Pending ₹{{ summary.overdueAmount | number: '1.2-2' }}</span>
</button>
<button class="rdd-card rdd-card--warn" [class.rdd-card--active]="extraFilter === 'lien'" (click)="showExtra('lien')">
<span class="rdd-card__label"><fa-icon icon="lock"></fa-icon> Under Lien (Loan)</span>
<span class="rdd-card__val">{{ summary.lienCount }}</span>
<span class="rdd-card__sub">Lien ₹{{ summary.lienAmount | number: '1.2-2' }}</span>
</button>
</div>
</section>
<!-- 2. Installment health -->
<section class="rdd-section">
<h3 class="rdd-section__title">Installment Health</h3>
<div class="rdd-health">
<div class="rdd-tiles">
<button class="rdd-tile" [class.rdd-tile--active]="stageFilter === 'DUE_TODAY'" (click)="showStage('DUE_TODAY')">
<span class="rdd-tile__dot rdd-tile__dot--neutral"></span>
<span class="rdd-tile__label">Due today</span>
<span class="rdd-tile__val">{{ summary.dueTodayCount }}</span>
<span class="rdd-tile__sub">{{ summary.dueTodayPaidCount }} paid · {{ summary.dueTodayCount - summary.dueTodayPaidCount }} pending</span>
</button>
<button class="rdd-tile" [class.rdd-tile--active]="stageFilter === 'IN_GRACE'" (click)="showStage('IN_GRACE')">
<span class="rdd-tile__dot rdd-tile__dot--warn"></span>
<span class="rdd-tile__label">Late, in grace</span>
<span class="rdd-tile__val">{{ summary.inGraceCount }}</span>
<span class="rdd-tile__sub">₹{{ summary.inGraceAmount | number: '1.0-0' }} · no penalty yet</span>
</button>
<button class="rdd-tile" [class.rdd-tile--active]="stageFilter === 'PAST_GRACE'" (click)="showStage('PAST_GRACE')">
<span class="rdd-tile__dot rdd-tile__dot--danger"></span>
<span class="rdd-tile__label">Past grace</span>
<span class="rdd-tile__val">{{ summary.pastGraceCount }}</span>
<span class="rdd-tile__sub">₹{{ summary.pastGraceAmount | number: '1.0-0' }} · penalty applies</span>
</button>
<div class="rdd-tile rdd-tile--static">
<span class="rdd-tile__dot rdd-tile__dot--success"></span>
<span class="rdd-tile__label">Penalty income</span>
<span class="rdd-tile__val">₹{{ penaltyIncomeThisMonth | number: '1.0-0' }}</span>
<span class="rdd-tile__sub">This month · ₹{{ penaltyIncomeTotal | number: '1.0-0' }} in all</span>
</div>
</div>
<div class="rdd-ageing">
<div class="rdd-ageing__title">How late are overdue RDs?</div>
@for (b of ageingBuckets; track b.key) {
<button class="rdd-ageing__row" [class.rdd-ageing__row--active]="extraFilter === b.key" (click)="showExtra(b.key)">
<span class="rdd-ageing__label">{{ b.label }}</span>
<span class="rdd-ageing__track">
<span class="rdd-ageing__bar" [style.width.%]="ageingWidth(b.key)"></span>
</span>
<span class="rdd-ageing__count">{{ summary.ageing[b.key] || 0 }}</span>
</button>
}
</div>
</div>
</section>
<!-- 3. Action list -->
<section class="rdd-section">
<h3 class="rdd-section__title">RD List – What to Do Next</h3>
<div class="rdd-toolbar">
<div class="rdd-search">
<fa-icon icon="search" class="rdd-search__icon"></fa-icon>
<input class="rdd-search__input" type="text" placeholder="Account no. or client name" [(ngModel)]="search" />
</div>
<select class="rdd-select" [(ngModel)]="officeFilter">
<option [ngValue]="''">All branches</option>
@for (o of offices; track o.id) {
<option [ngValue]="o.id">{{ o.name }}</option>
}
</select>
<select class="rdd-select" [(ngModel)]="productFilter">
<option [ngValue]="''">All products</option>
@for (p of products; track p.id) {
<option [ngValue]="p.id">{{ p.name }}</option>
}
</select>
<select class="rdd-select" [(ngModel)]="stageFilter" (ngModelChange)="extraFilter = ''">
<option [ngValue]="''">All statuses</option>
@for (k of stageKeys; track k) {
<option [ngValue]="k">{{ stages[k].label }}</option>
}
</select>
@if (anyFilter) {
<button class="rdd-btn rdd-btn--slim" (click)="resetFilters()"><fa-icon icon="undo"></fa-icon> Clear</button>
}
<span class="rdd-toolbar__spacer"></span>
<span class="rdd-count"
><strong>{{ visibleRows.length }}</strong> of {{ rows.length }} RDs</span
>
</div>
@if (loading) {
<div class="rdd-state"><fa-icon icon="spinner" [class.fa-spin]="true"></fa-icon> Loading RDs...</div>
} @else if (visibleRows.length === 0) {
<div class="rdd-state">
<fa-icon icon="inbox"></fa-icon>
{{ rows.length ? 'No RDs match these filters.' : 'No running Recurring Deposits.' }}
</div>
} @else {
<div class="rdd-table-card">
<table class="rdd-table">
<thead>
<tr>
<th>Account</th>
<th>Client</th>
<th>Product</th>
<th class="text-right">Installment</th>
<th>Next Due</th>
<th class="text-right">Overdue</th>
<th>Maturity</th>
<th>Status</th>
<th class="text-center">Auto Debit</th>
<th class="text-right">Lien</th>
<th class="text-center">Action</th>
</tr>
</thead>
<tbody>
@for (r of visibleRows; track r.id) {
<tr class="rdd-row" (click)="openAccount(r)">
<td>
<span class="rdd-mono">{{ r.accountNo }}</span>
<div class="rdd-sub">{{ r.officeName }}</div>
</td>
<td class="rdd-strong">{{ r.clientName }}</td>
<td class="rdd-muted">{{ r.productName }}</td>
<td class="text-right">
<span class="rdd-mono">₹{{ r.installmentAmount | number: '1.2-2' }}</span>
<div class="rdd-sub">{{ r.paidInstallments }} of {{ r.totalInstallments }} paid</div>
</td>
<td>
<span class="rdd-mono">{{ r.nextDueDate || '—' }}</span>
<div class="rdd-sub" [class.rdd-sub--danger]="r.daysLate > 0">{{ dueText(r) }}</div>
</td>
<td class="text-right">
@if (r.overdueInstallments > 0) {
<span class="rdd-mono rdd-danger">₹{{ r.overdueAmount | number: '1.2-2' }}</span>
<div class="rdd-sub">
{{ r.overdueInstallments }} installment{{ r.overdueInstallments === 1 ? '' : 's' }}
</div>
} @else {
<span class="rdd-muted">—</span>
}
</td>
<td>
<span class="rdd-mono">{{ r.maturityDate || '—' }}</span>
<div class="rdd-sub">{{ maturityText(r) }}</div>
</td>
<td>
<span [class]="stageClass(r.stage)" [title]="r.meta.hint">{{ r.meta.label }}</span>
@if (r.penaltyCount > 0) {
<div class="rdd-sub">Penalty ₹{{ r.penaltyAmount | number: '1.0-0' }} ({{ r.penaltyCount }}x)</div>
}
</td>
<td class="text-center">
@if (r.autoDebit) {
<span class="rdd-yes" [title]="'From ' + (r.linkedAccountNo || 'linked savings')">On</span>
} @else {
<span class="rdd-muted">Off</span>
}
</td>
<td class="text-right">
@if (r.lienAmount > 0) {
<span class="rdd-mono">₹{{ r.lienAmount | number: '1.0-0' }}</span>
} @else {
<span class="rdd-muted">—</span>
}
</td>
<td class="text-center rdd-actions" (click)="$event.stopPropagation()">
@if (r.stage === 'MATURED') {
<button class="rdd-btn rdd-btn--primary rdd-btn--xs" (click)="closeAccount(r)">Close</button>
}
<button class="rdd-btn rdd-btn--xs" (click)="openAccount(r)">View</button>
</td>
</tr>
}
</tbody>
</table>
</div>
}
</section>
</div>