Files
cbsnexora/src/app/tasks/view-checker-inbox/view-checker-inbox.component.html
T
niteshandClaude Opus 5 e8097bc2cb feat(tasks): open a checker inbox entry in a popup instead of a page
Clicking a row navigated away to its own page, costing the checker the list and
whatever search they had set up. It now opens in a dialog over the list, the
same pattern the Disbursement and Closure Requests tabs already use.

ViewCheckerInboxComponent gained the optional MatDialogRef/MAT_DIALOG_DATA pair
rather than being duplicated, so the direct route still works for a bookmarked
link. Two differences follow from being a dialog:

 - the list rows carry only summary fields, so the detail (which is what has
   commandAsJson) is fetched here; by route it stays resolver-provided. The
   template reads checkerInboxDetail.* unguarded, so it is now behind an @if
   with a loading state -- otherwise a dialog would render against undefined.
 - commandAsJson is absent on some entries (a DELETE carries no payload) and
   JSON.parse(undefined) throws. By route that broke the page; in a dialog it
   would have left an empty shell open. Parsing is now guarded.

The list only reloads when something was actually actioned, since reload()
re-navigates the route and would otherwise discard the checker's search on a
plain close.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-01 18:30:24 +05:30

131 lines
5.4 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.vci--dialog]="isDialog">
@if (isDialog) {
<div class="vci-dialog-bar">
<span class="vci-dialog-bar__title">{{ 'labels.heading.View Checker Inbox' | translate }}</span>
<span class="vci-dialog-bar__close" (click)="close()">✕ {{ 'labels.buttons.Close' | translate }}</span>
</div>
}
<!-- As a dialog the detail is fetched rather than resolved, so nothing below can be rendered
until it arrives — the template reads checkerInboxDetail.* unguarded. -->
@if (loading) {
<div class="vci-loading">{{ 'labels.heading.Loading' | translate }}…</div>
}
@if (checkerInboxDetail) {
@if (isProductEditEntry) {
<div class="container m-b-20">
<div class="mat-elevation-z1" style="padding: 12px 16px; border-left: 4px solid #f59e0b; background: #fffbeb">
This is a product edit awaiting approval. Approve or reject it from
<strong>Approvals &gt; Pending Product Edits</strong> instead — actioning it here would not release its lock.
</div>
</div>
} @else {
<div class="layout-row align-end gap-1percent layout-lt-md-column container m-b-20">
<button mat-raised-button color="success" (click)="approveChecker()">
<fa-icon icon="check" class="m-r-10"></fa-icon>{{ 'labels.buttons.Approve' | translate }}
</button>
<button mat-raised-button color="warn" (click)="deleteChecker()">
<fa-icon icon="trash" class="m-r-10"></fa-icon>{{ 'labels.buttons.Delete' | translate }}
</button>
<button mat-raised-button color="reject" (click)="rejectChecker()">
<fa-icon icon="times" class="m-r-10"></fa-icon>{{ 'labels.buttons.Reject' | translate }}
</button>
</div>
}
<div class="container">
<mat-card>
<mat-card-content>
<div class="layout-row-wrap responsive-column">
<h2 class="mat-h2 flex-fill">{{ 'labels.heading.View Checker Inbox' | translate }}</h2>
<mat-divider [inset]="true"></mat-divider>
<h3 class="mat-h3 flex-fill">{{ 'labels.heading.Details' | translate }}</h3>
<mat-divider [inset]="true"></mat-divider>
<div class="flex-fill">
<span class="flex-40">{{ 'labels.inputs.ID' | translate }}:</span>
<span class="flex-60">{{ checkerInboxDetail.id }}</span>
</div>
<div class="flex-fill">
<span class="flex-40">{{ 'labels.inputs.Status' | translate }}:</span>
<span class="flex-60">{{ checkerInboxDetail.processingResult }}</span>
</div>
<div class="flex-fill">
<span class="flex-40">{{ 'labels.inputs.User' | translate }}:</span>
<span class="flex-60">{{ checkerInboxDetail.maker }}</span>
</div>
<div class="flex-fill">
<span class="flex-40">{{ 'labels.inputs.Action' | translate }}:</span>
<span class="flex-60">{{ checkerInboxDetail.actionName }}</span>
</div>
<div class="flex-fill">
<span class="flex-40">{{ 'labels.inputs.Entity' | translate }}:</span>
<span class="flex-60">{{ checkerInboxDetail.entityName }}</span>
</div>
@if (checkerInboxDetail.resourceId) {
<div class="flex-fill">
<span class="flex-40">{{ 'labels.inputs.Resource ID' | translate }}:</span>
<span class="flex-60">{{ checkerInboxDetail.resourceId }}</span>
</div>
}
<div class="flex-fill">
<span class="flex-40">{{ 'labels.inputs.Date' | translate }}:</span>
<span class="flex-60">{{ checkerInboxDetail.madeOnDate | dateFormat }}</span>
</div>
@if (checkerInboxDetail.officeName) {
<div class="flex-fill">
<span class="flex-40">{{ 'labels.inputs.Office' | translate }}:</span>
<span class="flex-60">{{ checkerInboxDetail.officeName }}</span>
</div>
}
@if (checkerInboxDetail.savingsAccountNo) {
<div class="flex-fill">
<span class="flex-40">{{ 'labels.inputs.Savings Account Number' | translate }}:</span>
<span class="flex-60">{{ checkerInboxDetail.savingsAccountNo }}</span>
</div>
}
@if (checkerInboxDetail.groupLevelName) {
<div class="flex-fill">
<span class="flex-40"> {{ checkerInboxDetail.groupLevelName }}</span>
<span class="flex-60">{{ checkerInboxDetail.groupName }}</span>
</div>
}
@if (displayJSONData) {
<h3 class="mat-h3 flex-fill">{{ 'labels.heading.Command' | translate }}</h3>
<mat-divider [inset]="true"></mat-divider>
@for (json of jsondata | keyvalue; track json) {
<div class="flex-fill">
<span class="flex-40">{{ json.key }}:</span>
<span class="flex-60">{{ json.value }}</span>
</div>
}
}
</div>
</mat-card-content>
</mat-card>
</div>
}
</div>