feat: letter-mgmt module + digital UPI/IMPS/ATM-POS reports + header redesign
letter-mgmt (new module): - Notice page: overdue loan list with filters, KPI strip, bulk actions, call disposition logging (Promise-to-Pay, Not Reachable, etc.), Speed Post dispatch dialog with consignment + post-office tracking, PDF preview + download, call-contact dialog with primary / alt / family / nominee numbers and per-contact disposition history. - Certificates: Loan Interest, Share, Balance, Form 60 (no-PAN flow), Form 15G/H (auto age-based), Hypothecation, NOC - each with shared preview dialog (six tone variants) and jsPDF generator using a common letterhead / summary-grid / signature-seal helper. digital: - IMPS module: report (P2A/P2P/Aadhaar tabs) + entry form with MMID/mobile lookup, NPCI switch resolve-to-A/C+IFSC BANL flow, sender autocomplete, hide sender field for P2P/Aadhaar, charges + 18% GST + waive checkbox, per-sender today-only history dialog. - UPI report with app-mix tab and full transaction filtering. - ATM/POS/ECOM hub with three ticket cards routing to today/status/cycle. - NEFT/RTGS entry: sender-account autocomplete, charges + GST + waive, field reorder (sender before amount), NEFT cap / RTGS floor validation, History button opening per-sender today's transactions. - NEFT/RTGS report: horizontal-bar trend leaderboard replacing tall bars. shell + theme: - Header redesigned with IBM Plex Sans 12/500 typography, 11-column grid per row, top-accent hover indicator, bordered cells via grid-gap. - Live KPI ticker below menu (CASH, TXN TODAY, CLEARING IN/OUT, NPA, CASA, CD RATIO, RBI CIRC, REPO) with marquee scroll, pause-on-hover, brand-blue gradient, amber bottom strip, pulsing red LIVE chip. - Sidebar 'KYC Management' -> 'KYC & ReKYC Management'. - Letter Mgmt / certificate menu items wired with green icon hints for items that have a working page. access-control: - MFA card layout compacted; method header inlines back button + title. icons: - Register faTruck/TruckFast, faEllipsisV/H, faCommentDots. - Add IBM Plex Sans Google Fonts import to index.html. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 4.7
parent
4322f37c6d
commit
325228c514
+57
-36
@@ -6,41 +6,62 @@
|
||||
file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
-->
|
||||
|
||||
<div class="container">
|
||||
<mat-card>
|
||||
<form [formGroup]="activateClientForm" (ngSubmit)="submit()">
|
||||
<mat-card-content>
|
||||
<div class="layout-column">
|
||||
<mat-form-field (click)="activationDatePicker.open()">
|
||||
<mat-label>{{ 'labels.inputs.Activated On Date' | translate }}</mat-label>
|
||||
<input
|
||||
matInput
|
||||
[min]="minDate"
|
||||
[max]="maxDate"
|
||||
[matDatepicker]="activationDatePicker"
|
||||
required
|
||||
formControlName="activationDate"
|
||||
/>
|
||||
<mat-datepicker-toggle matSuffix [for]="activationDatePicker"></mat-datepicker-toggle>
|
||||
<mat-datepicker #activationDatePicker></mat-datepicker>
|
||||
@if (activateClientForm.controls.activationDate.hasError('required')) {
|
||||
<mat-error>
|
||||
{{ 'labels.inputs.Activated On Date' | translate }} {{ 'labels.commons.is' | translate }}
|
||||
<strong>{{ 'labels.commons.required' | translate }}</strong>
|
||||
</mat-error>
|
||||
}
|
||||
</mat-form-field>
|
||||
</div>
|
||||
</mat-card-content>
|
||||
<div class="ca-root">
|
||||
<!-- HERO -->
|
||||
<div class="ca-hero">
|
||||
<div class="ca-hero-icon"><fa-icon icon="check-circle"></fa-icon></div>
|
||||
<div class="ca-hero-text">
|
||||
<div class="ca-hero-eyebrow">Client Action</div>
|
||||
<h2 class="ca-hero-title">{{ 'labels.heading.Activate Client' | translate }}</h2>
|
||||
<p class="ca-hero-sub">
|
||||
Activating moves this client from <strong>Pending</strong> to <strong>Active</strong>. Once active, the client
|
||||
can hold accounts, take loans and transact normally.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<mat-card-actions class="layout-row align-center gap-5px responsive-column">
|
||||
<button type="button" mat-raised-button [routerLink]="['../../']">
|
||||
{{ 'labels.buttons.Cancel' | translate }}
|
||||
</button>
|
||||
<button mat-raised-button color="primary" [disabled]="!activateClientForm.valid">
|
||||
{{ 'labels.buttons.Confirm' | translate }}
|
||||
</button>
|
||||
</mat-card-actions>
|
||||
</form>
|
||||
</mat-card>
|
||||
<form [formGroup]="activateClientForm" (ngSubmit)="submit()" class="ca-card">
|
||||
<div class="ca-card-body">
|
||||
<div class="ca-form-row">
|
||||
<mat-form-field appearance="outline" (click)="activationDatePicker.open()">
|
||||
<mat-label>{{ 'labels.inputs.Activated On Date' | translate }}</mat-label>
|
||||
<input
|
||||
matInput
|
||||
[min]="minDate"
|
||||
[max]="maxDate"
|
||||
[matDatepicker]="activationDatePicker"
|
||||
required
|
||||
formControlName="activationDate"
|
||||
/>
|
||||
<mat-datepicker-toggle matSuffix [for]="activationDatePicker"></mat-datepicker-toggle>
|
||||
<mat-datepicker #activationDatePicker></mat-datepicker>
|
||||
@if (activateClientForm.controls.activationDate.hasError('required')) {
|
||||
<mat-error>
|
||||
{{ 'labels.inputs.Activated On Date' | translate }} {{ 'labels.commons.is' | translate }}
|
||||
<strong>{{ 'labels.commons.required' | translate }}</strong>
|
||||
</mat-error>
|
||||
}
|
||||
</mat-form-field>
|
||||
</div>
|
||||
|
||||
<div class="ca-notice">
|
||||
<fa-icon icon="info-circle"></fa-icon>
|
||||
<span>
|
||||
The activation date must be on or before today's business date. After confirmation, account opening and
|
||||
onboarding workflows are unlocked for this client.
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="ca-actions">
|
||||
<button type="button" class="ca-btn ca-btn--cancel" [routerLink]="['../../']">
|
||||
<fa-icon icon="times"></fa-icon>
|
||||
<span>{{ 'labels.buttons.Cancel' | translate }}</span>
|
||||
</button>
|
||||
<button type="submit" class="ca-btn ca-btn--confirm" [disabled]="!activateClientForm.valid">
|
||||
<fa-icon icon="check"></fa-icon>
|
||||
<span>{{ 'labels.buttons.Confirm' | translate }}</span>
|
||||
</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
+8
-2
@@ -6,6 +6,12 @@
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
.container {
|
||||
max-width: 30rem;
|
||||
@use 'assets/styles/client-action' as ca;
|
||||
|
||||
@include ca.client-action-styles;
|
||||
|
||||
/* Activate-specific green accent (success / go) */
|
||||
:host {
|
||||
--ca-accent: #15803d;
|
||||
--ca-accent-l: #dcfce7;
|
||||
}
|
||||
|
||||
+3
-1
@@ -15,6 +15,7 @@ import { ActivatedRoute, Router, RouterLink } from '@angular/router';
|
||||
import { ClientsService } from 'app/clients/clients.service';
|
||||
import { Dates } from 'app/core/utils/dates';
|
||||
import { SettingsService } from 'app/settings/settings.service';
|
||||
import { FaIconComponent } from '@fortawesome/angular-fontawesome';
|
||||
import { STANDALONE_SHARED_IMPORTS } from 'app/standalone-shared.module';
|
||||
|
||||
/**
|
||||
@@ -25,7 +26,8 @@ import { STANDALONE_SHARED_IMPORTS } from 'app/standalone-shared.module';
|
||||
templateUrl: './activate-client.component.html',
|
||||
styleUrls: ['./activate-client.component.scss'],
|
||||
imports: [
|
||||
...STANDALONE_SHARED_IMPORTS
|
||||
...STANDALONE_SHARED_IMPORTS,
|
||||
FaIconComponent
|
||||
]
|
||||
})
|
||||
export class ActivateClientComponent implements OnInit {
|
||||
|
||||
+139
-110
@@ -6,121 +6,150 @@
|
||||
file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
-->
|
||||
|
||||
<div class="container">
|
||||
<mat-card>
|
||||
<form [formGroup]="clientChargeForm" (ngSubmit)="submit()">
|
||||
<mat-card-content>
|
||||
<div class="layout-column">
|
||||
<mat-form-field>
|
||||
<mat-label>{{ 'labels.inputs.Charge' | translate }}</mat-label>
|
||||
<mat-select required formControlName="chargeId">
|
||||
@for (clientCharge of clientChargeOptions; track clientCharge) {
|
||||
<mat-option [value]="clientCharge.id">
|
||||
{{ clientCharge.name + ' (' + clientCharge.currency.name + ')' }}
|
||||
</mat-option>
|
||||
}
|
||||
</mat-select>
|
||||
@if (clientChargeForm.controls.chargeId.hasError('required')) {
|
||||
<div class="ca-root">
|
||||
<div class="ca-hero">
|
||||
<div class="ca-hero-icon"><fa-icon icon="receipt"></fa-icon></div>
|
||||
<div class="ca-hero-text">
|
||||
<div class="ca-hero-eyebrow">Client Action</div>
|
||||
<h2 class="ca-hero-title">{{ 'labels.buttons.Add Charge' | translate }}</h2>
|
||||
<p class="ca-hero-sub">
|
||||
Attach a one-time fee or a recurring charge to this client. The charge can be linked to a specific account or
|
||||
held at the client level for ad-hoc collection.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<form [formGroup]="clientChargeForm" (ngSubmit)="submit()" class="ca-card">
|
||||
<div class="ca-card-body">
|
||||
<div class="ca-form-row">
|
||||
<mat-form-field appearance="outline">
|
||||
<mat-label>{{ 'labels.inputs.Charge' | translate }}</mat-label>
|
||||
<mat-select required formControlName="chargeId">
|
||||
@for (clientCharge of clientChargeOptions; track clientCharge) {
|
||||
<mat-option [value]="clientCharge.id">{{
|
||||
clientCharge.name + ' (' + clientCharge.currency.name + ')'
|
||||
}}</mat-option>
|
||||
}
|
||||
</mat-select>
|
||||
@if (clientChargeForm.controls.chargeId.hasError('required')) {
|
||||
<mat-error>
|
||||
{{ 'labels.inputs.Charge' | translate }} {{ 'labels.commons.is' | translate }}
|
||||
<strong>{{ 'labels.commons.required' | translate }}</strong>
|
||||
</mat-error>
|
||||
}
|
||||
</mat-form-field>
|
||||
</div>
|
||||
|
||||
@if (chargeDetails) {
|
||||
<div class="ca-form-row">
|
||||
<mat-form-field appearance="outline">
|
||||
<mat-label>{{ 'labels.inputs.Amount' | translate }}</mat-label>
|
||||
<input type="number" required matInput formControlName="amount" />
|
||||
@if (clientChargeForm.controls.amount.hasError('required')) {
|
||||
<mat-error>
|
||||
{{ 'labels.inputs.Charge' | translate }} {{ 'labels.commons.is' | translate }}
|
||||
{{ 'labels.inputs.Amount' | translate }} {{ 'labels.commons.is' | translate }}
|
||||
<strong>{{ 'labels.commons.required' | translate }}</strong>
|
||||
</mat-error>
|
||||
}
|
||||
</mat-form-field>
|
||||
|
||||
@if (chargeDetails) {
|
||||
<div class="layout-column">
|
||||
<mat-form-field>
|
||||
<mat-label>{{ 'labels.inputs.Amount' | translate }}</mat-label>
|
||||
<input type="number" required matInput formControlName="amount" />
|
||||
@if (clientChargeForm.controls.amount.hasError('required')) {
|
||||
<mat-error>
|
||||
{{ 'labels.inputs.Amount' | translate }} {{ 'labels.commons.is' | translate }}
|
||||
<strong>{{ 'labels.commons.required' | translate }}</strong>
|
||||
</mat-error>
|
||||
}
|
||||
</mat-form-field>
|
||||
<mat-form-field>
|
||||
<mat-label>{{ 'labels.inputs.Charge Calculation' | translate }}</mat-label>
|
||||
<mat-select formControlName="chargeCalculationType">
|
||||
@for (chargeCalculation of chargeDetails.chargeCalculationTypeOptions; track chargeCalculation) {
|
||||
<mat-option [value]="chargeCalculation.id">
|
||||
{{ chargeCalculation.value }}
|
||||
</mat-option>
|
||||
}
|
||||
</mat-select>
|
||||
</mat-form-field>
|
||||
<mat-form-field>
|
||||
<mat-label>{{ 'labels.inputs.Charge time type' | translate }}</mat-label>
|
||||
<mat-select formControlName="chargeTimeType">
|
||||
@for (chargeTime of chargeDetails.chargeTimeTypeOptions; track chargeTime) {
|
||||
<mat-option [value]="chargeTime.id">
|
||||
{{ chargeTime.value }}
|
||||
</mat-option>
|
||||
}
|
||||
</mat-select>
|
||||
</mat-form-field>
|
||||
@if (clientChargeForm.contains('dueDate')) {
|
||||
<mat-form-field (click)="dueDatePicker.open()">
|
||||
<mat-label>{{ 'labels.inputs.Due for collection on' | translate }}</mat-label>
|
||||
<input
|
||||
matInput
|
||||
[min]="minDate"
|
||||
[max]="maxDate"
|
||||
[matDatepicker]="dueDatePicker"
|
||||
required
|
||||
formControlName="dueDate"
|
||||
/>
|
||||
<mat-datepicker-toggle matSuffix [for]="dueDatePicker"></mat-datepicker-toggle>
|
||||
<mat-datepicker #dueDatePicker></mat-datepicker>
|
||||
@if (clientChargeForm.controls.dueDate.hasError('required')) {
|
||||
<mat-error>
|
||||
{{ 'labels.inputs.Due for collection on' | translate }} {{ 'labels.commons.is' | translate }}
|
||||
<strong>{{ 'labels.commons.required' | translate }}</strong>
|
||||
</mat-error>
|
||||
}
|
||||
</mat-form-field>
|
||||
}
|
||||
@if (clientChargeForm.contains('feeOnMonthDay')) {
|
||||
<mat-form-field (click)="feeOnMonthDayPicker.open()">
|
||||
<mat-label>{{ 'labels.inputs.Due On' | translate }}</mat-label>
|
||||
<input
|
||||
matInput
|
||||
[min]="minDate"
|
||||
[max]="maxDate"
|
||||
[matDatepicker]="feeOnMonthDayPicker"
|
||||
required
|
||||
formControlName="feeOnMonthDay"
|
||||
/>
|
||||
<mat-datepicker-toggle matSuffix [for]="feeOnMonthDayPicker"></mat-datepicker-toggle>
|
||||
<mat-datepicker #feeOnMonthDayPicker></mat-datepicker>
|
||||
@if (clientChargeForm.controls.feeOnMonthDay.hasError('required')) {
|
||||
<mat-error>
|
||||
{{ 'labels.inputs.Due Date' | translate }} {{ 'labels.commons.is' | translate }}
|
||||
<strong>{{ 'labels.commons.required' | translate }}</strong>
|
||||
</mat-error>
|
||||
}
|
||||
</mat-form-field>
|
||||
}
|
||||
@if (clientChargeForm.contains('feeInterval')) {
|
||||
<mat-form-field>
|
||||
<mat-label>{{ 'labels.inputs.Repeats Every' | translate }}</mat-label>
|
||||
<input matInput formControlName="feeInterval" />
|
||||
</mat-form-field>
|
||||
}
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
|
||||
<mat-card-actions class="layout-row layout-xs-column layout-align-center gap-5px">
|
||||
<button type="button" mat-raised-button [routerLink]="['../../']">
|
||||
{{ 'labels.buttons.Cancel' | translate }}
|
||||
</button>
|
||||
<button mat-raised-button color="primary" [disabled]="!clientChargeForm.valid">
|
||||
{{ 'labels.buttons.Submit' | translate }}
|
||||
</button>
|
||||
</mat-card-actions>
|
||||
</mat-card-content>
|
||||
</form>
|
||||
</mat-card>
|
||||
<div class="ca-form-row">
|
||||
<mat-form-field appearance="outline">
|
||||
<mat-label>{{ 'labels.inputs.Charge Calculation' | translate }}</mat-label>
|
||||
<mat-select formControlName="chargeCalculationType">
|
||||
@for (chargeCalculation of chargeDetails.chargeCalculationTypeOptions; track chargeCalculation) {
|
||||
<mat-option [value]="chargeCalculation.id">{{ chargeCalculation.value }}</mat-option>
|
||||
}
|
||||
</mat-select>
|
||||
</mat-form-field>
|
||||
</div>
|
||||
|
||||
<div class="ca-form-row">
|
||||
<mat-form-field appearance="outline">
|
||||
<mat-label>{{ 'labels.inputs.Charge time type' | translate }}</mat-label>
|
||||
<mat-select formControlName="chargeTimeType">
|
||||
@for (chargeTime of chargeDetails.chargeTimeTypeOptions; track chargeTime) {
|
||||
<mat-option [value]="chargeTime.id">{{ chargeTime.value }}</mat-option>
|
||||
}
|
||||
</mat-select>
|
||||
</mat-form-field>
|
||||
</div>
|
||||
|
||||
@if (clientChargeForm.contains('dueDate')) {
|
||||
<div class="ca-form-row">
|
||||
<mat-form-field appearance="outline" (click)="dueDatePicker.open()">
|
||||
<mat-label>{{ 'labels.inputs.Due for collection on' | translate }}</mat-label>
|
||||
<input
|
||||
matInput
|
||||
[min]="minDate"
|
||||
[max]="maxDate"
|
||||
[matDatepicker]="dueDatePicker"
|
||||
required
|
||||
formControlName="dueDate"
|
||||
/>
|
||||
<mat-datepicker-toggle matSuffix [for]="dueDatePicker"></mat-datepicker-toggle>
|
||||
<mat-datepicker #dueDatePicker></mat-datepicker>
|
||||
@if (clientChargeForm.controls.dueDate.hasError('required')) {
|
||||
<mat-error>
|
||||
{{ 'labels.inputs.Due for collection on' | translate }} {{ 'labels.commons.is' | translate }}
|
||||
<strong>{{ 'labels.commons.required' | translate }}</strong>
|
||||
</mat-error>
|
||||
}
|
||||
</mat-form-field>
|
||||
</div>
|
||||
}
|
||||
|
||||
@if (clientChargeForm.contains('feeOnMonthDay')) {
|
||||
<div class="ca-form-row">
|
||||
<mat-form-field appearance="outline" (click)="feeOnMonthDayPicker.open()">
|
||||
<mat-label>{{ 'labels.inputs.Due On' | translate }}</mat-label>
|
||||
<input
|
||||
matInput
|
||||
[min]="minDate"
|
||||
[max]="maxDate"
|
||||
[matDatepicker]="feeOnMonthDayPicker"
|
||||
required
|
||||
formControlName="feeOnMonthDay"
|
||||
/>
|
||||
<mat-datepicker-toggle matSuffix [for]="feeOnMonthDayPicker"></mat-datepicker-toggle>
|
||||
<mat-datepicker #feeOnMonthDayPicker></mat-datepicker>
|
||||
@if (clientChargeForm.controls.feeOnMonthDay.hasError('required')) {
|
||||
<mat-error>
|
||||
{{ 'labels.inputs.Due Date' | translate }} {{ 'labels.commons.is' | translate }}
|
||||
<strong>{{ 'labels.commons.required' | translate }}</strong>
|
||||
</mat-error>
|
||||
}
|
||||
</mat-form-field>
|
||||
</div>
|
||||
}
|
||||
|
||||
@if (clientChargeForm.contains('feeInterval')) {
|
||||
<div class="ca-form-row">
|
||||
<mat-form-field appearance="outline">
|
||||
<mat-label>{{ 'labels.inputs.Repeats Every' | translate }}</mat-label>
|
||||
<input matInput formControlName="feeInterval" />
|
||||
</mat-form-field>
|
||||
</div>
|
||||
}
|
||||
|
||||
<div class="ca-notice">
|
||||
<fa-icon icon="info-circle"></fa-icon>
|
||||
<span>
|
||||
The calculation type and timing determine when this charge is auto-applied (e.g. monthly fee, annual
|
||||
membership, ad-hoc). Verify the amount and due date before submitting.
|
||||
</span>
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
|
||||
<div class="ca-actions">
|
||||
<button type="button" class="ca-btn ca-btn--cancel" [routerLink]="['../../']">
|
||||
<fa-icon icon="times"></fa-icon><span>{{ 'labels.buttons.Cancel' | translate }}</span>
|
||||
</button>
|
||||
<button type="submit" class="ca-btn ca-btn--confirm" [disabled]="!clientChargeForm.valid">
|
||||
<fa-icon icon="check"></fa-icon><span>{{ 'labels.buttons.Submit' | translate }}</span>
|
||||
</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
+8
-2
@@ -6,6 +6,12 @@
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
.container {
|
||||
width: 37rem;
|
||||
@use 'assets/styles/client-action' as ca;
|
||||
|
||||
@include ca.client-action-styles;
|
||||
|
||||
/* Add Charge — amber accent (financial / fee) */
|
||||
:host {
|
||||
--ca-accent: #b45309;
|
||||
--ca-accent-l: #fef3c7;
|
||||
}
|
||||
|
||||
+3
-1
@@ -21,6 +21,7 @@ import { Router, ActivatedRoute, RouterLink } from '@angular/router';
|
||||
import { ClientsService } from 'app/clients/clients.service';
|
||||
import { Dates } from 'app/core/utils/dates';
|
||||
import { SettingsService } from 'app/settings/settings.service';
|
||||
import { FaIconComponent } from '@fortawesome/angular-fontawesome';
|
||||
import { STANDALONE_SHARED_IMPORTS } from 'app/standalone-shared.module';
|
||||
|
||||
/**
|
||||
@@ -31,7 +32,8 @@ import { STANDALONE_SHARED_IMPORTS } from 'app/standalone-shared.module';
|
||||
templateUrl: './add-client-charge.component.html',
|
||||
styleUrls: ['./add-client-charge.component.scss'],
|
||||
imports: [
|
||||
...STANDALONE_SHARED_IMPORTS
|
||||
...STANDALONE_SHARED_IMPORTS,
|
||||
FaIconComponent
|
||||
]
|
||||
})
|
||||
export class AddClientChargeComponent implements OnInit {
|
||||
|
||||
+107
-70
@@ -6,81 +6,118 @@
|
||||
file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
-->
|
||||
|
||||
<div class="container">
|
||||
<mat-card>
|
||||
<form [formGroup]="clientCollateralForm" (ngSubmit)="submit()">
|
||||
<mat-card-content>
|
||||
<div class="layout-column">
|
||||
<mat-form-field>
|
||||
<mat-label>{{ 'labels.inputs.Collateral' | translate }}</mat-label>
|
||||
<mat-select required formControlName="collateralId">
|
||||
@for (clientCollateral of clientCollateralOptions; track clientCollateral) {
|
||||
<mat-option [value]="clientCollateral.id">
|
||||
{{ clientCollateral.name }}
|
||||
</mat-option>
|
||||
}
|
||||
</mat-select>
|
||||
@if (clientCollateralForm.controls.collateralId.hasError('required')) {
|
||||
<div class="ca-root">
|
||||
<div class="ca-hero">
|
||||
<div class="ca-hero-icon"><fa-icon icon="cube"></fa-icon></div>
|
||||
<div class="ca-hero-text">
|
||||
<div class="ca-hero-eyebrow">Client Action</div>
|
||||
<h2 class="ca-hero-title">{{ 'labels.buttons.Create Collateral' | translate }}</h2>
|
||||
<p class="ca-hero-sub">
|
||||
Record an asset pledged by this client as security for credit (e.g. property, vehicle, deposit). Collateral
|
||||
values feed loan eligibility and LTV calculations.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<form [formGroup]="clientCollateralForm" (ngSubmit)="submit()" class="ca-card">
|
||||
<div class="ca-card-body">
|
||||
<div class="ca-form-row">
|
||||
<mat-form-field appearance="outline">
|
||||
<mat-label>{{ 'labels.inputs.Collateral' | translate }}</mat-label>
|
||||
<mat-select required formControlName="collateralId">
|
||||
@for (clientCollateral of clientCollateralOptions; track clientCollateral) {
|
||||
<mat-option [value]="clientCollateral.id">{{ clientCollateral.name }}</mat-option>
|
||||
}
|
||||
</mat-select>
|
||||
@if (clientCollateralForm.controls.collateralId.hasError('required')) {
|
||||
<mat-error>
|
||||
{{ 'labels.inputs.Collateral' | translate }} {{ 'labels.commons.is' | translate }}
|
||||
<strong>{{ 'labels.commons.required' | translate }}</strong>
|
||||
</mat-error>
|
||||
}
|
||||
</mat-form-field>
|
||||
</div>
|
||||
|
||||
@if (collateralDetails) {
|
||||
<div class="ca-form-row">
|
||||
<mat-form-field appearance="outline">
|
||||
<mat-label>{{ 'labels.inputs.name' | translate }}</mat-label>
|
||||
<input matInput required formControlName="name" />
|
||||
</mat-form-field>
|
||||
</div>
|
||||
|
||||
<div class="ca-form-row">
|
||||
<mat-form-field appearance="outline">
|
||||
<mat-label>{{ 'labels.inputs.Type/Quality' | translate }}</mat-label>
|
||||
<input matInput required formControlName="quality" />
|
||||
</mat-form-field>
|
||||
</div>
|
||||
|
||||
<div class="ca-form-row">
|
||||
<mat-form-field appearance="outline">
|
||||
<mat-label>{{ 'labels.inputs.Unit Type' | translate }}</mat-label>
|
||||
<input matInput required formControlName="unitType" />
|
||||
</mat-form-field>
|
||||
</div>
|
||||
|
||||
<div class="ca-form-row">
|
||||
<mat-form-field appearance="outline">
|
||||
<mat-label>{{ 'labels.inputs.Base Price' | translate }}</mat-label>
|
||||
<input matInput required formControlName="basePrice" />
|
||||
</mat-form-field>
|
||||
</div>
|
||||
|
||||
<div class="ca-form-row">
|
||||
<mat-form-field appearance="outline">
|
||||
<mat-label>{{ 'labels.inputs.Percentage To Base' | translate }}</mat-label>
|
||||
<input matInput required formControlName="pctToBase" />
|
||||
</mat-form-field>
|
||||
</div>
|
||||
|
||||
<div class="ca-form-row">
|
||||
<mat-form-field appearance="outline">
|
||||
<mat-label>{{ 'labels.inputs.Quantity' | translate }}</mat-label>
|
||||
<input matInput required formControlName="quantity" />
|
||||
@if (clientCollateralForm.controls.quantity.hasError('required')) {
|
||||
<mat-error>
|
||||
{{ 'labels.inputs.Collateral' | translate }} {{ 'labels.commons.is' | translate }}
|
||||
{{ 'labels.inputs.Quantity' | translate }} {{ 'labels.commons.is' | translate }}
|
||||
<strong>{{ 'labels.commons.required' | translate }}</strong>
|
||||
</mat-error>
|
||||
}
|
||||
</mat-form-field>
|
||||
|
||||
@if (collateralDetails) {
|
||||
<div class="layout-column">
|
||||
<mat-form-field>
|
||||
<mat-label>{{ 'labels.inputs.name' | translate }}</mat-label>
|
||||
<input matInput required formControlName="name" />
|
||||
</mat-form-field>
|
||||
<mat-form-field>
|
||||
<mat-label>{{ 'labels.inputs.Type/Quality' | translate }}</mat-label>
|
||||
<input matInput required formControlName="quality" />
|
||||
</mat-form-field>
|
||||
<mat-form-field>
|
||||
<mat-label>{{ 'labels.inputs.Unit Type' | translate }}</mat-label>
|
||||
<input matInput required formControlName="unitType" />
|
||||
</mat-form-field>
|
||||
<mat-form-field>
|
||||
<mat-label>{{ 'labels.inputs.Base Price' | translate }}</mat-label>
|
||||
<input matInput required formControlName="basePrice" />
|
||||
</mat-form-field>
|
||||
<mat-form-field>
|
||||
<mat-label>{{ 'labels.inputs.Percentage To Base' | translate }}</mat-label>
|
||||
<input matInput required formControlName="pctToBase" />
|
||||
</mat-form-field>
|
||||
<mat-form-field>
|
||||
<mat-label>{{ 'labels.inputs.Quantity' | translate }}</mat-label>
|
||||
<input matInput required formControlName="quantity" />
|
||||
@if (clientCollateralForm.controls.quantity.hasError('required')) {
|
||||
<mat-error>
|
||||
{{ 'labels.inputs.Quantity' | translate }} {{ 'labels.commons.is' | translate }}
|
||||
<strong>{{ 'labels.commons.required' | translate }}</strong>
|
||||
</mat-error>
|
||||
}
|
||||
</mat-form-field>
|
||||
<mat-form-field>
|
||||
<mat-label>{{ 'labels.inputs.Total' | translate }}</mat-label>
|
||||
<input matInput required formControlName="totalValue" />
|
||||
</mat-form-field>
|
||||
<mat-form-field>
|
||||
<mat-label>{{ 'labels.inputs.Total Collateral Value' | translate }}</mat-label>
|
||||
<input matInput required formControlName="totalCollateralValue" />
|
||||
</mat-form-field>
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
</mat-card-content>
|
||||
|
||||
<mat-card-actions class="layout-row layout-xs-column layout-align-center gap-5px">
|
||||
<button type="button" mat-raised-button [routerLink]="['../../']">
|
||||
{{ 'labels.buttons.Cancel' | translate }}
|
||||
</button>
|
||||
<button mat-raised-button color="primary" [disabled]="!clientCollateralForm.valid">
|
||||
{{ 'labels.buttons.Submit' | translate }}
|
||||
</button>
|
||||
</mat-card-actions>
|
||||
</form>
|
||||
</mat-card>
|
||||
<div class="ca-form-row">
|
||||
<mat-form-field appearance="outline">
|
||||
<mat-label>{{ 'labels.inputs.Total' | translate }}</mat-label>
|
||||
<input matInput required formControlName="totalValue" />
|
||||
</mat-form-field>
|
||||
</div>
|
||||
|
||||
<div class="ca-form-row">
|
||||
<mat-form-field appearance="outline">
|
||||
<mat-label>{{ 'labels.inputs.Total Collateral Value' | translate }}</mat-label>
|
||||
<input matInput required formControlName="totalCollateralValue" />
|
||||
</mat-form-field>
|
||||
</div>
|
||||
|
||||
<div class="ca-notice">
|
||||
<fa-icon icon="info-circle"></fa-icon>
|
||||
<span>
|
||||
Total Collateral Value = Base Price × Percentage-to-Base × Quantity. Verify the figures before submitting —
|
||||
this is used by underwriting and LTV checks.
|
||||
</span>
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
|
||||
<div class="ca-actions">
|
||||
<button type="button" class="ca-btn ca-btn--cancel" [routerLink]="['../../']">
|
||||
<fa-icon icon="times"></fa-icon><span>{{ 'labels.buttons.Cancel' | translate }}</span>
|
||||
</button>
|
||||
<button type="submit" class="ca-btn ca-btn--confirm" [disabled]="!clientCollateralForm.valid">
|
||||
<fa-icon icon="check"></fa-icon><span>{{ 'labels.buttons.Submit' | translate }}</span>
|
||||
</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
+8
-2
@@ -6,6 +6,12 @@
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
.container {
|
||||
width: 37rem;
|
||||
@use 'assets/styles/client-action' as ca;
|
||||
|
||||
@include ca.client-action-styles;
|
||||
|
||||
/* Create Collateral — purple accent (asset / security) */
|
||||
:host {
|
||||
--ca-accent: #6d28d9;
|
||||
--ca-accent-l: #ede9fe;
|
||||
}
|
||||
|
||||
+3
-1
@@ -17,6 +17,7 @@ import { ActivatedRoute, Router, RouterLink } from '@angular/router';
|
||||
import { ClientsService } from 'app/clients/clients.service';
|
||||
import { ProductsService } from 'app/products/products.service';
|
||||
import { SettingsService } from 'app/settings/settings.service';
|
||||
import { FaIconComponent } from '@fortawesome/angular-fontawesome';
|
||||
import { STANDALONE_SHARED_IMPORTS } from 'app/standalone-shared.module';
|
||||
|
||||
@Component({
|
||||
@@ -24,7 +25,8 @@ import { STANDALONE_SHARED_IMPORTS } from 'app/standalone-shared.module';
|
||||
templateUrl: './add-client-collateral.component.html',
|
||||
styleUrls: ['./add-client-collateral.component.scss'],
|
||||
imports: [
|
||||
...STANDALONE_SHARED_IMPORTS
|
||||
...STANDALONE_SHARED_IMPORTS,
|
||||
FaIconComponent
|
||||
]
|
||||
})
|
||||
export class AddClientCollateralComponent implements OnInit {
|
||||
|
||||
+62
-43
@@ -6,53 +6,72 @@
|
||||
file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
-->
|
||||
|
||||
<div class="container m-b-20">
|
||||
<mat-card>
|
||||
<form [formGroup]="clientScreenReportForm" (ngSubmit)="generate()">
|
||||
<mat-card-content>
|
||||
<div>
|
||||
<mat-form-field class="flex-fill">
|
||||
<mat-label>{{ 'labels.inputs.Client Screen Reports' | translate }}</mat-label>
|
||||
<mat-select formControlName="templateId">
|
||||
@for (template of templatesData; track template) {
|
||||
<mat-option [value]="template.id">
|
||||
{{ template.name }}
|
||||
</mat-option>
|
||||
}
|
||||
</mat-select>
|
||||
@if (clientScreenReportForm.controls.templateId.hasError('required')) {
|
||||
<mat-error>
|
||||
{{ 'labels.inputs.Screen Report' | translate }} {{ 'labels.commons.is' | translate }}
|
||||
<strong>{{ 'labels.commons.required' | translate }}</strong>
|
||||
</mat-error>
|
||||
<div class="ca-root ca-root--wide">
|
||||
<div class="ca-hero">
|
||||
<div class="ca-hero-icon"><fa-icon icon="chart-bar"></fa-icon></div>
|
||||
<div class="ca-hero-text">
|
||||
<div class="ca-hero-eyebrow">Client Action</div>
|
||||
<h2 class="ca-hero-title">{{ 'labels.buttons.Client Screen Reports' | translate }}</h2>
|
||||
<p class="ca-hero-sub">
|
||||
Generate an on-screen client report from one of the configured templates. The rendered output is printable and
|
||||
can be saved as PDF from the browser print dialog.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<form [formGroup]="clientScreenReportForm" (ngSubmit)="generate()" class="ca-card">
|
||||
<div class="ca-card-body">
|
||||
<div class="ca-form-row">
|
||||
<mat-form-field appearance="outline">
|
||||
<mat-label>{{ 'labels.inputs.Client Screen Reports' | translate }}</mat-label>
|
||||
<mat-select formControlName="templateId">
|
||||
@for (template of templatesData; track template) {
|
||||
<mat-option [value]="template.id">{{ template.name }}</mat-option>
|
||||
}
|
||||
</mat-form-field>
|
||||
</div>
|
||||
</mat-card-content>
|
||||
</mat-select>
|
||||
@if (clientScreenReportForm.controls.templateId.hasError('required')) {
|
||||
<mat-error>
|
||||
{{ 'labels.inputs.Screen Report' | translate }} {{ 'labels.commons.is' | translate }}
|
||||
<strong>{{ 'labels.commons.required' | translate }}</strong>
|
||||
</mat-error>
|
||||
}
|
||||
</mat-form-field>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<mat-card-actions class="layout-row align-center gap-5px actions-spacing responsive-column">
|
||||
<button type="button" mat-raised-button [routerLink]="['../../']">
|
||||
{{ 'labels.buttons.Cancel' | translate }}
|
||||
</button>
|
||||
<button mat-raised-button color="primary" [disabled]="!clientScreenReportForm.valid">
|
||||
<fa-icon icon="cogs" size="sm" class="m-r-10"></fa-icon>{{ 'labels.buttons.Generate Report' | translate }}
|
||||
</button>
|
||||
</mat-card-actions>
|
||||
</form>
|
||||
</mat-card>
|
||||
</div>
|
||||
|
||||
<div #output class="container m-t-20">
|
||||
<mat-card class="layout-column gap-3percent">
|
||||
<div class="layout-align-end">
|
||||
<button mat-raised-button color="primary" [disabled]="!template" (click)="print()">
|
||||
<fa-icon icon="file" class="m-r-10"></fa-icon>
|
||||
{{ 'labels.buttons.Print' | translate }}
|
||||
<div class="ca-actions">
|
||||
<button type="button" class="ca-btn ca-btn--cancel" [routerLink]="['../../']">
|
||||
<fa-icon icon="times"></fa-icon><span>{{ 'labels.buttons.Cancel' | translate }}</span>
|
||||
</button>
|
||||
<button type="submit" class="ca-btn ca-btn--confirm" [disabled]="!clientScreenReportForm.valid">
|
||||
<fa-icon icon="cogs"></fa-icon><span>{{ 'labels.buttons.Generate Report' | translate }}</span>
|
||||
</button>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
<div #screenReport class="layout-align-center">
|
||||
<p>{{ 'labels.text.Please select a screen report.' | translate }}</p>
|
||||
<div #output class="ca-card">
|
||||
<div class="ca-card-body">
|
||||
<div class="csr-output-head">
|
||||
<div>
|
||||
<div class="csr-output-eyebrow">Report Output</div>
|
||||
<div class="csr-output-title">
|
||||
{{ template ? template.name : ('labels.text.Please select a screen report.' | translate) }}
|
||||
</div>
|
||||
</div>
|
||||
<button type="button" class="ca-btn ca-btn--confirm" [disabled]="!template" (click)="print()">
|
||||
<fa-icon icon="file"></fa-icon>
|
||||
<span>{{ 'labels.buttons.Print' | translate }}</span>
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<div #screenReport class="csr-output-body">
|
||||
@if (!template) {
|
||||
<div class="csr-empty">
|
||||
<div class="csr-empty-ic"><fa-icon icon="chart-bar"></fa-icon></div>
|
||||
<p>{{ 'labels.text.Please select a screen report.' | translate }}</p>
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
</mat-card>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
+68
-21
@@ -6,32 +6,79 @@
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
.container {
|
||||
max-width: 37rem;
|
||||
@use 'assets/styles/client-action' as ca;
|
||||
|
||||
.print {
|
||||
align-self: flex-end;
|
||||
}
|
||||
@include ca.client-action-styles;
|
||||
|
||||
/* Screen Reports — indigo accent (analytics / reporting) */
|
||||
:host {
|
||||
--ca-accent: #3730a3;
|
||||
--ca-accent-l: #e0e7ff;
|
||||
}
|
||||
|
||||
::ng-deep mat-card {
|
||||
margin-bottom: 1rem;
|
||||
padding: 1rem;
|
||||
box-shadow: 0 2px 4px rgb(0 0 0 / 10%);
|
||||
border: 1px solid var(--border-color, #ddd);
|
||||
border-radius: 8px;
|
||||
background-color: var(--card-background, #fff);
|
||||
transition:
|
||||
background-color 0.3s ease,
|
||||
border-color 0.3s ease;
|
||||
/* Wider container for the report output */
|
||||
.ca-root--wide {
|
||||
max-width: 1100px;
|
||||
}
|
||||
|
||||
::ng-deep .container.m-t-20 mat-card p {
|
||||
display: block;
|
||||
margin-top: -1.9rem;
|
||||
/* Report output header inside the second card */
|
||||
.csr-output-head {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
gap: 16px;
|
||||
padding-bottom: 14px;
|
||||
margin-bottom: 14px;
|
||||
border-bottom: 1px dashed var(--ca-g200);
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
|
||||
.actions-spacing {
|
||||
margin-top: 1rem;
|
||||
padding: 0 1rem;
|
||||
.csr-output-eyebrow {
|
||||
font-size: 10.5px;
|
||||
font-weight: 700;
|
||||
text-transform: uppercase;
|
||||
letter-spacing: 0.06em;
|
||||
color: var(--ca-g500);
|
||||
margin-bottom: 2px;
|
||||
}
|
||||
|
||||
.csr-output-title {
|
||||
font-size: 15px;
|
||||
font-weight: 700;
|
||||
color: var(--ca-g900);
|
||||
}
|
||||
|
||||
.csr-output-body {
|
||||
background: var(--ca-g50);
|
||||
border: 1px solid var(--ca-g200);
|
||||
border-radius: 10px;
|
||||
padding: 18px;
|
||||
min-height: 140px;
|
||||
font-size: 13px;
|
||||
color: var(--ca-g900);
|
||||
overflow-x: auto;
|
||||
}
|
||||
|
||||
.csr-empty {
|
||||
text-align: center;
|
||||
padding: 28px 16px;
|
||||
}
|
||||
|
||||
.csr-empty-ic {
|
||||
width: 52px;
|
||||
height: 52px;
|
||||
margin: 0 auto 10px;
|
||||
border-radius: 14px;
|
||||
background: var(--ca-accent-l);
|
||||
color: var(--ca-accent);
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
font-size: 22px;
|
||||
}
|
||||
|
||||
.csr-empty p {
|
||||
margin: 0;
|
||||
font-size: 13px;
|
||||
color: var(--ca-g500);
|
||||
}
|
||||
|
||||
+73
-52
@@ -6,58 +6,79 @@
|
||||
file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
-->
|
||||
|
||||
<div class="container">
|
||||
<mat-card>
|
||||
<form [formGroup]="closeClientForm" (ngSubmit)="submit()">
|
||||
<mat-card-content>
|
||||
<div class="layout-column">
|
||||
<mat-form-field (click)="closureDatePicker.open()">
|
||||
<mat-label>{{ 'labels.inputs.Closed On Date' | translate }}</mat-label>
|
||||
<input
|
||||
matInput
|
||||
[min]="minDate"
|
||||
[max]="maxDate"
|
||||
[matDatepicker]="closureDatePicker"
|
||||
required
|
||||
formControlName="closureDate"
|
||||
/>
|
||||
<mat-datepicker-toggle matSuffix [for]="closureDatePicker"></mat-datepicker-toggle>
|
||||
<mat-datepicker #closureDatePicker></mat-datepicker>
|
||||
@if (closeClientForm.controls.closureDate.hasError('required')) {
|
||||
<mat-error>
|
||||
{{ 'labels.inputs.Closed On Date' | translate }} {{ 'labels.commons.is' | translate }}
|
||||
<strong>{{ 'labels.commons.required' | translate }}</strong>
|
||||
</mat-error>
|
||||
}
|
||||
</mat-form-field>
|
||||
<div class="ca-root">
|
||||
<!-- HERO -->
|
||||
<div class="ca-hero">
|
||||
<div class="ca-hero-icon"><fa-icon icon="times-circle"></fa-icon></div>
|
||||
<div class="ca-hero-text">
|
||||
<div class="ca-hero-eyebrow">Client Action</div>
|
||||
<h2 class="ca-hero-title">{{ 'labels.heading.Close Client' | translate }}</h2>
|
||||
<p class="ca-hero-sub">
|
||||
Closing the client moves them to a <strong>Closed</strong> state. Outstanding loans or active savings must be
|
||||
settled or transferred before closure is permitted.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<mat-form-field class="flex-48">
|
||||
<mat-label>{{ 'labels.inputs.Closure Reason' | translate }}</mat-label>
|
||||
<mat-select formControlName="closureReasonId">
|
||||
@for (reason of closureData; track reason) {
|
||||
<mat-option [value]="reason.id">
|
||||
{{ reason.name }}
|
||||
</mat-option>
|
||||
}
|
||||
</mat-select>
|
||||
@if (closeClientForm.controls.closureReasonId.hasError('required')) {
|
||||
<mat-error>
|
||||
{{ 'labels.inputs.Closure Reason' | translate }} {{ 'labels.commons.is' | translate }}
|
||||
<strong>{{ 'labels.commons.required' | translate }}</strong>
|
||||
</mat-error>
|
||||
}
|
||||
</mat-form-field>
|
||||
</div>
|
||||
</mat-card-content>
|
||||
<form [formGroup]="closeClientForm" (ngSubmit)="submit()" class="ca-card">
|
||||
<div class="ca-card-body">
|
||||
<div class="ca-form-row">
|
||||
<mat-form-field appearance="outline" (click)="closureDatePicker.open()">
|
||||
<mat-label>{{ 'labels.inputs.Closed On Date' | translate }}</mat-label>
|
||||
<input
|
||||
matInput
|
||||
[min]="minDate"
|
||||
[max]="maxDate"
|
||||
[matDatepicker]="closureDatePicker"
|
||||
required
|
||||
formControlName="closureDate"
|
||||
/>
|
||||
<mat-datepicker-toggle matSuffix [for]="closureDatePicker"></mat-datepicker-toggle>
|
||||
<mat-datepicker #closureDatePicker></mat-datepicker>
|
||||
@if (closeClientForm.controls.closureDate.hasError('required')) {
|
||||
<mat-error>
|
||||
{{ 'labels.inputs.Closed On Date' | translate }} {{ 'labels.commons.is' | translate }}
|
||||
<strong>{{ 'labels.commons.required' | translate }}</strong>
|
||||
</mat-error>
|
||||
}
|
||||
</mat-form-field>
|
||||
</div>
|
||||
|
||||
<mat-card-actions class="layout-row align-center gap-5px responsive-column">
|
||||
<button type="button" mat-raised-button [routerLink]="['../../']">
|
||||
{{ 'labels.buttons.Cancel' | translate }}
|
||||
</button>
|
||||
<button mat-raised-button color="warn" [disabled]="!closeClientForm.valid">
|
||||
{{ 'labels.buttons.Confirm' | translate }}
|
||||
</button>
|
||||
</mat-card-actions>
|
||||
</form>
|
||||
</mat-card>
|
||||
<div class="ca-form-row">
|
||||
<mat-form-field appearance="outline">
|
||||
<mat-label>{{ 'labels.inputs.Closure Reason' | translate }}</mat-label>
|
||||
<mat-select formControlName="closureReasonId">
|
||||
@for (reason of closureData; track reason) {
|
||||
<mat-option [value]="reason.id">{{ reason.name }}</mat-option>
|
||||
}
|
||||
</mat-select>
|
||||
@if (closeClientForm.controls.closureReasonId.hasError('required')) {
|
||||
<mat-error>
|
||||
{{ 'labels.inputs.Closure Reason' | translate }} {{ 'labels.commons.is' | translate }}
|
||||
<strong>{{ 'labels.commons.required' | translate }}</strong>
|
||||
</mat-error>
|
||||
}
|
||||
</mat-form-field>
|
||||
</div>
|
||||
|
||||
<div class="ca-notice">
|
||||
<fa-icon icon="exclamation-triangle"></fa-icon>
|
||||
<span>
|
||||
This action is <strong>irreversible</strong>. Once closed, the client cannot transact or open new accounts.
|
||||
Use <em>Reactivate</em> only if the closure was made in error.
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="ca-actions">
|
||||
<button type="button" class="ca-btn ca-btn--cancel" [routerLink]="['../../']">
|
||||
<fa-icon icon="times"></fa-icon>
|
||||
<span>{{ 'labels.buttons.Cancel' | translate }}</span>
|
||||
</button>
|
||||
<button type="submit" class="ca-btn ca-btn--confirm" [disabled]="!closeClientForm.valid">
|
||||
<fa-icon icon="check"></fa-icon>
|
||||
<span>{{ 'labels.buttons.Confirm' | translate }}</span>
|
||||
</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
+8
-2
@@ -6,6 +6,12 @@
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
.container {
|
||||
max-width: 37rem;
|
||||
@use 'assets/styles/client-action' as ca;
|
||||
|
||||
@include ca.client-action-styles;
|
||||
|
||||
/* Close-specific red accent (destructive) */
|
||||
:host {
|
||||
--ca-accent: #c0392b;
|
||||
--ca-accent-l: #fee2e2;
|
||||
}
|
||||
|
||||
@@ -15,6 +15,7 @@ import { ActivatedRoute, Router, RouterLink } from '@angular/router';
|
||||
import { ClientsService } from 'app/clients/clients.service';
|
||||
import { Dates } from 'app/core/utils/dates';
|
||||
import { SettingsService } from 'app/settings/settings.service';
|
||||
import { FaIconComponent } from '@fortawesome/angular-fontawesome';
|
||||
import { STANDALONE_SHARED_IMPORTS } from 'app/standalone-shared.module';
|
||||
|
||||
/**
|
||||
@@ -25,7 +26,8 @@ import { STANDALONE_SHARED_IMPORTS } from 'app/standalone-shared.module';
|
||||
templateUrl: './close-client.component.html',
|
||||
styleUrls: ['./close-client.component.scss'],
|
||||
imports: [
|
||||
...STANDALONE_SHARED_IMPORTS
|
||||
...STANDALONE_SHARED_IMPORTS,
|
||||
FaIconComponent
|
||||
]
|
||||
})
|
||||
export class CloseClientComponent implements OnInit {
|
||||
|
||||
+36
-16
@@ -6,11 +6,23 @@
|
||||
file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
-->
|
||||
|
||||
<div class="container">
|
||||
<mat-card>
|
||||
<form [formGroup]="reactivateClientForm" (ngSubmit)="submit()">
|
||||
<mat-card-content>
|
||||
<mat-form-field class="flex-fill" (click)="reactivationDatePicker.open()">
|
||||
<div class="ca-root">
|
||||
<div class="ca-hero">
|
||||
<div class="ca-hero-icon"><fa-icon icon="redo"></fa-icon></div>
|
||||
<div class="ca-hero-text">
|
||||
<div class="ca-hero-eyebrow">Client Action</div>
|
||||
<h2 class="ca-hero-title">{{ 'labels.heading.Reactivate Client' | translate }}</h2>
|
||||
<p class="ca-hero-sub">
|
||||
Bring a previously <strong>Closed</strong> client back to <strong>Active</strong>. After reactivation the client
|
||||
may transact and open accounts again.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<form [formGroup]="reactivateClientForm" (ngSubmit)="submit()" class="ca-card">
|
||||
<div class="ca-card-body">
|
||||
<div class="ca-form-row">
|
||||
<mat-form-field appearance="outline" (click)="reactivationDatePicker.open()">
|
||||
<mat-label>{{ 'labels.inputs.Re Activation On Date' | translate }}</mat-label>
|
||||
<input
|
||||
matInput
|
||||
@@ -29,16 +41,24 @@
|
||||
</mat-error>
|
||||
}
|
||||
</mat-form-field>
|
||||
</mat-card-content>
|
||||
</div>
|
||||
|
||||
<mat-card-actions class="layout-row align-center gap-5px responsive-column">
|
||||
<button type="button" mat-raised-button [routerLink]="['../../']">
|
||||
{{ 'labels.buttons.Cancel' | translate }}
|
||||
</button>
|
||||
<button mat-raised-button color="primary" [disabled]="!reactivateClientForm.valid">
|
||||
{{ 'labels.buttons.Confirm' | translate }}
|
||||
</button>
|
||||
</mat-card-actions>
|
||||
</form>
|
||||
</mat-card>
|
||||
<div class="ca-notice">
|
||||
<fa-icon icon="info-circle"></fa-icon>
|
||||
<span>
|
||||
Reactivation re-opens the client record. Closed loans and savings stay closed; new accounts can now be
|
||||
created.
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="ca-actions">
|
||||
<button type="button" class="ca-btn ca-btn--cancel" [routerLink]="['../../']">
|
||||
<fa-icon icon="times"></fa-icon><span>{{ 'labels.buttons.Cancel' | translate }}</span>
|
||||
</button>
|
||||
<button type="submit" class="ca-btn ca-btn--confirm" [disabled]="!reactivateClientForm.valid">
|
||||
<fa-icon icon="check"></fa-icon><span>{{ 'labels.buttons.Confirm' | translate }}</span>
|
||||
</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
+8
-2
@@ -6,6 +6,12 @@
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
.container {
|
||||
max-width: 37rem;
|
||||
@use 'assets/styles/client-action' as ca;
|
||||
|
||||
@include ca.client-action-styles;
|
||||
|
||||
/* Reactivate-specific green accent */
|
||||
:host {
|
||||
--ca-accent: #15803d;
|
||||
--ca-accent-l: #dcfce7;
|
||||
}
|
||||
|
||||
+3
-1
@@ -15,6 +15,7 @@ import { ActivatedRoute, Router, RouterLink } from '@angular/router';
|
||||
import { ClientsService } from 'app/clients/clients.service';
|
||||
import { Dates } from 'app/core/utils/dates';
|
||||
import { SettingsService } from 'app/settings/settings.service';
|
||||
import { FaIconComponent } from '@fortawesome/angular-fontawesome';
|
||||
import { STANDALONE_SHARED_IMPORTS } from 'app/standalone-shared.module';
|
||||
|
||||
/**
|
||||
@@ -25,7 +26,8 @@ import { STANDALONE_SHARED_IMPORTS } from 'app/standalone-shared.module';
|
||||
templateUrl: './reactivate-client.component.html',
|
||||
styleUrls: ['./reactivate-client.component.scss'],
|
||||
imports: [
|
||||
...STANDALONE_SHARED_IMPORTS
|
||||
...STANDALONE_SHARED_IMPORTS,
|
||||
FaIconComponent
|
||||
]
|
||||
})
|
||||
export class ReactivateClientComponent implements OnInit {
|
||||
|
||||
+73
-52
@@ -6,58 +6,79 @@
|
||||
file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
-->
|
||||
|
||||
<div class="container">
|
||||
<mat-card>
|
||||
<form [formGroup]="rejectClientForm" (ngSubmit)="submit()">
|
||||
<mat-card-content>
|
||||
<div class="layout-column">
|
||||
<mat-form-field (click)="rejectionDatePicker.open()">
|
||||
<mat-label>{{ 'labels.inputs.Rejection Date' | translate }}</mat-label>
|
||||
<input
|
||||
matInput
|
||||
[min]="minDate"
|
||||
[max]="maxDate"
|
||||
[matDatepicker]="rejectionDatePicker"
|
||||
required
|
||||
formControlName="rejectionDate"
|
||||
/>
|
||||
<mat-datepicker-toggle matSuffix [for]="rejectionDatePicker"></mat-datepicker-toggle>
|
||||
<mat-datepicker #rejectionDatePicker></mat-datepicker>
|
||||
@if (rejectClientForm.controls.rejectionDate.hasError('required')) {
|
||||
<mat-error>
|
||||
{{ 'labels.inputs.Rejection Date' | translate }} {{ 'labels.commons.is' | translate }}
|
||||
<strong>{{ 'labels.commons.required' | translate }}</strong>
|
||||
</mat-error>
|
||||
}
|
||||
</mat-form-field>
|
||||
<div class="ca-root">
|
||||
<!-- HERO -->
|
||||
<div class="ca-hero">
|
||||
<div class="ca-hero-icon"><fa-icon icon="ban"></fa-icon></div>
|
||||
<div class="ca-hero-text">
|
||||
<div class="ca-hero-eyebrow">Client Action</div>
|
||||
<h2 class="ca-hero-title">{{ 'labels.heading.Reject Client' | translate }}</h2>
|
||||
<p class="ca-hero-sub">
|
||||
Reject this client application when onboarding cannot be approved (e.g. failed KYC, regulatory hit, document
|
||||
mismatch). The reason is recorded for audit and compliance.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<mat-form-field class="flex-48">
|
||||
<mat-label>{{ 'labels.inputs.Rejection Reason' | translate }}</mat-label>
|
||||
<mat-select formControlName="rejectionReasonId">
|
||||
@for (reason of rejectionData; track reason) {
|
||||
<mat-option [value]="reason.id">
|
||||
{{ reason.name }}
|
||||
</mat-option>
|
||||
}
|
||||
</mat-select>
|
||||
@if (rejectClientForm.controls.rejectionReasonId.hasError('required')) {
|
||||
<mat-error>
|
||||
{{ 'labels.inputs.Rejection Reason' | translate }} {{ 'labels.commons.is' | translate }}
|
||||
<strong>{{ 'labels.commons.required' | translate }}</strong>
|
||||
</mat-error>
|
||||
}
|
||||
</mat-form-field>
|
||||
</div>
|
||||
</mat-card-content>
|
||||
<form [formGroup]="rejectClientForm" (ngSubmit)="submit()" class="ca-card">
|
||||
<div class="ca-card-body">
|
||||
<div class="ca-form-row">
|
||||
<mat-form-field appearance="outline" (click)="rejectionDatePicker.open()">
|
||||
<mat-label>{{ 'labels.inputs.Rejection Date' | translate }}</mat-label>
|
||||
<input
|
||||
matInput
|
||||
[min]="minDate"
|
||||
[max]="maxDate"
|
||||
[matDatepicker]="rejectionDatePicker"
|
||||
required
|
||||
formControlName="rejectionDate"
|
||||
/>
|
||||
<mat-datepicker-toggle matSuffix [for]="rejectionDatePicker"></mat-datepicker-toggle>
|
||||
<mat-datepicker #rejectionDatePicker></mat-datepicker>
|
||||
@if (rejectClientForm.controls.rejectionDate.hasError('required')) {
|
||||
<mat-error>
|
||||
{{ 'labels.inputs.Rejection Date' | translate }} {{ 'labels.commons.is' | translate }}
|
||||
<strong>{{ 'labels.commons.required' | translate }}</strong>
|
||||
</mat-error>
|
||||
}
|
||||
</mat-form-field>
|
||||
</div>
|
||||
|
||||
<mat-card-actions class="layout-row align-center gap-5px responsive-column">
|
||||
<button type="button" mat-raised-button [routerLink]="['../../']">
|
||||
{{ 'labels.buttons.Cancel' | translate }}
|
||||
</button>
|
||||
<button mat-raised-button color="warn" [disabled]="!rejectClientForm.valid">
|
||||
{{ 'labels.buttons.Confirm' | translate }}
|
||||
</button>
|
||||
</mat-card-actions>
|
||||
</form>
|
||||
</mat-card>
|
||||
<div class="ca-form-row">
|
||||
<mat-form-field appearance="outline">
|
||||
<mat-label>{{ 'labels.inputs.Rejection Reason' | translate }}</mat-label>
|
||||
<mat-select formControlName="rejectionReasonId">
|
||||
@for (reason of rejectionData; track reason) {
|
||||
<mat-option [value]="reason.id">{{ reason.name }}</mat-option>
|
||||
}
|
||||
</mat-select>
|
||||
@if (rejectClientForm.controls.rejectionReasonId.hasError('required')) {
|
||||
<mat-error>
|
||||
{{ 'labels.inputs.Rejection Reason' | translate }} {{ 'labels.commons.is' | translate }}
|
||||
<strong>{{ 'labels.commons.required' | translate }}</strong>
|
||||
</mat-error>
|
||||
}
|
||||
</mat-form-field>
|
||||
</div>
|
||||
|
||||
<div class="ca-notice">
|
||||
<fa-icon icon="exclamation-triangle"></fa-icon>
|
||||
<span>
|
||||
Rejection moves the client to a <strong>Rejected</strong> state and is final. Use <em>Undo Rejection</em> if
|
||||
the decision was made in error.
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="ca-actions">
|
||||
<button type="button" class="ca-btn ca-btn--cancel" [routerLink]="['../../']">
|
||||
<fa-icon icon="times"></fa-icon>
|
||||
<span>{{ 'labels.buttons.Cancel' | translate }}</span>
|
||||
</button>
|
||||
<button type="submit" class="ca-btn ca-btn--confirm" [disabled]="!rejectClientForm.valid">
|
||||
<fa-icon icon="check"></fa-icon>
|
||||
<span>{{ 'labels.buttons.Confirm' | translate }}</span>
|
||||
</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
+8
-2
@@ -6,6 +6,12 @@
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
.container {
|
||||
max-width: 37rem;
|
||||
@use 'assets/styles/client-action' as ca;
|
||||
|
||||
@include ca.client-action-styles;
|
||||
|
||||
/* Reject-specific red accent (final / blocked) */
|
||||
:host {
|
||||
--ca-accent: #c0392b;
|
||||
--ca-accent-l: #fee2e2;
|
||||
}
|
||||
|
||||
+3
-1
@@ -15,6 +15,7 @@ import { ActivatedRoute, Router, RouterLink } from '@angular/router';
|
||||
import { ClientsService } from 'app/clients/clients.service';
|
||||
import { Dates } from 'app/core/utils/dates';
|
||||
import { SettingsService } from 'app/settings/settings.service';
|
||||
import { FaIconComponent } from '@fortawesome/angular-fontawesome';
|
||||
import { STANDALONE_SHARED_IMPORTS } from 'app/standalone-shared.module';
|
||||
|
||||
/**
|
||||
@@ -25,7 +26,8 @@ import { STANDALONE_SHARED_IMPORTS } from 'app/standalone-shared.module';
|
||||
templateUrl: './reject-client.component.html',
|
||||
styleUrls: ['./reject-client.component.scss'],
|
||||
imports: [
|
||||
...STANDALONE_SHARED_IMPORTS
|
||||
...STANDALONE_SHARED_IMPORTS,
|
||||
FaIconComponent
|
||||
]
|
||||
})
|
||||
export class RejectClientComponent implements OnInit {
|
||||
|
||||
+84
-55
@@ -6,63 +6,92 @@
|
||||
file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
-->
|
||||
|
||||
<div class="container">
|
||||
<mat-card>
|
||||
<form [formGroup]="transferClientForm" (ngSubmit)="submit()">
|
||||
<mat-card-content>
|
||||
<div class="layout-column">
|
||||
<mat-form-field>
|
||||
<mat-label>{{ 'labels.inputs.Office' | translate }}</mat-label>
|
||||
<mat-select required formControlName="destinationOfficeId">
|
||||
@for (office of officeData; track office) {
|
||||
<mat-option [value]="office.id">
|
||||
{{ office.name }}
|
||||
</mat-option>
|
||||
}
|
||||
</mat-select>
|
||||
@if (transferClientForm.controls.destinationOfficeId.hasError('required')) {
|
||||
<mat-error>
|
||||
{{ 'labels.inputs.Office' | translate }} {{ 'labels.commons.is' | translate }}
|
||||
<strong>{{ 'labels.commons.required' | translate }}</strong>
|
||||
</mat-error>
|
||||
<div class="ca-root">
|
||||
<!-- HERO -->
|
||||
<div class="ca-hero">
|
||||
<div class="ca-hero-icon"><fa-icon icon="exchange"></fa-icon></div>
|
||||
<div class="ca-hero-text">
|
||||
<div class="ca-hero-eyebrow">Client Action</div>
|
||||
<h2 class="ca-hero-title">{{ 'labels.heading.Transfer Client' | translate }}</h2>
|
||||
<p class="ca-hero-sub">
|
||||
Move this client to a different office or branch. The destination office will need to
|
||||
<strong>accept</strong> the proposed transfer before it takes effect. The client's accounts move with them.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<form [formGroup]="transferClientForm" (ngSubmit)="submit()" class="ca-card">
|
||||
<div class="ca-card-body">
|
||||
<div class="ca-form-row">
|
||||
<mat-form-field appearance="outline">
|
||||
<mat-label>{{ 'labels.inputs.Office' | translate }}</mat-label>
|
||||
<mat-select required formControlName="destinationOfficeId">
|
||||
@for (office of officeData; track office) {
|
||||
<mat-option [value]="office.id">{{ office.name }}</mat-option>
|
||||
}
|
||||
</mat-form-field>
|
||||
</mat-select>
|
||||
@if (transferClientForm.controls.destinationOfficeId.hasError('required')) {
|
||||
<mat-error>
|
||||
{{ 'labels.inputs.Office' | translate }} {{ 'labels.commons.is' | translate }}
|
||||
<strong>{{ 'labels.commons.required' | translate }}</strong>
|
||||
</mat-error>
|
||||
}
|
||||
</mat-form-field>
|
||||
</div>
|
||||
|
||||
<mat-form-field (click)="transferDatePicker.open()">
|
||||
<mat-label>{{ 'labels.inputs.Transfer Date' | translate }}</mat-label>
|
||||
<input
|
||||
matInput
|
||||
[min]="minDate"
|
||||
[max]="maxDate"
|
||||
[matDatepicker]="transferDatePicker"
|
||||
required
|
||||
formControlName="transferDate"
|
||||
/>
|
||||
<mat-datepicker-toggle matSuffix [for]="transferDatePicker"></mat-datepicker-toggle>
|
||||
<mat-datepicker #transferDatePicker></mat-datepicker>
|
||||
@if (transferClientForm.controls.transferDate.hasError('required')) {
|
||||
<mat-error>
|
||||
{{ 'labels.inputs.Transfer Date' | translate }} {{ 'labels.commons.is' | translate }}
|
||||
<strong>{{ 'labels.commons.required' | translate }}</strong>
|
||||
</mat-error>
|
||||
}
|
||||
</mat-form-field>
|
||||
<div class="ca-form-row">
|
||||
<mat-form-field appearance="outline" (click)="transferDatePicker.open()">
|
||||
<mat-label>{{ 'labels.inputs.Transfer Date' | translate }}</mat-label>
|
||||
<input
|
||||
matInput
|
||||
[min]="minDate"
|
||||
[max]="maxDate"
|
||||
[matDatepicker]="transferDatePicker"
|
||||
required
|
||||
formControlName="transferDate"
|
||||
/>
|
||||
<mat-datepicker-toggle matSuffix [for]="transferDatePicker"></mat-datepicker-toggle>
|
||||
<mat-datepicker #transferDatePicker></mat-datepicker>
|
||||
@if (transferClientForm.controls.transferDate.hasError('required')) {
|
||||
<mat-error>
|
||||
{{ 'labels.inputs.Transfer Date' | translate }} {{ 'labels.commons.is' | translate }}
|
||||
<strong>{{ 'labels.commons.required' | translate }}</strong>
|
||||
</mat-error>
|
||||
}
|
||||
</mat-form-field>
|
||||
</div>
|
||||
|
||||
<mat-form-field>
|
||||
<mat-label>{{ 'labels.inputs.Note' | translate }}</mat-label>
|
||||
<textarea matInput formControlName="note" cdkTextareaAutosize cdkAutosizeMinRows="2"></textarea>
|
||||
</mat-form-field>
|
||||
</div>
|
||||
</mat-card-content>
|
||||
<div class="ca-form-row">
|
||||
<mat-form-field appearance="outline">
|
||||
<mat-label>{{ 'labels.inputs.Note' | translate }}</mat-label>
|
||||
<textarea
|
||||
matInput
|
||||
formControlName="note"
|
||||
cdkTextareaAutosize
|
||||
cdkAutosizeMinRows="2"
|
||||
placeholder="Optional — reason or context for the transfer"
|
||||
></textarea>
|
||||
</mat-form-field>
|
||||
</div>
|
||||
|
||||
<mat-card-actions class="layout-row align-center gap-5px responsive-column">
|
||||
<button type="button" mat-raised-button [routerLink]="['../../']">
|
||||
{{ 'labels.buttons.Cancel' | translate }}
|
||||
</button>
|
||||
<button mat-raised-button color="primary" [disabled]="!transferClientForm.valid">
|
||||
{{ 'labels.buttons.Confirm' | translate }}
|
||||
</button>
|
||||
</mat-card-actions>
|
||||
</form>
|
||||
</mat-card>
|
||||
<div class="ca-notice">
|
||||
<fa-icon icon="info-circle"></fa-icon>
|
||||
<span>
|
||||
The transfer is created as <strong>proposed</strong> until the destination office accepts it. Until then it
|
||||
can be withdrawn from the client's <em>Actions → Undo Transfer</em> menu.
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="ca-actions">
|
||||
<button type="button" class="ca-btn ca-btn--cancel" [routerLink]="['../../']">
|
||||
<fa-icon icon="times"></fa-icon>
|
||||
<span>{{ 'labels.buttons.Cancel' | translate }}</span>
|
||||
</button>
|
||||
<button type="submit" class="ca-btn ca-btn--confirm" [disabled]="!transferClientForm.valid">
|
||||
<fa-icon icon="paper-plane"></fa-icon>
|
||||
<span>{{ 'labels.buttons.Confirm' | translate }}</span>
|
||||
</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
+8
-2
@@ -6,6 +6,12 @@
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
.container {
|
||||
max-width: 37rem;
|
||||
@use 'assets/styles/client-action' as ca;
|
||||
|
||||
@include ca.client-action-styles;
|
||||
|
||||
/* Transfer-specific blue accent (informational / routing) */
|
||||
:host {
|
||||
--ca-accent: #1d4ed8;
|
||||
--ca-accent-l: #eff6ff;
|
||||
}
|
||||
|
||||
+3
-1
@@ -16,6 +16,7 @@ import { ClientsService } from 'app/clients/clients.service';
|
||||
import { Dates } from 'app/core/utils/dates';
|
||||
import { SettingsService } from 'app/settings/settings.service';
|
||||
import { CdkTextareaAutosize } from '@angular/cdk/text-field';
|
||||
import { FaIconComponent } from '@fortawesome/angular-fontawesome';
|
||||
import { STANDALONE_SHARED_IMPORTS } from 'app/standalone-shared.module';
|
||||
|
||||
/**
|
||||
@@ -27,7 +28,8 @@ import { STANDALONE_SHARED_IMPORTS } from 'app/standalone-shared.module';
|
||||
styleUrls: ['./transfer-client.component.scss'],
|
||||
imports: [
|
||||
...STANDALONE_SHARED_IMPORTS,
|
||||
CdkTextareaAutosize
|
||||
CdkTextareaAutosize,
|
||||
FaIconComponent
|
||||
]
|
||||
})
|
||||
export class TransferClientComponent implements OnInit {
|
||||
|
||||
+35
-16
@@ -6,11 +6,22 @@
|
||||
file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
-->
|
||||
|
||||
<div class="container">
|
||||
<mat-card>
|
||||
<form [formGroup]="undoClientRejectionForm" (ngSubmit)="submit()">
|
||||
<mat-card-content>
|
||||
<mat-form-field class="flex-fill" (click)="reopenedDatePicker.open()">
|
||||
<div class="ca-root">
|
||||
<div class="ca-hero">
|
||||
<div class="ca-hero-icon"><fa-icon icon="undo"></fa-icon></div>
|
||||
<div class="ca-hero-text">
|
||||
<div class="ca-hero-eyebrow">Client Action</div>
|
||||
<h2 class="ca-hero-title">{{ 'labels.heading.Undo Client Rejection' | translate }}</h2>
|
||||
<p class="ca-hero-sub">
|
||||
Reverse a prior rejection and re-open this client back to the <strong>Pending</strong> state for further review.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<form [formGroup]="undoClientRejectionForm" (ngSubmit)="submit()" class="ca-card">
|
||||
<div class="ca-card-body">
|
||||
<div class="ca-form-row">
|
||||
<mat-form-field appearance="outline" (click)="reopenedDatePicker.open()">
|
||||
<mat-label>{{ 'labels.inputs.Reopened On Date' | translate }}</mat-label>
|
||||
<input
|
||||
matInput
|
||||
@@ -29,16 +40,24 @@
|
||||
</mat-error>
|
||||
}
|
||||
</mat-form-field>
|
||||
</mat-card-content>
|
||||
</div>
|
||||
|
||||
<mat-card-actions class="layout-row align-center gap-5px responsive-column">
|
||||
<button type="button" mat-raised-button [routerLink]="['../../']">
|
||||
{{ 'labels.buttons.Cancel' | translate }}
|
||||
</button>
|
||||
<button mat-raised-button color="primary" [disabled]="!undoClientRejectionForm.valid">
|
||||
{{ 'labels.buttons.Confirm' | translate }}
|
||||
</button>
|
||||
</mat-card-actions>
|
||||
</form>
|
||||
</mat-card>
|
||||
<div class="ca-notice">
|
||||
<fa-icon icon="info-circle"></fa-icon>
|
||||
<span
|
||||
>The client returns to <strong>Pending</strong> — you can then activate, withdraw or re-reject as
|
||||
appropriate.</span
|
||||
>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="ca-actions">
|
||||
<button type="button" class="ca-btn ca-btn--cancel" [routerLink]="['../../']">
|
||||
<fa-icon icon="times"></fa-icon><span>{{ 'labels.buttons.Cancel' | translate }}</span>
|
||||
</button>
|
||||
<button type="submit" class="ca-btn ca-btn--confirm" [disabled]="!undoClientRejectionForm.valid">
|
||||
<fa-icon icon="check"></fa-icon><span>{{ 'labels.buttons.Confirm' | translate }}</span>
|
||||
</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
+3
-1
@@ -15,6 +15,7 @@ import { ActivatedRoute, Router, RouterLink } from '@angular/router';
|
||||
import { ClientsService } from 'app/clients/clients.service';
|
||||
import { Dates } from 'app/core/utils/dates';
|
||||
import { SettingsService } from 'app/settings/settings.service';
|
||||
import { FaIconComponent } from '@fortawesome/angular-fontawesome';
|
||||
import { STANDALONE_SHARED_IMPORTS } from 'app/standalone-shared.module';
|
||||
|
||||
/**
|
||||
@@ -25,7 +26,8 @@ import { STANDALONE_SHARED_IMPORTS } from 'app/standalone-shared.module';
|
||||
templateUrl: './undo-client-rejection.component.html',
|
||||
styleUrls: ['./undo-client-rejection.component.scss'],
|
||||
imports: [
|
||||
...STANDALONE_SHARED_IMPORTS
|
||||
...STANDALONE_SHARED_IMPORTS,
|
||||
FaIconComponent
|
||||
]
|
||||
})
|
||||
export class UndoClientRejectionComponent implements OnInit {
|
||||
|
||||
+49
-33
@@ -6,38 +6,54 @@
|
||||
file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
-->
|
||||
|
||||
<div class="container">
|
||||
<mat-card>
|
||||
<form [formGroup]="clientSavingsAccountForm" (ngSubmit)="submit()">
|
||||
<mat-card-content>
|
||||
<div class="layout-column">
|
||||
<mat-form-field class="flex-48">
|
||||
<mat-label>{{ 'labels.inputs.Default Savings Account' | translate }}</mat-label>
|
||||
<mat-select formControlName="savingsAccountId">
|
||||
@for (account of savingsAccounts; track account) {
|
||||
<mat-option [value]="account.id">
|
||||
{{ account.accountNo }}
|
||||
</mat-option>
|
||||
}
|
||||
</mat-select>
|
||||
@if (clientSavingsAccountForm.controls.savingsAccountId.hasError('required')) {
|
||||
<mat-error>
|
||||
{{ 'labels.inputs.Account' | translate }} {{ 'labels.commons.is' | translate }}
|
||||
<strong>{{ 'labels.commons.required' | translate }}</strong>
|
||||
</mat-error>
|
||||
}
|
||||
</mat-form-field>
|
||||
</div>
|
||||
</mat-card-content>
|
||||
<div class="ca-root">
|
||||
<div class="ca-hero">
|
||||
<div class="ca-hero-icon"><fa-icon icon="piggy-bank"></fa-icon></div>
|
||||
<div class="ca-hero-text">
|
||||
<div class="ca-hero-eyebrow">Client Action</div>
|
||||
<h2 class="ca-hero-title">{{ 'labels.buttons.Update Default Savings' | translate }}</h2>
|
||||
<p class="ca-hero-sub">
|
||||
Pick which savings account is the <strong>default</strong> for this client. Auto-debit instructions, fee
|
||||
collections and loan disbursals will use this account unless explicitly overridden.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<mat-card-actions class="layout-row align-center gap-5px responsive-column">
|
||||
<button type="button" mat-raised-button [routerLink]="['../../']">
|
||||
{{ 'labels.buttons.Cancel' | translate }}
|
||||
</button>
|
||||
<button mat-raised-button color="primary" [disabled]="!clientSavingsAccountForm.valid">
|
||||
{{ 'labels.buttons.Confirm' | translate }}
|
||||
</button>
|
||||
</mat-card-actions>
|
||||
</form>
|
||||
</mat-card>
|
||||
<form [formGroup]="clientSavingsAccountForm" (ngSubmit)="submit()" class="ca-card">
|
||||
<div class="ca-card-body">
|
||||
<div class="ca-form-row">
|
||||
<mat-form-field appearance="outline">
|
||||
<mat-label>{{ 'labels.inputs.Default Savings Account' | translate }}</mat-label>
|
||||
<mat-select formControlName="savingsAccountId">
|
||||
@for (account of savingsAccounts; track account) {
|
||||
<mat-option [value]="account.id">{{ account.accountNo }}</mat-option>
|
||||
}
|
||||
</mat-select>
|
||||
@if (clientSavingsAccountForm.controls.savingsAccountId.hasError('required')) {
|
||||
<mat-error>
|
||||
{{ 'labels.inputs.Account' | translate }} {{ 'labels.commons.is' | translate }}
|
||||
<strong>{{ 'labels.commons.required' | translate }}</strong>
|
||||
</mat-error>
|
||||
}
|
||||
</mat-form-field>
|
||||
</div>
|
||||
|
||||
<div class="ca-notice">
|
||||
<fa-icon icon="info-circle"></fa-icon>
|
||||
<span>
|
||||
Changing the default does not move any existing balances or scheduled instructions — it only affects
|
||||
<strong>new</strong> debits/credits that look up the client's default account.
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="ca-actions">
|
||||
<button type="button" class="ca-btn ca-btn--cancel" [routerLink]="['../../']">
|
||||
<fa-icon icon="times"></fa-icon><span>{{ 'labels.buttons.Cancel' | translate }}</span>
|
||||
</button>
|
||||
<button type="submit" class="ca-btn ca-btn--confirm" [disabled]="!clientSavingsAccountForm.valid">
|
||||
<fa-icon icon="check"></fa-icon><span>{{ 'labels.buttons.Confirm' | translate }}</span>
|
||||
</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
+8
-2
@@ -6,6 +6,12 @@
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
.container {
|
||||
max-width: 37rem;
|
||||
@use 'assets/styles/client-action' as ca;
|
||||
|
||||
@include ca.client-action-styles;
|
||||
|
||||
/* Update Default Savings — teal accent */
|
||||
:host {
|
||||
--ca-accent: #0e7e6b;
|
||||
--ca-accent-l: #ccfbf1;
|
||||
}
|
||||
|
||||
+3
-1
@@ -13,6 +13,7 @@ import { ActivatedRoute, Router, RouterLink } from '@angular/router';
|
||||
|
||||
/** Custom Services */
|
||||
import { ClientsService } from 'app/clients/clients.service';
|
||||
import { FaIconComponent } from '@fortawesome/angular-fontawesome';
|
||||
import { STANDALONE_SHARED_IMPORTS } from 'app/standalone-shared.module';
|
||||
|
||||
/**
|
||||
@@ -23,7 +24,8 @@ import { STANDALONE_SHARED_IMPORTS } from 'app/standalone-shared.module';
|
||||
templateUrl: './update-client-savings-account.component.html',
|
||||
styleUrls: ['./update-client-savings-account.component.scss'],
|
||||
imports: [
|
||||
...STANDALONE_SHARED_IMPORTS
|
||||
...STANDALONE_SHARED_IMPORTS,
|
||||
FaIconComponent
|
||||
]
|
||||
})
|
||||
export class UpdateClientSavingsAccountComponent implements OnInit {
|
||||
|
||||
+73
-52
@@ -6,58 +6,79 @@
|
||||
file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
-->
|
||||
|
||||
<div class="container">
|
||||
<mat-card>
|
||||
<form [formGroup]="withdrawClientForm" (ngSubmit)="submit()">
|
||||
<mat-card-content>
|
||||
<div class="layout-column">
|
||||
<mat-form-field (click)="withdrawalDatePicker.open()">
|
||||
<mat-label>{{ 'labels.inputs.Withdrawal Date' | translate }}</mat-label>
|
||||
<input
|
||||
matInput
|
||||
[min]="minDate"
|
||||
[max]="maxDate"
|
||||
[matDatepicker]="withdrawalDatePicker"
|
||||
required
|
||||
formControlName="withdrawalDate"
|
||||
/>
|
||||
<mat-datepicker-toggle matSuffix [for]="withdrawalDatePicker"></mat-datepicker-toggle>
|
||||
<mat-datepicker #withdrawalDatePicker></mat-datepicker>
|
||||
@if (withdrawClientForm.controls.withdrawalDate.hasError('required')) {
|
||||
<mat-error>
|
||||
{{ 'labels.inputs.Withdrawal Date' | translate }} {{ 'labels.commons.is' | translate }}
|
||||
<strong>{{ 'labels.commons.required' | translate }}</strong>
|
||||
</mat-error>
|
||||
}
|
||||
</mat-form-field>
|
||||
<div class="ca-root">
|
||||
<!-- HERO -->
|
||||
<div class="ca-hero">
|
||||
<div class="ca-hero-icon"><fa-icon icon="undo"></fa-icon></div>
|
||||
<div class="ca-hero-text">
|
||||
<div class="ca-hero-eyebrow">Client Action</div>
|
||||
<h2 class="ca-hero-title">{{ 'labels.heading.Withdraw Client' | translate }}</h2>
|
||||
<p class="ca-hero-sub">
|
||||
Withdraw a <strong>Pending</strong> client when onboarding will not proceed (e.g. customer changed their mind).
|
||||
The record is preserved with a withdrawn status and can be re-opened later if needed.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<mat-form-field class="flex-48">
|
||||
<mat-label>{{ 'labels.inputs.Withdrawal Reason' | translate }}</mat-label>
|
||||
<mat-select formControlName="withdrawalReasonId">
|
||||
@for (reason of withdrawalData; track reason) {
|
||||
<mat-option [value]="reason.id">
|
||||
{{ reason.name }}
|
||||
</mat-option>
|
||||
}
|
||||
</mat-select>
|
||||
@if (withdrawClientForm.controls.withdrawalReasonId.hasError('required')) {
|
||||
<mat-error>
|
||||
{{ 'labels.inputs.Withdrawal Reason' | translate }} {{ 'labels.commons.is' | translate }}
|
||||
<strong>{{ 'labels.commons.required' | translate }}</strong>
|
||||
</mat-error>
|
||||
}
|
||||
</mat-form-field>
|
||||
</div>
|
||||
</mat-card-content>
|
||||
<form [formGroup]="withdrawClientForm" (ngSubmit)="submit()" class="ca-card">
|
||||
<div class="ca-card-body">
|
||||
<div class="ca-form-row">
|
||||
<mat-form-field appearance="outline" (click)="withdrawalDatePicker.open()">
|
||||
<mat-label>{{ 'labels.inputs.Withdrawal Date' | translate }}</mat-label>
|
||||
<input
|
||||
matInput
|
||||
[min]="minDate"
|
||||
[max]="maxDate"
|
||||
[matDatepicker]="withdrawalDatePicker"
|
||||
required
|
||||
formControlName="withdrawalDate"
|
||||
/>
|
||||
<mat-datepicker-toggle matSuffix [for]="withdrawalDatePicker"></mat-datepicker-toggle>
|
||||
<mat-datepicker #withdrawalDatePicker></mat-datepicker>
|
||||
@if (withdrawClientForm.controls.withdrawalDate.hasError('required')) {
|
||||
<mat-error>
|
||||
{{ 'labels.inputs.Withdrawal Date' | translate }} {{ 'labels.commons.is' | translate }}
|
||||
<strong>{{ 'labels.commons.required' | translate }}</strong>
|
||||
</mat-error>
|
||||
}
|
||||
</mat-form-field>
|
||||
</div>
|
||||
|
||||
<mat-card-actions class="layout-row align-center gap-5px responsive-column">
|
||||
<button type="button" mat-raised-button [routerLink]="['../../']">
|
||||
{{ 'labels.buttons.Cancel' | translate }}
|
||||
</button>
|
||||
<button mat-raised-button color="primary" [disabled]="!withdrawClientForm.valid">
|
||||
{{ 'labels.buttons.Confirm' | translate }}
|
||||
</button>
|
||||
</mat-card-actions>
|
||||
</form>
|
||||
</mat-card>
|
||||
<div class="ca-form-row">
|
||||
<mat-form-field appearance="outline">
|
||||
<mat-label>{{ 'labels.inputs.Withdrawal Reason' | translate }}</mat-label>
|
||||
<mat-select formControlName="withdrawalReasonId">
|
||||
@for (reason of withdrawalData; track reason) {
|
||||
<mat-option [value]="reason.id">{{ reason.name }}</mat-option>
|
||||
}
|
||||
</mat-select>
|
||||
@if (withdrawClientForm.controls.withdrawalReasonId.hasError('required')) {
|
||||
<mat-error>
|
||||
{{ 'labels.inputs.Withdrawal Reason' | translate }} {{ 'labels.commons.is' | translate }}
|
||||
<strong>{{ 'labels.commons.required' | translate }}</strong>
|
||||
</mat-error>
|
||||
}
|
||||
</mat-form-field>
|
||||
</div>
|
||||
|
||||
<div class="ca-notice">
|
||||
<fa-icon icon="info-circle"></fa-icon>
|
||||
<span>
|
||||
A reason is required for audit. The client record is retained and can be reactivated later via the
|
||||
<strong>Undo Withdrawal</strong> action.
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="ca-actions">
|
||||
<button type="button" class="ca-btn ca-btn--cancel" [routerLink]="['../../']">
|
||||
<fa-icon icon="times"></fa-icon>
|
||||
<span>{{ 'labels.buttons.Cancel' | translate }}</span>
|
||||
</button>
|
||||
<button type="submit" class="ca-btn ca-btn--confirm" [disabled]="!withdrawClientForm.valid">
|
||||
<fa-icon icon="check"></fa-icon>
|
||||
<span>{{ 'labels.buttons.Confirm' | translate }}</span>
|
||||
</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
+8
-2
@@ -6,6 +6,12 @@
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
.container {
|
||||
max-width: 37rem;
|
||||
@use 'assets/styles/client-action' as ca;
|
||||
|
||||
@include ca.client-action-styles;
|
||||
|
||||
/* Withdraw-specific amber accent (caution / pause) */
|
||||
:host {
|
||||
--ca-accent: #b45309;
|
||||
--ca-accent-l: #fef3c7;
|
||||
}
|
||||
|
||||
+3
-1
@@ -15,6 +15,7 @@ import { ActivatedRoute, Router, RouterLink } from '@angular/router';
|
||||
import { ClientsService } from 'app/clients/clients.service';
|
||||
import { Dates } from 'app/core/utils/dates';
|
||||
import { SettingsService } from 'app/settings/settings.service';
|
||||
import { FaIconComponent } from '@fortawesome/angular-fontawesome';
|
||||
import { STANDALONE_SHARED_IMPORTS } from 'app/standalone-shared.module';
|
||||
|
||||
/**
|
||||
@@ -25,7 +26,8 @@ import { STANDALONE_SHARED_IMPORTS } from 'app/standalone-shared.module';
|
||||
templateUrl: './withdraw-client.component.html',
|
||||
styleUrls: ['./withdraw-client.component.scss'],
|
||||
imports: [
|
||||
...STANDALONE_SHARED_IMPORTS
|
||||
...STANDALONE_SHARED_IMPORTS,
|
||||
FaIconComponent
|
||||
]
|
||||
})
|
||||
export class WithdrawClientComponent implements OnInit {
|
||||
|
||||
Reference in New Issue
Block a user