feat: implement cashier dashboard, dividend dashboards, share accounts views, and checker tasks
This commit is contained in:
@@ -103,6 +103,12 @@
|
||||
<div class="detail-value">{{ resolutionNumber }}</div>
|
||||
</div>
|
||||
}
|
||||
@if (resolutionDate) {
|
||||
<div class="detail-block">
|
||||
<div class="detail-label">Resolution Date</div>
|
||||
<div class="detail-value">{{ resolutionDate | dateFormat }}</div>
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -133,64 +139,71 @@
|
||||
|
||||
<!-- Transactions Table -->
|
||||
@if (filteredTransactions.length > 0) {
|
||||
<table class="statement-table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th class="col-sr">#</th>
|
||||
<th class="col-date">Date</th>
|
||||
<th class="col-desc">Description</th>
|
||||
<th class="col-ref">Ref No.</th>
|
||||
<th class="col-amount text-right">Shares Purchased</th>
|
||||
<th class="col-amount text-right">Shares Redeemed</th>
|
||||
<th class="col-balance text-right">Share Balance</th>
|
||||
<th class="col-amount text-right">Amount (₹)</th>
|
||||
<th class="col-desc">Resolution No. / Meeting</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
@for (txn of filteredTransactions; track txn.id; let i = $index) {
|
||||
<tr [class.debit-row]="isRedeem(txn)" [class.credit-row]="!isRedeem(txn)">
|
||||
<td class="col-sr text-center">{{ i + 1 }}</td>
|
||||
<td class="col-date">{{ txn.purchasedDate | dateFormat }}</td>
|
||||
<td class="col-desc">
|
||||
<span class="txn-desc">{{ txn.type.value }} ({{ txn.status.value }})</span>
|
||||
</td>
|
||||
<td class="col-ref text-muted mono">{{ txn.id }}</td>
|
||||
<td class="col-amount text-right credit-amount">
|
||||
@if (!isRedeem(txn)) {
|
||||
{{ txn.numberOfShares }}
|
||||
}
|
||||
</td>
|
||||
<td class="col-amount text-right debit-amount">
|
||||
@if (isRedeem(txn)) {
|
||||
{{ txn.numberOfShares }}
|
||||
}
|
||||
</td>
|
||||
<td class="col-balance text-right balance-amount">{{ txn.runningBalance }}</td>
|
||||
<td class="col-amount text-right">
|
||||
{{ txn.amount | currency: currency?.code : 'symbol-narrow' : '1.2-2' }}
|
||||
</td>
|
||||
<td class="col-desc">
|
||||
@if (isRedeem(txn)) {
|
||||
{{ txn.resolutionNumber || '—' }}
|
||||
@if (txn.meetingDate) {
|
||||
({{ txn.meetingDate | dateFormat }})
|
||||
}
|
||||
} @else {
|
||||
—
|
||||
}
|
||||
</td>
|
||||
<div class="statement-table-scroll">
|
||||
<table class="statement-table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th class="col-sr text-center">#</th>
|
||||
<th class="col-date text-left">Date</th>
|
||||
<th class="col-desc text-left">Description</th>
|
||||
<th class="col-ref text-center">Ref No.</th>
|
||||
<th class="col-amount text-right">Shares Purchased</th>
|
||||
<th class="col-amount text-right">Shares Redeemed</th>
|
||||
<th class="col-balance text-right">Share Balance</th>
|
||||
<th class="col-amount text-right">Amount (₹)</th>
|
||||
<th class="col-resolution text-left">Resolution No. / Meeting</th>
|
||||
</tr>
|
||||
}
|
||||
</tbody>
|
||||
<tfoot>
|
||||
<tr class="total-row">
|
||||
<td colspan="6" class="text-right total-label">Closing Share Balance</td>
|
||||
<td class="text-right closing-balance">{{ totalApprovedShares }}</td>
|
||||
<td colspan="2"></td>
|
||||
</tr>
|
||||
</tfoot>
|
||||
</table>
|
||||
</thead>
|
||||
<tbody>
|
||||
@for (txn of filteredTransactions; track txn.id; let i = $index) {
|
||||
<tr [class.debit-row]="isRedeem(txn)" [class.credit-row]="!isRedeem(txn)">
|
||||
<td class="col-sr text-center">{{ i + 1 }}</td>
|
||||
<td class="col-date text-left">{{ txn.purchasedDate | dateFormat }}</td>
|
||||
<td class="col-desc text-left">
|
||||
<span class="txn-desc">{{ txn.type.value }} ({{ txn.status.value }})</span>
|
||||
</td>
|
||||
<td class="col-ref text-center text-muted mono">{{ txn.id }}</td>
|
||||
<td class="col-amount text-right credit-amount">
|
||||
@if (!isRedeem(txn)) {
|
||||
{{ txn.numberOfShares }}
|
||||
}
|
||||
</td>
|
||||
<td class="col-amount text-right debit-amount">
|
||||
@if (isRedeem(txn)) {
|
||||
{{ txn.numberOfShares }}
|
||||
}
|
||||
</td>
|
||||
<td class="col-balance text-right balance-amount">{{ txn.runningBalance }}</td>
|
||||
<td class="col-amount text-right">
|
||||
{{ txn.amount | currency: currency?.code : 'symbol-narrow' : '1.2-2' }}
|
||||
</td>
|
||||
<td class="col-resolution text-left">
|
||||
@if (isRedeem(txn)) {
|
||||
{{ txn.resolutionNumber || '—' }}
|
||||
@if (txn.meetingDate) {
|
||||
({{ txn.meetingDate | dateFormat }})
|
||||
}
|
||||
} @else {
|
||||
<!-- Purchases are authorised by the share account's own board resolution, which is
|
||||
held on the account rather than the transaction. -->
|
||||
{{ resolutionNumber || '—' }}
|
||||
@if (resolutionDate) {
|
||||
({{ resolutionDate | dateFormat }})
|
||||
}
|
||||
}
|
||||
</td>
|
||||
</tr>
|
||||
}
|
||||
</tbody>
|
||||
<tfoot>
|
||||
<tr class="total-row">
|
||||
<td colspan="6" class="text-right total-label">Closing Share Balance</td>
|
||||
<td class="text-right closing-balance">{{ totalApprovedShares }}</td>
|
||||
<td colspan="2"></td>
|
||||
</tr>
|
||||
</tfoot>
|
||||
</table>
|
||||
</div>
|
||||
} @else {
|
||||
<div class="no-data-block">
|
||||
<mat-icon>inbox</mat-icon>
|
||||
|
||||
@@ -214,6 +214,14 @@ $row-alt: #f4f7fb;
|
||||
}
|
||||
|
||||
// ─── Transactions Table ───────────────────────────────────────────────────────
|
||||
// The columns below are fixed-width so each cell stays under its own header. On a narrow
|
||||
// viewport that total exceeds the card, so the table scrolls here rather than being clipped
|
||||
// by the wrapper's overflow:hidden.
|
||||
.statement-table-scroll {
|
||||
width: 100%;
|
||||
overflow-x: auto;
|
||||
}
|
||||
|
||||
.statement-table {
|
||||
width: 100%;
|
||||
border-collapse: collapse;
|
||||
@@ -225,6 +233,10 @@ $row-alt: #f4f7fb;
|
||||
border-bottom: 2px solid $bank-primary;
|
||||
}
|
||||
|
||||
// Headers default to left so each one starts exactly where its cell's text starts; the
|
||||
// numeric columns opt into right alignment via .text-right below. Without this the browser
|
||||
// (and Material's table styles) can centre the heading while the cell stays left, which
|
||||
// reads as the whole column being out of position.
|
||||
thead th {
|
||||
padding: 9px 10px;
|
||||
font-size: 11px;
|
||||
@@ -233,6 +245,25 @@ $row-alt: #f4f7fb;
|
||||
text-transform: uppercase;
|
||||
letter-spacing: 0.4px;
|
||||
white-space: nowrap;
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
// Alignment helpers must win over the thead default above, for header and cell alike, so
|
||||
// a column's heading and its values always share one alignment.
|
||||
thead th,
|
||||
tbody td,
|
||||
tfoot td {
|
||||
&.text-right {
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
&.text-center {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
&.text-left {
|
||||
text-align: left;
|
||||
}
|
||||
}
|
||||
|
||||
tbody tr {
|
||||
@@ -274,20 +305,36 @@ $row-alt: #f4f7fb;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
// Description is the only flexible column: it absorbs the leftover width so every other
|
||||
// column keeps the fixed size its header needs and stays aligned with its cells.
|
||||
.col-desc {
|
||||
min-width: 140px;
|
||||
width: auto;
|
||||
min-width: 160px;
|
||||
}
|
||||
|
||||
// Board Resolution No. / Meeting Date — wide enough to hold "00RK2 (14 August 2026)"
|
||||
// on one line so it does not crowd the right-aligned Amount column beside it.
|
||||
.col-resolution {
|
||||
width: 190px;
|
||||
white-space: nowrap;
|
||||
padding-left: 16px;
|
||||
}
|
||||
|
||||
.col-ref {
|
||||
width: 70px;
|
||||
width: 80px;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
// Sized to the widest header label ("Shares Purchased") so the numeric cells sit directly
|
||||
// under their own heading rather than drifting toward the neighbouring column.
|
||||
.col-amount {
|
||||
width: 100px;
|
||||
width: 128px;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.col-balance {
|
||||
width: 90px;
|
||||
width: 112px;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
// ─── Amount colors ────────────────────────────────────────────────────────────
|
||||
@@ -335,6 +382,10 @@ $row-alt: #f4f7fb;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.text-left {
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
.text-muted {
|
||||
color: #999;
|
||||
}
|
||||
@@ -450,6 +501,12 @@ $row-alt: #f4f7fb;
|
||||
border-radius: 0;
|
||||
}
|
||||
|
||||
// On paper there is nothing to scroll — let the table lay out at full width so no
|
||||
// column is cut off at the page edge.
|
||||
.statement-table-scroll {
|
||||
overflow-x: visible;
|
||||
}
|
||||
|
||||
.bank-header {
|
||||
-webkit-print-color-adjust: exact;
|
||||
print-color-adjust: exact;
|
||||
|
||||
@@ -47,6 +47,7 @@ export class SharesPassbookTabComponent implements OnInit {
|
||||
status = '';
|
||||
activatedOnDate: any = null;
|
||||
resolutionNumber = '';
|
||||
resolutionDate: any = null;
|
||||
savingsAccountNumber = '';
|
||||
totalApprovedShares = 0;
|
||||
currentMarketPrice = 0;
|
||||
@@ -75,6 +76,7 @@ export class SharesPassbookTabComponent implements OnInit {
|
||||
this.status = account.status?.value || '';
|
||||
this.activatedOnDate = account.timeline?.activatedDate || null;
|
||||
this.resolutionNumber = account.resolutionNumber || '';
|
||||
this.resolutionDate = account.resolutionDate || null;
|
||||
this.savingsAccountNumber = account.savingsAccountNumber || '';
|
||||
this.totalApprovedShares = account.summary?.totalApprovedShares || 0;
|
||||
this.currentMarketPrice = account.currentMarketPrice || 0;
|
||||
|
||||
Reference in New Issue
Block a user