fix(credit-bureau): keep customer enquiry list stable and add back navigation in alert detail
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -12,6 +12,12 @@
|
|||||||
<div class="cic-empty">Loading…</div>
|
<div class="cic-empty">Loading…</div>
|
||||||
}
|
}
|
||||||
@if (alert) {
|
@if (alert) {
|
||||||
|
@if (history.length) {
|
||||||
|
<div class="cic-alert info" style="margin-bottom: 12px">
|
||||||
|
You are viewing another enquiry of this customer.
|
||||||
|
<button class="cic-btn sm" style="margin-left: 8px" (click)="back()">← Back to previous enquiry</button>
|
||||||
|
</div>
|
||||||
|
}
|
||||||
<div style="display: flex; justify-content: space-between; gap: 12px; align-items: flex-start">
|
<div style="display: flex; justify-content: space-between; gap: 12px; align-items: flex-start">
|
||||||
<div>
|
<div>
|
||||||
<h3 style="margin-bottom: 4px">
|
<h3 style="margin-bottom: 4px">
|
||||||
@@ -160,8 +166,8 @@
|
|||||||
@if (alert.otherAlertsOfCustomer?.length) {
|
@if (alert.otherAlertsOfCustomer?.length) {
|
||||||
<div class="cic-card" style="margin-top: 14px; margin-bottom: 0">
|
<div class="cic-card" style="margin-top: 14px; margin-bottom: 0">
|
||||||
<h2>
|
<h2>
|
||||||
Other enquiries on this customer
|
All enquiries on this customer
|
||||||
<span class="cic-card-sub">{{ alert.otherAlertsOfCustomer?.length }} more</span>
|
<span class="cic-card-sub">{{ customerEnquiries.length }} in total</span>
|
||||||
</h2>
|
</h2>
|
||||||
<div class="cic-table-wrap">
|
<div class="cic-table-wrap">
|
||||||
<table class="cic-table">
|
<table class="cic-table">
|
||||||
@@ -174,10 +180,19 @@
|
|||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
<tbody>
|
<tbody>
|
||||||
@for (o of alert.otherAlertsOfCustomer; track o.id) {
|
@for (o of customerEnquiries; track o.id) {
|
||||||
<tr class="clickable" (click)="alertId = o.id; load()">
|
<tr
|
||||||
|
class="clickable"
|
||||||
|
[style.background]="o.id === alert.id ? '#eef4ff' : null"
|
||||||
|
(click)="o.id !== alert.id && openOther(o.id)"
|
||||||
|
>
|
||||||
<td>{{ o.enquiryDate | date: 'dd MMM yyyy' }}</td>
|
<td>{{ o.enquiryDate | date: 'dd MMM yyyy' }}</td>
|
||||||
<td>{{ o.loanType }}</td>
|
<td>
|
||||||
|
{{ o.loanType }}
|
||||||
|
@if (o.id === alert.id) {
|
||||||
|
<b>(shown above)</b>
|
||||||
|
}
|
||||||
|
</td>
|
||||||
<td class="num">{{ o.amount | number: '1.0-0' }}</td>
|
<td class="num">{{ o.amount | number: '1.0-0' }}</td>
|
||||||
<td>
|
<td>
|
||||||
<span class="cic-badge" [class]="'cic-badge ' + statusTone(o.status)">{{ o.status }}</span>
|
<span class="cic-badge" [class]="'cic-badge ' + statusTone(o.status)">{{ o.status }}</span>
|
||||||
|
|||||||
@@ -52,6 +52,10 @@ export class CicAlertDetailComponent implements OnChanges {
|
|||||||
info: string | null = null;
|
info: string | null = null;
|
||||||
showRaw = false;
|
showRaw = false;
|
||||||
|
|
||||||
|
/** Alerts visited before the current one, so the user can go back after opening another enquiry of the customer. */
|
||||||
|
history: number[] = [];
|
||||||
|
private autoSeen = true;
|
||||||
|
|
||||||
action: 'ACTIONED' | 'DISMISSED' | null = null;
|
action: 'ACTIONED' | 'DISMISSED' | null = null;
|
||||||
remarks = '';
|
remarks = '';
|
||||||
|
|
||||||
@@ -59,9 +63,27 @@ export class CicAlertDetailComponent implements OnChanges {
|
|||||||
readonly statusTone = cicStatusTone;
|
readonly statusTone = cicStatusTone;
|
||||||
|
|
||||||
ngOnChanges(): void {
|
ngOnChanges(): void {
|
||||||
|
this.history = [];
|
||||||
|
this.autoSeen = true;
|
||||||
if (this.alertId) this.load();
|
if (this.alertId) this.load();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
openOther(id: number): void {
|
||||||
|
if (this.alertId) this.history.push(this.alertId);
|
||||||
|
this.alertId = id;
|
||||||
|
// Only the alert opened from the dashboard counts as "seen"; browsing the customer's other enquiries changes nothing.
|
||||||
|
this.autoSeen = false;
|
||||||
|
this.load();
|
||||||
|
}
|
||||||
|
|
||||||
|
back(): void {
|
||||||
|
const id = this.history.pop();
|
||||||
|
if (!id) return;
|
||||||
|
this.alertId = id;
|
||||||
|
this.autoSeen = false;
|
||||||
|
this.load();
|
||||||
|
}
|
||||||
|
|
||||||
load(): void {
|
load(): void {
|
||||||
if (!this.alertId) return;
|
if (!this.alertId) return;
|
||||||
this.loading = true;
|
this.loading = true;
|
||||||
@@ -73,8 +95,9 @@ export class CicAlertDetailComponent implements OnChanges {
|
|||||||
next: (a) => {
|
next: (a) => {
|
||||||
this.alert = a;
|
this.alert = a;
|
||||||
this.loading = false;
|
this.loading = false;
|
||||||
|
setTimeout(() => document.querySelector('.cic-modal')?.scrollTo({ top: 0 }));
|
||||||
// Opening a new alert is seeing it.
|
// Opening a new alert is seeing it.
|
||||||
if (a.status === 'NEW' && a.clientId) this.setStatus('SEEN', null, true);
|
if (this.autoSeen && a.status === 'NEW' && a.clientId) this.setStatus('SEEN', null, true);
|
||||||
},
|
},
|
||||||
error: (e) => {
|
error: (e) => {
|
||||||
this.loading = false;
|
this.loading = false;
|
||||||
@@ -139,6 +162,15 @@ export class CicAlertDetailComponent implements OnChanges {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** All of the customer's enquiries, this one included, in a fixed order so the list does not reshuffle when one is opened. */
|
||||||
|
get customerEnquiries(): CicAlert[] {
|
||||||
|
if (!this.alert) return [];
|
||||||
|
return [
|
||||||
|
this.alert,
|
||||||
|
...(this.alert.otherAlertsOfCustomer ?? [])
|
||||||
|
].sort((x, y) => (y.enquiryDate ?? '').localeCompare(x.enquiryDate ?? '') || y.id - x.id);
|
||||||
|
}
|
||||||
|
|
||||||
get exposure(): number {
|
get exposure(): number {
|
||||||
return (this.alert?.clientLoans ?? []).reduce((s, l) => s + Number(l.outstanding ?? 0), 0);
|
return (this.alert?.clientLoans ?? []).reduce((s, l) => s + Number(l.outstanding ?? 0), 0);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user