Files
cbsnexora/src/app/reports/reports.component.html
T
keshav 352a65cb5d
build-run / Run Lint, Build and Deploy (push) Canceled after 0s
Publish Image in Docker Hub / build (push) Canceled after 0s
Playwright E2E Tests / Run Playwright Tests (push) Canceled after 0s
Tests / testRigor (push) Canceled after 0s
feat: implement DIP/MNRL lookups and enhance Sanctions screening workflows
- Implement DIP/MNRL lookup logs table, filtering, and detail review under reports.
- Integrate DIP verification gating on client creation, allowing officers to record PROCEEDED/REJECTED decisions with reasons.
- Upgrade Sanctions verification dialog to support comparing Name, DOB, and Nationality particulars.
- Add Sanctions disposition recording (FALSE_POSITIVE / CONFIRMED_MATCH) awaiting Principal Officer approval.
- Add sanctions-alert-review-dialog for reviewers to assess and escalate/clear flagged names.
- Enforce strict screening reset logic on client name changes, preventing bypass of existing blocks.
- Update routes and shell menu navigation to include DIP/MNRL Lookups and Sanctions Logs.
2026-08-14 10:44:00 +05:30

155 lines
6.1 KiB
HTML

<!--
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="rpt-container">
<!-- Header -->
<div class="rpt-header">
<div class="rpt-header__left">
<div class="rpt-logomark"><span></span><span></span><span></span><span></span></div>
<h2 class="rpt-header__title">{{ 'labels.menus.Reports' | translate }}</h2>
<span class="rpt-header__badge">{{ reportsData?.length || 0 }} reports</span>
</div>
<!--
Sanctions alerts are not a runnable report, so they never appear in the category tiles
below — yet this is where the Principal Officer has to come to clear a flagged screening.
Without this link the review queue was reachable only by typing the URL.
-->
<a class="rpt-header__action" routerLink="/reports/sanctions-logs">
<i class="fas fa-shield-alt"></i>
Sanctions Screening &amp; Alerts
</a>
</div>
<!-- ===== LEVEL 0: All Categories ===== -->
@if (!selectedCategory) {
<div class="rpt-search-row">
<mat-form-field appearance="outline" class="rpt-search">
<i class="fas fa-search rpt-search__icon" matPrefix></i>
<input matInput placeholder="Search all reports..." (keyup)="applyFilter($event.target.value)" />
</mat-form-field>
</div>
@if (isSearching) {
<ng-container *ngTemplateOutlet="reportTable"></ng-container>
}
@if (!isSearching) {
<div class="rpt-tiles">
@for (cat of categories; track cat.name) {
<div class="rpt-tile" (click)="selectCategory(cat.name)">
<div class="rpt-tile__icon" [ngClass]="cat.color"><i [class]="'fas ' + cat.icon"></i></div>
<div class="rpt-tile__info">
<span class="rpt-tile__name">{{ cat.name }}</span>
<span class="rpt-tile__count">{{ cat.count }} reports</span>
</div>
<i class="fas fa-chevron-right rpt-tile__arrow"></i>
</div>
}
</div>
}
}
<!-- ===== LEVEL 1: Category Selected ===== -->
@if (selectedCategory) {
<div class="rpt-detail">
<!-- Breadcrumb -->
<div class="rpt-detail__header">
<button
mat-stroked-button
class="rpt-back-btn"
(click)="selectedSubCategory ? backToSubCategories() : clearCategory()"
>
<i class="fas fa-arrow-left"></i>
{{ selectedSubCategory ? selectedCategory : 'All Categories' }}
</button>
<h3 class="rpt-detail__title">{{ selectedSubCategory || selectedCategory }}</h3>
<span class="rpt-header__badge">
{{ selectedSubCategory ? dataSource.data.length : filteredReports.length }} reports
</span>
</div>
<!-- Sub-Category Tiles (for large categories like Loan) -->
@if (showSubCategories) {
<div class="rpt-search-row">
<mat-form-field appearance="outline" class="rpt-search">
<i class="fas fa-search rpt-search__icon" matPrefix></i>
<input
matInput
placeholder="Search in {{ selectedCategory }}..."
(keyup)="applyFilter($event.target.value)"
/>
</mat-form-field>
</div>
@if (isSearching) {
<ng-container *ngTemplateOutlet="reportTable"></ng-container>
}
@if (!isSearching) {
<div class="rpt-tiles rpt-tiles--sub">
@for (sub of subCategories; track sub.name) {
<div class="rpt-tile" (click)="selectSubCategory(sub)">
<div class="rpt-tile__icon" [ngClass]="sub.color"><i [class]="'fas ' + sub.icon"></i></div>
<div class="rpt-tile__info">
<span class="rpt-tile__name">{{ sub.name }}</span>
<span class="rpt-tile__count">{{ sub.count }} reports</span>
</div>
<i class="fas fa-chevron-right rpt-tile__arrow"></i>
</div>
}
</div>
}
}
<!-- Direct Table (small categories or sub-category selected) -->
@if (!showSubCategories) {
<div class="rpt-search-row">
<mat-form-field appearance="outline" class="rpt-search">
<i class="fas fa-search rpt-search__icon" matPrefix></i>
<input matInput placeholder="Search reports..." (keyup)="applyFilter($event.target.value)" />
</mat-form-field>
</div>
<ng-container *ngTemplateOutlet="reportTable"></ng-container>
}
</div>
}
</div>
<!-- ===== Reusable Report Table Template ===== -->
<ng-template #reportTable>
<div class="rpt-table-wrap">
<table mat-table [dataSource]="dataSource" matSort class="rpt-table">
<ng-container matColumnDef="reportName">
<th mat-header-cell *matHeaderCellDef mat-sort-header>{{ 'labels.inputs.name' | translate }}</th>
<td mat-cell *matCellDef="let report" class="rpt-cell-link">{{ report.reportName }}</td>
</ng-container>
<ng-container matColumnDef="reportType">
<th mat-header-cell *matHeaderCellDef mat-sort-header>{{ 'labels.inputs.Type' | translate }}</th>
<td mat-cell *matCellDef="let report">
<span class="rpt-type-badge">{{ 'labels.text.' + report.reportType | translate }}</span>
</td>
</ng-container>
<ng-container matColumnDef="reportCategory">
<th mat-header-cell *matHeaderCellDef mat-sort-header>{{ 'labels.inputs.Category' | translate }}</th>
<td mat-cell *matCellDef="let report">
<span class="rpt-cat-badge">{{ 'labels.text.' + report.reportCategory | translate }}</span>
</td>
</ng-container>
<tr mat-header-row *matHeaderRowDef="displayedColumns"></tr>
<tr
mat-row
*matRowDef="let row; columns: displayedColumns"
class="rpt-row"
[routerLink]="['/reports', 'run', row.reportName]"
[queryParams]="{ type: row.reportType, id: row.id }"
></tr>
</table>
<mat-paginator [pageSizeOptions]="[10, 25, 50, 100]" showFirstLastButtons></mat-paginator>
</div>
</ng-template>