Conflicts resolved in: - src/app/clients/clients-view/ckyc-tab/ckyc-tab.component.html - src/app/clients/clients-view/ckyc-tab/ckyc-tab.component.ts Kept dev's CKYC architecture (upload dialog, real per-artefact endpoints) and layered feature/bugfix's fixes on top: upload file validation, missing-file badge, silent preview download, and image/PDF view button. Also includes the CKYC "Image of Client" upload-state fix and the client-change state-leak fix in the same component. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
132 lines
4.9 KiB
HTML
132 lines
4.9 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/.
|
|
-->
|
|
|
|
<h2 mat-dialog-title class="kdu-title">
|
|
<mat-icon>description</mat-icon>
|
|
Update {{ data.documentName }}
|
|
</h2>
|
|
|
|
<mat-dialog-content class="kdu-body">
|
|
<!-- Why this is being asked for, in the words the alert used. -->
|
|
@if (data.reason) {
|
|
<div class="kdu-reason">
|
|
<mat-icon>schedule</mat-icon>
|
|
<span>{{ data.reason }}</span>
|
|
</div>
|
|
}
|
|
|
|
<form [formGroup]="form" class="kdu-form">
|
|
<mat-form-field appearance="outline" class="kdu-field kdu-field--wide">
|
|
<mat-label>Document Number</mat-label>
|
|
<input matInput formControlName="documentNumber" autocomplete="off" />
|
|
@if (form.get('documentNumber')?.hasError('required') && form.get('documentNumber')?.touched) {
|
|
<mat-error>Document number is required</mat-error>
|
|
}
|
|
</mat-form-field>
|
|
|
|
<mat-form-field appearance="outline" class="kdu-field">
|
|
<mat-label>Issued On</mat-label>
|
|
<input matInput [matDatepicker]="issuePicker" formControlName="issueDate" />
|
|
<mat-datepicker-toggle matSuffix [for]="issuePicker"></mat-datepicker-toggle>
|
|
<mat-datepicker #issuePicker></mat-datepicker>
|
|
</mat-form-field>
|
|
|
|
<mat-form-field appearance="outline" class="kdu-field">
|
|
<mat-label>Valid Till</mat-label>
|
|
<input matInput [matDatepicker]="expiryPicker" formControlName="expiryDate" />
|
|
<mat-datepicker-toggle matSuffix [for]="expiryPicker"></mat-datepicker-toggle>
|
|
<mat-datepicker #expiryPicker></mat-datepicker>
|
|
<mat-hint>Blank if it does not expire</mat-hint>
|
|
</mat-form-field>
|
|
|
|
<!-- Only where the KYC record is already verified. Changing what a verified record holds is an
|
|
amendment, and the reason goes on the record with it. -->
|
|
@if (data.requiresRemarks) {
|
|
<mat-form-field appearance="outline" class="kdu-field kdu-field--wide">
|
|
<mat-label>Reason for update</mat-label>
|
|
<textarea
|
|
matInput
|
|
formControlName="remarks"
|
|
rows="2"
|
|
placeholder="e.g. Document expired — fresh copy collected from the customer"
|
|
></textarea>
|
|
<mat-hint>Recorded against the verified KYC record</mat-hint>
|
|
@if (form.get('remarks')?.hasError('required') && form.get('remarks')?.touched) {
|
|
<mat-error>A reason is required to change a verified KYC record</mat-error>
|
|
}
|
|
</mat-form-field>
|
|
}
|
|
</form>
|
|
|
|
<div class="kdu-scans">
|
|
<div class="kdu-scans__head">Scanned copy</div>
|
|
<p class="kdu-scans__hint">
|
|
Leave a side untouched to keep the scan already on file. The previous copy is kept either way.
|
|
</p>
|
|
|
|
<div class="kdu-sides">
|
|
@for (slot of slots; track slot) {
|
|
<div class="kdu-side">
|
|
<div class="kdu-side__label">
|
|
{{ slot === 'front' ? 'Front' : 'Back' }}
|
|
@if (isReplaced(slot)) {
|
|
<span class="kdu-side__new">New</span>
|
|
}
|
|
</div>
|
|
|
|
<div class="kdu-side__frame" [class.kdu-side__frame--new]="isReplaced(slot)">
|
|
@if (previewOf(slot)) {
|
|
<img [src]="previewOf(slot)" [alt]="slot === 'front' ? 'Front of document' : 'Back of document'" />
|
|
} @else if (isReplaced(slot)) {
|
|
<!-- Picked, but not an image (a PDF, say) — named rather than shown. -->
|
|
<div class="kdu-side__file">
|
|
<mat-icon>insert_drive_file</mat-icon>
|
|
<span>{{ pickedName(slot) }}</span>
|
|
</div>
|
|
} @else {
|
|
<div class="kdu-side__none">Not on file</div>
|
|
}
|
|
</div>
|
|
|
|
<div class="kdu-side__actions">
|
|
<button type="button" mat-stroked-button class="kdu-side__btn" (click)="sideInput.click()">
|
|
{{ previewOf(slot) || isReplaced(slot) ? 'Choose new scan' : 'Upload scan' }}
|
|
</button>
|
|
@if (isReplaced(slot)) {
|
|
<button
|
|
type="button"
|
|
mat-icon-button
|
|
class="kdu-side__undo"
|
|
matTooltip="Keep the scan already on file"
|
|
(click)="clearPick(slot)"
|
|
>
|
|
<mat-icon>undo</mat-icon>
|
|
</button>
|
|
}
|
|
</div>
|
|
<input #sideInput type="file" hidden accept="image/*,application/pdf" (change)="onFilePicked($event, slot)" />
|
|
</div>
|
|
}
|
|
</div>
|
|
</div>
|
|
</mat-dialog-content>
|
|
|
|
<mat-dialog-actions align="end" class="kdu-actions">
|
|
<button mat-stroked-button type="button" (click)="cancel()">Cancel</button>
|
|
<button
|
|
mat-flat-button
|
|
color="primary"
|
|
type="button"
|
|
[disabled]="form.invalid || !hasChanges"
|
|
[matTooltip]="!hasChanges ? 'Change a detail or add a scan first' : ''"
|
|
(click)="submit()"
|
|
>
|
|
Save Document
|
|
</button>
|
|
</mat-dialog-actions>
|