feat: non-individual entity UI improvements — hide individual-only sections, fix legal form display, send extended fields to API
- Hide Family Members tab/section for non-individual entities in client view, create flow, and preview - Hide Financial & Classification section for non-individual entities in personal data and preview - Fix legal form column in clients list — fetch legalForm from client API for correct display - Add person/business icon before client name in list rows - Remove unsupportedNpd filter — send authorizedSignatory, additionalInfo, dateOfRegistration to API - Add registration number format hint (mat-hint) based on constitution type - Add spacing between verification row and constitution type dropdowns - Reduce table cell padding and prevent action buttons from being clipped - Add missing MPL-2.0 license headers Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 4.6
parent
ab01111424
commit
b890d24bb7
@@ -6,37 +6,44 @@
|
||||
file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
-->
|
||||
|
||||
<div class="container m-b-20 layout-row align-end gap-20px">
|
||||
<div #buttonCreateCharge class="in-block">
|
||||
<button mat-raised-button color="primary" [routerLink]="['create']" *mifosxHasPermission="'CREATE_CHARGE'">
|
||||
<fa-icon icon="plus" class="m-r-10"></fa-icon>
|
||||
{{ 'labels.text.Create Charge' | translate }}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="container">
|
||||
<div #filter class="layout-row gap-20px">
|
||||
<mat-form-field class="flex-fill flex-68">
|
||||
<mat-label>{{ 'labels.inputs.Filter' | translate }}</mat-label>
|
||||
<input matInput (keyup)="applyFilter($event.target.value)" />
|
||||
</mat-form-field>
|
||||
<mat-form-field class="flex-28">
|
||||
<mat-select
|
||||
placeholder="{{ 'labels.inputs.Filter' | translate }}"
|
||||
(selectionChange)="filterByAppliesTo($event.value)"
|
||||
>
|
||||
@for (chargeAppliesTo of chargeAppliesToOptions; track chargeAppliesTo) {
|
||||
<mat-option [value]="chargeAppliesTo.id">
|
||||
{{ chargeAppliesTo.value | translateKey: 'catalogs' }}
|
||||
</mat-option>
|
||||
}
|
||||
</mat-select>
|
||||
</mat-form-field>
|
||||
<div class="table-header">
|
||||
<div class="table-title-group">
|
||||
<h2 class="table-title">
|
||||
<i class="fas fa-file-invoice-dollar title-icon"></i>
|
||||
{{ 'labels.heading.Charges' | translate }}
|
||||
</h2>
|
||||
</div>
|
||||
|
||||
<div class="table-actions">
|
||||
<mat-form-field appearance="outline" class="table-search">
|
||||
<i matPrefix class="fas fa-search"></i>
|
||||
<mat-label>{{ 'labels.inputs.Filter' | translate }}</mat-label>
|
||||
<input matInput (keyup)="applyFilter($event.target.value)" />
|
||||
</mat-form-field>
|
||||
|
||||
<mat-form-field appearance="outline" class="table-search" #filter>
|
||||
<mat-label>{{ 'labels.inputs.Applies To' | translate }}</mat-label>
|
||||
<mat-select (selectionChange)="filterByAppliesTo($event.value)">
|
||||
@for (chargeAppliesTo of chargeAppliesToOptions; track chargeAppliesTo) {
|
||||
<mat-option [value]="chargeAppliesTo.id">
|
||||
{{ chargeAppliesTo.value | translateKey: 'catalogs' }}
|
||||
</mat-option>
|
||||
}
|
||||
</mat-select>
|
||||
</mat-form-field>
|
||||
|
||||
<div class="table-buttons" #buttonCreateCharge>
|
||||
<button mat-flat-button color="primary" class="btn-create" [routerLink]="['create']" *mifosxHasPermission="'CREATE_CHARGE'">
|
||||
<fa-icon icon="plus" class="m-r-10"></fa-icon>
|
||||
{{ 'labels.text.Create Charge' | translate }}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div #chargesTable class="mat-elevation-z8">
|
||||
<table mat-table [dataSource]="dataSource" matSort>
|
||||
<div class="table-container" #chargesTable>
|
||||
<table mat-table [dataSource]="dataSource" matSort class="modern-table">
|
||||
<ng-container matColumnDef="name">
|
||||
<th mat-header-cell *matHeaderCellDef mat-sort-header>{{ 'labels.inputs.Name' | translate }}</th>
|
||||
<td mat-cell *matCellDef="let charge">{{ charge.name }}</td>
|
||||
@@ -107,7 +114,7 @@
|
||||
</ng-container>
|
||||
|
||||
<tr mat-header-row *matHeaderRowDef="displayedColumns"></tr>
|
||||
<tr mat-row *matRowDef="let row; columns: displayedColumns" [routerLink]="[row.id]" class="select-row"></tr>
|
||||
<tr mat-row *matRowDef="let row; columns: displayedColumns" [routerLink]="[row.id]" class="table-row"></tr>
|
||||
</table>
|
||||
|
||||
<mat-paginator [pageSizeOptions]="[10, 25, 50, 100]" showFirstLastButtons></mat-paginator>
|
||||
|
||||
@@ -6,13 +6,7 @@
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
table {
|
||||
width: 100%;
|
||||
|
||||
.select-row:hover {
|
||||
cursor: pointer;
|
||||
}
|
||||
}
|
||||
@use '../../shared/styles/list-layout' as *;
|
||||
|
||||
.true {
|
||||
color: #32cd32;
|
||||
|
||||
@@ -6,284 +6,302 @@
|
||||
file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
-->
|
||||
|
||||
<div class="container">
|
||||
<mat-card>
|
||||
<form [formGroup]="chargeForm" (ngSubmit)="submit()">
|
||||
<mat-card-content>
|
||||
<div class="layout-row-wrap gap-2px responsive-column">
|
||||
<mat-form-field class="flex-48">
|
||||
<mat-label>{{ 'labels.inputs.Charge Applies To' | translate }}</mat-label>
|
||||
<mat-select required formControlName="chargeAppliesTo">
|
||||
@for (chargeAppliesTo of chargesTemplateData.chargeAppliesToOptions; track chargeAppliesTo) {
|
||||
<mat-option [value]="chargeAppliesTo.id">
|
||||
{{ chargeAppliesTo.value | translateKey: 'catalogs' }}
|
||||
</mat-option>
|
||||
}
|
||||
</mat-select>
|
||||
@if (chargeForm.controls.chargeAppliesTo.hasError('required')) {
|
||||
<div class="cc-container">
|
||||
<div class="cc-header">
|
||||
<div class="cc-header__icon"><i class="fas fa-file-invoice-dollar"></i></div>
|
||||
<h1 class="cc-header__title">{{ 'labels.text.Create Charge' | translate }}</h1>
|
||||
</div>
|
||||
|
||||
<form [formGroup]="chargeForm" (ngSubmit)="submit()">
|
||||
<!-- Section 1: Charge Type -->
|
||||
<div class="cc-section">
|
||||
<div class="cc-section__header">
|
||||
<i class="fas fa-tag"></i>
|
||||
<h3>{{ 'labels.inputs.Charge Applies To' | translate }}</h3>
|
||||
</div>
|
||||
<div class="cc-section__body">
|
||||
<mat-form-field appearance="outline" class="full-width">
|
||||
<mat-label>{{ 'labels.inputs.Charge Applies To' | translate }}</mat-label>
|
||||
<mat-select required formControlName="chargeAppliesTo">
|
||||
@for (chargeAppliesTo of chargesTemplateData.chargeAppliesToOptions; track chargeAppliesTo) {
|
||||
<mat-option [value]="chargeAppliesTo.id">
|
||||
{{ chargeAppliesTo.value | translateKey: 'catalogs' }}
|
||||
</mat-option>
|
||||
}
|
||||
</mat-select>
|
||||
@if (chargeForm.controls.chargeAppliesTo.hasError('required')) {
|
||||
<mat-error>
|
||||
{{ 'labels.inputs.Charge Applies To' | translate }} {{ 'labels.commons.is' | translate }}
|
||||
<strong>{{ 'labels.commons.required' | translate }}</strong>
|
||||
</mat-error>
|
||||
}
|
||||
</mat-form-field>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Section 2: Charge Details (conditional) -->
|
||||
@if (chargeForm.controls.chargeAppliesTo.value) {
|
||||
<div class="cc-section">
|
||||
<div class="cc-section__header">
|
||||
<i class="fas fa-list-alt"></i>
|
||||
<h3>{{ 'labels.heading.Charge Details' | translate }}</h3>
|
||||
</div>
|
||||
<div class="cc-section__body cc-grid">
|
||||
<mat-form-field appearance="outline">
|
||||
<mat-label>{{ 'labels.inputs.Charge Name' | translate }}</mat-label>
|
||||
<input matInput required formControlName="name" />
|
||||
@if (chargeForm.controls.name.hasError('required')) {
|
||||
<mat-error>
|
||||
{{ 'labels.inputs.Charge Applies To' | translate }} {{ 'labels.commons.is' | translate }}
|
||||
{{ 'labels.inputs.Charge Name' | translate }} {{ 'labels.commons.is' | translate }}
|
||||
<strong>{{ 'labels.commons.required' | translate }}</strong>
|
||||
</mat-error>
|
||||
}
|
||||
</mat-form-field>
|
||||
|
||||
<mat-divider [inset]="true"></mat-divider>
|
||||
<mat-form-field appearance="outline">
|
||||
<mat-label>{{ 'labels.inputs.Currency' | translate }}</mat-label>
|
||||
<mat-select required formControlName="currencyCode">
|
||||
@for (currency of chargesTemplateData.currencyOptions; track currency) {
|
||||
<mat-option [value]="currency.code">
|
||||
{{ currency.name }}
|
||||
</mat-option>
|
||||
}
|
||||
</mat-select>
|
||||
@if (chargeForm.controls.currencyCode.hasError('required')) {
|
||||
<mat-error>
|
||||
{{ 'labels.inputs.Currency' | translate }} {{ 'labels.commons.is' | translate }}
|
||||
<strong>{{ 'labels.commons.required' | translate }}</strong>
|
||||
</mat-error>
|
||||
}
|
||||
</mat-form-field>
|
||||
|
||||
@if (chargeForm.controls.chargeAppliesTo.value) {
|
||||
<div class="layout-row-wrap gap-2percent layout-lt-md-column form-section">
|
||||
<mat-form-field class="flex-48">
|
||||
<mat-label>{{ 'labels.inputs.Charge Name' | translate }}</mat-label>
|
||||
<input matInput required formControlName="name" />
|
||||
@if (chargeForm.controls.name.hasError('required')) {
|
||||
<mat-error>
|
||||
{{ 'labels.inputs.Charge Name' | translate }} {{ 'labels.commons.is' | translate }}
|
||||
<strong>{{ 'labels.commons.required' | translate }}</strong>
|
||||
</mat-error>
|
||||
<mat-form-field appearance="outline">
|
||||
<mat-label>{{ 'labels.inputs.Charge Time Type' | translate }}</mat-label>
|
||||
<mat-select required formControlName="chargeTimeType">
|
||||
@for (chargeTimeType of chargeTimeTypeData; track chargeTimeType) {
|
||||
<mat-option [value]="chargeTimeType.id">
|
||||
{{ chargeTimeType.value | translateKey: 'catalogs' }}
|
||||
</mat-option>
|
||||
}
|
||||
</mat-select>
|
||||
@if (chargeForm.controls.chargeTimeType.hasError('required')) {
|
||||
<mat-error>
|
||||
{{ 'labels.inputs.Charge Time Type' | translate }} {{ 'labels.commons.is' | translate }}
|
||||
<strong>{{ 'labels.commons.required' | translate }}</strong>
|
||||
</mat-error>
|
||||
}
|
||||
</mat-form-field>
|
||||
|
||||
<mat-form-field appearance="outline">
|
||||
<mat-label>{{ 'labels.inputs.Charge Calculation Type' | translate }}</mat-label>
|
||||
<mat-select required formControlName="chargeCalculationType">
|
||||
@for (chargeCalculationType of filteredChargeCalculationType(); track chargeCalculationType) {
|
||||
<mat-option [value]="chargeCalculationType.id">
|
||||
{{ chargeCalculationType.value | translateKey: 'catalogs' }}
|
||||
</mat-option>
|
||||
}
|
||||
</mat-select>
|
||||
@if (chargeForm.controls.chargeCalculationType.hasError('required')) {
|
||||
<mat-error>
|
||||
{{ 'labels.inputs.Charge Calculation Type' | translate }} {{ 'labels.commons.is' | translate }}
|
||||
<strong>{{ 'labels.commons.required' | translate }}</strong>
|
||||
</mat-error>
|
||||
}
|
||||
</mat-form-field>
|
||||
|
||||
@if (chargeForm.controls.chargeAppliesTo.value === 1) {
|
||||
<mat-form-field appearance="outline">
|
||||
<mat-label>{{ 'labels.inputs.Charge Payment Mode' | translate }}</mat-label>
|
||||
<mat-select required formControlName="chargePaymentMode">
|
||||
@for (chargePaymentMode of chargesTemplateData.chargePaymetModeOptions; track chargePaymentMode) {
|
||||
<mat-option [value]="chargePaymentMode.id">
|
||||
{{ chargePaymentMode.value | translateKey: 'catalogs' }}
|
||||
</mat-option>
|
||||
}
|
||||
</mat-form-field>
|
||||
<mat-form-field class="flex-48">
|
||||
<mat-label>{{ 'labels.inputs.Currency' | translate }}</mat-label>
|
||||
<mat-select required formControlName="currencyCode">
|
||||
@for (currency of chargesTemplateData.currencyOptions; track currency) {
|
||||
<mat-option [value]="currency.code">
|
||||
{{ currency.name }}
|
||||
</mat-option>
|
||||
}
|
||||
</mat-select>
|
||||
@if (chargeForm.controls.currencyCode.hasError('required')) {
|
||||
<mat-error>
|
||||
{{ 'labels.inputs.Currency' | translate }} {{ 'labels.commons.is' | translate }}
|
||||
<strong>{{ 'labels.commons.required' | translate }}</strong>
|
||||
</mat-error>
|
||||
}
|
||||
</mat-form-field>
|
||||
<mat-form-field class="flex-48">
|
||||
<mat-label>{{ 'labels.inputs.Charge Time Type' | translate }}</mat-label>
|
||||
<mat-select required formControlName="chargeTimeType">
|
||||
@for (chargeTimeType of chargeTimeTypeData; track chargeTimeType) {
|
||||
<mat-option [value]="chargeTimeType.id">
|
||||
{{ chargeTimeType.value | translateKey: 'catalogs' }}
|
||||
</mat-option>
|
||||
}
|
||||
</mat-select>
|
||||
@if (chargeForm.controls.chargeTimeType.hasError('required')) {
|
||||
<mat-error>
|
||||
{{ 'labels.inputs.Charge Time Type' | translate }} {{ 'labels.commons.is' | translate }}
|
||||
<strong>{{ 'labels.commons.required' | translate }}</strong>
|
||||
</mat-error>
|
||||
}
|
||||
</mat-form-field>
|
||||
<mat-form-field class="flex-48">
|
||||
<mat-label>{{ 'labels.inputs.Charge Calculation Type' | translate }}</mat-label>
|
||||
<mat-select required formControlName="chargeCalculationType">
|
||||
@for (chargeCalculationType of filteredChargeCalculationType(); track chargeCalculationType) {
|
||||
<mat-option [value]="chargeCalculationType.id">
|
||||
{{ chargeCalculationType.value | translateKey: 'catalogs' }}
|
||||
</mat-option>
|
||||
}
|
||||
</mat-select>
|
||||
@if (chargeForm.controls.chargeCalculationType.hasError('required')) {
|
||||
<mat-error>
|
||||
{{ 'labels.inputs.Charge Calculation Type' | translate }} {{ 'labels.commons.is' | translate }}
|
||||
<strong>{{ 'labels.commons.required' | translate }}</strong>
|
||||
</mat-error>
|
||||
}
|
||||
</mat-form-field>
|
||||
@if (chargeForm.controls.chargeAppliesTo.value === 1) {
|
||||
<mat-form-field class="flex-48">
|
||||
<mat-label>{{ 'labels.inputs.Charge Payment Mode' | translate }}</mat-label>
|
||||
<mat-select required formControlName="chargePaymentMode">
|
||||
@for (chargePaymentMode of chargesTemplateData.chargePaymetModeOptions; track chargePaymentMode) {
|
||||
<mat-option [value]="chargePaymentMode.id">
|
||||
{{ chargePaymentMode.value | translateKey: 'catalogs' }}
|
||||
</mat-option>
|
||||
}
|
||||
</mat-select>
|
||||
@if (chargeForm.controls.chargePaymentMode.hasError('required')) {
|
||||
<mat-error>
|
||||
{{ 'labels.inputs.Charge Payment Mode' | translate }} {{ 'labels.commons.is' | translate }}
|
||||
<strong>{{ 'labels.commons.required' | translate }}</strong>
|
||||
</mat-error>
|
||||
}
|
||||
</mat-form-field>
|
||||
</mat-select>
|
||||
@if (chargeForm.controls.chargePaymentMode.hasError('required')) {
|
||||
<mat-error>
|
||||
{{ 'labels.inputs.Charge Payment Mode' | translate }} {{ 'labels.commons.is' | translate }}
|
||||
<strong>{{ 'labels.commons.required' | translate }}</strong>
|
||||
</mat-error>
|
||||
}
|
||||
@if (chargeForm.controls.chargeTimeType.value === 9) {
|
||||
<div class="flex-48 add-fee-frequency-wrapper">
|
||||
<mat-checkbox labelPosition="before" formControlName="addFeeFrequency">
|
||||
{{ 'labels.inputs.Add Fee Frequency' | translate }}
|
||||
</mat-checkbox>
|
||||
</div>
|
||||
}
|
||||
@if (chargeForm.controls.chargeTimeType.value === 9 && chargeForm.controls.addFeeFrequency.value) {
|
||||
<mat-form-field class="flex-48">
|
||||
<mat-label>{{ 'labels.inputs.Frequency Interval' | translate }}</mat-label>
|
||||
<input matInput required formControlName="feeInterval" />
|
||||
@if (chargeForm.controls.feeInterval.hasError('required')) {
|
||||
<mat-error>
|
||||
{{ 'labels.inputs.Frequency Interval' | translate }} {{ 'labels.commons.is' | translate }}
|
||||
<strong>{{ 'labels.commons.required' | translate }}</strong>
|
||||
</mat-error>
|
||||
}
|
||||
@if (chargeForm.controls.feeInterval.hasError('pattern')) {
|
||||
<mat-error>
|
||||
{{ 'labels.inputs.Frequency Interval' | translate }}
|
||||
<strong>{{ 'labels.commons.must be a positive integer' | translate }}</strong>
|
||||
</mat-error>
|
||||
}
|
||||
</mat-form-field>
|
||||
}
|
||||
@if (chargeForm.controls.chargeTimeType.value === 9 && chargeForm.controls.addFeeFrequency.value) {
|
||||
<mat-form-field class="flex-48">
|
||||
<mat-label>{{ 'labels.inputs.Charge Frequency' | translate }}</mat-label>
|
||||
<mat-select required formControlName="feeFrequency">
|
||||
@for (feeFrequency of chargesTemplateData.feeFrequencyOptions; track feeFrequency) {
|
||||
<mat-option [value]="feeFrequency.id">
|
||||
{{ feeFrequency.value | translateKey: 'catalogs' }}
|
||||
</mat-option>
|
||||
}
|
||||
</mat-select>
|
||||
@if (chargeForm.controls.feeFrequency.hasError('required')) {
|
||||
<mat-error>
|
||||
{{ 'labels.inputs.Charge Frequency' | translate }} {{ 'labels.commons.is' | translate }}
|
||||
<strong>{{ 'labels.commons.required' | translate }}</strong>
|
||||
</mat-error>
|
||||
}
|
||||
</mat-form-field>
|
||||
}
|
||||
@if (chargeForm.controls.chargeTimeType.value === 6 || chargeForm.controls.chargeTimeType.value === 7) {
|
||||
<mat-form-field (click)="dueDatePicker.open()" class="flex-48">
|
||||
<mat-label>{{ 'labels.inputs.Due Date' | translate }}</mat-label>
|
||||
<input
|
||||
matInput
|
||||
[min]="minDate"
|
||||
[max]="maxDate"
|
||||
[matDatepicker]="dueDatePicker"
|
||||
required
|
||||
formControlName="feeOnMonthDay"
|
||||
/>
|
||||
<mat-datepicker-toggle matSuffix [for]="dueDatePicker"></mat-datepicker-toggle>
|
||||
<mat-datepicker #dueDatePicker></mat-datepicker>
|
||||
@if (chargeForm.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 (chargeForm.controls.chargeTimeType.value === 7 || chargeForm.controls.chargeTimeType.value === 11) {
|
||||
<mat-form-field class="flex-48">
|
||||
<mat-label>{{ 'labels.inputs.Repeat Every' | translate }} ({{ repeatEveryLabel }})</mat-label>
|
||||
<input matInput required formControlName="feeInterval" />
|
||||
@if (chargeForm.controls.feeInterval.hasError('required')) {
|
||||
<mat-error>
|
||||
{{ 'labels.inputs.Repeat Every' | translate }} ({{ repeatEveryLabel }})
|
||||
{{ 'labels.commons.is' | translate }} <strong>{{ 'labels.commons.required' | translate }}</strong>
|
||||
</mat-error>
|
||||
}
|
||||
@if (
|
||||
(chargeForm.controls.feeInterval.hasError('min') ||
|
||||
chargeForm.controls.feeInterval.hasError('max')) &&
|
||||
!chargeForm.controls.feeInterval.hasError('pattern')
|
||||
) {
|
||||
<mat-error>
|
||||
{{ 'labels.inputs.Repeat Every' | translate }} ({{ repeatEveryLabel }})
|
||||
<strong>{{ 'labels.commons.must be between 1 and 12' | translate }}</strong>
|
||||
</mat-error>
|
||||
}
|
||||
@if (chargeForm.controls.feeInterval.hasError('pattern')) {
|
||||
<mat-error>
|
||||
{{ 'labels.inputs.Repeat Every' | translate }} ({{ repeatEveryLabel }})
|
||||
<strong>{{ 'labels.commons.must be a positive integer' | translate }}</strong>
|
||||
</mat-error>
|
||||
}
|
||||
</mat-form-field>
|
||||
}
|
||||
<mat-form-field class="flex-48">
|
||||
<mat-label>{{ 'labels.inputs.Amount' | translate }}</mat-label>
|
||||
<input matInput required formControlName="amount" />
|
||||
@if (chargeForm.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>
|
||||
<!--
|
||||
* minCap and maxCap only allowed for loan ,shares and savings entitites
|
||||
* In Loan case: Only for the "charge calculation type" set as "%amount", "% loan amount+interest", "%interest",and"%disbursement amount".
|
||||
* In saving case: Only for 1. charge time type is "withdrawlfee" or "savings no activity fee" with charge calculation type as "% amount"
|
||||
* In shares case: Only for charge time type: SHARE_PURCHASE and SHARE_REDEEM and with charge calculation type as % amount only
|
||||
-->
|
||||
@if (showMinMaxCap()) {
|
||||
<mat-form-field class="flex-48">
|
||||
<mat-label>{{ 'labels.inputs.Minimum Charge Cap' | translate }}</mat-label>
|
||||
<input matInput autofocus formControlName="minCap" mifosxValidateOnFocus />
|
||||
@if (chargeForm.controls.minCap.hasError('maxValue')) {
|
||||
<mat-error>
|
||||
{{ 'errors.validation.msg.loanproduct.minimumGap.not.greater.than.specified.number' | translate }}
|
||||
({{ chargeForm.controls.maxCap.value }})
|
||||
</mat-error>
|
||||
}
|
||||
</mat-form-field>
|
||||
}
|
||||
@if (showMinMaxCap()) {
|
||||
<mat-form-field class="flex-48">
|
||||
<mat-label>{{ 'labels.inputs.Maximum Charge Cap' | translate }}</mat-label>
|
||||
<input matInput autofocus formControlName="maxCap" mifosxValidateOnFocus />
|
||||
@if (chargeForm.controls.maxCap.hasError('minValue')) {
|
||||
<mat-error>
|
||||
{{ 'errors.validation.msg.loanproduct.maximumGap.not.greater.than.specified.number' | translate }}
|
||||
({{ chargeForm.controls.minCap.value }})
|
||||
</mat-error>
|
||||
}
|
||||
</mat-form-field>
|
||||
}
|
||||
@if (chargeForm.controls.chargeAppliesTo.value === 3) {
|
||||
<mifosx-gl-account-selector
|
||||
class="flex-48"
|
||||
[inputFormControl]="chargeForm.controls.incomeAccountId"
|
||||
[glAccountList]="incomeAndLiabilityAccountData"
|
||||
[inputLabel]="'Income from Charge'"
|
||||
>
|
||||
</mifosx-gl-account-selector>
|
||||
}
|
||||
<mat-form-field class="flex-48">
|
||||
<mat-label>{{ 'labels.inputs.Tax Group' | translate }}</mat-label>
|
||||
<mat-select formControlName="taxGroupId">
|
||||
@for (taxGroup of chargesTemplateData.taxGroupOptions; track taxGroup) {
|
||||
<mat-option [value]="taxGroup.id">
|
||||
{{ taxGroup.name }}
|
||||
</mat-option>
|
||||
}
|
||||
</mat-select>
|
||||
</mat-form-field>
|
||||
<div class="flex-48 layout-row gap-2percent layout-lt-md-column">
|
||||
<div class="flex-50 active-wrapper">
|
||||
<mat-checkbox labelPosition="before" formControlName="active">
|
||||
{{ 'labels.status.Active' | translate }}
|
||||
</mat-checkbox>
|
||||
</div>
|
||||
<div class="flex-50 penalty-wrapper">
|
||||
<mat-checkbox labelPosition="before" formControlName="penalty">
|
||||
{{ 'labels.commons.Is' | translate }} {{ 'labels.inputs.Penalty' | translate }}
|
||||
</mat-checkbox>
|
||||
</div>
|
||||
</div>
|
||||
</mat-form-field>
|
||||
}
|
||||
|
||||
@if (chargeForm.controls.chargeTimeType.value === 9) {
|
||||
<div class="cc-checkbox-row">
|
||||
<mat-checkbox labelPosition="before" formControlName="addFeeFrequency">
|
||||
{{ 'labels.inputs.Add Fee Frequency' | translate }}
|
||||
</mat-checkbox>
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
</mat-card-content>
|
||||
|
||||
<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]="!chargeForm.valid" *mifosxHasPermission="'CREATE_CHARGE'">
|
||||
{{ 'labels.buttons.Submit' | translate }}
|
||||
</button>
|
||||
</mat-card-actions>
|
||||
</form>
|
||||
</mat-card>
|
||||
@if (chargeForm.controls.chargeTimeType.value === 9 && chargeForm.controls.addFeeFrequency.value) {
|
||||
<mat-form-field appearance="outline">
|
||||
<mat-label>{{ 'labels.inputs.Frequency Interval' | translate }}</mat-label>
|
||||
<input matInput required formControlName="feeInterval" />
|
||||
@if (chargeForm.controls.feeInterval.hasError('required')) {
|
||||
<mat-error>
|
||||
{{ 'labels.inputs.Frequency Interval' | translate }} {{ 'labels.commons.is' | translate }}
|
||||
<strong>{{ 'labels.commons.required' | translate }}</strong>
|
||||
</mat-error>
|
||||
}
|
||||
@if (chargeForm.controls.feeInterval.hasError('pattern')) {
|
||||
<mat-error>
|
||||
{{ 'labels.inputs.Frequency Interval' | translate }}
|
||||
<strong>{{ 'labels.commons.must be a positive integer' | translate }}</strong>
|
||||
</mat-error>
|
||||
}
|
||||
</mat-form-field>
|
||||
}
|
||||
|
||||
@if (chargeForm.controls.chargeTimeType.value === 9 && chargeForm.controls.addFeeFrequency.value) {
|
||||
<mat-form-field appearance="outline">
|
||||
<mat-label>{{ 'labels.inputs.Charge Frequency' | translate }}</mat-label>
|
||||
<mat-select required formControlName="feeFrequency">
|
||||
@for (feeFrequency of chargesTemplateData.feeFrequencyOptions; track feeFrequency) {
|
||||
<mat-option [value]="feeFrequency.id">
|
||||
{{ feeFrequency.value | translateKey: 'catalogs' }}
|
||||
</mat-option>
|
||||
}
|
||||
</mat-select>
|
||||
@if (chargeForm.controls.feeFrequency.hasError('required')) {
|
||||
<mat-error>
|
||||
{{ 'labels.inputs.Charge Frequency' | translate }} {{ 'labels.commons.is' | translate }}
|
||||
<strong>{{ 'labels.commons.required' | translate }}</strong>
|
||||
</mat-error>
|
||||
}
|
||||
</mat-form-field>
|
||||
}
|
||||
|
||||
@if (chargeForm.controls.chargeTimeType.value === 6 || chargeForm.controls.chargeTimeType.value === 7) {
|
||||
<mat-form-field appearance="outline" (click)="dueDatePicker.open()">
|
||||
<mat-label>{{ 'labels.inputs.Due Date' | translate }}</mat-label>
|
||||
<input
|
||||
matInput
|
||||
[min]="minDate"
|
||||
[max]="maxDate"
|
||||
[matDatepicker]="dueDatePicker"
|
||||
required
|
||||
formControlName="feeOnMonthDay"
|
||||
/>
|
||||
<mat-datepicker-toggle matSuffix [for]="dueDatePicker"></mat-datepicker-toggle>
|
||||
<mat-datepicker #dueDatePicker></mat-datepicker>
|
||||
@if (chargeForm.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 (chargeForm.controls.chargeTimeType.value === 7 || chargeForm.controls.chargeTimeType.value === 11) {
|
||||
<mat-form-field appearance="outline">
|
||||
<mat-label>{{ 'labels.inputs.Repeat Every' | translate }} ({{ repeatEveryLabel }})</mat-label>
|
||||
<input matInput required formControlName="feeInterval" />
|
||||
@if (chargeForm.controls.feeInterval.hasError('required')) {
|
||||
<mat-error>
|
||||
{{ 'labels.inputs.Repeat Every' | translate }} ({{ repeatEveryLabel }})
|
||||
{{ 'labels.commons.is' | translate }} <strong>{{ 'labels.commons.required' | translate }}</strong>
|
||||
</mat-error>
|
||||
}
|
||||
@if (
|
||||
(chargeForm.controls.feeInterval.hasError('min') ||
|
||||
chargeForm.controls.feeInterval.hasError('max')) &&
|
||||
!chargeForm.controls.feeInterval.hasError('pattern')
|
||||
) {
|
||||
<mat-error>
|
||||
{{ 'labels.inputs.Repeat Every' | translate }} ({{ repeatEveryLabel }})
|
||||
<strong>{{ 'labels.commons.must be between 1 and 12' | translate }}</strong>
|
||||
</mat-error>
|
||||
}
|
||||
@if (chargeForm.controls.feeInterval.hasError('pattern')) {
|
||||
<mat-error>
|
||||
{{ 'labels.inputs.Repeat Every' | translate }} ({{ repeatEveryLabel }})
|
||||
<strong>{{ 'labels.commons.must be a positive integer' | translate }}</strong>
|
||||
</mat-error>
|
||||
}
|
||||
</mat-form-field>
|
||||
}
|
||||
|
||||
<mat-form-field appearance="outline">
|
||||
<mat-label>{{ 'labels.inputs.Amount' | translate }}</mat-label>
|
||||
<input matInput required formControlName="amount" />
|
||||
@if (chargeForm.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>
|
||||
|
||||
@if (showMinMaxCap()) {
|
||||
<mat-form-field appearance="outline">
|
||||
<mat-label>{{ 'labels.inputs.Minimum Charge Cap' | translate }}</mat-label>
|
||||
<input matInput autofocus formControlName="minCap" mifosxValidateOnFocus />
|
||||
@if (chargeForm.controls.minCap.hasError('maxValue')) {
|
||||
<mat-error>
|
||||
{{ 'errors.validation.msg.loanproduct.minimumGap.not.greater.than.specified.number' | translate }}
|
||||
({{ chargeForm.controls.maxCap.value }})
|
||||
</mat-error>
|
||||
}
|
||||
</mat-form-field>
|
||||
}
|
||||
|
||||
@if (showMinMaxCap()) {
|
||||
<mat-form-field appearance="outline">
|
||||
<mat-label>{{ 'labels.inputs.Maximum Charge Cap' | translate }}</mat-label>
|
||||
<input matInput autofocus formControlName="maxCap" mifosxValidateOnFocus />
|
||||
@if (chargeForm.controls.maxCap.hasError('minValue')) {
|
||||
<mat-error>
|
||||
{{ 'errors.validation.msg.loanproduct.maximumGap.not.greater.than.specified.number' | translate }}
|
||||
({{ chargeForm.controls.minCap.value }})
|
||||
</mat-error>
|
||||
}
|
||||
</mat-form-field>
|
||||
}
|
||||
|
||||
@if (chargeForm.controls.chargeAppliesTo.value === 3) {
|
||||
<mifosx-gl-account-selector
|
||||
[inputFormControl]="chargeForm.controls.incomeAccountId"
|
||||
[glAccountList]="incomeAndLiabilityAccountData"
|
||||
[inputLabel]="'Income from Charge'"
|
||||
>
|
||||
</mifosx-gl-account-selector>
|
||||
}
|
||||
|
||||
<mat-form-field appearance="outline">
|
||||
<mat-label>{{ 'labels.inputs.Tax Group' | translate }}</mat-label>
|
||||
<mat-select formControlName="taxGroupId">
|
||||
@for (taxGroup of chargesTemplateData.taxGroupOptions; track taxGroup) {
|
||||
<mat-option [value]="taxGroup.id">
|
||||
{{ taxGroup.name }}
|
||||
</mat-option>
|
||||
}
|
||||
</mat-select>
|
||||
</mat-form-field>
|
||||
|
||||
<div class="cc-checkbox-row cc-checkbox-pair">
|
||||
<mat-checkbox labelPosition="before" formControlName="active">
|
||||
{{ 'labels.status.Active' | translate }}
|
||||
</mat-checkbox>
|
||||
<mat-checkbox labelPosition="before" formControlName="penalty">
|
||||
{{ 'labels.commons.Is' | translate }} {{ 'labels.inputs.Penalty' | translate }}
|
||||
</mat-checkbox>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
|
||||
<!-- Action Bar -->
|
||||
<div class="cc-actions">
|
||||
<button type="button" mat-raised-button [routerLink]="['../']">
|
||||
{{ 'labels.buttons.Cancel' | translate }}
|
||||
</button>
|
||||
<button mat-flat-button color="primary" [disabled]="!chargeForm.valid" *mifosxHasPermission="'CREATE_CHARGE'">
|
||||
{{ 'labels.buttons.Submit' | translate }}
|
||||
</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
@@ -6,14 +6,103 @@
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
.penalty-wrapper {
|
||||
padding: 17.5px 0;
|
||||
.cc-container {
|
||||
max-width: 960px;
|
||||
margin: 0 auto;
|
||||
padding: 24px 16px;
|
||||
}
|
||||
|
||||
.active-wrapper {
|
||||
padding: 17.5px 0;
|
||||
.cc-header {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 12px;
|
||||
margin-bottom: 24px;
|
||||
|
||||
&__icon {
|
||||
width: 40px;
|
||||
height: 40px;
|
||||
border-radius: 10px;
|
||||
background: linear-gradient(135deg, #0ea5e9 0%, #1353a0 100%);
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
color: #fff;
|
||||
font-size: 18px;
|
||||
}
|
||||
|
||||
&__title {
|
||||
font-size: 20px;
|
||||
font-weight: 600;
|
||||
color: #202124;
|
||||
margin: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.add-fee-frequency-wrapper {
|
||||
padding: 17.5px 0;
|
||||
.cc-section {
|
||||
border: 1px solid #e2e8f0;
|
||||
border-radius: 10px;
|
||||
overflow: hidden;
|
||||
background: #fff;
|
||||
margin-bottom: 16px;
|
||||
|
||||
&__header {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
padding: 12px 24px;
|
||||
background: #f8f9fa;
|
||||
border-bottom: 1px solid #e8eaed;
|
||||
|
||||
i {
|
||||
font-size: 14px;
|
||||
color: #0ea5e9;
|
||||
}
|
||||
|
||||
h3 {
|
||||
font-size: 14px;
|
||||
font-weight: 600;
|
||||
color: #202124;
|
||||
margin: 0;
|
||||
}
|
||||
}
|
||||
|
||||
&__body {
|
||||
padding: 16px 24px;
|
||||
|
||||
.full-width {
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.cc-grid {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(2, 1fr);
|
||||
gap: 4px 16px;
|
||||
}
|
||||
|
||||
.cc-checkbox-row {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 16px;
|
||||
padding: 4px 0;
|
||||
}
|
||||
|
||||
.cc-checkbox-pair {
|
||||
grid-column: 1 / -1;
|
||||
}
|
||||
|
||||
.cc-actions {
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
gap: 12px;
|
||||
margin-top: 20px;
|
||||
padding: 16px 0;
|
||||
border-top: 1px solid rgba(0, 0, 0, 0.08);
|
||||
}
|
||||
|
||||
@media (max-width: 600px) {
|
||||
.cc-grid {
|
||||
grid-template-columns: 1fr;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -23,7 +23,6 @@ import { SettingsService } from 'app/settings/settings.service';
|
||||
import { Dates } from 'app/core/utils/dates';
|
||||
import { minNumberValueValidator } from 'app/shared/validators/min-number-value.validator';
|
||||
import { maxNumberValueValidator } from 'app/shared/validators/max-number-value.validator';
|
||||
import { MatDivider } from '@angular/material/divider';
|
||||
import { MatCheckbox } from '@angular/material/checkbox';
|
||||
import { ValidateOnFocusDirective } from '../../../directives/validate-on-focus.directive';
|
||||
import { GlAccountSelectorComponent } from '../../../shared/accounting/gl-account-selector/gl-account-selector.component';
|
||||
@@ -38,7 +37,6 @@ import { STANDALONE_SHARED_IMPORTS } from 'app/standalone-shared.module';
|
||||
styleUrls: ['./create-charge.component.scss'],
|
||||
imports: [
|
||||
...STANDALONE_SHARED_IMPORTS,
|
||||
MatDivider,
|
||||
MatCheckbox,
|
||||
ValidateOnFocusDirective,
|
||||
GlAccountSelectorComponent
|
||||
|
||||
@@ -6,276 +6,288 @@
|
||||
file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
-->
|
||||
|
||||
<div class="container">
|
||||
<mat-card>
|
||||
<form [formGroup]="chargeForm" (ngSubmit)="submit()">
|
||||
<mat-card-content>
|
||||
<div class="layout-row-wrap gap-2px responsive-column">
|
||||
<mat-form-field class="flex-48">
|
||||
<mat-label>{{ 'labels.inputs.Charge Applies To' | translate }}</mat-label>
|
||||
<mat-select required formControlName="chargeAppliesTo">
|
||||
@for (chargeAppliesTo of chargeData.chargeAppliesToOptions; track chargeAppliesTo) {
|
||||
<mat-option [value]="chargeAppliesTo.id">
|
||||
{{ chargeAppliesTo.value | translateKey: 'catalogs' }}
|
||||
<div class="ec-container">
|
||||
<div class="ec-header">
|
||||
<div class="ec-header__icon"><i class="fas fa-edit"></i></div>
|
||||
<h1 class="ec-header__title">{{ 'labels.heading.Edit' | translate }} {{ 'labels.inputs.Charge' | translate }}</h1>
|
||||
</div>
|
||||
|
||||
<form [formGroup]="chargeForm" (ngSubmit)="submit()">
|
||||
<!-- Section 1: Charge Type -->
|
||||
<div class="ec-section">
|
||||
<div class="ec-section__header">
|
||||
<i class="fas fa-tag"></i>
|
||||
<h3>{{ 'labels.inputs.Charge Applies To' | translate }}</h3>
|
||||
</div>
|
||||
<div class="ec-section__body">
|
||||
<mat-form-field appearance="outline" class="full-width">
|
||||
<mat-label>{{ 'labels.inputs.Charge Applies To' | translate }}</mat-label>
|
||||
<mat-select required formControlName="chargeAppliesTo">
|
||||
@for (chargeAppliesTo of chargeData.chargeAppliesToOptions; track chargeAppliesTo) {
|
||||
<mat-option [value]="chargeAppliesTo.id">
|
||||
{{ chargeAppliesTo.value | translateKey: 'catalogs' }}
|
||||
</mat-option>
|
||||
}
|
||||
</mat-select>
|
||||
</mat-form-field>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Section 2: Charge Details -->
|
||||
<div class="ec-section">
|
||||
<div class="ec-section__header">
|
||||
<i class="fas fa-list-alt"></i>
|
||||
<h3>{{ 'labels.heading.Charge Details' | translate }}</h3>
|
||||
</div>
|
||||
<div class="ec-section__body ec-grid">
|
||||
<mat-form-field appearance="outline">
|
||||
<mat-label>{{ 'labels.inputs.Name' | translate }}</mat-label>
|
||||
<input matInput required autofocus formControlName="name" />
|
||||
@if (chargeForm.controls.name.hasError('required')) {
|
||||
<mat-error>
|
||||
{{ 'labels.inputs.Name' | translate }} {{ 'labels.commons.is' | translate }}
|
||||
<strong>{{ 'labels.commons.required' | translate }}</strong>
|
||||
</mat-error>
|
||||
}
|
||||
</mat-form-field>
|
||||
|
||||
<mat-form-field appearance="outline">
|
||||
<mat-label>{{ 'labels.inputs.Currency' | translate }}</mat-label>
|
||||
<mat-select required formControlName="currencyCode">
|
||||
@for (currency of chargeData.currencyOptions; track currency) {
|
||||
<mat-option [value]="currency.code">
|
||||
{{ currency.name }}
|
||||
</mat-option>
|
||||
}
|
||||
</mat-select>
|
||||
@if (chargeForm.controls.currencyCode.hasError('required')) {
|
||||
<mat-error>
|
||||
{{ 'labels.inputs.Currency' | translate }} {{ 'labels.inputs.Type' | translate }}
|
||||
{{ 'labels.commons.is' | translate }} <strong>{{ 'labels.commons.required' | translate }}</strong>
|
||||
</mat-error>
|
||||
}
|
||||
</mat-form-field>
|
||||
|
||||
<mat-form-field appearance="outline">
|
||||
<mat-label>{{ 'labels.inputs.Charge Time Type' | translate }}</mat-label>
|
||||
<mat-select required formControlName="chargeTimeType">
|
||||
@for (chargeTime of chargeTimeTypeOptions; track chargeTime) {
|
||||
<mat-option [value]="chargeTime.id">
|
||||
{{ chargeTime.value | translateKey: 'catalogs' }}
|
||||
</mat-option>
|
||||
}
|
||||
</mat-select>
|
||||
@if (chargeForm.controls.chargeTimeType.hasError('required')) {
|
||||
<mat-error>
|
||||
{{ 'labels.inputs.Charge Time Type' | translate }} {{ 'labels.commons.is' | translate }}
|
||||
<strong>{{ 'labels.commons.required' | translate }}</strong>
|
||||
</mat-error>
|
||||
}
|
||||
</mat-form-field>
|
||||
|
||||
<mat-form-field appearance="outline">
|
||||
<mat-label>{{ 'labels.inputs.Charge Calculation' | translate }}</mat-label>
|
||||
<mat-select required formControlName="chargeCalculationType">
|
||||
@for (chargeCalculation of chargeCalculationTypeOptions; track chargeCalculation) {
|
||||
<mat-option [value]="chargeCalculation.id">
|
||||
{{ chargeCalculation.value | translateKey: 'catalogs' }}
|
||||
</mat-option>
|
||||
}
|
||||
</mat-select>
|
||||
@if (chargeForm.controls.chargeCalculationType.hasError('required')) {
|
||||
<mat-error>
|
||||
{{ 'labels.inputs.Charge Calculation Type' | translate }} {{ 'labels.commons.is' | translate }}
|
||||
<strong>{{ 'labels.commons.required' | translate }}</strong>
|
||||
</mat-error>
|
||||
}
|
||||
</mat-form-field>
|
||||
|
||||
@if (chargePaymentMode) {
|
||||
<mat-form-field appearance="outline">
|
||||
<mat-label>{{ 'labels.inputs.Charge Payment By' | translate }}</mat-label>
|
||||
<mat-select required formControlName="chargePaymentMode">
|
||||
@for (chargePaymentMode of chargeData.chargePaymetModeOptions; track chargePaymentMode) {
|
||||
<mat-option [value]="chargePaymentMode.id">
|
||||
{{ chargePaymentMode.value | translateKey: 'catalogs' }}
|
||||
</mat-option>
|
||||
}
|
||||
</mat-select>
|
||||
</mat-form-field>
|
||||
</div>
|
||||
|
||||
<div class="layout-row-wrap gap-2percent layout-lt-md-column form-section">
|
||||
<mat-form-field class="flex-48">
|
||||
<mat-label>{{ 'labels.inputs.Name' | translate }}</mat-label>
|
||||
<input matInput required autofocus formControlName="name" />
|
||||
@if (chargeForm.controls.name.hasError('required')) {
|
||||
@if (chargeForm.controls.chargePaymentMode.hasError('required')) {
|
||||
<mat-error>
|
||||
{{ 'labels.inputs.Name' | translate }} {{ 'labels.commons.is' | translate }}
|
||||
{{ 'labels.inputs.Charge Payment Mode' | translate }} {{ 'labels.commons.is' | translate }}
|
||||
<strong>{{ 'labels.commons.required' | translate }}</strong>
|
||||
</mat-error>
|
||||
}
|
||||
</mat-form-field>
|
||||
}
|
||||
|
||||
<mat-form-field class="flex-48">
|
||||
<mat-label>{{ 'labels.inputs.Currency' | translate }}</mat-label>
|
||||
<mat-select required formControlName="currencyCode">
|
||||
@for (currency of chargeData.currencyOptions; track currency) {
|
||||
<mat-option [value]="currency.code">
|
||||
{{ currency.name }}
|
||||
</mat-option>
|
||||
}
|
||||
</mat-select>
|
||||
@if (chargeForm.controls.currencyCode.hasError('required')) {
|
||||
<mat-form-field appearance="outline">
|
||||
<mat-label>{{ 'labels.inputs.Amount' | translate }}</mat-label>
|
||||
<input matInput required autofocus type="text" formControlName="amount" />
|
||||
@if (chargeForm.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>
|
||||
|
||||
<!--
|
||||
* minCap and maxCap only allowed for loan ,shares and savings entitites
|
||||
* In Loan case: Only for the "charge calculation type" set as "%amount", "% loan amount+interest", "%interest",and "%disbursement amount".
|
||||
* In saving case: Only for 1. charge time type is "withdrawlfee" or "savings no activity fee" with charge calculation type as "% amount"
|
||||
* In shares case: Only for charge time type: SHARE_PURCHASE and SHARE_REDEEM and with charge calculation type as % amount only
|
||||
-->
|
||||
@if (
|
||||
(chargeForm.controls.chargeAppliesTo.value === 1 &&
|
||||
(chargeForm.controls.chargeCalculationType.value === 2 ||
|
||||
chargeForm.controls.chargeCalculationType.value === 3 ||
|
||||
chargeForm.controls.chargeCalculationType.value === 4 ||
|
||||
chargeForm.controls.chargeCalculationType.value === 5)) ||
|
||||
(chargeForm.controls.chargeAppliesTo.value === 2 &&
|
||||
(chargeForm.controls.chargeTimeType.value === 16 || chargeForm.controls.chargeTimeType.value === 5) &&
|
||||
chargeForm.controls.chargeCalculationType.value === 2) ||
|
||||
(chargeForm.controls.chargeAppliesTo.value === 4 &&
|
||||
(chargeForm.controls.chargeTimeType.value === 14 || chargeForm.controls.chargeTimeType.value === 15) &&
|
||||
chargeForm.controls.chargeCalculationType.value === 2)
|
||||
) {
|
||||
<mat-form-field appearance="outline">
|
||||
<mat-label>{{ 'labels.inputs.Minimum Charge Cap' | translate }}</mat-label>
|
||||
<input matInput autofocus formControlName="minCap" mifosxValidateOnFocus />
|
||||
@if (chargeForm.controls.minCap.hasError('maxValue')) {
|
||||
<mat-error>
|
||||
{{ 'labels.inputs.Currency' | translate }} {{ 'labels.inputs.Type' | translate }}
|
||||
{{ 'labels.commons.is' | translate }} <strong>{{ 'labels.commons.required' | translate }}</strong>
|
||||
{{ 'errors.validation.msg.loanproduct.minimumGap.not.greater.than.specified.number' | translate }} ({{
|
||||
chargeForm.controls.maxCap.value
|
||||
}})
|
||||
</mat-error>
|
||||
}
|
||||
</mat-form-field>
|
||||
|
||||
<mat-form-field class="flex-48">
|
||||
<mat-label>{{ 'labels.inputs.Charge Time Type' | translate }}</mat-label>
|
||||
<mat-select required formControlName="chargeTimeType">
|
||||
@for (chargeTime of chargeTimeTypeOptions; track chargeTime) {
|
||||
<mat-option [value]="chargeTime.id">
|
||||
{{ chargeTime.value | translateKey: 'catalogs' }}
|
||||
</mat-option>
|
||||
}
|
||||
</mat-select>
|
||||
@if (chargeForm.controls.chargeTimeType.hasError('required')) {
|
||||
}
|
||||
@if (
|
||||
(chargeForm.controls.chargeAppliesTo.value === 1 &&
|
||||
(chargeForm.controls.chargeCalculationType.value === 2 ||
|
||||
chargeForm.controls.chargeCalculationType.value === 3 ||
|
||||
chargeForm.controls.chargeCalculationType.value === 4 ||
|
||||
chargeForm.controls.chargeCalculationType.value === 5)) ||
|
||||
(chargeForm.controls.chargeAppliesTo.value === 2 &&
|
||||
(chargeForm.controls.chargeTimeType.value === 16 || chargeForm.controls.chargeTimeType.value === 5) &&
|
||||
chargeForm.controls.chargeCalculationType.value === 2) ||
|
||||
(chargeForm.controls.chargeAppliesTo.value === 4 &&
|
||||
(chargeForm.controls.chargeTimeType.value === 14 || chargeForm.controls.chargeTimeType.value === 15) &&
|
||||
chargeForm.controls.chargeCalculationType.value === 2)
|
||||
) {
|
||||
<mat-form-field appearance="outline">
|
||||
<mat-label>{{ 'labels.inputs.Maximum Charge Cap' | translate }}</mat-label>
|
||||
<input matInput autofocus formControlName="maxCap" mifosxValidateOnFocus />
|
||||
@if (chargeForm.controls.maxCap.hasError('minValue')) {
|
||||
<mat-error>
|
||||
{{ 'labels.inputs.Charge Time Type' | translate }} {{ 'labels.commons.is' | translate }}
|
||||
<strong>{{ 'labels.commons.required' | translate }}</strong>
|
||||
{{ 'errors.validation.msg.loanproduct.maximumGap.not.greater.than.specified.number' | translate }} ({{
|
||||
chargeForm.controls.minCap.value
|
||||
}})
|
||||
</mat-error>
|
||||
}
|
||||
</mat-form-field>
|
||||
}
|
||||
|
||||
<mat-form-field class="flex-48">
|
||||
<mat-label>{{ 'labels.inputs.Charge Calculation' | translate }}</mat-label>
|
||||
<mat-select required formControlName="chargeCalculationType">
|
||||
@for (chargeCalculation of chargeCalculationTypeOptions; track chargeCalculation) {
|
||||
<mat-option [value]="chargeCalculation.id">
|
||||
{{ chargeCalculation.value | translateKey: 'catalogs' }}
|
||||
@if (showGLAccount) {
|
||||
<mifosx-gl-account-selector
|
||||
[inputFormControl]="chargeForm.controls.incomeAccountId"
|
||||
[glAccountList]="chargeData.incomeOrLiabilityAccountOptions.incomeAccountOptions"
|
||||
[required]="true"
|
||||
[inputLabel]="'Income from Charge'"
|
||||
>
|
||||
</mifosx-gl-account-selector>
|
||||
}
|
||||
|
||||
<mat-form-field appearance="outline">
|
||||
<mat-label>{{ 'labels.inputs.Tax Group' | translate }}</mat-label>
|
||||
@if (chargeData.taxGroup) {
|
||||
<mat-select formControlName="taxGroupId">
|
||||
@for (taxGroup of chargeData.taxGroupOptions; track taxGroup) {
|
||||
<mat-option [value]="taxGroup.id">
|
||||
{{ taxGroup.name }}
|
||||
</mat-option>
|
||||
}
|
||||
</mat-select>
|
||||
@if (chargeForm.controls.chargeCalculationType.hasError('required')) {
|
||||
<mat-error>
|
||||
{{ 'labels.inputs.Charge Calculation Type' | translate }} {{ 'labels.commons.is' | translate }}
|
||||
<strong>{{ 'labels.commons.required' | translate }}</strong>
|
||||
</mat-error>
|
||||
}
|
||||
</mat-form-field>
|
||||
|
||||
@if (chargePaymentMode) {
|
||||
<mat-form-field class="flex-48">
|
||||
<mat-label>{{ 'labels.inputs.Charge Payment By' | translate }}</mat-label>
|
||||
<mat-select required formControlName="chargePaymentMode">
|
||||
@for (chargePaymentMode of chargeData.chargePaymetModeOptions; track chargePaymentMode) {
|
||||
<mat-option [value]="chargePaymentMode.id">
|
||||
{{ chargePaymentMode.value | translateKey: 'catalogs' }}
|
||||
</mat-option>
|
||||
}
|
||||
</mat-select>
|
||||
@if (chargeForm.controls.chargePaymentMode.hasError('required')) {
|
||||
<mat-error>
|
||||
{{ 'labels.inputs.Charge Payment Mode' | translate }} {{ 'labels.commons.is' | translate }}
|
||||
<strong>{{ 'labels.commons.required' | translate }}</strong>
|
||||
</mat-error>
|
||||
}
|
||||
</mat-form-field>
|
||||
}
|
||||
|
||||
<mat-form-field class="flex-48">
|
||||
<mat-label>{{ 'labels.inputs.Amount' | translate }}</mat-label>
|
||||
<input matInput required autofocus type="text" formControlName="amount" />
|
||||
@if (chargeForm.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>
|
||||
<!--
|
||||
* minCap and maxCap only allowed for loan ,shares and savings entitites
|
||||
* In Loan case: Only for the "charge calculation type" set as "%amount", "% loan amount+interest", "%interest",and "%disbursement amount".
|
||||
* In saving case: Only for 1. charge time type is "withdrawlfee" or "savings no activity fee" with charge calculation type as "% amount"
|
||||
* In shares case: Only for charge time type: SHARE_PURCHASE and SHARE_REDEEM and with charge calculation type as % amount only
|
||||
-->
|
||||
@if (
|
||||
(chargeForm.controls.chargeAppliesTo.value === 1 &&
|
||||
(chargeForm.controls.chargeCalculationType.value === 2 ||
|
||||
chargeForm.controls.chargeCalculationType.value === 3 ||
|
||||
chargeForm.controls.chargeCalculationType.value === 4 ||
|
||||
chargeForm.controls.chargeCalculationType.value === 5)) ||
|
||||
(chargeForm.controls.chargeAppliesTo.value === 2 &&
|
||||
(chargeForm.controls.chargeTimeType.value === 16 || chargeForm.controls.chargeTimeType.value === 5) &&
|
||||
chargeForm.controls.chargeCalculationType.value === 2) ||
|
||||
(chargeForm.controls.chargeAppliesTo.value === 4 &&
|
||||
(chargeForm.controls.chargeTimeType.value === 14 || chargeForm.controls.chargeTimeType.value === 15) &&
|
||||
chargeForm.controls.chargeCalculationType.value === 2)
|
||||
) {
|
||||
<mat-form-field class="flex-48">
|
||||
<mat-label>{{ 'labels.inputs.Minimum Charge Cap' | translate }}</mat-label>
|
||||
<input matInput autofocus formControlName="minCap" mifosxValidateOnFocus />
|
||||
@if (chargeForm.controls.minCap.hasError('maxValue')) {
|
||||
<mat-error>
|
||||
{{ 'errors.validation.msg.loanproduct.minimumGap.not.greater.than.specified.number' | translate }} ({{
|
||||
chargeForm.controls.maxCap.value
|
||||
}})
|
||||
</mat-error>
|
||||
@if (!chargeData.taxGroup) {
|
||||
<mat-select formControlName="taxGroupId">
|
||||
@for (taxGroup of chargeData.taxGroupOptions; track taxGroup) {
|
||||
<mat-option [value]="taxGroup.id">
|
||||
{{ taxGroup.name }}
|
||||
</mat-option>
|
||||
}
|
||||
</mat-form-field>
|
||||
}
|
||||
@if (
|
||||
(chargeForm.controls.chargeAppliesTo.value === 1 &&
|
||||
(chargeForm.controls.chargeCalculationType.value === 2 ||
|
||||
chargeForm.controls.chargeCalculationType.value === 3 ||
|
||||
chargeForm.controls.chargeCalculationType.value === 4 ||
|
||||
chargeForm.controls.chargeCalculationType.value === 5)) ||
|
||||
(chargeForm.controls.chargeAppliesTo.value === 2 &&
|
||||
(chargeForm.controls.chargeTimeType.value === 16 || chargeForm.controls.chargeTimeType.value === 5) &&
|
||||
chargeForm.controls.chargeCalculationType.value === 2) ||
|
||||
(chargeForm.controls.chargeAppliesTo.value === 4 &&
|
||||
(chargeForm.controls.chargeTimeType.value === 14 || chargeForm.controls.chargeTimeType.value === 15) &&
|
||||
chargeForm.controls.chargeCalculationType.value === 2)
|
||||
) {
|
||||
<mat-form-field class="flex-48">
|
||||
<mat-label>{{ 'labels.inputs.Maximum Charge Cap' | translate }}</mat-label>
|
||||
<input matInput autofocus formControlName="maxCap" mifosxValidateOnFocus />
|
||||
@if (chargeForm.controls.maxCap.hasError('minValue')) {
|
||||
<mat-error>
|
||||
{{ 'errors.validation.msg.loanproduct.maximumGap.not.greater.than.specified.number' | translate }} ({{
|
||||
chargeForm.controls.minCap.value
|
||||
}})
|
||||
</mat-error>
|
||||
}
|
||||
</mat-form-field>
|
||||
</mat-select>
|
||||
}
|
||||
</mat-form-field>
|
||||
|
||||
@if (showGLAccount) {
|
||||
<mifosx-gl-account-selector
|
||||
class="flex-48"
|
||||
[inputFormControl]="chargeForm.controls.incomeAccountId"
|
||||
[glAccountList]="chargeData.incomeOrLiabilityAccountOptions.incomeAccountOptions"
|
||||
[required]="true"
|
||||
[inputLabel]="'Income from Charge'"
|
||||
@if (addFeeFrequency) {
|
||||
<div class="ec-checkbox-row">
|
||||
<mat-checkbox
|
||||
labelPosition="before"
|
||||
[checked]="addFeeFrequency && showFeeOptions"
|
||||
(change)="getFeeFrequency($event.checked)"
|
||||
>
|
||||
</mifosx-gl-account-selector>
|
||||
}
|
||||
|
||||
<mat-form-field class="flex-48">
|
||||
<mat-label>{{ 'labels.inputs.Tax Group' | translate }}</mat-label>
|
||||
@if (chargeData.taxGroup) {
|
||||
<mat-select formControlName="taxGroupId">
|
||||
@for (taxGroup of chargeData.taxGroupOptions; track taxGroup) {
|
||||
<mat-option [value]="taxGroup.id">
|
||||
{{ taxGroup.name }}
|
||||
</mat-option>
|
||||
}
|
||||
</mat-select>
|
||||
}
|
||||
|
||||
@if (!chargeData.taxGroup) {
|
||||
<mat-select formControlName="taxGroupId">
|
||||
@for (taxGroup of chargeData.taxGroupOptions; track taxGroup) {
|
||||
<mat-option [value]="taxGroup.id">
|
||||
{{ taxGroup.name }}
|
||||
</mat-option>
|
||||
}
|
||||
</mat-select>
|
||||
}
|
||||
</mat-form-field>
|
||||
|
||||
@if (addFeeFrequency) {
|
||||
<div class="password-never-expires-wrapper checkbox flex-48">
|
||||
<mat-checkbox
|
||||
labelPosition="before"
|
||||
[checked]="addFeeFrequency && showFeeOptions"
|
||||
(change)="getFeeFrequency($event.checked)"
|
||||
>
|
||||
{{ 'labels.inputs.Add Fee Frequency' | translate }}
|
||||
</mat-checkbox>
|
||||
</div>
|
||||
}
|
||||
|
||||
@if (addFeeFrequency && showFeeOptions) {
|
||||
<mat-form-field class="flex-48">
|
||||
<mat-label>{{ 'labels.inputs.Frequency Interval' | translate }}</mat-label>
|
||||
<input matInput required autofocus type="text" formControlName="feeInterval" />
|
||||
@if (chargeForm.controls.feeInterval.hasError('required')) {
|
||||
<mat-error>
|
||||
{{ 'labels.inputs.Frequency Interval' | translate }} {{ 'labels.commons.is' | translate }}
|
||||
<strong>{{ 'labels.commons.required' | translate }}</strong>
|
||||
</mat-error>
|
||||
}
|
||||
</mat-form-field>
|
||||
}
|
||||
|
||||
@if (addFeeFrequency && showFeeOptions) {
|
||||
<mat-form-field class="flex-48">
|
||||
<mat-label>{{ 'labels.inputs.Charge Frequency' | translate }}</mat-label>
|
||||
<mat-select required formControlName="feeFrequency">
|
||||
@for (chargeFrequency of chargeData.feeFrequencyOptions; track chargeFrequency) {
|
||||
<mat-option [value]="chargeFrequency.id">
|
||||
{{ chargeFrequency.value | translateKey: 'catalogs' }}
|
||||
</mat-option>
|
||||
}
|
||||
</mat-select>
|
||||
@if (chargeForm.controls.feeFrequency.hasError('required')) {
|
||||
<mat-error>
|
||||
{{ 'labels.inputs.Add Fee Frequency' | translate }} {{ 'labels.commons.is' | translate }}
|
||||
<strong>{{ 'labels.commons.required' | translate }}</strong>
|
||||
</mat-error>
|
||||
}
|
||||
</mat-form-field>
|
||||
}
|
||||
</div>
|
||||
|
||||
<div class="layout-row-wrap gap-2percent layout-lt-md-column form-section">
|
||||
<div class="password-never-expires-wrapper flex-48">
|
||||
<mat-checkbox labelPosition="before" formControlName="active">
|
||||
{{ 'labels.status.Active' | translate }}
|
||||
{{ 'labels.inputs.Add Fee Frequency' | translate }}
|
||||
</mat-checkbox>
|
||||
</div>
|
||||
}
|
||||
|
||||
@if (addFeeFrequency && showFeeOptions) {
|
||||
<mat-form-field appearance="outline">
|
||||
<mat-label>{{ 'labels.inputs.Frequency Interval' | translate }}</mat-label>
|
||||
<input matInput required autofocus type="text" formControlName="feeInterval" />
|
||||
@if (chargeForm.controls.feeInterval.hasError('required')) {
|
||||
<mat-error>
|
||||
{{ 'labels.inputs.Frequency Interval' | translate }} {{ 'labels.commons.is' | translate }}
|
||||
<strong>{{ 'labels.commons.required' | translate }}</strong>
|
||||
</mat-error>
|
||||
}
|
||||
</mat-form-field>
|
||||
}
|
||||
|
||||
@if (addFeeFrequency && showFeeOptions) {
|
||||
<mat-form-field appearance="outline">
|
||||
<mat-label>{{ 'labels.inputs.Charge Frequency' | translate }}</mat-label>
|
||||
<mat-select required formControlName="feeFrequency">
|
||||
@for (chargeFrequency of chargeData.feeFrequencyOptions; track chargeFrequency) {
|
||||
<mat-option [value]="chargeFrequency.id">
|
||||
{{ chargeFrequency.value | translateKey: 'catalogs' }}
|
||||
</mat-option>
|
||||
}
|
||||
</mat-select>
|
||||
@if (chargeForm.controls.feeFrequency.hasError('required')) {
|
||||
<mat-error>
|
||||
{{ 'labels.inputs.Add Fee Frequency' | translate }} {{ 'labels.commons.is' | translate }}
|
||||
<strong>{{ 'labels.commons.required' | translate }}</strong>
|
||||
</mat-error>
|
||||
}
|
||||
</mat-form-field>
|
||||
}
|
||||
|
||||
<div class="ec-checkbox-row ec-checkbox-pair">
|
||||
<mat-checkbox labelPosition="before" formControlName="active">
|
||||
{{ 'labels.status.Active' | translate }}
|
||||
</mat-checkbox>
|
||||
|
||||
@if (showPenalty) {
|
||||
<div class="send-password-to-email-wrapper flex-48">
|
||||
<mat-checkbox labelPosition="before" formControlName="penalty">
|
||||
{{ 'labels.commons.Is' | translate }} {{ 'labels.inputs.Penalty' | translate }}
|
||||
</mat-checkbox>
|
||||
</div>
|
||||
<mat-checkbox labelPosition="before" formControlName="penalty">
|
||||
{{ 'labels.commons.Is' | translate }} {{ 'labels.inputs.Penalty' | translate }}
|
||||
</mat-checkbox>
|
||||
}
|
||||
</div>
|
||||
</mat-card-content>
|
||||
</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]="!chargeForm.valid" *mifosxHasPermission="'UPDATE_CHARGE'">
|
||||
{{ 'labels.buttons.Submit' | translate }}
|
||||
</button>
|
||||
</mat-card-actions>
|
||||
</form>
|
||||
</mat-card>
|
||||
<!-- Action Bar -->
|
||||
<div class="ec-actions">
|
||||
<button type="button" mat-raised-button [routerLink]="['../']">
|
||||
{{ 'labels.buttons.Cancel' | translate }}
|
||||
</button>
|
||||
<button mat-flat-button color="primary" [disabled]="!chargeForm.valid" *mifosxHasPermission="'UPDATE_CHARGE'">
|
||||
{{ 'labels.buttons.Submit' | translate }}
|
||||
</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
@@ -6,10 +6,103 @@
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
.checkbox {
|
||||
padding-top: 10px;
|
||||
.ec-container {
|
||||
max-width: 960px;
|
||||
margin: 0 auto;
|
||||
padding: 24px 16px;
|
||||
}
|
||||
|
||||
.form-section {
|
||||
margin-top: 10px;
|
||||
.ec-header {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 12px;
|
||||
margin-bottom: 24px;
|
||||
|
||||
&__icon {
|
||||
width: 40px;
|
||||
height: 40px;
|
||||
border-radius: 10px;
|
||||
background: linear-gradient(135deg, #0ea5e9 0%, #1353a0 100%);
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
color: #fff;
|
||||
font-size: 18px;
|
||||
}
|
||||
|
||||
&__title {
|
||||
font-size: 20px;
|
||||
font-weight: 600;
|
||||
color: #202124;
|
||||
margin: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.ec-section {
|
||||
border: 1px solid #e2e8f0;
|
||||
border-radius: 10px;
|
||||
overflow: hidden;
|
||||
background: #fff;
|
||||
margin-bottom: 16px;
|
||||
|
||||
&__header {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
padding: 12px 24px;
|
||||
background: #f8f9fa;
|
||||
border-bottom: 1px solid #e8eaed;
|
||||
|
||||
i {
|
||||
font-size: 14px;
|
||||
color: #0ea5e9;
|
||||
}
|
||||
|
||||
h3 {
|
||||
font-size: 14px;
|
||||
font-weight: 600;
|
||||
color: #202124;
|
||||
margin: 0;
|
||||
}
|
||||
}
|
||||
|
||||
&__body {
|
||||
padding: 16px 24px;
|
||||
|
||||
.full-width {
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.ec-grid {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(2, 1fr);
|
||||
gap: 4px 16px;
|
||||
}
|
||||
|
||||
.ec-checkbox-row {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 16px;
|
||||
padding: 4px 0;
|
||||
}
|
||||
|
||||
.ec-checkbox-pair {
|
||||
grid-column: 1 / -1;
|
||||
}
|
||||
|
||||
.ec-actions {
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
gap: 12px;
|
||||
margin-top: 20px;
|
||||
padding: 16px 0;
|
||||
border-top: 1px solid rgba(0, 0, 0, 0.08);
|
||||
}
|
||||
|
||||
@media (max-width: 600px) {
|
||||
.ec-grid {
|
||||
grid-template-columns: 1fr;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,169 +6,125 @@
|
||||
file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
-->
|
||||
|
||||
<div class="layout-row align-end gap-2px responsive-column container m-b-20">
|
||||
<button mat-raised-button color="primary" [routerLink]="['edit']" *mifosxHasPermission="'UPDATE_CHARGE'">
|
||||
<fa-icon icon="edit" class="m-r-10"></fa-icon>
|
||||
{{ 'labels.heading.Edit' | translate }}
|
||||
</button>
|
||||
<button mat-raised-button color="warn" (click)="deleteCharge()" *mifosxHasPermission="'DELETE_CHARGE'">
|
||||
<fa-icon icon="trash" class="m-r-10"></fa-icon>
|
||||
{{ 'labels.heading.Delete' | translate }}
|
||||
</button>
|
||||
</div>
|
||||
<div class="vc-container">
|
||||
<div class="vc-top-bar">
|
||||
<h1 class="vc-top-bar__title">
|
||||
<i class="fas fa-file-invoice-dollar"></i>
|
||||
{{ chargeData.name }}
|
||||
</h1>
|
||||
<div class="vc-top-bar__actions">
|
||||
<button mat-flat-button color="primary" [routerLink]="['edit']" *mifosxHasPermission="'UPDATE_CHARGE'">
|
||||
<fa-icon icon="edit" class="m-r-10"></fa-icon>
|
||||
{{ 'labels.heading.Edit' | translate }}
|
||||
</button>
|
||||
<button mat-flat-button color="warn" (click)="deleteCharge()" *mifosxHasPermission="'DELETE_CHARGE'">
|
||||
<fa-icon icon="trash" class="m-r-10"></fa-icon>
|
||||
{{ 'labels.heading.Delete' | translate }}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="container">
|
||||
<mat-card>
|
||||
<mat-card-content>
|
||||
<div class="layout-row-wrap">
|
||||
<div class="flex-50 mat-body-strong">
|
||||
{{ 'labels.inputs.Charge Name' | translate }}
|
||||
</div>
|
||||
|
||||
<div class="flex-50">
|
||||
{{ chargeData.name }}
|
||||
</div>
|
||||
|
||||
<div class="flex-50 mat-body-strong">
|
||||
{{ 'labels.inputs.Charge Applies To' | translate }}
|
||||
</div>
|
||||
|
||||
<div class="flex-50">
|
||||
{{ chargeData.chargeAppliesTo.value | translateKey: 'catalogs' }}
|
||||
</div>
|
||||
|
||||
<div class="flex-50 mat-body-strong">
|
||||
{{ 'labels.inputs.Penalty' | translate }}
|
||||
</div>
|
||||
|
||||
<div class="flex-50">
|
||||
{{ chargeData.penalty === true | yesNo }}
|
||||
</div>
|
||||
|
||||
<div class="flex-50 mat-body-strong">
|
||||
{{ 'labels.inputs.Currency' | translate }}
|
||||
</div>
|
||||
|
||||
<div class="flex-50">
|
||||
{{ chargeData.currency.name }}
|
||||
</div>
|
||||
|
||||
<div class="flex-50 mat-body-strong">
|
||||
{{ 'labels.inputs.Amount' | translate }}
|
||||
</div>
|
||||
|
||||
<div class="flex-50">
|
||||
{{ chargeData.amount }}
|
||||
</div>
|
||||
|
||||
@if (minCap) {
|
||||
<div class="flex-50 mat-body-strong">
|
||||
{{ 'labels.inputs.Minimum Charge Cap' | translate }}
|
||||
</div>
|
||||
}
|
||||
|
||||
@if (minCap) {
|
||||
<div class="flex-50">
|
||||
{{ chargeData.minCap }}
|
||||
</div>
|
||||
}
|
||||
|
||||
@if (maxCap) {
|
||||
<div class="flex-50 mat-body-strong">
|
||||
{{ 'labels.inputs.Maximum Charge Cap' | translate }}
|
||||
</div>
|
||||
}
|
||||
|
||||
@if (maxCap) {
|
||||
<div class="flex-50">
|
||||
{{ chargeData.maxCap }}
|
||||
</div>
|
||||
}
|
||||
|
||||
<div class="flex-50 mat-body-strong">
|
||||
{{ 'labels.inputs.Charge Time Type' | translate }}
|
||||
</div>
|
||||
|
||||
<div class="flex-50">
|
||||
{{ chargeData.chargeTimeType.value | translateKey: 'catalogs' }}
|
||||
</div>
|
||||
|
||||
<div class="flex-50 mat-body-strong">
|
||||
{{ 'labels.inputs.Charge Calculation Type' | translate }}
|
||||
</div>
|
||||
|
||||
<div class="flex-50">
|
||||
{{ chargeData.chargeCalculationType.value | translateKey: 'catalogs' }}
|
||||
</div>
|
||||
|
||||
<div class="flex-50 mat-body-strong">
|
||||
{{ 'labels.inputs.Charge Payment Mode' | translate }}
|
||||
</div>
|
||||
|
||||
<div class="flex-50">
|
||||
{{ chargeData.chargePaymentMode.value | translateKey: 'catalogs' }}
|
||||
</div>
|
||||
|
||||
<div class="flex-50 mat-body-strong">
|
||||
{{ 'labels.status.Active' | translate }}
|
||||
</div>
|
||||
|
||||
<div class="flex-50">
|
||||
{{ chargeData.active === true | yesNo }}
|
||||
</div>
|
||||
|
||||
@if (chargeData.chargeTimeType.id === 9 && chargeData.feeFrequency) {
|
||||
<div class="flex-50 mat-body-strong">
|
||||
{{ 'labels.inputs.Add Fee Frequency' | translate }}
|
||||
</div>
|
||||
}
|
||||
|
||||
@if (chargeData.chargeTimeType.id === 9 && chargeData.feeFrequency && chargeData.feeFrequency) {
|
||||
<div class="flex-50">
|
||||
{{ chargeData.feeFrequency.value | translateKey: 'catalogs' }}
|
||||
</div>
|
||||
}
|
||||
|
||||
@if (chargeData.chargeTimeType.id === 9 && chargeData.feeInterval) {
|
||||
<div class="flex-50 mat-body-strong">
|
||||
{{ 'labels.inputs.Frequency Interval' | translate }}
|
||||
</div>
|
||||
}
|
||||
|
||||
@if (chargeData.chargeTimeType.id === 9 && chargeData.feeInterval) {
|
||||
<div class="flex-50">
|
||||
{{ chargeData.feeInterval }}
|
||||
</div>
|
||||
}
|
||||
|
||||
@if (chargeData.incomeOrLiabilityAccount) {
|
||||
<mifosx-gl-account-display
|
||||
class="flex-100"
|
||||
[accountTitle]="'Income From Charges'"
|
||||
[glAccount]="chargeData.incomeOrLiabilityAccount"
|
||||
[withTitle]="'50%'"
|
||||
>
|
||||
</mifosx-gl-account-display>
|
||||
}
|
||||
|
||||
@if (chargeData.taxGroup) {
|
||||
<div class="flex-50 mat-body-strong">
|
||||
{{ 'labels.inputs.Tax Group' | translate }}
|
||||
</div>
|
||||
}
|
||||
|
||||
@if (chargeData.taxGroup) {
|
||||
<div class="flex-50">
|
||||
{{ chargeData.taxGroup.name }}
|
||||
</div>
|
||||
}
|
||||
<div class="vc-section">
|
||||
<div class="vc-section__header">
|
||||
<i class="fas fa-list-alt"></i>
|
||||
<h3>{{ 'labels.heading.Charge Details' | translate }}</h3>
|
||||
</div>
|
||||
<div class="vc-section__body">
|
||||
<div class="vc-row">
|
||||
<span class="vc-row__label">{{ 'labels.inputs.Charge Name' | translate }}</span>
|
||||
<span class="vc-row__value">{{ chargeData.name }}</span>
|
||||
</div>
|
||||
|
||||
<div class="layout-row layout-align-center gap-2percent column-on-mobile">
|
||||
<button type="button" mat-raised-button color="primary" [routerLink]="['../']">
|
||||
{{ 'labels.buttons.Back' | translate }}
|
||||
</button>
|
||||
<div class="vc-row">
|
||||
<span class="vc-row__label">{{ 'labels.inputs.Charge Applies To' | translate }}</span>
|
||||
<span class="vc-row__value">{{ chargeData.chargeAppliesTo.value | translateKey: 'catalogs' }}</span>
|
||||
</div>
|
||||
</mat-card-content>
|
||||
</mat-card>
|
||||
|
||||
<div class="vc-row">
|
||||
<span class="vc-row__label">{{ 'labels.inputs.Penalty' | translate }}</span>
|
||||
<span class="vc-row__value">{{ chargeData.penalty === true | yesNo }}</span>
|
||||
</div>
|
||||
|
||||
<div class="vc-row">
|
||||
<span class="vc-row__label">{{ 'labels.inputs.Currency' | translate }}</span>
|
||||
<span class="vc-row__value">{{ chargeData.currency.name }}</span>
|
||||
</div>
|
||||
|
||||
<div class="vc-row">
|
||||
<span class="vc-row__label">{{ 'labels.inputs.Amount' | translate }}</span>
|
||||
<span class="vc-row__value">{{ chargeData.amount }}</span>
|
||||
</div>
|
||||
|
||||
@if (minCap) {
|
||||
<div class="vc-row">
|
||||
<span class="vc-row__label">{{ 'labels.inputs.Minimum Charge Cap' | translate }}</span>
|
||||
<span class="vc-row__value">{{ chargeData.minCap }}</span>
|
||||
</div>
|
||||
}
|
||||
|
||||
@if (maxCap) {
|
||||
<div class="vc-row">
|
||||
<span class="vc-row__label">{{ 'labels.inputs.Maximum Charge Cap' | translate }}</span>
|
||||
<span class="vc-row__value">{{ chargeData.maxCap }}</span>
|
||||
</div>
|
||||
}
|
||||
|
||||
<div class="vc-row">
|
||||
<span class="vc-row__label">{{ 'labels.inputs.Charge Time Type' | translate }}</span>
|
||||
<span class="vc-row__value">{{ chargeData.chargeTimeType.value | translateKey: 'catalogs' }}</span>
|
||||
</div>
|
||||
|
||||
<div class="vc-row">
|
||||
<span class="vc-row__label">{{ 'labels.inputs.Charge Calculation Type' | translate }}</span>
|
||||
<span class="vc-row__value">{{ chargeData.chargeCalculationType.value | translateKey: 'catalogs' }}</span>
|
||||
</div>
|
||||
|
||||
<div class="vc-row">
|
||||
<span class="vc-row__label">{{ 'labels.inputs.Charge Payment Mode' | translate }}</span>
|
||||
<span class="vc-row__value">{{ chargeData.chargePaymentMode.value | translateKey: 'catalogs' }}</span>
|
||||
</div>
|
||||
|
||||
<div class="vc-row">
|
||||
<span class="vc-row__label">{{ 'labels.status.Active' | translate }}</span>
|
||||
<span class="vc-row__value">{{ chargeData.active === true | yesNo }}</span>
|
||||
</div>
|
||||
|
||||
@if (chargeData.chargeTimeType.id === 9 && chargeData.feeFrequency) {
|
||||
<div class="vc-row">
|
||||
<span class="vc-row__label">{{ 'labels.inputs.Add Fee Frequency' | translate }}</span>
|
||||
<span class="vc-row__value">{{ chargeData.feeFrequency.value | translateKey: 'catalogs' }}</span>
|
||||
</div>
|
||||
}
|
||||
|
||||
@if (chargeData.chargeTimeType.id === 9 && chargeData.feeInterval) {
|
||||
<div class="vc-row">
|
||||
<span class="vc-row__label">{{ 'labels.inputs.Frequency Interval' | translate }}</span>
|
||||
<span class="vc-row__value">{{ chargeData.feeInterval }}</span>
|
||||
</div>
|
||||
}
|
||||
|
||||
@if (chargeData.incomeOrLiabilityAccount) {
|
||||
<mifosx-gl-account-display
|
||||
class="vc-gl-account"
|
||||
[accountTitle]="'Income From Charges'"
|
||||
[glAccount]="chargeData.incomeOrLiabilityAccount"
|
||||
[withTitle]="'50%'"
|
||||
>
|
||||
</mifosx-gl-account-display>
|
||||
}
|
||||
|
||||
@if (chargeData.taxGroup) {
|
||||
<div class="vc-row">
|
||||
<span class="vc-row__label">{{ 'labels.inputs.Tax Group' | translate }}</span>
|
||||
<span class="vc-row__value">{{ chargeData.taxGroup.name }}</span>
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="vc-actions">
|
||||
<button type="button" mat-raised-button [routerLink]="['../']">
|
||||
{{ 'labels.buttons.Back' | translate }}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -6,13 +6,124 @@
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
.container {
|
||||
max-width: 37rem;
|
||||
.vc-container {
|
||||
max-width: 960px;
|
||||
margin: 0 auto;
|
||||
padding: 24px 16px;
|
||||
}
|
||||
|
||||
.content {
|
||||
div {
|
||||
margin: 1rem 0;
|
||||
word-wrap: break-word;
|
||||
.vc-top-bar {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
margin-bottom: 24px;
|
||||
flex-wrap: wrap;
|
||||
gap: 12px;
|
||||
|
||||
&__title {
|
||||
font-size: 20px;
|
||||
font-weight: 600;
|
||||
color: #202124;
|
||||
margin: 0;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 10px;
|
||||
|
||||
i {
|
||||
color: #1353a0;
|
||||
font-size: 18px;
|
||||
}
|
||||
}
|
||||
|
||||
&__actions {
|
||||
display: flex;
|
||||
gap: 8px;
|
||||
}
|
||||
}
|
||||
|
||||
.vc-section {
|
||||
border: 1px solid #e2e8f0;
|
||||
border-radius: 10px;
|
||||
overflow: hidden;
|
||||
background: #fff;
|
||||
margin-bottom: 16px;
|
||||
|
||||
&__header {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
padding: 12px 24px;
|
||||
background: #f8f9fa;
|
||||
border-bottom: 1px solid #e8eaed;
|
||||
|
||||
i {
|
||||
font-size: 14px;
|
||||
color: #0ea5e9;
|
||||
}
|
||||
|
||||
h3 {
|
||||
font-size: 14px;
|
||||
font-weight: 600;
|
||||
color: #202124;
|
||||
margin: 0;
|
||||
}
|
||||
}
|
||||
|
||||
&__body {
|
||||
padding: 4px 24px;
|
||||
}
|
||||
}
|
||||
|
||||
.vc-row {
|
||||
display: flex;
|
||||
padding: 6px 0;
|
||||
border-bottom: 1px solid #f1f3f4;
|
||||
|
||||
&:last-child {
|
||||
border-bottom: none;
|
||||
}
|
||||
|
||||
&__label {
|
||||
flex: 0 0 40%;
|
||||
font-size: 13px;
|
||||
font-weight: 500;
|
||||
color: #5f6368;
|
||||
}
|
||||
|
||||
&__value {
|
||||
flex: 1;
|
||||
font-size: 13px;
|
||||
color: #202124;
|
||||
}
|
||||
}
|
||||
|
||||
.vc-gl-account {
|
||||
display: block;
|
||||
padding: 6px 0;
|
||||
border-bottom: 1px solid #f1f3f4;
|
||||
}
|
||||
|
||||
.vc-actions {
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
gap: 12px;
|
||||
margin-top: 20px;
|
||||
padding: 16px 0;
|
||||
border-top: 1px solid rgba(0, 0, 0, 0.08);
|
||||
}
|
||||
|
||||
@media (max-width: 600px) {
|
||||
.vc-top-bar {
|
||||
flex-direction: column;
|
||||
align-items: flex-start;
|
||||
}
|
||||
|
||||
.vc-row {
|
||||
flex-direction: column;
|
||||
gap: 2px;
|
||||
|
||||
&__label {
|
||||
flex: none;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,22 +6,30 @@
|
||||
file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
-->
|
||||
|
||||
<div class="container m-b-20 layout-row align-end gap-20px">
|
||||
<button mat-raised-button color="primary" [routerLink]="['create']" *mifosxHasPermission="'CREATE_CHARGE'">
|
||||
<fa-icon icon="plus" class="m-r-10"></fa-icon>
|
||||
{{ 'labels.text.Create Collateral' | translate }}
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<div class="container">
|
||||
<div class="layout-row gap-20px">
|
||||
<mat-form-field class="flex-fill">
|
||||
<mat-label>{{ 'labels.inputs.Filter' | translate }}</mat-label>
|
||||
<input matInput (keyup)="applyFilter($event.target.value)" />
|
||||
</mat-form-field>
|
||||
<div class="table-header">
|
||||
<div class="table-title-group">
|
||||
<h2 class="table-title">
|
||||
<i class="fas fa-shield-alt title-icon"></i>
|
||||
{{ 'labels.text.Collateral' | translate }}
|
||||
</h2>
|
||||
</div>
|
||||
<div class="table-actions">
|
||||
<mat-form-field appearance="outline" class="table-search">
|
||||
<i matPrefix class="fas fa-search"></i>
|
||||
<input matInput (keyup)="applyFilter($event.target.value)" placeholder="{{ 'labels.inputs.Filter' | translate }}" />
|
||||
</mat-form-field>
|
||||
<div class="table-buttons">
|
||||
<button mat-flat-button color="primary" class="btn-create" [routerLink]="['create']" *mifosxHasPermission="'CREATE_CHARGE'">
|
||||
<fa-icon icon="plus" class="m-r-10"></fa-icon>
|
||||
{{ 'labels.text.Create Collateral' | translate }}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="mat-elevation-z8">
|
||||
<table mat-table [dataSource]="dataSource" matSort>
|
||||
|
||||
<div class="table-container">
|
||||
<table mat-table [dataSource]="dataSource" matSort class="modern-table">
|
||||
<ng-container matColumnDef="name">
|
||||
<th mat-header-cell *matHeaderCellDef mat-sort-header>{{ 'labels.inputs.Name' | translate }}</th>
|
||||
<td mat-cell *matCellDef="let collateral">{{ collateral.name }}</td>
|
||||
@@ -48,7 +56,7 @@
|
||||
</ng-container>
|
||||
|
||||
<tr mat-header-row *matHeaderRowDef="displayedColumns"></tr>
|
||||
<tr mat-row *matRowDef="let row; columns: displayedColumns" [routerLink]="[row.id]" class="select-row"></tr>
|
||||
<tr mat-row *matRowDef="let row; columns: displayedColumns" [routerLink]="[row.id]" class="table-row"></tr>
|
||||
</table>
|
||||
|
||||
<mat-paginator [pageSizeOptions]="[10, 25, 50, 100]" showFirstLastButtons></mat-paginator>
|
||||
|
||||
@@ -6,26 +6,4 @@
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
table {
|
||||
width: 100%;
|
||||
|
||||
.select-row:hover {
|
||||
cursor: pointer;
|
||||
}
|
||||
}
|
||||
|
||||
.true {
|
||||
color: #32cd32;
|
||||
}
|
||||
|
||||
.false {
|
||||
color: #f44366;
|
||||
}
|
||||
|
||||
.ispenalty {
|
||||
color: #32cd32;
|
||||
}
|
||||
|
||||
.nopenalty {
|
||||
color: #f44366;
|
||||
}
|
||||
@use '../../shared/styles/list-layout' as *;
|
||||
|
||||
@@ -6,93 +6,105 @@
|
||||
file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
-->
|
||||
|
||||
<div class="container">
|
||||
<mat-card>
|
||||
<form [formGroup]="collateralForm" (ngSubmit)="submit()">
|
||||
<mat-card-content>
|
||||
<div class="layout-row-wrap gap-2px responsive-column">
|
||||
<mat-form-field class="flex-48">
|
||||
<mat-label>{{ 'labels.inputs.Name' | translate }}</mat-label>
|
||||
<input matInput required formControlName="name" />
|
||||
@if (collateralForm.controls.name.hasError('required')) {
|
||||
<mat-error>
|
||||
{{ 'labels.inputs.Name' | translate }} {{ 'labels.commons.is' | translate }}
|
||||
<strong>{{ 'labels.commons.required' | translate }}</strong>
|
||||
</mat-error>
|
||||
}
|
||||
</mat-form-field>
|
||||
<mat-form-field class="flex-48">
|
||||
<mat-label>{{ 'labels.inputs.Type/Quality' | translate }}</mat-label>
|
||||
<input matInput required formControlName="quality" />
|
||||
@if (collateralForm.controls.quality.hasError('required')) {
|
||||
<mat-error>
|
||||
{{ 'labels.inputs.Type/Quality' | translate }} {{ 'labels.commons.is' | translate }}
|
||||
<strong>{{ 'labels.commons.required' | translate }}</strong>
|
||||
</mat-error>
|
||||
}
|
||||
</mat-form-field>
|
||||
<mat-form-field class="flex-48">
|
||||
<mat-label>{{ 'labels.inputs.Unit Type' | translate }}</mat-label>
|
||||
<input matInput required formControlName="unitType" />
|
||||
@if (collateralForm.controls.unitType.hasError('required')) {
|
||||
<mat-error>
|
||||
{{ 'labels.inputs.Unit Type' | translate }} {{ 'labels.commons.is' | translate }}
|
||||
<strong>{{ 'labels.commons.required' | translate }}</strong>
|
||||
</mat-error>
|
||||
}
|
||||
</mat-form-field>
|
||||
<mat-form-field class="flex-48">
|
||||
<mat-label>{{ 'labels.inputs.Base Price' | translate }}</mat-label>
|
||||
<input matInput required formControlName="basePrice" />
|
||||
@if (collateralForm.controls.basePrice.hasError('required')) {
|
||||
<mat-error>
|
||||
{{ 'labels.inputs.Base Price' | translate }} {{ 'labels.commons.is' | translate }}
|
||||
<strong>{{ 'labels.commons.required' | translate }}</strong>
|
||||
</mat-error>
|
||||
}
|
||||
</mat-form-field>
|
||||
<mat-form-field class="flex-48">
|
||||
<mat-label>{{ 'labels.inputs.Percentage to Base' | translate }}</mat-label>
|
||||
<input matInput required formControlName="pctToBase" />
|
||||
@if (collateralForm.controls.pctToBase.hasError('required')) {
|
||||
<mat-error>
|
||||
{{ 'labels.inputs.Percentage to Base' | translate }} {{ 'labels.commons.is' | translate }}
|
||||
<strong>{{ 'labels.commons.required' | translate }}</strong>
|
||||
</mat-error>
|
||||
}
|
||||
</mat-form-field>
|
||||
<mat-form-field class="flex-48">
|
||||
<mat-label>{{ 'labels.heading.Currency' | translate }}</mat-label>
|
||||
<mat-select required formControlName="currency">
|
||||
@for (currency of collateralTemplateData; track currency) {
|
||||
<mat-option [value]="currency.code">
|
||||
{{ currency.name }}
|
||||
</mat-option>
|
||||
}
|
||||
</mat-select>
|
||||
@if (collateralForm.controls.currency.hasError('required')) {
|
||||
<mat-error>
|
||||
{{ 'labels.heading.Currency' | translate }} {{ 'labels.commons.is' | translate }}
|
||||
<strong>{{ 'labels.commons.required' | translate }}</strong>
|
||||
</mat-error>
|
||||
}
|
||||
</mat-form-field>
|
||||
</div>
|
||||
</mat-card-content>
|
||||
<div class="ccl-container">
|
||||
<div class="ccl-page-header">
|
||||
<i class="fas fa-shield-alt ccl-page-header__icon"></i>
|
||||
<h2 class="ccl-page-header__title">{{ 'labels.text.Create Collateral' | translate }}</h2>
|
||||
</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]="!collateralForm.valid"
|
||||
*mifosxHasPermission="'CREATE_CHARGE'"
|
||||
>
|
||||
{{ 'labels.buttons.Submit' | translate }}
|
||||
</button>
|
||||
</mat-card-actions>
|
||||
</form>
|
||||
</mat-card>
|
||||
<form [formGroup]="collateralForm" (ngSubmit)="submit()">
|
||||
<div class="ccl-section">
|
||||
<div class="ccl-section__header">
|
||||
<i class="fas fa-info-circle"></i>
|
||||
<h3>{{ 'labels.heading.Collateral Details' | translate }}</h3>
|
||||
</div>
|
||||
<div class="ccl-section__body">
|
||||
<mat-form-field appearance="outline">
|
||||
<mat-label>{{ 'labels.inputs.Name' | translate }}</mat-label>
|
||||
<input matInput required formControlName="name" />
|
||||
@if (collateralForm.controls.name.hasError('required')) {
|
||||
<mat-error>
|
||||
{{ 'labels.inputs.Name' | translate }} {{ 'labels.commons.is' | translate }}
|
||||
<strong>{{ 'labels.commons.required' | translate }}</strong>
|
||||
</mat-error>
|
||||
}
|
||||
</mat-form-field>
|
||||
|
||||
<mat-form-field appearance="outline">
|
||||
<mat-label>{{ 'labels.inputs.Type/Quality' | translate }}</mat-label>
|
||||
<input matInput required formControlName="quality" />
|
||||
@if (collateralForm.controls.quality.hasError('required')) {
|
||||
<mat-error>
|
||||
{{ 'labels.inputs.Type/Quality' | translate }} {{ 'labels.commons.is' | translate }}
|
||||
<strong>{{ 'labels.commons.required' | translate }}</strong>
|
||||
</mat-error>
|
||||
}
|
||||
</mat-form-field>
|
||||
|
||||
<mat-form-field appearance="outline">
|
||||
<mat-label>{{ 'labels.inputs.Unit Type' | translate }}</mat-label>
|
||||
<input matInput required formControlName="unitType" />
|
||||
@if (collateralForm.controls.unitType.hasError('required')) {
|
||||
<mat-error>
|
||||
{{ 'labels.inputs.Unit Type' | translate }} {{ 'labels.commons.is' | translate }}
|
||||
<strong>{{ 'labels.commons.required' | translate }}</strong>
|
||||
</mat-error>
|
||||
}
|
||||
</mat-form-field>
|
||||
|
||||
<mat-form-field appearance="outline">
|
||||
<mat-label>{{ 'labels.inputs.Base Price' | translate }}</mat-label>
|
||||
<input matInput required formControlName="basePrice" />
|
||||
@if (collateralForm.controls.basePrice.hasError('required')) {
|
||||
<mat-error>
|
||||
{{ 'labels.inputs.Base Price' | translate }} {{ 'labels.commons.is' | translate }}
|
||||
<strong>{{ 'labels.commons.required' | translate }}</strong>
|
||||
</mat-error>
|
||||
}
|
||||
</mat-form-field>
|
||||
|
||||
<mat-form-field appearance="outline">
|
||||
<mat-label>{{ 'labels.inputs.Percentage to Base' | translate }}</mat-label>
|
||||
<input matInput required formControlName="pctToBase" />
|
||||
@if (collateralForm.controls.pctToBase.hasError('required')) {
|
||||
<mat-error>
|
||||
{{ 'labels.inputs.Percentage to Base' | translate }} {{ 'labels.commons.is' | translate }}
|
||||
<strong>{{ 'labels.commons.required' | translate }}</strong>
|
||||
</mat-error>
|
||||
}
|
||||
</mat-form-field>
|
||||
|
||||
<mat-form-field appearance="outline">
|
||||
<mat-label>{{ 'labels.heading.Currency' | translate }}</mat-label>
|
||||
<mat-select required formControlName="currency">
|
||||
@for (currency of collateralTemplateData; track currency) {
|
||||
<mat-option [value]="currency.code">
|
||||
{{ currency.name }}
|
||||
</mat-option>
|
||||
}
|
||||
</mat-select>
|
||||
@if (collateralForm.controls.currency.hasError('required')) {
|
||||
<mat-error>
|
||||
{{ 'labels.heading.Currency' | translate }} {{ 'labels.commons.is' | translate }}
|
||||
<strong>{{ 'labels.commons.required' | translate }}</strong>
|
||||
</mat-error>
|
||||
}
|
||||
</mat-form-field>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="ccl-actions">
|
||||
<button type="button" mat-raised-button [routerLink]="['../']">
|
||||
{{ 'labels.buttons.Cancel' | translate }}
|
||||
</button>
|
||||
<button
|
||||
mat-flat-button
|
||||
color="primary"
|
||||
[disabled]="!collateralForm.valid"
|
||||
*mifosxHasPermission="'CREATE_CHARGE'"
|
||||
>
|
||||
{{ 'labels.buttons.Submit' | translate }}
|
||||
</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
@@ -5,3 +5,78 @@
|
||||
* 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/.
|
||||
*/
|
||||
|
||||
.ccl-container {
|
||||
max-width: 960px;
|
||||
margin: 0 auto;
|
||||
padding: 24px 16px;
|
||||
}
|
||||
|
||||
.ccl-page-header {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 10px;
|
||||
margin-bottom: 24px;
|
||||
|
||||
&__icon {
|
||||
font-size: 20px;
|
||||
color: #1353a0;
|
||||
}
|
||||
|
||||
&__title {
|
||||
font-size: 20px;
|
||||
font-weight: 600;
|
||||
color: #202124;
|
||||
margin: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.ccl-section {
|
||||
border: 1px solid #e2e8f0;
|
||||
border-radius: 10px;
|
||||
overflow: hidden;
|
||||
background: #fff;
|
||||
|
||||
&__header {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
padding: 12px 24px;
|
||||
background: #f8f9fa;
|
||||
border-bottom: 1px solid #e8eaed;
|
||||
|
||||
i {
|
||||
font-size: 14px;
|
||||
color: #0ea5e9;
|
||||
}
|
||||
|
||||
h3 {
|
||||
font-size: 14px;
|
||||
font-weight: 600;
|
||||
color: #202124;
|
||||
margin: 0;
|
||||
}
|
||||
}
|
||||
|
||||
&__body {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(2, 1fr);
|
||||
gap: 4px 16px;
|
||||
padding: 16px 24px;
|
||||
}
|
||||
}
|
||||
|
||||
.ccl-actions {
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
gap: 12px;
|
||||
margin-top: 20px;
|
||||
padding: 16px 0;
|
||||
border-top: 1px solid rgba(0, 0, 0, 0.08);
|
||||
}
|
||||
|
||||
@media (max-width: 600px) {
|
||||
.ccl-section__body {
|
||||
grid-template-columns: 1fr;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,98 +6,105 @@
|
||||
file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
-->
|
||||
|
||||
<div class="container">
|
||||
<mat-card>
|
||||
<form [formGroup]="collateralForm" (ngSubmit)="submit()">
|
||||
<mat-card-content>
|
||||
<div class="layout-row-wrap gap-2px responsive-column">
|
||||
<mat-form-field class="flex-48">
|
||||
<mat-label>{{ 'labels.inputs.Name' | translate }}</mat-label>
|
||||
<input matInput required autoFocus formControlName="name" />
|
||||
@if (collateralForm.controls.name.hasError('required')) {
|
||||
<mat-error>
|
||||
{{ 'labels.inputs.Name' | translate }} {{ 'labels.commons.is' | translate }}
|
||||
<strong>{{ 'labels.commons.required' | translate }}</strong>
|
||||
</mat-error>
|
||||
}
|
||||
</mat-form-field>
|
||||
<div class="ecl-container">
|
||||
<div class="ecl-page-header">
|
||||
<i class="fas fa-shield-alt ecl-page-header__icon"></i>
|
||||
<h2 class="ecl-page-header__title">{{ 'labels.heading.Edit Collateral' | translate }}</h2>
|
||||
</div>
|
||||
|
||||
<mat-form-field class="flex-48">
|
||||
<mat-label>{{ 'labels.inputs.Type/Quality' | translate }}</mat-label>
|
||||
<input matInput required autoFocus formControlName="quality" />
|
||||
@if (collateralForm.controls.quality.hasError('required')) {
|
||||
<mat-error>
|
||||
{{ 'labels.inputs.Type/Quality' | translate }} {{ 'labels.commons.is' | translate }}
|
||||
<strong>{{ 'labels.commons.required' | translate }}</strong>
|
||||
</mat-error>
|
||||
}
|
||||
</mat-form-field>
|
||||
<form [formGroup]="collateralForm" (ngSubmit)="submit()">
|
||||
<div class="ecl-section">
|
||||
<div class="ecl-section__header">
|
||||
<i class="fas fa-info-circle"></i>
|
||||
<h3>{{ 'labels.heading.Collateral Details' | translate }}</h3>
|
||||
</div>
|
||||
<div class="ecl-section__body">
|
||||
<mat-form-field appearance="outline">
|
||||
<mat-label>{{ 'labels.inputs.Name' | translate }}</mat-label>
|
||||
<input matInput required autoFocus formControlName="name" />
|
||||
@if (collateralForm.controls.name.hasError('required')) {
|
||||
<mat-error>
|
||||
{{ 'labels.inputs.Name' | translate }} {{ 'labels.commons.is' | translate }}
|
||||
<strong>{{ 'labels.commons.required' | translate }}</strong>
|
||||
</mat-error>
|
||||
}
|
||||
</mat-form-field>
|
||||
|
||||
<mat-form-field class="flex-48">
|
||||
<mat-label>{{ 'labels.inputs.Unit Type' | translate }}</mat-label>
|
||||
<input matInput required autoFocus formControlName="unitType" />
|
||||
@if (collateralForm.controls.unitType.hasError('required')) {
|
||||
<mat-error>
|
||||
{{ 'labels.inputs.Unit Type' | translate }} {{ 'labels.commons.is' | translate }}
|
||||
<strong>{{ 'labels.commons.required' | translate }}</strong>
|
||||
</mat-error>
|
||||
}
|
||||
</mat-form-field>
|
||||
<mat-form-field appearance="outline">
|
||||
<mat-label>{{ 'labels.inputs.Type/Quality' | translate }}</mat-label>
|
||||
<input matInput required autoFocus formControlName="quality" />
|
||||
@if (collateralForm.controls.quality.hasError('required')) {
|
||||
<mat-error>
|
||||
{{ 'labels.inputs.Type/Quality' | translate }} {{ 'labels.commons.is' | translate }}
|
||||
<strong>{{ 'labels.commons.required' | translate }}</strong>
|
||||
</mat-error>
|
||||
}
|
||||
</mat-form-field>
|
||||
|
||||
<mat-form-field class="flex-48">
|
||||
<mat-label>{{ 'labels.inputs.Base Price' | translate }}</mat-label>
|
||||
<input matInput required autoFocus formControlName="basePrice" />
|
||||
@if (collateralForm.controls.basePrice.hasError('required')) {
|
||||
<mat-error>
|
||||
{{ 'labels.inputs.Base Price' | translate }} {{ 'labels.commons.is' | translate }}
|
||||
<strong>{{ 'labels.commons.required' | translate }}</strong>
|
||||
</mat-error>
|
||||
}
|
||||
</mat-form-field>
|
||||
<mat-form-field appearance="outline">
|
||||
<mat-label>{{ 'labels.inputs.Unit Type' | translate }}</mat-label>
|
||||
<input matInput required autoFocus formControlName="unitType" />
|
||||
@if (collateralForm.controls.unitType.hasError('required')) {
|
||||
<mat-error>
|
||||
{{ 'labels.inputs.Unit Type' | translate }} {{ 'labels.commons.is' | translate }}
|
||||
<strong>{{ 'labels.commons.required' | translate }}</strong>
|
||||
</mat-error>
|
||||
}
|
||||
</mat-form-field>
|
||||
|
||||
<mat-form-field class="flex-48">
|
||||
<mat-label>{{ 'labels.inputs.Percentage to Base' | translate }}</mat-label>
|
||||
<input matInput required autoFocus formControlName="pctToBase" />
|
||||
@if (collateralForm.controls.pctToBase.hasError('required')) {
|
||||
<mat-error>
|
||||
{{ 'labels.inputs.Percentage to Base' | translate }} {{ 'labels.commons.is' | translate }}
|
||||
<strong>{{ 'labels.commons.required' | translate }}</strong>
|
||||
</mat-error>
|
||||
}
|
||||
</mat-form-field>
|
||||
<mat-form-field appearance="outline">
|
||||
<mat-label>{{ 'labels.inputs.Base Price' | translate }}</mat-label>
|
||||
<input matInput required autoFocus formControlName="basePrice" />
|
||||
@if (collateralForm.controls.basePrice.hasError('required')) {
|
||||
<mat-error>
|
||||
{{ 'labels.inputs.Base Price' | translate }} {{ 'labels.commons.is' | translate }}
|
||||
<strong>{{ 'labels.commons.required' | translate }}</strong>
|
||||
</mat-error>
|
||||
}
|
||||
</mat-form-field>
|
||||
|
||||
<mat-form-field class="flex-48">
|
||||
<mat-label>{{ 'labels.heading.Currency' | translate }}</mat-label>
|
||||
<mat-select required formControlName="currency">
|
||||
@for (currency of collateralTemplateData; track currency) {
|
||||
<mat-option [value]="currency.code">
|
||||
{{ currency.name }}
|
||||
</mat-option>
|
||||
}
|
||||
</mat-select>
|
||||
@if (collateralForm.controls.currency.hasError('required')) {
|
||||
<mat-error>
|
||||
{{ 'labels.heading.Currency' | translate }} {{ 'labels.commons.is' | translate }}
|
||||
<strong>{{ 'labels.commons.required' | translate }}</strong>
|
||||
</mat-error>
|
||||
}
|
||||
</mat-form-field>
|
||||
</div>
|
||||
</mat-card-content>
|
||||
<mat-form-field appearance="outline">
|
||||
<mat-label>{{ 'labels.inputs.Percentage to Base' | translate }}</mat-label>
|
||||
<input matInput required autoFocus formControlName="pctToBase" />
|
||||
@if (collateralForm.controls.pctToBase.hasError('required')) {
|
||||
<mat-error>
|
||||
{{ 'labels.inputs.Percentage to Base' | translate }} {{ 'labels.commons.is' | translate }}
|
||||
<strong>{{ 'labels.commons.required' | translate }}</strong>
|
||||
</mat-error>
|
||||
}
|
||||
</mat-form-field>
|
||||
|
||||
<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]="!collateralForm.valid"
|
||||
*mifosxHasPermission="'UPDATE_CHARGE'"
|
||||
>
|
||||
{{ 'labels.buttons.Submit' | translate }}
|
||||
</button>
|
||||
</mat-card-actions>
|
||||
</form>
|
||||
</mat-card>
|
||||
<mat-form-field appearance="outline">
|
||||
<mat-label>{{ 'labels.heading.Currency' | translate }}</mat-label>
|
||||
<mat-select required formControlName="currency">
|
||||
@for (currency of collateralTemplateData; track currency) {
|
||||
<mat-option [value]="currency.code">
|
||||
{{ currency.name }}
|
||||
</mat-option>
|
||||
}
|
||||
</mat-select>
|
||||
@if (collateralForm.controls.currency.hasError('required')) {
|
||||
<mat-error>
|
||||
{{ 'labels.heading.Currency' | translate }} {{ 'labels.commons.is' | translate }}
|
||||
<strong>{{ 'labels.commons.required' | translate }}</strong>
|
||||
</mat-error>
|
||||
}
|
||||
</mat-form-field>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="ecl-actions">
|
||||
<button type="button" mat-raised-button [routerLink]="['../']">
|
||||
{{ 'labels.buttons.Cancel' | translate }}
|
||||
</button>
|
||||
<button
|
||||
mat-flat-button
|
||||
color="primary"
|
||||
[disabled]="!collateralForm.valid"
|
||||
*mifosxHasPermission="'UPDATE_CHARGE'"
|
||||
>
|
||||
{{ 'labels.buttons.Submit' | translate }}
|
||||
</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
@@ -5,3 +5,78 @@
|
||||
* 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/.
|
||||
*/
|
||||
|
||||
.ecl-container {
|
||||
max-width: 960px;
|
||||
margin: 0 auto;
|
||||
padding: 24px 16px;
|
||||
}
|
||||
|
||||
.ecl-page-header {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 10px;
|
||||
margin-bottom: 24px;
|
||||
|
||||
&__icon {
|
||||
font-size: 20px;
|
||||
color: #1353a0;
|
||||
}
|
||||
|
||||
&__title {
|
||||
font-size: 20px;
|
||||
font-weight: 600;
|
||||
color: #202124;
|
||||
margin: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.ecl-section {
|
||||
border: 1px solid #e2e8f0;
|
||||
border-radius: 10px;
|
||||
overflow: hidden;
|
||||
background: #fff;
|
||||
|
||||
&__header {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
padding: 12px 24px;
|
||||
background: #f8f9fa;
|
||||
border-bottom: 1px solid #e8eaed;
|
||||
|
||||
i {
|
||||
font-size: 14px;
|
||||
color: #0ea5e9;
|
||||
}
|
||||
|
||||
h3 {
|
||||
font-size: 14px;
|
||||
font-weight: 600;
|
||||
color: #202124;
|
||||
margin: 0;
|
||||
}
|
||||
}
|
||||
|
||||
&__body {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(2, 1fr);
|
||||
gap: 4px 16px;
|
||||
padding: 16px 24px;
|
||||
}
|
||||
}
|
||||
|
||||
.ecl-actions {
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
gap: 12px;
|
||||
margin-top: 20px;
|
||||
padding: 16px 0;
|
||||
border-top: 1px solid rgba(0, 0, 0, 0.08);
|
||||
}
|
||||
|
||||
@media (max-width: 600px) {
|
||||
.ecl-section__body {
|
||||
grid-template-columns: 1fr;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,69 +6,54 @@
|
||||
file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
-->
|
||||
|
||||
<div class="layout-row align-end gap-2px responsive-column container m-b-20">
|
||||
<button mat-raised-button color="primary" [routerLink]="['edit']">
|
||||
<fa-icon icon="edit" class="m-r-10"></fa-icon>
|
||||
{{ 'labels.heading.Edit' | translate }}
|
||||
</button>
|
||||
<button mat-raised-button color="warn" (click)="deleteCollateral()">
|
||||
<fa-icon icon="trash" class="m-r-10"></fa-icon>
|
||||
{{ 'labels.heading.Delete' | translate }}
|
||||
</button>
|
||||
</div>
|
||||
<div class="vcl-container">
|
||||
<div class="vcl-top-bar">
|
||||
<div class="vcl-top-bar__title">
|
||||
<i class="fas fa-shield-alt vcl-top-bar__icon"></i>
|
||||
<h2>{{ collateralData.name }}</h2>
|
||||
</div>
|
||||
<div class="vcl-top-bar__actions">
|
||||
<button mat-flat-button color="primary" [routerLink]="['edit']">
|
||||
<fa-icon icon="edit" class="m-r-10"></fa-icon>
|
||||
{{ 'labels.heading.Edit' | translate }}
|
||||
</button>
|
||||
<button mat-flat-button color="warn" (click)="deleteCollateral()">
|
||||
<fa-icon icon="trash" class="m-r-10"></fa-icon>
|
||||
{{ 'labels.heading.Delete' | translate }}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="container">
|
||||
<mat-card>
|
||||
<mat-card-content>
|
||||
<div class="layout-row-wrap">
|
||||
<div class="flex-50 mat-body-strong">
|
||||
{{ 'labels.inputs.Collateral Name' | translate }}
|
||||
</div>
|
||||
|
||||
<div class="flex-50">
|
||||
{{ collateralData.name }}
|
||||
</div>
|
||||
|
||||
<div class="flex-50 mat-body-strong">
|
||||
{{ 'labels.inputs.Type/Quality' | translate }}
|
||||
</div>
|
||||
|
||||
<div class="flex-50">
|
||||
{{ collateralData.quality }}
|
||||
</div>
|
||||
|
||||
<div class="flex-50 mat-body-strong">
|
||||
{{ 'labels.inputs.Base Price' | translate }}
|
||||
</div>
|
||||
|
||||
<div class="flex-50">
|
||||
{{ collateralData.basePrice }}
|
||||
</div>
|
||||
|
||||
<div class="flex-50 mat-body-strong">
|
||||
{{ 'labels.inputs.Base Percentage' | translate }}
|
||||
</div>
|
||||
|
||||
<div class="flex-50">
|
||||
{{ collateralData.pctToBase }}
|
||||
</div>
|
||||
|
||||
<div class="flex-50 mat-body-strong">
|
||||
{{ 'labels.inputs.Unit Type' | translate }}
|
||||
</div>
|
||||
|
||||
<div class="flex-50">
|
||||
{{ collateralData.unitType }}
|
||||
</div>
|
||||
|
||||
<div class="flex-50 mat-body-strong">
|
||||
{{ 'labels.heading.Currency' | translate }}
|
||||
</div>
|
||||
|
||||
<div class="flex-50">
|
||||
{{ collateralData.currency }}
|
||||
</div>
|
||||
<div class="vcl-section">
|
||||
<div class="vcl-section__header">
|
||||
<i class="fas fa-info-circle"></i>
|
||||
<h3>{{ 'labels.heading.Collateral Details' | translate }}</h3>
|
||||
</div>
|
||||
<div class="vcl-section__body">
|
||||
<div class="vcl-row">
|
||||
<span class="vcl-row__label">{{ 'labels.inputs.Collateral Name' | translate }}</span>
|
||||
<span class="vcl-row__value">{{ collateralData.name }}</span>
|
||||
</div>
|
||||
</mat-card-content>
|
||||
</mat-card>
|
||||
<div class="vcl-row">
|
||||
<span class="vcl-row__label">{{ 'labels.inputs.Type/Quality' | translate }}</span>
|
||||
<span class="vcl-row__value">{{ collateralData.quality }}</span>
|
||||
</div>
|
||||
<div class="vcl-row">
|
||||
<span class="vcl-row__label">{{ 'labels.inputs.Base Price' | translate }}</span>
|
||||
<span class="vcl-row__value">{{ collateralData.basePrice }}</span>
|
||||
</div>
|
||||
<div class="vcl-row">
|
||||
<span class="vcl-row__label">{{ 'labels.inputs.Base Percentage' | translate }}</span>
|
||||
<span class="vcl-row__value">{{ collateralData.pctToBase }}</span>
|
||||
</div>
|
||||
<div class="vcl-row">
|
||||
<span class="vcl-row__label">{{ 'labels.inputs.Unit Type' | translate }}</span>
|
||||
<span class="vcl-row__value">{{ collateralData.unitType }}</span>
|
||||
</div>
|
||||
<div class="vcl-row">
|
||||
<span class="vcl-row__label">{{ 'labels.heading.Currency' | translate }}</span>
|
||||
<span class="vcl-row__value">{{ collateralData.currency }}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -6,13 +6,111 @@
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
.container {
|
||||
max-width: 37rem;
|
||||
.vcl-container {
|
||||
max-width: 960px;
|
||||
margin: 0 auto;
|
||||
padding: 24px 16px;
|
||||
}
|
||||
|
||||
.content {
|
||||
div {
|
||||
margin: 1rem 0;
|
||||
word-wrap: break-word;
|
||||
.vcl-top-bar {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
margin-bottom: 24px;
|
||||
flex-wrap: wrap;
|
||||
gap: 12px;
|
||||
|
||||
&__title {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 10px;
|
||||
|
||||
h2 {
|
||||
font-size: 20px;
|
||||
font-weight: 600;
|
||||
color: #202124;
|
||||
margin: 0;
|
||||
}
|
||||
}
|
||||
|
||||
&__icon {
|
||||
font-size: 20px;
|
||||
color: #1353a0;
|
||||
}
|
||||
|
||||
&__actions {
|
||||
display: flex;
|
||||
gap: 10px;
|
||||
}
|
||||
}
|
||||
|
||||
.vcl-section {
|
||||
border: 1px solid #e2e8f0;
|
||||
border-radius: 10px;
|
||||
overflow: hidden;
|
||||
background: #fff;
|
||||
|
||||
&__header {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
padding: 12px 24px;
|
||||
background: #f8f9fa;
|
||||
border-bottom: 1px solid #e8eaed;
|
||||
|
||||
i {
|
||||
font-size: 14px;
|
||||
color: #0ea5e9;
|
||||
}
|
||||
|
||||
h3 {
|
||||
font-size: 14px;
|
||||
font-weight: 600;
|
||||
color: #202124;
|
||||
margin: 0;
|
||||
}
|
||||
}
|
||||
|
||||
&__body {
|
||||
padding: 8px 24px;
|
||||
}
|
||||
}
|
||||
|
||||
.vcl-row {
|
||||
display: flex;
|
||||
padding: 6px 0;
|
||||
border-bottom: 1px solid #f1f3f4;
|
||||
|
||||
&:last-child {
|
||||
border-bottom: none;
|
||||
}
|
||||
|
||||
&__label {
|
||||
flex: 0 0 40%;
|
||||
font-size: 13px;
|
||||
font-weight: 500;
|
||||
color: #5f6368;
|
||||
}
|
||||
|
||||
&__value {
|
||||
flex: 1;
|
||||
font-size: 13px;
|
||||
color: #202124;
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 600px) {
|
||||
.vcl-top-bar {
|
||||
flex-direction: column;
|
||||
align-items: flex-start;
|
||||
}
|
||||
|
||||
.vcl-row {
|
||||
flex-direction: column;
|
||||
gap: 2px;
|
||||
|
||||
&__label {
|
||||
flex: none;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+124
-56
@@ -1,67 +1,135 @@
|
||||
<div class="container">
|
||||
<mat-stepper orientation="vertical" [linear]="false" class="mat-elevation-z8" labelPosition="bottom">
|
||||
<ng-template matStepperIcon="number"><fa-icon icon="pencil-alt" size="sm"></fa-icon></ng-template>
|
||||
<ng-template matStepperIcon="edit"><fa-icon icon="pencil-alt" size="sm"></fa-icon></ng-template>
|
||||
<ng-template matStepperIcon="done"><fa-icon icon="check" size="sm"></fa-icon></ng-template>
|
||||
<ng-template matStepperIcon="error"><fa-icon icon="exclamation-triangle" size="lg"></fa-icon></ng-template>
|
||||
<ng-template matStepperIcon="preview"><fa-icon icon="eye" size="sm"></fa-icon></ng-template>
|
||||
<!--
|
||||
Copyright since 2025 Mifos Initiative
|
||||
|
||||
<mat-step [stepControl]="detailsForm">
|
||||
<ng-template matStepLabel>{{ 'labels.inputs.DETAILS' | translate }}</ng-template>
|
||||
<mifosx-saving-product-details-step></mifosx-saving-product-details-step>
|
||||
</mat-step>
|
||||
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/.
|
||||
-->
|
||||
|
||||
<mat-step [stepControl]="currencyForm">
|
||||
<ng-template matStepLabel>{{ 'labels.inputs.CURRENCY' | translate }}</ng-template>
|
||||
<mifosx-saving-product-currency-step
|
||||
[savingProductsTemplate]="currentProductsTemplate"
|
||||
></mifosx-saving-product-currency-step>
|
||||
</mat-step>
|
||||
<div class="cp-container">
|
||||
<div class="cp-header">
|
||||
<i class="fas fa-credit-card cp-header__icon"></i>
|
||||
<h2 class="cp-header__title">{{ 'labels.heading.Create Current Product' | translate }}</h2>
|
||||
</div>
|
||||
|
||||
<mat-step [stepControl]="termsForm">
|
||||
<ng-template matStepLabel>{{ 'labels.inputs.TERMS' | translate }}</ng-template>
|
||||
<mifosx-saving-product-terms-step
|
||||
[savingProductsTemplate]="currentProductsTemplate"
|
||||
></mifosx-saving-product-terms-step>
|
||||
</mat-step>
|
||||
<mat-tab-group class="cp-tabs" animationDuration="200ms" [preserveContent]="true" [(selectedIndex)]="selectedTabIndex">
|
||||
<mat-tab>
|
||||
<ng-template mat-tab-label>
|
||||
<i class="fas fa-info-circle cp-tab-icon"></i>
|
||||
{{ 'labels.inputs.DETAILS' | translate }}
|
||||
</ng-template>
|
||||
<div class="cp-tab-content">
|
||||
<mifosx-saving-product-details-step></mifosx-saving-product-details-step>
|
||||
</div>
|
||||
</mat-tab>
|
||||
|
||||
<mat-step [stepControl]="settingsForm">
|
||||
<ng-template matStepLabel>{{ 'labels.inputs.SETTINGS' | translate }}</ng-template>
|
||||
<mifosx-saving-product-settings-step
|
||||
[savingProductsTemplate]="currentProductsTemplate"
|
||||
></mifosx-saving-product-settings-step>
|
||||
</mat-step>
|
||||
<mat-tab>
|
||||
<ng-template mat-tab-label>
|
||||
<i class="fas fa-coins cp-tab-icon"></i>
|
||||
{{ 'labels.inputs.CURRENCY' | translate }}
|
||||
</ng-template>
|
||||
<div class="cp-tab-content">
|
||||
<mifosx-saving-product-currency-step
|
||||
[savingProductsTemplate]="currentProductsTemplate"
|
||||
></mifosx-saving-product-currency-step>
|
||||
</div>
|
||||
</mat-tab>
|
||||
|
||||
<mat-step>
|
||||
<ng-template matStepLabel>{{ 'labels.inputs.CHARGES' | translate }}</ng-template>
|
||||
<mifosx-saving-product-charges-step
|
||||
[savingProductsTemplate]="currentProductsTemplate"
|
||||
[currencyCode]="currencyForm.get('currencyCode')"
|
||||
></mifosx-saving-product-charges-step>
|
||||
</mat-step>
|
||||
<mat-tab>
|
||||
<ng-template mat-tab-label>
|
||||
<i class="fas fa-sliders-h cp-tab-icon"></i>
|
||||
{{ 'labels.inputs.TERMS' | translate }}
|
||||
</ng-template>
|
||||
<div class="cp-tab-content">
|
||||
<mifosx-saving-product-terms-step
|
||||
[savingProductsTemplate]="currentProductsTemplate"
|
||||
></mifosx-saving-product-terms-step>
|
||||
</div>
|
||||
</mat-tab>
|
||||
|
||||
<mat-step [stepControl]="accountingForm">
|
||||
<ng-template matStepLabel>{{ 'labels.inputs.ACCOUNTING' | translate }}</ng-template>
|
||||
<mifosx-saving-product-accounting-step
|
||||
[savingProductsTemplate]="currentProductsTemplate"
|
||||
[accountingRuleData]="accountingRuleData"
|
||||
[isDormancyTrackingActive]="settingsForm.get('isDormancyTrackingActive')"
|
||||
[savingProductFormValid]="formValid"
|
||||
[allowOverdraft]="settingsForm.get('allowOverdraft')"
|
||||
></mifosx-saving-product-accounting-step>
|
||||
</mat-step>
|
||||
<mat-tab>
|
||||
<ng-template mat-tab-label>
|
||||
<i class="fas fa-cog cp-tab-icon"></i>
|
||||
{{ 'labels.inputs.SETTINGS' | translate }}
|
||||
</ng-template>
|
||||
<div class="cp-tab-content">
|
||||
<mifosx-saving-product-settings-step
|
||||
[savingProductsTemplate]="currentProductsTemplate"
|
||||
></mifosx-saving-product-settings-step>
|
||||
</div>
|
||||
</mat-tab>
|
||||
|
||||
@if (formValid) {
|
||||
<mat-step state="preview" completed>
|
||||
<ng-template matStepLabel>{{ 'labels.inputs.PREVIEW' | translate }}</ng-template>
|
||||
<mifosx-saving-product-preview-step
|
||||
<mat-tab>
|
||||
<ng-template mat-tab-label>
|
||||
<i class="fas fa-receipt cp-tab-icon"></i>
|
||||
{{ 'labels.inputs.CHARGES' | translate }}
|
||||
</ng-template>
|
||||
<div class="cp-tab-content">
|
||||
<mifosx-saving-product-charges-step
|
||||
[savingProductsTemplate]="currentProductsTemplate"
|
||||
[currencyCode]="currencyForm.get('currencyCode')"
|
||||
></mifosx-saving-product-charges-step>
|
||||
</div>
|
||||
</mat-tab>
|
||||
|
||||
<mat-tab>
|
||||
<ng-template mat-tab-label>
|
||||
<i class="fas fa-book cp-tab-icon"></i>
|
||||
{{ 'labels.inputs.ACCOUNTING' | translate }}
|
||||
</ng-template>
|
||||
<div class="cp-tab-content">
|
||||
<mifosx-saving-product-accounting-step
|
||||
[savingProductsTemplate]="currentProductsTemplate"
|
||||
[accountingRuleData]="accountingRuleData"
|
||||
[savingProduct]="currentProduct"
|
||||
[taskPermission]="'CREATE_CURRENTPRODUCT'"
|
||||
(submitEvent)="submit()"
|
||||
></mifosx-saving-product-preview-step>
|
||||
</mat-step>
|
||||
[isDormancyTrackingActive]="settingsForm.get('isDormancyTrackingActive')"
|
||||
[savingProductFormValid]="formValid"
|
||||
[allowOverdraft]="settingsForm.get('allowOverdraft')"
|
||||
></mifosx-saving-product-accounting-step>
|
||||
</div>
|
||||
</mat-tab>
|
||||
|
||||
@if (formValid) {
|
||||
<mat-tab>
|
||||
<ng-template mat-tab-label>
|
||||
<i class="fas fa-eye cp-tab-icon"></i>
|
||||
{{ 'labels.inputs.PREVIEW' | translate }}
|
||||
</ng-template>
|
||||
<div class="cp-tab-content">
|
||||
<mifosx-saving-product-preview-step
|
||||
[savingProductsTemplate]="currentProductsTemplate"
|
||||
[accountingRuleData]="accountingRuleData"
|
||||
[savingProduct]="currentProduct"
|
||||
[taskPermission]="'CREATE_CURRENTPRODUCT'"
|
||||
(submitEvent)="submit()"
|
||||
></mifosx-saving-product-preview-step>
|
||||
</div>
|
||||
</mat-tab>
|
||||
}
|
||||
</mat-stepper>
|
||||
</mat-tab-group>
|
||||
|
||||
<div class="cp-action-bar">
|
||||
<button mat-raised-button [routerLink]="['../']" class="cp-action-bar__cancel">
|
||||
{{ 'labels.buttons.Cancel' | translate }}
|
||||
</button>
|
||||
<div class="cp-action-bar__right">
|
||||
@if (selectedTabIndex > 0) {
|
||||
<button mat-raised-button (click)="selectedTabIndex = selectedTabIndex - 1">
|
||||
<i class="fas fa-arrow-left" style="margin-right: 8px;"></i>
|
||||
{{ 'labels.buttons.Previous' | translate }}
|
||||
</button>
|
||||
}
|
||||
@if (selectedTabIndex < totalTabs - 1) {
|
||||
<button mat-raised-button color="primary" (click)="selectedTabIndex = selectedTabIndex + 1">
|
||||
{{ 'labels.buttons.Next' | translate }}
|
||||
<i class="fas fa-arrow-right" style="margin-left: 8px;"></i>
|
||||
</button>
|
||||
}
|
||||
@if (formValid && selectedTabIndex === totalTabs - 1) {
|
||||
<button mat-raised-button color="primary" (click)="submit()">
|
||||
<i class="fas fa-check" style="margin-right: 8px;"></i>
|
||||
{{ 'labels.buttons.Submit' | translate }}
|
||||
</button>
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
+89
-3
@@ -1,4 +1,90 @@
|
||||
fa-icon {
|
||||
position: relative;
|
||||
left: 5%;
|
||||
/**
|
||||
* 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/.
|
||||
*/
|
||||
|
||||
$primary: #1353a0;
|
||||
|
||||
.cp-container {
|
||||
max-width: 960px;
|
||||
margin: 0 auto;
|
||||
padding: 24px 16px;
|
||||
}
|
||||
|
||||
.cp-header {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 10px;
|
||||
margin-bottom: 20px;
|
||||
|
||||
&__icon {
|
||||
font-size: 20px;
|
||||
color: $primary;
|
||||
}
|
||||
|
||||
&__title {
|
||||
margin: 0;
|
||||
font-size: 22px;
|
||||
font-weight: 500;
|
||||
}
|
||||
}
|
||||
|
||||
.cp-tabs {
|
||||
background: var(--md-sys-color-surface, #fff);
|
||||
border-radius: 8px;
|
||||
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.08);
|
||||
|
||||
::ng-deep {
|
||||
.mat-mdc-tab-header {
|
||||
border-bottom: 1px solid rgba(0, 0, 0, 0.08);
|
||||
}
|
||||
|
||||
.mat-mdc-tab {
|
||||
min-width: 120px;
|
||||
padding: 0 16px;
|
||||
height: 52px;
|
||||
}
|
||||
|
||||
.mat-mdc-tab-body-wrapper {
|
||||
min-height: 200px;
|
||||
}
|
||||
|
||||
.mat-mdc-tab-body {
|
||||
overflow: visible !important;
|
||||
}
|
||||
|
||||
.mat-mdc-tab-body-content {
|
||||
overflow: visible !important;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.cp-tab-icon {
|
||||
margin-right: 8px;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.cp-tab-content {
|
||||
padding: 24px 16px;
|
||||
}
|
||||
|
||||
.cp-action-bar {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
margin-top: 20px;
|
||||
padding: 16px 0;
|
||||
border-top: 1px solid rgba(0, 0, 0, 0.08);
|
||||
|
||||
&__cancel {
|
||||
color: rgba(0, 0, 0, 0.6);
|
||||
}
|
||||
|
||||
&__right {
|
||||
display: flex;
|
||||
gap: 12px;
|
||||
}
|
||||
}
|
||||
|
||||
+15
-7
@@ -1,3 +1,11 @@
|
||||
/**
|
||||
* 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/.
|
||||
*/
|
||||
|
||||
import { Component, ViewChild, inject } from '@angular/core';
|
||||
import { ActivatedRoute, Router } from '@angular/router';
|
||||
import { SavingProductDetailsStepComponent } from '../../saving-products/saving-product-stepper/saving-product-details-step/saving-product-details-step.component';
|
||||
@@ -10,8 +18,7 @@ import { SavingProductPreviewStepComponent } from '../../saving-products/saving-
|
||||
import { ProductsService } from 'app/products/products.service';
|
||||
import { SettingsService } from 'app/settings/settings.service';
|
||||
import { Accounting } from 'app/core/utils/accounting';
|
||||
import { MatStepper, MatStepperIcon, MatStep, MatStepLabel } from '@angular/material/stepper';
|
||||
import { FaIconComponent } from '@fortawesome/angular-fontawesome';
|
||||
import { MatTabsModule } from '@angular/material/tabs';
|
||||
import { STANDALONE_SHARED_IMPORTS } from 'app/standalone-shared.module';
|
||||
|
||||
@Component({
|
||||
@@ -20,11 +27,7 @@ import { STANDALONE_SHARED_IMPORTS } from 'app/standalone-shared.module';
|
||||
styleUrls: ['./create-current-product.component.scss'],
|
||||
imports: [
|
||||
...STANDALONE_SHARED_IMPORTS,
|
||||
MatStepper,
|
||||
MatStepperIcon,
|
||||
FaIconComponent,
|
||||
MatStep,
|
||||
MatStepLabel,
|
||||
MatTabsModule,
|
||||
SavingProductDetailsStepComponent,
|
||||
SavingProductCurrencyStepComponent,
|
||||
SavingProductTermsStepComponent,
|
||||
@@ -51,6 +54,7 @@ export class CreateCurrentProductComponent {
|
||||
|
||||
currentProductsTemplate: any;
|
||||
accountingRuleData: string[] = [];
|
||||
selectedTabIndex = 0;
|
||||
|
||||
constructor() {
|
||||
this.route.data.subscribe((data: { currentProductsTemplate: any }) => {
|
||||
@@ -75,6 +79,10 @@ export class CreateCurrentProductComponent {
|
||||
return this.accountingStep.savingProductAccountingForm;
|
||||
}
|
||||
|
||||
get totalTabs(): number {
|
||||
return this.formValid ? 7 : 6;
|
||||
}
|
||||
|
||||
get formValid() {
|
||||
return (
|
||||
this.detailsForm.valid &&
|
||||
|
||||
@@ -9,8 +9,9 @@
|
||||
|
||||
<div class="container">
|
||||
<div class="layout-row">
|
||||
<mat-form-field class="flex-fill">
|
||||
<mat-form-field appearance="outline" class="flex-fill">
|
||||
<mat-label>{{ 'labels.inputs.Filter' | translate }}</mat-label>
|
||||
<i matPrefix class="fas fa-search"></i>
|
||||
<input matInput (keyup)="applyFilter($event.target.value)" />
|
||||
</mat-form-field>
|
||||
</div>
|
||||
|
||||
+126
-91
@@ -6,105 +6,140 @@
|
||||
file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
-->
|
||||
|
||||
<div class="container">
|
||||
<mat-stepper
|
||||
orientation="vertical"
|
||||
[linear]="false"
|
||||
class="mat-elevation-z8"
|
||||
labelPosition="bottom"
|
||||
#fixedDepositProductStepper
|
||||
>
|
||||
<ng-template matStepperIcon="number">
|
||||
<fa-icon icon="pencil-alt" size="sm"></fa-icon>
|
||||
</ng-template>
|
||||
<div class="fdp-container">
|
||||
<div class="fdp-header">
|
||||
<i class="fas fa-piggy-bank fdp-header__icon"></i>
|
||||
<h2 class="fdp-header__title">{{ 'labels.heading.Create Fixed Deposit Product' | translate }}</h2>
|
||||
</div>
|
||||
|
||||
<ng-template matStepperIcon="edit">
|
||||
<fa-icon icon="pencil-alt" size="sm"></fa-icon>
|
||||
</ng-template>
|
||||
<mat-tab-group class="fdp-tabs" animationDuration="200ms" [preserveContent]="true" [(selectedIndex)]="selectedTabIndex">
|
||||
<mat-tab>
|
||||
<ng-template mat-tab-label>
|
||||
<i class="fas fa-info-circle fdp-tab-icon"></i>
|
||||
{{ 'labels.inputs.DETAILS' | translate }}
|
||||
</ng-template>
|
||||
<div class="fdp-tab-content">
|
||||
<mifosx-fixed-deposit-product-details-step></mifosx-fixed-deposit-product-details-step>
|
||||
</div>
|
||||
</mat-tab>
|
||||
|
||||
<ng-template matStepperIcon="done">
|
||||
<fa-icon icon="check" size="sm"></fa-icon>
|
||||
</ng-template>
|
||||
<mat-tab>
|
||||
<ng-template mat-tab-label>
|
||||
<i class="fas fa-coins fdp-tab-icon"></i>
|
||||
{{ 'labels.inputs.CURRENCY' | translate }}
|
||||
</ng-template>
|
||||
<div class="fdp-tab-content">
|
||||
<mifosx-fixed-deposit-product-currency-step
|
||||
[fixedDepositProductsTemplate]="fixedDepositProductsTemplate"
|
||||
></mifosx-fixed-deposit-product-currency-step>
|
||||
</div>
|
||||
</mat-tab>
|
||||
|
||||
<ng-template matStepperIcon="error">
|
||||
<fa-icon icon="exclamation-triangle" size="lg"></fa-icon>
|
||||
</ng-template>
|
||||
<mat-tab>
|
||||
<ng-template mat-tab-label>
|
||||
<i class="fas fa-sliders-h fdp-tab-icon"></i>
|
||||
{{ 'labels.inputs.TERMS' | translate }}
|
||||
</ng-template>
|
||||
<div class="fdp-tab-content">
|
||||
<mifosx-fixed-deposit-product-terms-step
|
||||
[fixedDepositProductsTemplate]="fixedDepositProductsTemplate"
|
||||
></mifosx-fixed-deposit-product-terms-step>
|
||||
</div>
|
||||
</mat-tab>
|
||||
|
||||
<ng-template matStepperIcon="preview">
|
||||
<fa-icon icon="eye" size="sm"></fa-icon>
|
||||
</ng-template>
|
||||
<mat-tab>
|
||||
<ng-template mat-tab-label>
|
||||
<i class="fas fa-cog fdp-tab-icon"></i>
|
||||
{{ 'labels.inputs.SETTINGS' | translate }}
|
||||
</ng-template>
|
||||
<div class="fdp-tab-content">
|
||||
<mifosx-fixed-deposit-product-settings-step
|
||||
[fixedDepositProductsTemplate]="fixedDepositProductsTemplate"
|
||||
></mifosx-fixed-deposit-product-settings-step>
|
||||
</div>
|
||||
</mat-tab>
|
||||
|
||||
<mat-step [stepControl]="fixedDepositProductDetailsForm">
|
||||
<ng-template matStepLabel>{{ 'labels.inputs.DETAILS' | translate }}</ng-template>
|
||||
<mat-tab>
|
||||
<ng-template mat-tab-label>
|
||||
<i class="fas fa-chart-area fdp-tab-icon"></i>
|
||||
{{ 'labels.inputs.INTEREST RATE CHART' | translate }}
|
||||
</ng-template>
|
||||
<div class="fdp-tab-content">
|
||||
<mifosx-fixed-deposit-product-interest-rate-chart-step
|
||||
[fixedDepositProductsTemplate]="fixedDepositProductsTemplate"
|
||||
></mifosx-fixed-deposit-product-interest-rate-chart-step>
|
||||
</div>
|
||||
</mat-tab>
|
||||
|
||||
<mifosx-fixed-deposit-product-details-step></mifosx-fixed-deposit-product-details-step>
|
||||
</mat-step>
|
||||
<mat-tab>
|
||||
<ng-template mat-tab-label>
|
||||
<i class="fas fa-receipt fdp-tab-icon"></i>
|
||||
{{ 'labels.inputs.CHARGES' | translate }}
|
||||
</ng-template>
|
||||
<div class="fdp-tab-content">
|
||||
<mifosx-fixed-deposit-product-charges-step
|
||||
[fixedDepositProductsTemplate]="fixedDepositProductsTemplate"
|
||||
[currencyCode]="fixedDepositProductCurrencyForm.get('currencyCode')"
|
||||
></mifosx-fixed-deposit-product-charges-step>
|
||||
</div>
|
||||
</mat-tab>
|
||||
|
||||
<mat-step [stepControl]="fixedDepositProductCurrencyForm">
|
||||
<ng-template matStepLabel>{{ 'labels.inputs.CURRENCY' | translate }}</ng-template>
|
||||
|
||||
<mifosx-fixed-deposit-product-currency-step
|
||||
[fixedDepositProductsTemplate]="fixedDepositProductsTemplate"
|
||||
></mifosx-fixed-deposit-product-currency-step>
|
||||
</mat-step>
|
||||
|
||||
<mat-step [stepControl]="fixedDepositProductTermsForm">
|
||||
<ng-template matStepLabel>{{ 'labels.inputs.TERMS' | translate }}</ng-template>
|
||||
|
||||
<mifosx-fixed-deposit-product-terms-step
|
||||
[fixedDepositProductsTemplate]="fixedDepositProductsTemplate"
|
||||
></mifosx-fixed-deposit-product-terms-step>
|
||||
</mat-step>
|
||||
|
||||
<mat-step [stepControl]="fixedDepositProductSettingsForm">
|
||||
<ng-template matStepLabel>{{ 'labels.inputs.SETTINGS' | translate }}</ng-template>
|
||||
|
||||
<mifosx-fixed-deposit-product-settings-step
|
||||
[fixedDepositProductsTemplate]="fixedDepositProductsTemplate"
|
||||
></mifosx-fixed-deposit-product-settings-step>
|
||||
</mat-step>
|
||||
|
||||
<mat-step [stepControl]="fixedDepositProductInterestRateChartForm">
|
||||
<ng-template matStepLabel>{{ 'labels.inputs.INTEREST RATE CHART' | translate }}</ng-template>
|
||||
|
||||
<mifosx-fixed-deposit-product-interest-rate-chart-step
|
||||
[fixedDepositProductsTemplate]="fixedDepositProductsTemplate"
|
||||
></mifosx-fixed-deposit-product-interest-rate-chart-step>
|
||||
</mat-step>
|
||||
|
||||
<mat-step>
|
||||
<ng-template matStepLabel>{{ 'labels.inputs.CHARGES' | translate }}</ng-template>
|
||||
|
||||
<mifosx-fixed-deposit-product-charges-step
|
||||
[fixedDepositProductsTemplate]="fixedDepositProductsTemplate"
|
||||
[currencyCode]="fixedDepositProductCurrencyForm.get('currencyCode')"
|
||||
>
|
||||
</mifosx-fixed-deposit-product-charges-step>
|
||||
</mat-step>
|
||||
|
||||
<mat-step [stepControl]="fixedDepositProductAccountingForm">
|
||||
<ng-template matStepLabel>{{ 'labels.inputs.ACCOUNTING' | translate }}</ng-template>
|
||||
|
||||
<mifosx-fixed-deposit-product-accounting-step
|
||||
[fixedDepositProductsTemplate]="fixedDepositProductsTemplate"
|
||||
[accountingRuleData]="accountingRuleData"
|
||||
[fixedDepositProductFormValid]="fixedDepositProductFormValid"
|
||||
>
|
||||
</mifosx-fixed-deposit-product-accounting-step>
|
||||
</mat-step>
|
||||
<mat-tab>
|
||||
<ng-template mat-tab-label>
|
||||
<i class="fas fa-book fdp-tab-icon"></i>
|
||||
{{ 'labels.inputs.ACCOUNTING' | translate }}
|
||||
</ng-template>
|
||||
<div class="fdp-tab-content">
|
||||
<mifosx-fixed-deposit-product-accounting-step
|
||||
[fixedDepositProductsTemplate]="fixedDepositProductsTemplate"
|
||||
[accountingRuleData]="accountingRuleData"
|
||||
[fixedDepositProductFormValid]="fixedDepositProductFormValid"
|
||||
></mifosx-fixed-deposit-product-accounting-step>
|
||||
</div>
|
||||
</mat-tab>
|
||||
|
||||
@if (fixedDepositProductFormValid) {
|
||||
<mat-step state="preview" completed>
|
||||
<ng-template matStepLabel>{{ 'labels.inputs.PREVIEW' | translate }}</ng-template>
|
||||
<mifosx-fixed-deposit-product-preview-step
|
||||
[fixedDepositProductsTemplate]="fixedDepositProductsTemplate"
|
||||
[chartSlabsDisplayedColumns]="fixedDepositProductInterestRateChartStep.chartSlabsDisplayedColumns"
|
||||
[accountingRuleData]="accountingRuleData"
|
||||
[fixedDepositProduct]="fixedDepositProduct"
|
||||
(submitEvent)="submit()"
|
||||
>
|
||||
</mifosx-fixed-deposit-product-preview-step>
|
||||
</mat-step>
|
||||
<mat-tab>
|
||||
<ng-template mat-tab-label>
|
||||
<i class="fas fa-eye fdp-tab-icon"></i>
|
||||
{{ 'labels.inputs.PREVIEW' | translate }}
|
||||
</ng-template>
|
||||
<div class="fdp-tab-content">
|
||||
<mifosx-fixed-deposit-product-preview-step
|
||||
[fixedDepositProductsTemplate]="fixedDepositProductsTemplate"
|
||||
[chartSlabsDisplayedColumns]="fixedDepositProductInterestRateChartStep.chartSlabsDisplayedColumns"
|
||||
[accountingRuleData]="accountingRuleData"
|
||||
[fixedDepositProduct]="fixedDepositProduct"
|
||||
(submitEvent)="submit()"
|
||||
></mifosx-fixed-deposit-product-preview-step>
|
||||
</div>
|
||||
</mat-tab>
|
||||
}
|
||||
</mat-stepper>
|
||||
</mat-tab-group>
|
||||
|
||||
<div class="fdp-action-bar">
|
||||
<button mat-raised-button [routerLink]="['../']" class="fdp-action-bar__cancel">
|
||||
{{ 'labels.buttons.Cancel' | translate }}
|
||||
</button>
|
||||
<div class="fdp-action-bar__right">
|
||||
@if (selectedTabIndex > 0) {
|
||||
<button mat-raised-button (click)="selectedTabIndex = selectedTabIndex - 1">
|
||||
<i class="fas fa-arrow-left" style="margin-right: 8px;"></i>
|
||||
{{ 'labels.buttons.Previous' | translate }}
|
||||
</button>
|
||||
}
|
||||
@if (selectedTabIndex < totalTabs - 1) {
|
||||
<button mat-raised-button color="primary" (click)="selectedTabIndex = selectedTabIndex + 1">
|
||||
{{ 'labels.buttons.Next' | translate }}
|
||||
<i class="fas fa-arrow-right" style="margin-left: 8px;"></i>
|
||||
</button>
|
||||
}
|
||||
@if (fixedDepositProductFormValid && selectedTabIndex === totalTabs - 1) {
|
||||
<button mat-raised-button color="primary" (click)="submit()">
|
||||
<i class="fas fa-check" style="margin-right: 8px;"></i>
|
||||
{{ 'labels.buttons.Submit' | translate }}
|
||||
</button>
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
+32
@@ -5,3 +5,35 @@
|
||||
* 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/.
|
||||
*/
|
||||
|
||||
$primary: #1353a0;
|
||||
|
||||
.fdp-container { max-width: 960px; margin: 0 auto; padding: 24px 16px; }
|
||||
|
||||
.fdp-header {
|
||||
display: flex; align-items: center; gap: 10px; margin-bottom: 20px;
|
||||
&__icon { font-size: 20px; color: $primary; }
|
||||
&__title { margin: 0; font-size: 22px; font-weight: 500; }
|
||||
}
|
||||
|
||||
.fdp-tabs {
|
||||
background: var(--md-sys-color-surface, #fff); border-radius: 8px;
|
||||
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.08);
|
||||
::ng-deep {
|
||||
.mat-mdc-tab-header { border-bottom: 1px solid rgba(0, 0, 0, 0.08); }
|
||||
.mat-mdc-tab { min-width: 100px; padding: 0 12px; height: 52px; }
|
||||
.mat-mdc-tab-body-wrapper { min-height: 200px; }
|
||||
.mat-mdc-tab-body { overflow: visible !important; }
|
||||
.mat-mdc-tab-body-content { overflow: visible !important; }
|
||||
}
|
||||
}
|
||||
|
||||
.fdp-tab-icon { margin-right: 8px; font-size: 14px; }
|
||||
.fdp-tab-content { padding: 24px 16px; }
|
||||
|
||||
.fdp-action-bar {
|
||||
display: flex; justify-content: space-between; align-items: center;
|
||||
margin-top: 20px; padding: 16px 0; border-top: 1px solid rgba(0, 0, 0, 0.08);
|
||||
&__cancel { color: rgba(0, 0, 0, 0.6); }
|
||||
&__right { display: flex; gap: 12px; }
|
||||
}
|
||||
|
||||
+7
-5
@@ -23,9 +23,9 @@ import { FixedDepositProductAccountingStepComponent } from '../fixed-deposit-pro
|
||||
import { ProductsService } from 'app/products/products.service';
|
||||
import { SettingsService } from 'app/settings/settings.service';
|
||||
import { Accounting } from 'app/core/utils/accounting';
|
||||
import { MatStepper, MatStepperIcon, MatStep, MatStepLabel } from '@angular/material/stepper';
|
||||
import { FaIconComponent } from '@fortawesome/angular-fontawesome';
|
||||
import { FixedDepositProductPreviewStepComponent } from '../fixed-deposit-product-stepper/fixed-deposit-product-preview-step/fixed-deposit-product-preview-step.component';
|
||||
import { MatTabsModule } from '@angular/material/tabs';
|
||||
import { STANDALONE_SHARED_IMPORTS } from 'app/standalone-shared.module';
|
||||
|
||||
@Component({
|
||||
@@ -34,11 +34,8 @@ import { STANDALONE_SHARED_IMPORTS } from 'app/standalone-shared.module';
|
||||
styleUrls: ['./create-fixed-deposit-product.component.scss'],
|
||||
imports: [
|
||||
...STANDALONE_SHARED_IMPORTS,
|
||||
MatStepper,
|
||||
MatStepperIcon,
|
||||
MatTabsModule,
|
||||
FaIconComponent,
|
||||
MatStep,
|
||||
MatStepLabel,
|
||||
FixedDepositProductDetailsStepComponent,
|
||||
FixedDepositProductCurrencyStepComponent,
|
||||
FixedDepositProductTermsStepComponent,
|
||||
@@ -73,6 +70,7 @@ export class CreateFixedDepositProductComponent {
|
||||
|
||||
fixedDepositProductsTemplate: any;
|
||||
accountingRuleData: string[] = [];
|
||||
selectedTabIndex = 0;
|
||||
|
||||
/**
|
||||
* @param {ActivatedRoute} route Activated Route.
|
||||
@@ -112,6 +110,10 @@ export class CreateFixedDepositProductComponent {
|
||||
return this.fixedDepositProductAccountingStep.fixedDepositProductAccountingForm;
|
||||
}
|
||||
|
||||
get totalTabs(): number {
|
||||
return this.fixedDepositProductFormValid ? 8 : 7;
|
||||
}
|
||||
|
||||
get fixedDepositProductFormValid() {
|
||||
return (
|
||||
this.fixedDepositProductDetailsForm.valid &&
|
||||
|
||||
+218
-183
@@ -7,25 +7,33 @@
|
||||
-->
|
||||
|
||||
<form [formGroup]="fixedDepositProductAccountingForm">
|
||||
<div class="layout-row-wrap gap-2px responsive-column">
|
||||
<mat-radio-group
|
||||
class="flex-98 layout-row gap-5percent layout-lt-md-column radio-group-spacing"
|
||||
formControlName="accountingRule"
|
||||
>
|
||||
@for (accountingRule of accountingRuleData; track accountingRule; let i = $index) {
|
||||
<mat-radio-button [value]="i + 1">
|
||||
{{ 'labels.accounting.' + accountingRule | translate }}
|
||||
</mat-radio-button>
|
||||
}
|
||||
</mat-radio-group>
|
||||
<div class="fdpa-section">
|
||||
<div class="fdpa-section__header">
|
||||
<i class="fas fa-book"></i>
|
||||
<h3>{{ 'labels.heading.Accounting' | translate }}</h3>
|
||||
</div>
|
||||
<div class="fdpa-grid">
|
||||
<div class="fdpa-field fdpa-field--full">
|
||||
<mat-radio-group class="fdpa-radio-group" formControlName="accountingRule">
|
||||
@for (accountingRule of accountingRuleData; track accountingRule; let i = $index) {
|
||||
<mat-radio-button [value]="i + 1">
|
||||
{{ 'labels.accounting.' + accountingRule | translate }}
|
||||
</mat-radio-button>
|
||||
}
|
||||
</mat-radio-group>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<mat-divider class="flex-98"></mat-divider>
|
||||
|
||||
@if (isCashOrAccrualAccounting()) {
|
||||
<div class="flex-fill layout-row-wrap gap-2percent layout-xs-column">
|
||||
<h4 class="mat-h4 flex-98">{{ 'labels.heading.Assets' | translate }}</h4>
|
||||
@if (isCashOrAccrualAccounting()) {
|
||||
<div class="fdpa-section">
|
||||
<div class="fdpa-section__header">
|
||||
<i class="fas fa-landmark"></i>
|
||||
<h3>{{ 'labels.heading.Assets' | translate }}</h3>
|
||||
</div>
|
||||
<div class="fdpa-grid">
|
||||
<mifosx-gl-account-selector
|
||||
class="flex-48"
|
||||
class="fdpa-field"
|
||||
[inputFormControl]="fixedDepositProductAccountingForm.controls.savingsReferenceAccountId"
|
||||
[glAccountList]="assetAccountData"
|
||||
[required]="true"
|
||||
@@ -34,7 +42,7 @@
|
||||
</mifosx-gl-account-selector>
|
||||
@if (isAccrualAccounting()) {
|
||||
<mifosx-gl-account-selector
|
||||
class="flex-48"
|
||||
class="fdpa-field"
|
||||
[inputFormControl]="fixedDepositProductAccountingForm.controls.feesReceivableAccountId"
|
||||
[glAccountList]="assetAccountData"
|
||||
[required]="true"
|
||||
@@ -44,7 +52,7 @@
|
||||
}
|
||||
@if (isAccrualAccounting()) {
|
||||
<mifosx-gl-account-selector
|
||||
class="flex-48"
|
||||
class="fdpa-field"
|
||||
[inputFormControl]="fixedDepositProductAccountingForm.controls.penaltiesReceivableAccountId"
|
||||
[glAccountList]="assetAccountData"
|
||||
[required]="true"
|
||||
@@ -52,10 +60,17 @@
|
||||
>
|
||||
</mifosx-gl-account-selector>
|
||||
}
|
||||
<mat-divider class="flex-98"></mat-divider>
|
||||
<h4 class="mat-h4 flex-98">{{ 'labels.heading.Liabilities' | translate }}</h4>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="fdpa-section">
|
||||
<div class="fdpa-section__header">
|
||||
<i class="fas fa-balance-scale"></i>
|
||||
<h3>{{ 'labels.heading.Liabilities' | translate }}</h3>
|
||||
</div>
|
||||
<div class="fdpa-grid">
|
||||
<mifosx-gl-account-selector
|
||||
class="flex-48"
|
||||
class="fdpa-field"
|
||||
[inputFormControl]="fixedDepositProductAccountingForm.controls.savingsControlAccountId"
|
||||
[glAccountList]="liabilityAccountData"
|
||||
[required]="true"
|
||||
@@ -63,7 +78,7 @@
|
||||
>
|
||||
</mifosx-gl-account-selector>
|
||||
<mifosx-gl-account-selector
|
||||
class="flex-48"
|
||||
class="fdpa-field"
|
||||
[inputFormControl]="fixedDepositProductAccountingForm.controls.transfersInSuspenseAccountId"
|
||||
[glAccountList]="liabilityAccountData"
|
||||
[required]="true"
|
||||
@@ -72,7 +87,7 @@
|
||||
</mifosx-gl-account-selector>
|
||||
@if (isAccrualAccounting()) {
|
||||
<mifosx-gl-account-selector
|
||||
class="flex-48"
|
||||
class="fdpa-field"
|
||||
[inputFormControl]="fixedDepositProductAccountingForm.controls.interestPayableAccountId"
|
||||
[glAccountList]="liabilityAccountData"
|
||||
[required]="true"
|
||||
@@ -80,20 +95,34 @@
|
||||
>
|
||||
</mifosx-gl-account-selector>
|
||||
}
|
||||
<mat-divider class="flex-98"></mat-divider>
|
||||
<h4 class="mat-h4 flex-98">{{ 'labels.heading.Expenses' | translate }}</h4>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="fdpa-section">
|
||||
<div class="fdpa-section__header">
|
||||
<i class="fas fa-arrow-circle-down"></i>
|
||||
<h3>{{ 'labels.heading.Expenses' | translate }}</h3>
|
||||
</div>
|
||||
<div class="fdpa-grid">
|
||||
<mifosx-gl-account-selector
|
||||
class="flex-48"
|
||||
class="fdpa-field"
|
||||
[inputFormControl]="fixedDepositProductAccountingForm.controls.interestOnSavingsAccountId"
|
||||
[glAccountList]="expenseAccountData"
|
||||
[required]="true"
|
||||
[inputLabel]="'Interest on savings'"
|
||||
>
|
||||
</mifosx-gl-account-selector>
|
||||
<mat-divider class="flex-98"></mat-divider>
|
||||
<h4 class="mat-h4 flex-98">{{ 'labels.heading.Income' | translate }}</h4>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="fdpa-section">
|
||||
<div class="fdpa-section__header">
|
||||
<i class="fas fa-arrow-circle-up"></i>
|
||||
<h3>{{ 'labels.heading.Income' | translate }}</h3>
|
||||
</div>
|
||||
<div class="fdpa-grid">
|
||||
<mifosx-gl-account-selector
|
||||
class="flex-48"
|
||||
class="fdpa-field"
|
||||
[inputFormControl]="fixedDepositProductAccountingForm.controls.incomeFromFeeAccountId"
|
||||
[glAccountList]="incomeAccountData"
|
||||
[required]="true"
|
||||
@@ -101,186 +130,192 @@
|
||||
>
|
||||
</mifosx-gl-account-selector>
|
||||
<mifosx-gl-account-selector
|
||||
class="flex-48"
|
||||
class="fdpa-field"
|
||||
[inputFormControl]="fixedDepositProductAccountingForm.controls.incomeFromPenaltyAccountId"
|
||||
[glAccountList]="incomeAccountData"
|
||||
[required]="true"
|
||||
[inputLabel]="'Income from penalties'"
|
||||
>
|
||||
</mifosx-gl-account-selector>
|
||||
<mat-divider class="flex-98"></mat-divider>
|
||||
<h3 class="mat-h3 flex-23">{{ 'labels.heading.Advanced Accounting Rules' | translate }}</h3>
|
||||
<mat-checkbox class="flex-73" formControlName="advancedAccountingRules"></mat-checkbox>
|
||||
@if (fixedDepositProductAccountingForm.value.advancedAccountingRules) {
|
||||
<div class="flex-fill layout-row-wrap gap-2percent responsive-column">
|
||||
<div class="flex-100 layout-row-wrap gap-2percent layout-lt-md-column">
|
||||
<h4 class="mat-h4 flex-63">
|
||||
{{ 'labels.heading.Configure Fund Sources for Payment Channels' | translate }}
|
||||
</h4>
|
||||
<div class="flex-33">
|
||||
<button
|
||||
type="button"
|
||||
mat-raised-button
|
||||
color="primary"
|
||||
(click)="add('PaymentFundSource', paymentChannelToFundSourceMappings)"
|
||||
>
|
||||
<fa-icon icon="plus" class="m-r-10"></fa-icon>
|
||||
{{ 'labels.buttons.Add' | translate }}
|
||||
</button>
|
||||
</div>
|
||||
@if (paymentChannelToFundSourceMappings.value.length !== 0) {
|
||||
<table
|
||||
class="flex-98 mat-elevation-z1"
|
||||
mat-table
|
||||
[dataSource]="paymentChannelToFundSourceMappings.value"
|
||||
>
|
||||
<ng-container matColumnDef="paymentTypeId">
|
||||
<th mat-header-cell *matHeaderCellDef>{{ 'labels.heading.Payment Type' | translate }}</th>
|
||||
<td mat-cell *matCellDef="let paymentFundSource">
|
||||
{{ paymentFundSource.paymentTypeId | find: paymentTypeData : 'id' : 'name' }}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="fdpa-section">
|
||||
<div class="fdpa-section__header">
|
||||
<i class="fas fa-cogs"></i>
|
||||
<h3>{{ 'labels.heading.Advanced Accounting Rules' | translate }}</h3>
|
||||
</div>
|
||||
<div class="fdpa-grid">
|
||||
<div class="fdpa-field fdpa-field--full fdpa-checkbox-row">
|
||||
<mat-checkbox formControlName="advancedAccountingRules"></mat-checkbox>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@if (fixedDepositProductAccountingForm.value.advancedAccountingRules) {
|
||||
<!-- Payment Fund Source -->
|
||||
<div class="fdpa-subsection">
|
||||
<div class="fdpa-subsection__header">
|
||||
<h4>{{ 'labels.heading.Configure Fund Sources for Payment Channels' | translate }}</h4>
|
||||
<button
|
||||
type="button"
|
||||
mat-raised-button
|
||||
color="primary"
|
||||
class="fdpa-add-btn"
|
||||
(click)="add('PaymentFundSource', paymentChannelToFundSourceMappings)"
|
||||
>
|
||||
<fa-icon icon="plus" class="m-r-10"></fa-icon>
|
||||
{{ 'labels.buttons.Add' | translate }}
|
||||
</button>
|
||||
</div>
|
||||
@if (paymentChannelToFundSourceMappings.value.length !== 0) {
|
||||
<div class="fdpa-table-wrapper">
|
||||
<table
|
||||
mat-table
|
||||
[dataSource]="paymentChannelToFundSourceMappings.value"
|
||||
>
|
||||
<ng-container matColumnDef="paymentTypeId">
|
||||
<th mat-header-cell *matHeaderCellDef>{{ 'labels.heading.Payment Type' | translate }}</th>
|
||||
<td mat-cell *matCellDef="let paymentFundSource">
|
||||
{{ paymentFundSource.paymentTypeId | find: paymentTypeData : 'id' : 'name' }}
|
||||
</td>
|
||||
</ng-container>
|
||||
<ng-container matColumnDef="fundSourceAccountId">
|
||||
<th mat-header-cell *matHeaderCellDef>{{ 'labels.inputs.Fund Source' | translate }}</th>
|
||||
<td mat-cell *matCellDef="let paymentFundSource">
|
||||
{{ paymentFundSource.fundSourceAccountId | find: assetAccountData : 'id' : 'name' }}
|
||||
</td>
|
||||
</ng-container>
|
||||
<ng-container matColumnDef="actions">
|
||||
<th mat-header-cell *matHeaderCellDef>{{ 'labels.buttons.Actions' | translate }}</th>
|
||||
<td mat-cell *matCellDef="let paymentFundSource; let i = index">
|
||||
<button
|
||||
mat-icon-button
|
||||
color="primary"
|
||||
(click)="edit('PaymentFundSource', paymentChannelToFundSourceMappings, i)"
|
||||
>
|
||||
<fa-icon icon="edit"></fa-icon>
|
||||
</button>
|
||||
<button mat-icon-button color="warn" (click)="delete(paymentChannelToFundSourceMappings, i)">
|
||||
<fa-icon icon="trash"></fa-icon>
|
||||
</button>
|
||||
</td>
|
||||
</ng-container>
|
||||
<tr mat-header-row *matHeaderRowDef="paymentFundSourceDisplayedColumns"></tr>
|
||||
<tr mat-row *matRowDef="let row; columns: paymentFundSourceDisplayedColumns"></tr>
|
||||
</table>
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
|
||||
@if (existCharges()) {
|
||||
<!-- Fees Income -->
|
||||
<div class="fdpa-subsection">
|
||||
<div class="fdpa-subsection__header">
|
||||
<h4>{{ 'labels.heading.Map Fees to Specific Income Accounts' | translate }}</h4>
|
||||
<button
|
||||
type="button"
|
||||
mat-raised-button
|
||||
color="primary"
|
||||
class="fdpa-add-btn"
|
||||
(click)="add('FeesIncome', feeToIncomeAccountMappings)"
|
||||
>
|
||||
<fa-icon icon="plus" class="m-r-10"></fa-icon>
|
||||
{{ 'labels.buttons.Add' | translate }}
|
||||
</button>
|
||||
</div>
|
||||
@if (feeToIncomeAccountMappings.value.length !== 0) {
|
||||
<div class="fdpa-table-wrapper">
|
||||
<table mat-table [dataSource]="feeToIncomeAccountMappings.value">
|
||||
<ng-container matColumnDef="chargeId">
|
||||
<th mat-header-cell *matHeaderCellDef>{{ 'labels.catalogs.Fees' | translate }}</th>
|
||||
<td mat-cell *matCellDef="let feesIncome">
|
||||
{{ feesIncome.chargeId | find: chargeData : 'id' : 'name' }}
|
||||
</td>
|
||||
</ng-container>
|
||||
<ng-container matColumnDef="fundSourceAccountId">
|
||||
<th mat-header-cell *matHeaderCellDef>{{ 'labels.inputs.Fund Source' | translate }}</th>
|
||||
<td mat-cell *matCellDef="let paymentFundSource">
|
||||
{{ paymentFundSource.fundSourceAccountId | find: assetAccountData : 'id' : 'name' }}
|
||||
<ng-container matColumnDef="incomeAccountId">
|
||||
<th mat-header-cell *matHeaderCellDef>{{ 'labels.inputs.Income Account' | translate }}</th>
|
||||
<td mat-cell *matCellDef="let feesIncome">
|
||||
{{ feesIncome.incomeAccountId | find: incomeAccountData : 'id' : 'name' }}
|
||||
</td>
|
||||
</ng-container>
|
||||
<ng-container matColumnDef="actions">
|
||||
<th mat-header-cell *matHeaderCellDef>{{ 'labels.buttons.Actions' | translate }}</th>
|
||||
<td mat-cell *matCellDef="let paymentFundSource; let i = index">
|
||||
<td mat-cell *matCellDef="let feesIncome; let i = index">
|
||||
<button
|
||||
mat-icon-button
|
||||
color="primary"
|
||||
(click)="edit('PaymentFundSource', paymentChannelToFundSourceMappings, i)"
|
||||
(click)="edit('FeesIncome', feeToIncomeAccountMappings, i)"
|
||||
>
|
||||
<fa-icon icon="edit"></fa-icon>
|
||||
</button>
|
||||
<button mat-icon-button color="warn" (click)="delete(paymentChannelToFundSourceMappings, i)">
|
||||
<button mat-icon-button color="warn" (click)="delete(feeToIncomeAccountMappings, i)">
|
||||
<fa-icon icon="trash"></fa-icon>
|
||||
</button>
|
||||
</td>
|
||||
</ng-container>
|
||||
<tr mat-header-row *matHeaderRowDef="paymentFundSourceDisplayedColumns"></tr>
|
||||
<tr mat-row *matRowDef="let row; columns: paymentFundSourceDisplayedColumns"></tr>
|
||||
<tr mat-header-row *matHeaderRowDef="feesPenaltyIncomeDisplayedColumns"></tr>
|
||||
<tr mat-row *matRowDef="let row; columns: feesPenaltyIncomeDisplayedColumns"></tr>
|
||||
</table>
|
||||
}
|
||||
</div>
|
||||
@if (existCharges()) {
|
||||
<div class="flex-100">
|
||||
<h4 class="mat-h4 flex-63">{{ 'labels.heading.Map Fees to Specific Income Accounts' | translate }}</h4>
|
||||
<div class="flex-33">
|
||||
<button
|
||||
type="button"
|
||||
mat-raised-button
|
||||
color="primary"
|
||||
(click)="add('FeesIncome', feeToIncomeAccountMappings)"
|
||||
>
|
||||
<fa-icon icon="plus" class="m-r-10"></fa-icon>
|
||||
{{ 'labels.buttons.Add' | translate }}
|
||||
</button>
|
||||
</div>
|
||||
@if (feeToIncomeAccountMappings.value.length !== 0) {
|
||||
<table class="flex-98 mat-elevation-z1" mat-table [dataSource]="feeToIncomeAccountMappings.value">
|
||||
<ng-container matColumnDef="chargeId">
|
||||
<th mat-header-cell *matHeaderCellDef>{{ 'labels.catalogs.Fees' | translate }}</th>
|
||||
<td mat-cell *matCellDef="let feesIncome">
|
||||
{{ feesIncome.chargeId | find: chargeData : 'id' : 'name' }}
|
||||
</td>
|
||||
</ng-container>
|
||||
<ng-container matColumnDef="incomeAccountId">
|
||||
<th mat-header-cell *matHeaderCellDef>{{ 'labels.inputs.Income Account' | translate }}</th>
|
||||
<td mat-cell *matCellDef="let feesIncome">
|
||||
{{ feesIncome.incomeAccountId | find: incomeAccountData : 'id' : 'name' }}
|
||||
</td>
|
||||
</ng-container>
|
||||
<ng-container matColumnDef="actions">
|
||||
<th mat-header-cell *matHeaderCellDef>{{ 'labels.buttons.Actions' | translate }}</th>
|
||||
<td mat-cell *matCellDef="let feesIncome; let i = index">
|
||||
<button
|
||||
mat-icon-button
|
||||
color="primary"
|
||||
(click)="edit('FeesIncome', feeToIncomeAccountMappings, i)"
|
||||
>
|
||||
<fa-icon icon="edit"></fa-icon>
|
||||
</button>
|
||||
<button mat-icon-button color="warn" (click)="delete(feeToIncomeAccountMappings, i)">
|
||||
<fa-icon icon="trash"></fa-icon>
|
||||
</button>
|
||||
</td>
|
||||
</ng-container>
|
||||
<tr mat-header-row *matHeaderRowDef="feesPenaltyIncomeDisplayedColumns"></tr>
|
||||
<tr mat-row *matRowDef="let row; columns: feesPenaltyIncomeDisplayedColumns"></tr>
|
||||
</table>
|
||||
}
|
||||
</div>
|
||||
}
|
||||
@if (existCharges()) {
|
||||
<div class="flex-100">
|
||||
<h4 class="mat-h4 flex-63">
|
||||
{{ 'labels.catalogs.Penalties' | translate }}
|
||||
{{ 'labels.heading.Map Penalties to Specific Income Accounts' | translate }}
|
||||
</h4>
|
||||
<div class="flex-33">
|
||||
<button
|
||||
type="button"
|
||||
mat-raised-button
|
||||
color="primary"
|
||||
(click)="add('PenaltyIncome', penaltyToIncomeAccountMappings)"
|
||||
>
|
||||
<fa-icon icon="plus" class="m-r-10"></fa-icon>
|
||||
{{ 'labels.buttons.Add' | translate }}
|
||||
</button>
|
||||
</div>
|
||||
@if (penaltyToIncomeAccountMappings.value.length !== 0) {
|
||||
<table class="flex-98 mat-elevation-z1" mat-table [dataSource]="penaltyToIncomeAccountMappings.value">
|
||||
<ng-container matColumnDef="chargeId">
|
||||
<th mat-header-cell *matHeaderCellDef>{{ 'labels.inputs.Penalty' | translate }}</th>
|
||||
<td mat-cell *matCellDef="let penaltyIncome">
|
||||
{{ penaltyIncome.chargeId | find: penaltyData : 'id' : 'name' }}
|
||||
</td>
|
||||
</ng-container>
|
||||
<ng-container matColumnDef="incomeAccountId">
|
||||
<th mat-header-cell *matHeaderCellDef>{{ 'labels.inputs.Income Account' | translate }}</th>
|
||||
<td mat-cell *matCellDef="let penaltyIncome">
|
||||
{{ penaltyIncome.incomeAccountId | find: incomeAccountData : 'id' : 'name' }}
|
||||
</td>
|
||||
</ng-container>
|
||||
<ng-container matColumnDef="actions">
|
||||
<th mat-header-cell *matHeaderCellDef>{{ 'labels.buttons.Actions' | translate }}</th>
|
||||
<td mat-cell *matCellDef="let penaltyIncome; let i = index">
|
||||
<button
|
||||
mat-icon-button
|
||||
color="primary"
|
||||
(click)="edit('PenaltyIncome', penaltyToIncomeAccountMappings, i)"
|
||||
>
|
||||
<fa-icon icon="edit"></fa-icon>
|
||||
</button>
|
||||
<button mat-icon-button color="warn" (click)="delete(penaltyToIncomeAccountMappings, i)">
|
||||
<fa-icon icon="trash"></fa-icon>
|
||||
</button>
|
||||
</td>
|
||||
</ng-container>
|
||||
<tr mat-header-row *matHeaderRowDef="feesPenaltyIncomeDisplayedColumns"></tr>
|
||||
<tr mat-row *matRowDef="let row; columns: feesPenaltyIncomeDisplayedColumns"></tr>
|
||||
</table>
|
||||
}
|
||||
</div>
|
||||
|
||||
<!-- Penalty Income -->
|
||||
<div class="fdpa-subsection">
|
||||
<div class="fdpa-subsection__header">
|
||||
<h4>
|
||||
{{ 'labels.catalogs.Penalties' | translate }}
|
||||
{{ 'labels.heading.Map Penalties to Specific Income Accounts' | translate }}
|
||||
</h4>
|
||||
<button
|
||||
type="button"
|
||||
mat-raised-button
|
||||
color="primary"
|
||||
class="fdpa-add-btn"
|
||||
(click)="add('PenaltyIncome', penaltyToIncomeAccountMappings)"
|
||||
>
|
||||
<fa-icon icon="plus" class="m-r-10"></fa-icon>
|
||||
{{ 'labels.buttons.Add' | translate }}
|
||||
</button>
|
||||
</div>
|
||||
@if (penaltyToIncomeAccountMappings.value.length !== 0) {
|
||||
<div class="fdpa-table-wrapper">
|
||||
<table mat-table [dataSource]="penaltyToIncomeAccountMappings.value">
|
||||
<ng-container matColumnDef="chargeId">
|
||||
<th mat-header-cell *matHeaderCellDef>{{ 'labels.inputs.Penalty' | translate }}</th>
|
||||
<td mat-cell *matCellDef="let penaltyIncome">
|
||||
{{ penaltyIncome.chargeId | find: penaltyData : 'id' : 'name' }}
|
||||
</td>
|
||||
</ng-container>
|
||||
<ng-container matColumnDef="incomeAccountId">
|
||||
<th mat-header-cell *matHeaderCellDef>{{ 'labels.inputs.Income Account' | translate }}</th>
|
||||
<td mat-cell *matCellDef="let penaltyIncome">
|
||||
{{ penaltyIncome.incomeAccountId | find: incomeAccountData : 'id' : 'name' }}
|
||||
</td>
|
||||
</ng-container>
|
||||
<ng-container matColumnDef="actions">
|
||||
<th mat-header-cell *matHeaderCellDef>{{ 'labels.buttons.Actions' | translate }}</th>
|
||||
<td mat-cell *matCellDef="let penaltyIncome; let i = index">
|
||||
<button
|
||||
mat-icon-button
|
||||
color="primary"
|
||||
(click)="edit('PenaltyIncome', penaltyToIncomeAccountMappings, i)"
|
||||
>
|
||||
<fa-icon icon="edit"></fa-icon>
|
||||
</button>
|
||||
<button mat-icon-button color="warn" (click)="delete(penaltyToIncomeAccountMappings, i)">
|
||||
<fa-icon icon="trash"></fa-icon>
|
||||
</button>
|
||||
</td>
|
||||
</ng-container>
|
||||
<tr mat-header-row *matHeaderRowDef="feesPenaltyIncomeDisplayedColumns"></tr>
|
||||
<tr mat-row *matRowDef="let row; columns: feesPenaltyIncomeDisplayedColumns"></tr>
|
||||
</table>
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
|
||||
<div class="layout-row align-center gap-2percent margin-t responsive-column">
|
||||
<button mat-raised-button matStepperPrevious>
|
||||
<fa-icon icon="arrow-left" class="m-r-10"></fa-icon>
|
||||
{{ 'labels.buttons.Previous' | translate }}
|
||||
</button>
|
||||
<button mat-raised-button matStepperNext [disabled]="!fixedDepositProductFormValid">
|
||||
{{ 'labels.buttons.Next' | translate }}
|
||||
<fa-icon icon="arrow-right" class="m-l-10"></fa-icon>
|
||||
</button>
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
}
|
||||
</form>
|
||||
|
||||
+95
-29
@@ -6,40 +6,106 @@
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
table {
|
||||
.fdpa-section {
|
||||
border: 1px solid #e2e8f0;
|
||||
border-radius: 10px;
|
||||
overflow: hidden;
|
||||
background: #fff;
|
||||
|
||||
& + & {
|
||||
margin-top: 16px;
|
||||
}
|
||||
|
||||
&__header {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 10px;
|
||||
padding: 12px 24px;
|
||||
background: #f8f9fa;
|
||||
border-bottom: 1px solid #e8eaed;
|
||||
|
||||
i {
|
||||
font-size: 14px;
|
||||
color: #0ea5e9;
|
||||
}
|
||||
|
||||
h3 {
|
||||
margin: 0;
|
||||
font-size: 14px;
|
||||
font-weight: 600;
|
||||
color: #202124;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.fdpa-grid {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(2, 1fr);
|
||||
gap: 4px 16px;
|
||||
padding: 16px 24px;
|
||||
|
||||
@media (max-width: 600px) {
|
||||
grid-template-columns: 1fr;
|
||||
}
|
||||
}
|
||||
|
||||
.fdpa-field {
|
||||
width: 100%;
|
||||
|
||||
&--full {
|
||||
grid-column: 1 / -1;
|
||||
}
|
||||
}
|
||||
|
||||
.mat-elevation-z1 {
|
||||
margin: 1em 0 1.5em;
|
||||
}
|
||||
|
||||
h3,
|
||||
h4 {
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
mat-radio-group,
|
||||
h4 {
|
||||
margin: 1em 0;
|
||||
}
|
||||
|
||||
mat-divider {
|
||||
margin: 1em 0 2em;
|
||||
}
|
||||
|
||||
.margin-t {
|
||||
margin-top: 1em;
|
||||
}
|
||||
|
||||
.radio-group-spacing {
|
||||
.fdpa-radio-group {
|
||||
display: flex;
|
||||
gap: 2rem;
|
||||
flex-direction: row;
|
||||
}
|
||||
gap: 24px;
|
||||
flex-wrap: wrap;
|
||||
|
||||
@media (width <= 768px) {
|
||||
.radio-group-spacing {
|
||||
@media (max-width: 600px) {
|
||||
flex-direction: column;
|
||||
}
|
||||
}
|
||||
|
||||
.fdpa-checkbox-row {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding: 4px 0;
|
||||
}
|
||||
|
||||
.fdpa-add-btn {
|
||||
height: 36px;
|
||||
border-radius: 8px;
|
||||
font-size: 13px;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.fdpa-subsection {
|
||||
padding: 0 24px 16px;
|
||||
|
||||
&__header {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
padding: 12px 0;
|
||||
flex-wrap: wrap;
|
||||
gap: 12px;
|
||||
|
||||
h4 {
|
||||
margin: 0;
|
||||
font-size: 14px;
|
||||
font-weight: 600;
|
||||
color: #202124;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.fdpa-table-wrapper {
|
||||
border: 1px solid #e2e8f0;
|
||||
border-radius: 8px;
|
||||
overflow: hidden;
|
||||
|
||||
table {
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
-5
@@ -25,7 +25,6 @@ import { Accounting } from 'app/core/utils/accounting';
|
||||
import { FormfieldBase } from 'app/shared/form-dialog/formfield/model/formfield-base';
|
||||
import { SelectBase } from 'app/shared/form-dialog/formfield/model/select-base';
|
||||
import { MatRadioGroup, MatRadioButton } from '@angular/material/radio';
|
||||
import { MatDivider } from '@angular/material/divider';
|
||||
import { GlAccountSelectorComponent } from '../../../../shared/accounting/gl-account-selector/gl-account-selector.component';
|
||||
import { MatCheckbox } from '@angular/material/checkbox';
|
||||
import { MatButton, MatIconButton } from '@angular/material/button';
|
||||
@@ -42,7 +41,6 @@ import {
|
||||
MatRowDef,
|
||||
MatRow
|
||||
} from '@angular/material/table';
|
||||
import { MatStepperPrevious, MatStepperNext } from '@angular/material/stepper';
|
||||
import { FindPipe } from '../../../../pipes/find.pipe';
|
||||
import { STANDALONE_SHARED_IMPORTS } from 'app/standalone-shared.module';
|
||||
|
||||
@@ -54,7 +52,6 @@ import { STANDALONE_SHARED_IMPORTS } from 'app/standalone-shared.module';
|
||||
...STANDALONE_SHARED_IMPORTS,
|
||||
MatRadioGroup,
|
||||
MatRadioButton,
|
||||
MatDivider,
|
||||
GlAccountSelectorComponent,
|
||||
MatCheckbox,
|
||||
FaIconComponent,
|
||||
@@ -69,8 +66,6 @@ import { STANDALONE_SHARED_IMPORTS } from 'app/standalone-shared.module';
|
||||
MatHeaderRow,
|
||||
MatRowDef,
|
||||
MatRow,
|
||||
MatStepperPrevious,
|
||||
MatStepperNext,
|
||||
FindPipe
|
||||
]
|
||||
})
|
||||
|
||||
+65
-68
@@ -6,80 +6,77 @@
|
||||
file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
-->
|
||||
|
||||
<div class="layout-row-wrap gap-2px responsive-column">
|
||||
<mat-form-field class="flex-48">
|
||||
<mat-label>{{ 'labels.inputs.Charge' | translate }}</mat-label>
|
||||
<mat-select #charge>
|
||||
@for (charge of chargeData | chargesFilter: chargesDataSource : currencyCode.value; track charge) {
|
||||
<mat-option [value]="charge">
|
||||
{{ charge.name }}
|
||||
</mat-option>
|
||||
}
|
||||
</mat-select>
|
||||
</mat-form-field>
|
||||
<div class="fdpch-section">
|
||||
<div class="fdpch-section__header">
|
||||
<i class="fas fa-money-check-alt"></i>
|
||||
<h3>{{ 'labels.inputs.Charge' | translate }}</h3>
|
||||
</div>
|
||||
<div class="fdpch-grid">
|
||||
<mat-form-field appearance="outline" class="fdpch-field">
|
||||
<mat-label>{{ 'labels.inputs.Charge' | translate }}</mat-label>
|
||||
<mat-select #charge>
|
||||
@for (charge of chargeData | chargesFilter: chargesDataSource : currencyCode.value; track charge) {
|
||||
<mat-option [value]="charge">
|
||||
{{ charge.name }}
|
||||
</mat-option>
|
||||
}
|
||||
</mat-select>
|
||||
</mat-form-field>
|
||||
|
||||
<div class="flex-48 align-center">
|
||||
<button type="button" mat-raised-button color="primary" (click)="addCharge(charge)" [disabled]="!charge.value">
|
||||
<fa-icon icon="plus" class="m-r-10"></fa-icon>
|
||||
{{ 'labels.buttons.Add' | translate }}
|
||||
</button>
|
||||
<div class="fdpch-field fdpch-btn-wrap">
|
||||
<button type="button" mat-raised-button color="primary" class="fdpch-add-btn" (click)="addCharge(charge)" [disabled]="!charge.value">
|
||||
<fa-icon icon="plus" class="m-r-10"></fa-icon>
|
||||
{{ 'labels.buttons.Add' | translate }}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<table
|
||||
class="flex-98 mat-elevation-z1"
|
||||
mat-table
|
||||
[dataSource]="chargesDataSource"
|
||||
[hidden]="chargesDataSource.length === 0"
|
||||
>
|
||||
<ng-container matColumnDef="name">
|
||||
<th mat-header-cell *matHeaderCellDef>{{ 'labels.inputs.Name' | translate }}</th>
|
||||
<td mat-cell *matCellDef="let charge">
|
||||
{{ charge.name + ', ' + charge.currency.displaySymbol }}
|
||||
</td>
|
||||
</ng-container>
|
||||
@if (chargesDataSource.length > 0) {
|
||||
<div class="fdpch-table-wrapper">
|
||||
<table
|
||||
mat-table
|
||||
[dataSource]="chargesDataSource"
|
||||
>
|
||||
<ng-container matColumnDef="name">
|
||||
<th mat-header-cell *matHeaderCellDef>{{ 'labels.inputs.Name' | translate }}</th>
|
||||
<td mat-cell *matCellDef="let charge">
|
||||
{{ charge.name + ', ' + charge.currency.displaySymbol }}
|
||||
</td>
|
||||
</ng-container>
|
||||
|
||||
<ng-container matColumnDef="chargeCalculationType">
|
||||
<th mat-header-cell *matHeaderCellDef>{{ 'labels.inputs.Type' | translate }}</th>
|
||||
<td mat-cell *matCellDef="let charge">
|
||||
{{ charge.chargeCalculationType.value }}
|
||||
</td>
|
||||
</ng-container>
|
||||
<ng-container matColumnDef="chargeCalculationType">
|
||||
<th mat-header-cell *matHeaderCellDef>{{ 'labels.inputs.Type' | translate }}</th>
|
||||
<td mat-cell *matCellDef="let charge">
|
||||
{{ charge.chargeCalculationType.value }}
|
||||
</td>
|
||||
</ng-container>
|
||||
|
||||
<ng-container matColumnDef="amount">
|
||||
<th mat-header-cell *matHeaderCellDef>{{ 'labels.inputs.Amount' | translate }}</th>
|
||||
<td mat-cell *matCellDef="let charge">
|
||||
{{ charge.amount | formatNumber }}
|
||||
</td>
|
||||
</ng-container>
|
||||
<ng-container matColumnDef="amount">
|
||||
<th mat-header-cell *matHeaderCellDef>{{ 'labels.inputs.Amount' | translate }}</th>
|
||||
<td mat-cell *matCellDef="let charge">
|
||||
{{ charge.amount | formatNumber }}
|
||||
</td>
|
||||
</ng-container>
|
||||
|
||||
<ng-container matColumnDef="chargeTimeType">
|
||||
<th mat-header-cell *matHeaderCellDef>{{ 'labels.inputs.Collected On' | translate }}</th>
|
||||
<td mat-cell *matCellDef="let charge">
|
||||
{{ charge.chargeTimeType.value }}
|
||||
</td>
|
||||
</ng-container>
|
||||
<ng-container matColumnDef="chargeTimeType">
|
||||
<th mat-header-cell *matHeaderCellDef>{{ 'labels.inputs.Collected On' | translate }}</th>
|
||||
<td mat-cell *matCellDef="let charge">
|
||||
{{ charge.chargeTimeType.value }}
|
||||
</td>
|
||||
</ng-container>
|
||||
|
||||
<ng-container matColumnDef="action">
|
||||
<th mat-header-cell *matHeaderCellDef>{{ 'labels.inputs.Actions' | translate }}</th>
|
||||
<td mat-cell *matCellDef="let charge">
|
||||
<button mat-icon-button color="warn" (click)="deleteCharge(charge)">
|
||||
<fa-icon icon="trash"></fa-icon>
|
||||
</button>
|
||||
</td>
|
||||
</ng-container>
|
||||
<ng-container matColumnDef="action">
|
||||
<th mat-header-cell *matHeaderCellDef>{{ 'labels.inputs.Actions' | translate }}</th>
|
||||
<td mat-cell *matCellDef="let charge">
|
||||
<button mat-icon-button color="warn" (click)="deleteCharge(charge)">
|
||||
<fa-icon icon="trash"></fa-icon>
|
||||
</button>
|
||||
</td>
|
||||
</ng-container>
|
||||
|
||||
<tr mat-header-row *matHeaderRowDef="displayedColumns"></tr>
|
||||
<tr mat-row *matRowDef="let row; columns: displayedColumns"></tr>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
<div class="layout-row responsive-column align-center gap-2px margin-t">
|
||||
<button mat-raised-button matStepperPrevious>
|
||||
<fa-icon icon="arrow-left" class="m-r-10"></fa-icon>
|
||||
{{ 'labels.buttons.Previous' | translate }}
|
||||
</button>
|
||||
<button mat-raised-button matStepperNext>
|
||||
{{ 'labels.buttons.Next' | translate }}
|
||||
<fa-icon icon="arrow-right" class="m-l-10"></fa-icon>
|
||||
</button>
|
||||
<tr mat-header-row *matHeaderRowDef="displayedColumns"></tr>
|
||||
<tr mat-row *matRowDef="let row; columns: displayedColumns"></tr>
|
||||
</table>
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
|
||||
+67
-5
@@ -6,14 +6,76 @@
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
table {
|
||||
.fdpch-section {
|
||||
border: 1px solid #e2e8f0;
|
||||
border-radius: 10px;
|
||||
overflow: hidden;
|
||||
background: #fff;
|
||||
|
||||
& + & {
|
||||
margin-top: 16px;
|
||||
}
|
||||
|
||||
&__header {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 10px;
|
||||
padding: 12px 24px;
|
||||
background: #f8f9fa;
|
||||
border-bottom: 1px solid #e8eaed;
|
||||
|
||||
i {
|
||||
font-size: 14px;
|
||||
color: #0ea5e9;
|
||||
}
|
||||
|
||||
h3 {
|
||||
margin: 0;
|
||||
font-size: 14px;
|
||||
font-weight: 600;
|
||||
color: #202124;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.fdpch-grid {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(2, 1fr);
|
||||
gap: 4px 16px;
|
||||
padding: 16px 24px;
|
||||
|
||||
@media (max-width: 600px) {
|
||||
grid-template-columns: 1fr;
|
||||
}
|
||||
}
|
||||
|
||||
.fdpch-field {
|
||||
width: 100%;
|
||||
|
||||
&--full {
|
||||
grid-column: 1 / -1;
|
||||
}
|
||||
}
|
||||
|
||||
.mat-elevation-z1 {
|
||||
margin: 1em 0 1.5em;
|
||||
.fdpch-btn-wrap {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.margin-t {
|
||||
margin-top: 1em;
|
||||
.fdpch-add-btn {
|
||||
height: 36px;
|
||||
border-radius: 8px;
|
||||
font-size: 13px;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.fdpch-table-wrapper {
|
||||
border: 1px solid #e2e8f0;
|
||||
border-radius: 8px;
|
||||
overflow: hidden;
|
||||
margin: 0 24px 16px;
|
||||
|
||||
table {
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
-3
@@ -26,7 +26,6 @@ import {
|
||||
MatRowDef,
|
||||
MatRow
|
||||
} from '@angular/material/table';
|
||||
import { MatStepperPrevious, MatStepperNext } from '@angular/material/stepper';
|
||||
import { ChargesFilterPipe } from '../../../../pipes/charges-filter.pipe';
|
||||
import { FormatNumberPipe } from '../../../../pipes/format-number.pipe';
|
||||
import { STANDALONE_SHARED_IMPORTS } from 'app/standalone-shared.module';
|
||||
@@ -49,8 +48,6 @@ import { STANDALONE_SHARED_IMPORTS } from 'app/standalone-shared.module';
|
||||
MatHeaderRow,
|
||||
MatRowDef,
|
||||
MatRow,
|
||||
MatStepperPrevious,
|
||||
MatStepperNext,
|
||||
ChargesFilterPipe,
|
||||
FormatNumberPipe
|
||||
]
|
||||
|
||||
+53
-56
@@ -7,66 +7,63 @@
|
||||
-->
|
||||
|
||||
<form [formGroup]="fixedDepositProductCurrencyForm">
|
||||
<div class="layout-row-wrap gap-2px responsive-column">
|
||||
<mat-form-field class="flex-48">
|
||||
<mat-label>{{ 'labels.inputs.Currency' | translate }}</mat-label>
|
||||
<mat-select formControlName="currencyCode" required>
|
||||
@for (currency of currencyData; track currency) {
|
||||
<mat-option [value]="currency.code">
|
||||
{{ currency.name }}
|
||||
</mat-option>
|
||||
}
|
||||
</mat-select>
|
||||
<mat-error>
|
||||
{{ 'labels.inputs.Currency' | translate }} {{ 'labels.commons.is' | translate }}
|
||||
<strong>{{ 'labels.commons.required' | translate }}</strong>
|
||||
</mat-error>
|
||||
</mat-form-field>
|
||||
|
||||
<mat-form-field class="flex-48">
|
||||
<mat-label>{{ 'labels.inputs.Decimal Places' | translate }}</mat-label>
|
||||
<input
|
||||
type="number"
|
||||
min="0"
|
||||
matInput
|
||||
matTooltip="{{ 'tooltips.Decimal places to be used to track and report' | translate }}"
|
||||
formControlName="digitsAfterDecimal"
|
||||
required
|
||||
/>
|
||||
<mat-error *ngIf="fixedDepositProductCurrencyForm.get('digitsAfterDecimal')?.hasError('required')">
|
||||
{{ 'labels.inputs.Decimal Places' | translate }} {{ 'labels.commons.is' | translate }}
|
||||
<strong>{{ 'labels.commons.required' | translate }}</strong>
|
||||
</mat-error>
|
||||
<mat-error *ngIf="fixedDepositProductCurrencyForm.get('digitsAfterDecimal')?.hasError('min')">
|
||||
{{ 'labels.inputs.Decimal Places' | translate }} {{ 'labels.commons.Minimum Value must be' | translate }}
|
||||
<strong>0</strong>
|
||||
</mat-error>
|
||||
</mat-form-field>
|
||||
|
||||
<mat-checkbox labelPosition="before" formControlName="setMultiples" class="flex-98 margin-t checkbox-align-center">
|
||||
{{ 'labels.inputs.Set the fixed deposit installment in multiples of' | translate }}
|
||||
</mat-checkbox>
|
||||
|
||||
@if (fixedDepositProductCurrencyForm.value.setMultiples) {
|
||||
<mat-form-field class="flex-48">
|
||||
<mat-label>{{ 'labels.inputs.Currency in multiples of' | translate }}</mat-label>
|
||||
<input type="number" min="1" matInput formControlName="inMultiplesOf" />
|
||||
<div class="fdpc-section">
|
||||
<div class="fdpc-section__header">
|
||||
<i class="fas fa-coins"></i>
|
||||
<h3>{{ 'labels.inputs.Currency' | translate }}</h3>
|
||||
</div>
|
||||
<div class="fdpc-grid">
|
||||
<mat-form-field appearance="outline" class="fdpc-field">
|
||||
<mat-label>{{ 'labels.inputs.Currency' | translate }}</mat-label>
|
||||
<mat-select formControlName="currencyCode" required>
|
||||
@for (currency of currencyData; track currency) {
|
||||
<mat-option [value]="currency.code">
|
||||
{{ currency.name }}
|
||||
</mat-option>
|
||||
}
|
||||
</mat-select>
|
||||
<mat-error>
|
||||
{{ 'labels.inputs.Currency in multiples of' | translate }} {{ 'labels.commons.is' | translate }}
|
||||
{{ 'labels.inputs.Currency' | translate }} {{ 'labels.commons.is' | translate }}
|
||||
<strong>{{ 'labels.commons.required' | translate }}</strong>
|
||||
</mat-error>
|
||||
</mat-form-field>
|
||||
}
|
||||
</div>
|
||||
|
||||
<div class="layout-row align-center gap-2percent margin-t responsive-column">
|
||||
<button mat-raised-button matStepperPrevious>
|
||||
<fa-icon icon="arrow-left" class="m-r-10"></fa-icon>
|
||||
{{ 'labels.buttons.Previous' | translate }}
|
||||
</button>
|
||||
<button mat-raised-button matStepperNext>
|
||||
{{ 'labels.buttons.Next' | translate }}
|
||||
<fa-icon icon="arrow-right" class="m-l-10"></fa-icon>
|
||||
</button>
|
||||
<mat-form-field appearance="outline" class="fdpc-field">
|
||||
<mat-label>{{ 'labels.inputs.Decimal Places' | translate }}</mat-label>
|
||||
<input
|
||||
type="number"
|
||||
min="0"
|
||||
matInput
|
||||
matTooltip="{{ 'tooltips.Decimal places to be used to track and report' | translate }}"
|
||||
formControlName="digitsAfterDecimal"
|
||||
required
|
||||
/>
|
||||
<mat-error *ngIf="fixedDepositProductCurrencyForm.get('digitsAfterDecimal')?.hasError('required')">
|
||||
{{ 'labels.inputs.Decimal Places' | translate }} {{ 'labels.commons.is' | translate }}
|
||||
<strong>{{ 'labels.commons.required' | translate }}</strong>
|
||||
</mat-error>
|
||||
<mat-error *ngIf="fixedDepositProductCurrencyForm.get('digitsAfterDecimal')?.hasError('min')">
|
||||
{{ 'labels.inputs.Decimal Places' | translate }} {{ 'labels.commons.Minimum Value must be' | translate }}
|
||||
<strong>0</strong>
|
||||
</mat-error>
|
||||
</mat-form-field>
|
||||
|
||||
<div class="fdpc-field fdpc-field--full fdpc-checkbox-row">
|
||||
<mat-checkbox labelPosition="before" formControlName="setMultiples">
|
||||
{{ 'labels.inputs.Set the fixed deposit installment in multiples of' | translate }}
|
||||
</mat-checkbox>
|
||||
</div>
|
||||
|
||||
@if (fixedDepositProductCurrencyForm.value.setMultiples) {
|
||||
<mat-form-field appearance="outline" class="fdpc-field">
|
||||
<mat-label>{{ 'labels.inputs.Currency in multiples of' | translate }}</mat-label>
|
||||
<input type="number" min="1" matInput formControlName="inMultiplesOf" />
|
||||
<mat-error>
|
||||
{{ 'labels.inputs.Currency in multiples of' | translate }} {{ 'labels.commons.is' | translate }}
|
||||
<strong>{{ 'labels.commons.required' | translate }}</strong>
|
||||
</mat-error>
|
||||
</mat-form-field>
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
+52
-3
@@ -6,10 +6,59 @@
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
.margin-t {
|
||||
margin-top: 1em;
|
||||
.fdpc-section {
|
||||
border: 1px solid #e2e8f0;
|
||||
border-radius: 10px;
|
||||
overflow: hidden;
|
||||
background: #fff;
|
||||
|
||||
& + & {
|
||||
margin-top: 16px;
|
||||
}
|
||||
|
||||
&__header {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 10px;
|
||||
padding: 12px 24px;
|
||||
background: #f8f9fa;
|
||||
border-bottom: 1px solid #e8eaed;
|
||||
|
||||
i {
|
||||
font-size: 14px;
|
||||
color: #0ea5e9;
|
||||
}
|
||||
|
||||
h3 {
|
||||
margin: 0;
|
||||
font-size: 14px;
|
||||
font-weight: 600;
|
||||
color: #202124;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.checkbox-align-center {
|
||||
.fdpc-grid {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(2, 1fr);
|
||||
gap: 4px 16px;
|
||||
padding: 16px 24px;
|
||||
|
||||
@media (max-width: 600px) {
|
||||
grid-template-columns: 1fr;
|
||||
}
|
||||
}
|
||||
|
||||
.fdpc-field {
|
||||
width: 100%;
|
||||
|
||||
&--full {
|
||||
grid-column: 1 / -1;
|
||||
}
|
||||
}
|
||||
|
||||
.fdpc-checkbox-row {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding: 4px 0;
|
||||
}
|
||||
|
||||
-5
@@ -10,10 +10,8 @@ import { Component, OnInit, Input, inject, DestroyRef } from '@angular/core';
|
||||
import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
|
||||
import { startWith } from 'rxjs/operators';
|
||||
import { UntypedFormGroup, UntypedFormBuilder, Validators, ReactiveFormsModule } from '@angular/forms';
|
||||
import { MatStepperPrevious, MatStepperNext } from '@angular/material/stepper';
|
||||
import { MatCheckbox } from '@angular/material/checkbox';
|
||||
import { MatTooltip } from '@angular/material/tooltip';
|
||||
import { FaIconComponent } from '@fortawesome/angular-fontawesome';
|
||||
import { STANDALONE_SHARED_IMPORTS } from 'app/standalone-shared.module';
|
||||
|
||||
@Component({
|
||||
@@ -23,9 +21,6 @@ import { STANDALONE_SHARED_IMPORTS } from 'app/standalone-shared.module';
|
||||
imports: [
|
||||
...STANDALONE_SHARED_IMPORTS,
|
||||
MatTooltip,
|
||||
MatStepperPrevious,
|
||||
FaIconComponent,
|
||||
MatStepperNext,
|
||||
MatCheckbox
|
||||
]
|
||||
})
|
||||
|
||||
+37
-42
@@ -7,49 +7,44 @@
|
||||
-->
|
||||
|
||||
<form [formGroup]="fixedDepositProductDetailsForm">
|
||||
<div class="layout-row-wrap gap-2px responsive-column">
|
||||
<mat-form-field class="flex-48">
|
||||
<mat-label>{{ 'labels.inputs.Product Name' | translate }}</mat-label>
|
||||
<input matInput formControlName="name" required />
|
||||
@if (fixedDepositProductDetailsForm.controls.name.hasError('required')) {
|
||||
<mat-error>
|
||||
{{ 'labels.inputs.Product Name' | translate }} {{ 'labels.commons.is' | translate }}
|
||||
<strong>{{ 'labels.commons.required' | translate }}</strong>
|
||||
</mat-error>
|
||||
}
|
||||
</mat-form-field>
|
||||
<div class="fdpd-section">
|
||||
<div class="fdpd-section__header">
|
||||
<i class="fas fa-info-circle"></i>
|
||||
<h3>{{ 'labels.inputs.Product Name' | translate }} & {{ 'labels.inputs.Description' | translate }}</h3>
|
||||
</div>
|
||||
<div class="fdpd-grid">
|
||||
<mat-form-field appearance="outline" class="fdpd-field">
|
||||
<mat-label>{{ 'labels.inputs.Product Name' | translate }}</mat-label>
|
||||
<input matInput formControlName="name" required />
|
||||
@if (fixedDepositProductDetailsForm.controls.name.hasError('required')) {
|
||||
<mat-error>
|
||||
{{ 'labels.inputs.Product Name' | translate }} {{ 'labels.commons.is' | translate }}
|
||||
<strong>{{ 'labels.commons.required' | translate }}</strong>
|
||||
</mat-error>
|
||||
}
|
||||
</mat-form-field>
|
||||
|
||||
<mat-form-field class="flex-48">
|
||||
<mat-label>{{ 'labels.inputs.Short Name' | translate }}</mat-label>
|
||||
<input matInput formControlName="shortName" maxlength="4" required />
|
||||
@if (fixedDepositProductDetailsForm.controls.shortName.hasError('required')) {
|
||||
<mat-error>
|
||||
{{ 'labels.inputs.Short Name' | translate }} {{ 'labels.commons.is' | translate }}
|
||||
<strong>{{ 'labels.commons.required' | translate }}</strong>
|
||||
</mat-error>
|
||||
}
|
||||
</mat-form-field>
|
||||
<mat-form-field appearance="outline" class="fdpd-field">
|
||||
<mat-label>{{ 'labels.inputs.Short Name' | translate }}</mat-label>
|
||||
<input matInput formControlName="shortName" maxlength="4" required />
|
||||
@if (fixedDepositProductDetailsForm.controls.shortName.hasError('required')) {
|
||||
<mat-error>
|
||||
{{ 'labels.inputs.Short Name' | translate }} {{ 'labels.commons.is' | translate }}
|
||||
<strong>{{ 'labels.commons.required' | translate }}</strong>
|
||||
</mat-error>
|
||||
}
|
||||
</mat-form-field>
|
||||
|
||||
<mat-form-field class="flex-98">
|
||||
<mat-label>{{ 'labels.inputs.Description' | translate }}</mat-label>
|
||||
<textarea matInput formControlName="description" required></textarea>
|
||||
@if (fixedDepositProductDetailsForm.controls.description.hasError('required')) {
|
||||
<mat-error>
|
||||
{{ 'labels.inputs.Description' | translate }} {{ 'labels.commons.is' | translate }}
|
||||
<strong>{{ 'labels.commons.required' | translate }}</strong>
|
||||
</mat-error>
|
||||
}
|
||||
</mat-form-field>
|
||||
</div>
|
||||
|
||||
<div class="layout-row align-center gap-2percent margin-t responsive-column">
|
||||
<button mat-raised-button matStepperPrevious disabled>
|
||||
<fa-icon icon="arrow-left" class="m-r-10"></fa-icon>
|
||||
{{ 'labels.buttons.Previous' | translate }}
|
||||
</button>
|
||||
<button mat-raised-button matStepperNext>
|
||||
{{ 'labels.buttons.Next' | translate }}
|
||||
<fa-icon icon="arrow-right" class="m-l-10"></fa-icon>
|
||||
</button>
|
||||
<mat-form-field appearance="outline" class="fdpd-field fdpd-field--full">
|
||||
<mat-label>{{ 'labels.inputs.Description' | translate }}</mat-label>
|
||||
<textarea matInput formControlName="description" required></textarea>
|
||||
@if (fixedDepositProductDetailsForm.controls.description.hasError('required')) {
|
||||
<mat-error>
|
||||
{{ 'labels.inputs.Description' | translate }} {{ 'labels.commons.is' | translate }}
|
||||
<strong>{{ 'labels.commons.required' | translate }}</strong>
|
||||
</mat-error>
|
||||
}
|
||||
</mat-form-field>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
+49
-2
@@ -6,6 +6,53 @@
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
.margin-t {
|
||||
margin-top: 1em;
|
||||
.fdpd-section {
|
||||
border: 1px solid #e2e8f0;
|
||||
border-radius: 10px;
|
||||
overflow: hidden;
|
||||
background: #fff;
|
||||
|
||||
& + & {
|
||||
margin-top: 16px;
|
||||
}
|
||||
|
||||
&__header {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 10px;
|
||||
padding: 12px 24px;
|
||||
background: #f8f9fa;
|
||||
border-bottom: 1px solid #e8eaed;
|
||||
|
||||
i {
|
||||
font-size: 14px;
|
||||
color: #0ea5e9;
|
||||
}
|
||||
|
||||
h3 {
|
||||
margin: 0;
|
||||
font-size: 14px;
|
||||
font-weight: 600;
|
||||
color: #202124;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.fdpd-grid {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(2, 1fr);
|
||||
gap: 4px 16px;
|
||||
padding: 16px 24px;
|
||||
|
||||
@media (max-width: 600px) {
|
||||
grid-template-columns: 1fr;
|
||||
}
|
||||
}
|
||||
|
||||
.fdpd-field {
|
||||
width: 100%;
|
||||
|
||||
&--full {
|
||||
grid-column: 1 / -1;
|
||||
}
|
||||
}
|
||||
|
||||
+1
-6
@@ -8,8 +8,6 @@
|
||||
|
||||
import { Component, OnInit, Input, inject } from '@angular/core';
|
||||
import { UntypedFormGroup, UntypedFormBuilder, Validators, ReactiveFormsModule } from '@angular/forms';
|
||||
import { MatStepperPrevious, MatStepperNext } from '@angular/material/stepper';
|
||||
import { FaIconComponent } from '@fortawesome/angular-fontawesome';
|
||||
import { STANDALONE_SHARED_IMPORTS } from 'app/standalone-shared.module';
|
||||
|
||||
@Component({
|
||||
@@ -17,10 +15,7 @@ import { STANDALONE_SHARED_IMPORTS } from 'app/standalone-shared.module';
|
||||
templateUrl: './fixed-deposit-product-details-step.component.html',
|
||||
styleUrls: ['./fixed-deposit-product-details-step.component.scss'],
|
||||
imports: [
|
||||
...STANDALONE_SHARED_IMPORTS,
|
||||
MatStepperPrevious,
|
||||
FaIconComponent,
|
||||
MatStepperNext
|
||||
...STANDALONE_SHARED_IMPORTS
|
||||
]
|
||||
})
|
||||
export class FixedDepositProductDetailsStepComponent implements OnInit {
|
||||
|
||||
+286
-286
@@ -7,298 +7,298 @@
|
||||
-->
|
||||
|
||||
<form [formGroup]="fixedDepositProductInterestRateChartForm">
|
||||
<div class="layout-row-wrap gap-2px responsive-column">
|
||||
<h4 class="mat-h3 flex-83">
|
||||
{{ 'labels.inputs.Interest Rate Chart' | translate }}
|
||||
<i class="fas fa-question" matTooltip="{{ 'tooltips.The interest rate chart' | translate }}"></i>
|
||||
</h4>
|
||||
|
||||
<div class="flex-13 layout-row align-start-center">
|
||||
<button type="button" mat-raised-button color="primary" (click)="addChart()">
|
||||
<div class="fdpi-section">
|
||||
<div class="fdpi-section__header">
|
||||
<i class="fas fa-chart-line"></i>
|
||||
<h3>{{ 'labels.inputs.Interest Rate Chart' | translate }}</h3>
|
||||
<span class="fdpi-spacer"></span>
|
||||
<button type="button" mat-raised-button color="primary" class="fdpi-add-btn" (click)="addChart()">
|
||||
<fa-icon icon="plus" class="m-r-10"></fa-icon>
|
||||
{{ 'labels.buttons.Add' | translate }}
|
||||
</button>
|
||||
</div>
|
||||
|
||||
@for (chart of charts.controls; track chart; let chartIndex = $index) {
|
||||
<div class="flex-fill layout-row-wrap responsive-column" formArrayName="charts">
|
||||
<mat-divider class="flex-98"></mat-divider>
|
||||
<div class="flex-fill layout-row-wrap responsive-column" [formGroupName]="chartIndex">
|
||||
<div class="flex-100" align="end">
|
||||
<button
|
||||
type="button"
|
||||
mat-icon-button
|
||||
color="warn"
|
||||
(click)="delete(charts, chartIndex)"
|
||||
matTooltip="{{ 'tooltips.Delete Interest Rate Chart' | translate }}"
|
||||
matTooltipPosition="left"
|
||||
>
|
||||
<fa-icon icon="trash"></fa-icon>
|
||||
</button>
|
||||
</div>
|
||||
<mat-form-field class="flex-28 m-r-5">
|
||||
<mat-label>{{ 'labels.inputs.Name' | translate }}</mat-label>
|
||||
<input matInput formControlName="name" required />
|
||||
@if (chart.get('name')?.touched && chart.get('name')?.hasError('required')) {
|
||||
<mat-error>
|
||||
{{ 'labels.inputs.Name' | translate }} {{ 'labels.commons.is' | translate }}
|
||||
<strong>{{ 'labels.commons.required' | translate }}</strong>
|
||||
</mat-error>
|
||||
}
|
||||
</mat-form-field>
|
||||
<mat-form-field class="flex-70">
|
||||
<mat-label>{{ 'labels.inputs.Description' | translate }}</mat-label>
|
||||
<textarea matInput formControlName="description" required></textarea>
|
||||
@if (chart.get('description')?.touched && chart.get('description')?.hasError('required')) {
|
||||
<mat-error>
|
||||
{{ 'labels.inputs.Description' | translate }} {{ 'labels.commons.is' | translate }}
|
||||
<strong>{{ 'labels.commons.required' | translate }}</strong>
|
||||
</mat-error>
|
||||
}
|
||||
</mat-form-field>
|
||||
<mat-form-field class="flex-48 m-r-5" (click)="validFromDatePicker.open()">
|
||||
<mat-label>{{ 'labels.inputs.From Date' | translate }}</mat-label>
|
||||
<input
|
||||
matInput
|
||||
[min]="minDate"
|
||||
[max]="maxDate"
|
||||
[matDatepicker]="validFromDatePicker"
|
||||
formControlName="fromDate"
|
||||
required
|
||||
/>
|
||||
<mat-datepicker-toggle matSuffix [for]="validFromDatePicker"></mat-datepicker-toggle>
|
||||
<mat-datepicker #validFromDatePicker></mat-datepicker>
|
||||
<mat-error>
|
||||
{{ 'labels.inputs.Valid from Date' | translate }} {{ 'labels.commons.is' | translate }}
|
||||
<strong>{{ 'labels.commons.required' | translate }}</strong>
|
||||
</mat-error>
|
||||
</mat-form-field>
|
||||
<mat-form-field class="flex-48 m-r-5" (click)="endDatePicker.open()">
|
||||
<mat-label>{{ 'labels.inputs.End Date' | translate }}</mat-label>
|
||||
<input matInput [min]="minDate" [max]="maxDate" [matDatepicker]="endDatePicker" formControlName="endDate" />
|
||||
<mat-datepicker-toggle matSuffix [for]="endDatePicker"></mat-datepicker-toggle>
|
||||
<mat-datepicker #endDatePicker></mat-datepicker>
|
||||
</mat-form-field>
|
||||
<div class="flex-100 layout-row align-between align-items-center">
|
||||
<mat-checkbox labelPosition="before" formControlName="isPrimaryGroupingByAmount">
|
||||
{{ 'labels.inputs.Is primary grouping by amount?' | translate }}
|
||||
</mat-checkbox>
|
||||
</div>
|
||||
<div class="center flex-100">
|
||||
<button type="button" mat-raised-button color="primary" (click)="addChartSlab(chart.controls.chartSlabs)">
|
||||
<fa-icon icon="plus" class="m-r-10"></fa-icon>
|
||||
{{ 'labels.buttons.Add Slab' | translate }}
|
||||
</button>
|
||||
</div>
|
||||
@if (chart.value.chartSlabs.length === 0) {
|
||||
<div class="flex-100">
|
||||
<h3 class="mat-h3">{{ 'labels.heading.It is required to add at least one Slab' | translate }}</h3>
|
||||
<div class="fdpi-body">
|
||||
@for (chart of charts.controls; track chart; let chartIndex = $index) {
|
||||
<div class="fdpi-chart-card" formArrayName="charts">
|
||||
<div class="fdpi-chart-card__top" [formGroupName]="chartIndex">
|
||||
<div class="fdpi-chart-card__actions">
|
||||
<button
|
||||
type="button"
|
||||
mat-icon-button
|
||||
color="warn"
|
||||
(click)="delete(charts, chartIndex)"
|
||||
matTooltip="{{ 'tooltips.Delete Interest Rate Chart' | translate }}"
|
||||
matTooltipPosition="left"
|
||||
>
|
||||
<fa-icon icon="trash"></fa-icon>
|
||||
</button>
|
||||
</div>
|
||||
}
|
||||
@if (chart.value.chartSlabs.length !== 0) {
|
||||
<table
|
||||
class="flex-98 mat-elevation-z1"
|
||||
mat-table
|
||||
[dataSource]="chart.value.chartSlabs"
|
||||
multiTemplateDataRows
|
||||
>
|
||||
<ng-container matColumnDef="period">
|
||||
<th mat-header-cell *matHeaderCellDef>{{ 'labels.inputs.Period' | translate }}</th>
|
||||
<td mat-cell *matCellDef="let chartSlab">
|
||||
{{
|
||||
chartSlab.fromPeriod +
|
||||
' - ' +
|
||||
chartSlab.toPeriod +
|
||||
' ' +
|
||||
(chartSlab.periodType | find: periodTypeData : 'id' : 'value')
|
||||
}}
|
||||
</td>
|
||||
</ng-container>
|
||||
<ng-container matColumnDef="amountRange">
|
||||
<th mat-header-cell *matHeaderCellDef>{{ 'labels.inputs.Amount Range' | translate }}</th>
|
||||
<td mat-cell *matCellDef="let chartSlab">
|
||||
{{ chartSlab.amountRangeFrom + ' - ' + chartSlab.amountRangeTo }}
|
||||
</td>
|
||||
</ng-container>
|
||||
<ng-container matColumnDef="annualInterestRate">
|
||||
<th mat-header-cell *matHeaderCellDef>{{ 'labels.inputs.Interest' | translate }}</th>
|
||||
<td mat-cell *matCellDef="let chartSlab">{{ chartSlab.annualInterestRate }} %</td>
|
||||
</ng-container>
|
||||
<ng-container matColumnDef="description">
|
||||
<th mat-header-cell *matHeaderCellDef>{{ 'labels.inputs.Description' | translate }}</th>
|
||||
<td mat-cell *matCellDef="let chartSlab">
|
||||
{{ chartSlab.description }}
|
||||
</td>
|
||||
</ng-container>
|
||||
<ng-container matColumnDef="actions">
|
||||
<th mat-header-cell *matHeaderCellDef>{{ 'labels.inputs.Actions' | translate }}</th>
|
||||
<td mat-cell *matCellDef="let chartSlab; let chartSlabIndex = dataIndex">
|
||||
<button
|
||||
mat-icon-button
|
||||
color="primary"
|
||||
(click)="editChartSlab(chart.controls.chartSlabs, chartSlabIndex)"
|
||||
>
|
||||
<fa-icon icon="edit"></fa-icon>
|
||||
</button>
|
||||
<button mat-icon-button color="warn" (click)="delete(chart.controls.chartSlabs, chartSlabIndex)">
|
||||
<fa-icon icon="trash"></fa-icon>
|
||||
</button>
|
||||
<button
|
||||
mat-button
|
||||
color="primary"
|
||||
(click)="
|
||||
expandChartSlabIndex[chartIndex] =
|
||||
expandChartSlabIndex[chartIndex] === chartSlabIndex ? null : chartSlabIndex
|
||||
"
|
||||
>
|
||||
@if (expandChartSlabIndex[chartIndex] !== chartSlabIndex) {
|
||||
<span>
|
||||
<fa-icon icon="eye" class="m-r-10"></fa-icon>
|
||||
{{ 'labels.buttons.View Incentives' | translate }}
|
||||
</span>
|
||||
}
|
||||
@if (expandChartSlabIndex[chartIndex] === chartSlabIndex) {
|
||||
<span>
|
||||
<fa-icon icon="eye-slash" class="m-r-10"></fa-icon>
|
||||
{{ 'labels.buttons.Hide Incentives' | translate }}
|
||||
</span>
|
||||
}
|
||||
</button>
|
||||
</td>
|
||||
</ng-container>
|
||||
<ng-container matColumnDef="incentives">
|
||||
<td
|
||||
mat-cell
|
||||
*matCellDef="let chartSlab; let chartSlabIndex = dataIndex"
|
||||
[attr.colspan]="chartSlabsDisplayedColumns[chartIndex].length"
|
||||
>
|
||||
<div
|
||||
class="layout-row-wrap flex-fill incentives"
|
||||
[@expandChartSlab]="chartSlabIndex === expandChartSlabIndex[chartIndex] ? 'expanded' : 'collapsed'"
|
||||
>
|
||||
<mat-card class="layout-row-wrap flex-fill">
|
||||
<h4 class="mat-h4 flex-63">
|
||||
{{ 'labels.heading.Incentives' | translate }}
|
||||
</h4>
|
||||
<div class="flex-13">
|
||||
<button
|
||||
mat-raised-button
|
||||
color="primary"
|
||||
(click)="addIncentive(getIncentives(chart.controls.chartSlabs, chartSlabIndex))"
|
||||
>
|
||||
<fa-icon icon="plus" class="m-r-10"></fa-icon>
|
||||
{{ 'labels.buttons.Add' | translate }}
|
||||
</button>
|
||||
</div>
|
||||
@if (chartSlab.incentives.length) {
|
||||
<table class="mat-elevation-z1 flex-fill" mat-table [dataSource]="chartSlab.incentives">
|
||||
<ng-container matColumnDef="entityType">
|
||||
<th mat-header-cell *matHeaderCellDef>{{ 'labels.inputs.Entity Type' | translate }}</th>
|
||||
<td mat-cell *matCellDef="let incentive">
|
||||
{{ incentive.entityType | find: entityTypeData : 'id' : 'value' }}
|
||||
</td>
|
||||
</ng-container>
|
||||
<ng-container matColumnDef="attributeName">
|
||||
<th mat-header-cell *matHeaderCellDef>{{ 'labels.inputs.Attribute Name' | translate }}</th>
|
||||
<td mat-cell *matCellDef="let incentive">
|
||||
{{ incentive.attributeName | find: attributeNameData : 'id' : 'value' }}
|
||||
</td>
|
||||
</ng-container>
|
||||
<ng-container matColumnDef="conditionType">
|
||||
<th mat-header-cell *matHeaderCellDef>{{ 'labels.inputs.Condition Type' | translate }}</th>
|
||||
<td mat-cell *matCellDef="let incentive">
|
||||
{{ incentive.conditionType | find: conditionTypeData : 'id' : 'value' }}
|
||||
</td>
|
||||
</ng-container>
|
||||
<ng-container matColumnDef="attributeValue">
|
||||
<th mat-header-cell *matHeaderCellDef>{{ 'labels.inputs.Attribute Value' | translate }}</th>
|
||||
<td mat-cell *matCellDef="let incentive">
|
||||
@switch (incentive.attributeName) {
|
||||
@case (2) {
|
||||
<span>{{ incentive.attributeValue | find: genderData : 'id' : 'name' }}</span>
|
||||
}
|
||||
@case (3) {
|
||||
<span>{{ incentive.attributeValue }}</span>
|
||||
}
|
||||
@case (4) {
|
||||
<span>{{ incentive.attributeValue | find: clientTypeData : 'id' : 'name' }}</span>
|
||||
}
|
||||
@case (5) {
|
||||
<span>{{
|
||||
incentive.attributeValue | find: clientClassificationData : 'id' : 'name'
|
||||
}}</span>
|
||||
}
|
||||
}
|
||||
</td>
|
||||
</ng-container>
|
||||
<ng-container matColumnDef="incentiveType">
|
||||
<th mat-header-cell *matHeaderCellDef>{{ 'labels.inputs.Incentive Type' | translate }}</th>
|
||||
<td mat-cell *matCellDef="let incentive">
|
||||
{{ incentive.incentiveType | find: incentiveTypeData : 'id' : 'value' }}
|
||||
</td>
|
||||
</ng-container>
|
||||
<ng-container matColumnDef="amount">
|
||||
<th mat-header-cell *matHeaderCellDef>{{ 'labels.inputs.Interest' | translate }}</th>
|
||||
<td mat-cell *matCellDef="let incentive">
|
||||
{{ incentive.amount }}
|
||||
</td>
|
||||
</ng-container>
|
||||
<ng-container matColumnDef="actions">
|
||||
<th mat-header-cell *matHeaderCellDef>{{ 'labels.inputs.Actions' | translate }}</th>
|
||||
<td mat-cell *matCellDef="let incentive; let incentiveIndex = index">
|
||||
<button
|
||||
mat-icon-button
|
||||
color="primary"
|
||||
(click)="
|
||||
editIncentive(
|
||||
getIncentives(chart.controls.chartSlabs, chartSlabIndex),
|
||||
incentiveIndex
|
||||
)
|
||||
"
|
||||
>
|
||||
<fa-icon icon="edit"></fa-icon>
|
||||
</button>
|
||||
<button
|
||||
mat-icon-button
|
||||
color="warn"
|
||||
(click)="
|
||||
delete(getIncentives(chart.controls.chartSlabs, chartSlabIndex), incentiveIndex)
|
||||
"
|
||||
>
|
||||
<fa-icon icon="trash"></fa-icon>
|
||||
</button>
|
||||
</td>
|
||||
</ng-container>
|
||||
<tr mat-header-row *matHeaderRowDef="incentivesDisplayedColumns"></tr>
|
||||
<tr mat-row *matRowDef="let row; columns: incentivesDisplayedColumns"></tr>
|
||||
</table>
|
||||
}
|
||||
</mat-card>
|
||||
</div>
|
||||
</td>
|
||||
</ng-container>
|
||||
<tr mat-header-row *matHeaderRowDef="chartSlabsDisplayedColumns[chartIndex]"></tr>
|
||||
<tr mat-row *matRowDef="let row; columns: chartSlabsDisplayedColumns[chartIndex]"></tr>
|
||||
<tr
|
||||
mat-row
|
||||
*matRowDef="let row; columns: chartSlabsIncentivesDisplayedColumns"
|
||||
class="incentives-row"
|
||||
></tr>
|
||||
</table>
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
|
||||
<div class="layout-row align-center gap-2percent margin-t responsive-column">
|
||||
<button mat-raised-button matStepperPrevious>
|
||||
<fa-icon icon="arrow-left" class="m-r-10"></fa-icon>
|
||||
{{ 'labels.buttons.Previous' | translate }}
|
||||
</button>
|
||||
<button mat-raised-button matStepperNext>
|
||||
{{ 'labels.buttons.Next' | translate }}
|
||||
<fa-icon icon="arrow-right" class="m-l-10"></fa-icon>
|
||||
</button>
|
||||
<div class="fdpi-grid">
|
||||
<mat-form-field appearance="outline" class="fdpi-field">
|
||||
<mat-label>{{ 'labels.inputs.Name' | translate }}</mat-label>
|
||||
<input matInput formControlName="name" required />
|
||||
@if (chart.get('name')?.touched && chart.get('name')?.hasError('required')) {
|
||||
<mat-error>
|
||||
{{ 'labels.inputs.Name' | translate }} {{ 'labels.commons.is' | translate }}
|
||||
<strong>{{ 'labels.commons.required' | translate }}</strong>
|
||||
</mat-error>
|
||||
}
|
||||
</mat-form-field>
|
||||
|
||||
<mat-form-field appearance="outline" class="fdpi-field fdpi-field--full">
|
||||
<mat-label>{{ 'labels.inputs.Description' | translate }}</mat-label>
|
||||
<textarea matInput formControlName="description" required></textarea>
|
||||
@if (chart.get('description')?.touched && chart.get('description')?.hasError('required')) {
|
||||
<mat-error>
|
||||
{{ 'labels.inputs.Description' | translate }} {{ 'labels.commons.is' | translate }}
|
||||
<strong>{{ 'labels.commons.required' | translate }}</strong>
|
||||
</mat-error>
|
||||
}
|
||||
</mat-form-field>
|
||||
|
||||
<mat-form-field appearance="outline" class="fdpi-field" (click)="validFromDatePicker.open()">
|
||||
<mat-label>{{ 'labels.inputs.From Date' | translate }}</mat-label>
|
||||
<input
|
||||
matInput
|
||||
[min]="minDate"
|
||||
[max]="maxDate"
|
||||
[matDatepicker]="validFromDatePicker"
|
||||
formControlName="fromDate"
|
||||
required
|
||||
/>
|
||||
<mat-datepicker-toggle matSuffix [for]="validFromDatePicker"></mat-datepicker-toggle>
|
||||
<mat-datepicker #validFromDatePicker></mat-datepicker>
|
||||
<mat-error>
|
||||
{{ 'labels.inputs.Valid from Date' | translate }} {{ 'labels.commons.is' | translate }}
|
||||
<strong>{{ 'labels.commons.required' | translate }}</strong>
|
||||
</mat-error>
|
||||
</mat-form-field>
|
||||
|
||||
<mat-form-field appearance="outline" class="fdpi-field" (click)="endDatePicker.open()">
|
||||
<mat-label>{{ 'labels.inputs.End Date' | translate }}</mat-label>
|
||||
<input matInput [min]="minDate" [max]="maxDate" [matDatepicker]="endDatePicker" formControlName="endDate" />
|
||||
<mat-datepicker-toggle matSuffix [for]="endDatePicker"></mat-datepicker-toggle>
|
||||
<mat-datepicker #endDatePicker></mat-datepicker>
|
||||
</mat-form-field>
|
||||
|
||||
<div class="fdpi-field fdpi-field--full fdpi-checkbox-row">
|
||||
<mat-checkbox labelPosition="before" formControlName="isPrimaryGroupingByAmount">
|
||||
{{ 'labels.inputs.Is primary grouping by amount?' | translate }}
|
||||
</mat-checkbox>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="fdpi-slab-actions">
|
||||
<button type="button" mat-raised-button color="primary" class="fdpi-add-btn" (click)="addChartSlab(chart.controls.chartSlabs)">
|
||||
<fa-icon icon="plus" class="m-r-10"></fa-icon>
|
||||
{{ 'labels.buttons.Add Slab' | translate }}
|
||||
</button>
|
||||
</div>
|
||||
|
||||
@if (chart.value.chartSlabs.length === 0) {
|
||||
<div class="fdpi-empty-message">
|
||||
<h3>{{ 'labels.heading.It is required to add at least one Slab' | translate }}</h3>
|
||||
</div>
|
||||
}
|
||||
|
||||
@if (chart.value.chartSlabs.length !== 0) {
|
||||
<div class="fdpi-table-wrapper">
|
||||
<table
|
||||
mat-table
|
||||
[dataSource]="chart.value.chartSlabs"
|
||||
multiTemplateDataRows
|
||||
>
|
||||
<ng-container matColumnDef="period">
|
||||
<th mat-header-cell *matHeaderCellDef>{{ 'labels.inputs.Period' | translate }}</th>
|
||||
<td mat-cell *matCellDef="let chartSlab">
|
||||
{{
|
||||
chartSlab.fromPeriod +
|
||||
' - ' +
|
||||
chartSlab.toPeriod +
|
||||
' ' +
|
||||
(chartSlab.periodType | find: periodTypeData : 'id' : 'value')
|
||||
}}
|
||||
</td>
|
||||
</ng-container>
|
||||
<ng-container matColumnDef="amountRange">
|
||||
<th mat-header-cell *matHeaderCellDef>{{ 'labels.inputs.Amount Range' | translate }}</th>
|
||||
<td mat-cell *matCellDef="let chartSlab">
|
||||
{{ chartSlab.amountRangeFrom + ' - ' + chartSlab.amountRangeTo }}
|
||||
</td>
|
||||
</ng-container>
|
||||
<ng-container matColumnDef="annualInterestRate">
|
||||
<th mat-header-cell *matHeaderCellDef>{{ 'labels.inputs.Interest' | translate }}</th>
|
||||
<td mat-cell *matCellDef="let chartSlab">{{ chartSlab.annualInterestRate }} %</td>
|
||||
</ng-container>
|
||||
<ng-container matColumnDef="description">
|
||||
<th mat-header-cell *matHeaderCellDef>{{ 'labels.inputs.Description' | translate }}</th>
|
||||
<td mat-cell *matCellDef="let chartSlab">
|
||||
{{ chartSlab.description }}
|
||||
</td>
|
||||
</ng-container>
|
||||
<ng-container matColumnDef="actions">
|
||||
<th mat-header-cell *matHeaderCellDef>{{ 'labels.inputs.Actions' | translate }}</th>
|
||||
<td mat-cell *matCellDef="let chartSlab; let chartSlabIndex = dataIndex">
|
||||
<button
|
||||
mat-icon-button
|
||||
color="primary"
|
||||
(click)="editChartSlab(chart.controls.chartSlabs, chartSlabIndex)"
|
||||
>
|
||||
<fa-icon icon="edit"></fa-icon>
|
||||
</button>
|
||||
<button mat-icon-button color="warn" (click)="delete(chart.controls.chartSlabs, chartSlabIndex)">
|
||||
<fa-icon icon="trash"></fa-icon>
|
||||
</button>
|
||||
<button
|
||||
mat-button
|
||||
color="primary"
|
||||
(click)="
|
||||
expandChartSlabIndex[chartIndex] =
|
||||
expandChartSlabIndex[chartIndex] === chartSlabIndex ? null : chartSlabIndex
|
||||
"
|
||||
>
|
||||
@if (expandChartSlabIndex[chartIndex] !== chartSlabIndex) {
|
||||
<span>
|
||||
<fa-icon icon="eye" class="m-r-10"></fa-icon>
|
||||
{{ 'labels.buttons.View Incentives' | translate }}
|
||||
</span>
|
||||
}
|
||||
@if (expandChartSlabIndex[chartIndex] === chartSlabIndex) {
|
||||
<span>
|
||||
<fa-icon icon="eye-slash" class="m-r-10"></fa-icon>
|
||||
{{ 'labels.buttons.Hide Incentives' | translate }}
|
||||
</span>
|
||||
}
|
||||
</button>
|
||||
</td>
|
||||
</ng-container>
|
||||
<ng-container matColumnDef="incentives">
|
||||
<td
|
||||
mat-cell
|
||||
*matCellDef="let chartSlab; let chartSlabIndex = dataIndex"
|
||||
[attr.colspan]="chartSlabsDisplayedColumns[chartIndex].length"
|
||||
>
|
||||
<div
|
||||
class="fdpi-incentives-wrap"
|
||||
[@expandChartSlab]="chartSlabIndex === expandChartSlabIndex[chartIndex] ? 'expanded' : 'collapsed'"
|
||||
>
|
||||
<mat-card class="fdpi-incentive-card">
|
||||
<h4>{{ 'labels.heading.Incentives' | translate }}</h4>
|
||||
<div class="fdpi-incentive-actions">
|
||||
<button
|
||||
mat-raised-button
|
||||
color="primary"
|
||||
class="fdpi-add-btn"
|
||||
(click)="addIncentive(getIncentives(chart.controls.chartSlabs, chartSlabIndex))"
|
||||
>
|
||||
<fa-icon icon="plus" class="m-r-10"></fa-icon>
|
||||
{{ 'labels.buttons.Add' | translate }}
|
||||
</button>
|
||||
</div>
|
||||
@if (chartSlab.incentives.length) {
|
||||
<div class="fdpi-table-wrapper">
|
||||
<table mat-table [dataSource]="chartSlab.incentives">
|
||||
<ng-container matColumnDef="entityType">
|
||||
<th mat-header-cell *matHeaderCellDef>{{ 'labels.inputs.Entity Type' | translate }}</th>
|
||||
<td mat-cell *matCellDef="let incentive">
|
||||
{{ incentive.entityType | find: entityTypeData : 'id' : 'value' }}
|
||||
</td>
|
||||
</ng-container>
|
||||
<ng-container matColumnDef="attributeName">
|
||||
<th mat-header-cell *matHeaderCellDef>{{ 'labels.inputs.Attribute Name' | translate }}</th>
|
||||
<td mat-cell *matCellDef="let incentive">
|
||||
{{ incentive.attributeName | find: attributeNameData : 'id' : 'value' }}
|
||||
</td>
|
||||
</ng-container>
|
||||
<ng-container matColumnDef="conditionType">
|
||||
<th mat-header-cell *matHeaderCellDef>{{ 'labels.inputs.Condition Type' | translate }}</th>
|
||||
<td mat-cell *matCellDef="let incentive">
|
||||
{{ incentive.conditionType | find: conditionTypeData : 'id' : 'value' }}
|
||||
</td>
|
||||
</ng-container>
|
||||
<ng-container matColumnDef="attributeValue">
|
||||
<th mat-header-cell *matHeaderCellDef>{{ 'labels.inputs.Attribute Value' | translate }}</th>
|
||||
<td mat-cell *matCellDef="let incentive">
|
||||
@switch (incentive.attributeName) {
|
||||
@case (2) {
|
||||
<span>{{ incentive.attributeValue | find: genderData : 'id' : 'name' }}</span>
|
||||
}
|
||||
@case (3) {
|
||||
<span>{{ incentive.attributeValue }}</span>
|
||||
}
|
||||
@case (4) {
|
||||
<span>{{ incentive.attributeValue | find: clientTypeData : 'id' : 'name' }}</span>
|
||||
}
|
||||
@case (5) {
|
||||
<span>{{
|
||||
incentive.attributeValue | find: clientClassificationData : 'id' : 'name'
|
||||
}}</span>
|
||||
}
|
||||
}
|
||||
</td>
|
||||
</ng-container>
|
||||
<ng-container matColumnDef="incentiveType">
|
||||
<th mat-header-cell *matHeaderCellDef>{{ 'labels.inputs.Incentive Type' | translate }}</th>
|
||||
<td mat-cell *matCellDef="let incentive">
|
||||
{{ incentive.incentiveType | find: incentiveTypeData : 'id' : 'value' }}
|
||||
</td>
|
||||
</ng-container>
|
||||
<ng-container matColumnDef="amount">
|
||||
<th mat-header-cell *matHeaderCellDef>{{ 'labels.inputs.Interest' | translate }}</th>
|
||||
<td mat-cell *matCellDef="let incentive">
|
||||
{{ incentive.amount }}
|
||||
</td>
|
||||
</ng-container>
|
||||
<ng-container matColumnDef="actions">
|
||||
<th mat-header-cell *matHeaderCellDef>{{ 'labels.inputs.Actions' | translate }}</th>
|
||||
<td mat-cell *matCellDef="let incentive; let incentiveIndex = index">
|
||||
<button
|
||||
mat-icon-button
|
||||
color="primary"
|
||||
(click)="
|
||||
editIncentive(
|
||||
getIncentives(chart.controls.chartSlabs, chartSlabIndex),
|
||||
incentiveIndex
|
||||
)
|
||||
"
|
||||
>
|
||||
<fa-icon icon="edit"></fa-icon>
|
||||
</button>
|
||||
<button
|
||||
mat-icon-button
|
||||
color="warn"
|
||||
(click)="
|
||||
delete(getIncentives(chart.controls.chartSlabs, chartSlabIndex), incentiveIndex)
|
||||
"
|
||||
>
|
||||
<fa-icon icon="trash"></fa-icon>
|
||||
</button>
|
||||
</td>
|
||||
</ng-container>
|
||||
<tr mat-header-row *matHeaderRowDef="incentivesDisplayedColumns"></tr>
|
||||
<tr mat-row *matRowDef="let row; columns: incentivesDisplayedColumns"></tr>
|
||||
</table>
|
||||
</div>
|
||||
}
|
||||
</mat-card>
|
||||
</div>
|
||||
</td>
|
||||
</ng-container>
|
||||
<tr mat-header-row *matHeaderRowDef="chartSlabsDisplayedColumns[chartIndex]"></tr>
|
||||
<tr mat-row *matRowDef="let row; columns: chartSlabsDisplayedColumns[chartIndex]"></tr>
|
||||
<tr
|
||||
mat-row
|
||||
*matRowDef="let row; columns: chartSlabsIncentivesDisplayedColumns"
|
||||
class="incentives-row"
|
||||
></tr>
|
||||
</table>
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
+125
-27
@@ -6,48 +6,146 @@
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
h3,
|
||||
h4 {
|
||||
font-weight: 500;
|
||||
margin: 1em 0;
|
||||
.fdpi-section {
|
||||
border: 1px solid #e2e8f0;
|
||||
border-radius: 10px;
|
||||
overflow: hidden;
|
||||
background: #fff;
|
||||
|
||||
& + & {
|
||||
margin-top: 16px;
|
||||
}
|
||||
|
||||
&__header {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 10px;
|
||||
padding: 12px 24px;
|
||||
background: #f8f9fa;
|
||||
border-bottom: 1px solid #e8eaed;
|
||||
|
||||
i {
|
||||
font-size: 14px;
|
||||
color: #0ea5e9;
|
||||
}
|
||||
|
||||
h3 {
|
||||
margin: 0;
|
||||
font-size: 14px;
|
||||
font-weight: 600;
|
||||
color: #202124;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
table {
|
||||
.fdpi-spacer {
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.fdpi-body {
|
||||
padding: 16px 24px;
|
||||
}
|
||||
|
||||
.fdpi-grid {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(2, 1fr);
|
||||
gap: 4px 16px;
|
||||
|
||||
@media (max-width: 600px) {
|
||||
grid-template-columns: 1fr;
|
||||
}
|
||||
}
|
||||
|
||||
.fdpi-field {
|
||||
width: 100%;
|
||||
|
||||
&--full {
|
||||
grid-column: 1 / -1;
|
||||
}
|
||||
}
|
||||
|
||||
.fdpi-checkbox-row {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding: 4px 0;
|
||||
}
|
||||
|
||||
.fdpi-add-btn {
|
||||
height: 36px;
|
||||
border-radius: 8px;
|
||||
font-size: 13px;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.fdpi-chart-card {
|
||||
border: 1px solid #e2e8f0;
|
||||
border-radius: 8px;
|
||||
overflow: hidden;
|
||||
margin-bottom: 16px;
|
||||
|
||||
&__top {
|
||||
padding: 16px;
|
||||
}
|
||||
|
||||
&__actions {
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
}
|
||||
}
|
||||
|
||||
.fdpi-slab-actions {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
padding: 8px 0;
|
||||
}
|
||||
|
||||
.fdpi-empty-message {
|
||||
text-align: center;
|
||||
padding: 16px;
|
||||
|
||||
h3 {
|
||||
margin: 0;
|
||||
font-size: 14px;
|
||||
font-weight: 500;
|
||||
color: #5f6368;
|
||||
}
|
||||
}
|
||||
|
||||
.fdpi-table-wrapper {
|
||||
border: 1px solid #e2e8f0;
|
||||
border-radius: 8px;
|
||||
overflow: hidden;
|
||||
margin-top: 12px;
|
||||
|
||||
table {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
tr.incentives-row {
|
||||
height: 0;
|
||||
|
||||
> td {
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.incentives {
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.mat-card {
|
||||
border-radius: 0;
|
||||
|
||||
> h4 {
|
||||
margin: 0.5em 0 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
mat-divider {
|
||||
margin: 1em 0;
|
||||
.fdpi-incentives-wrap {
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.mat-elevation-z1 {
|
||||
margin: 1em 0 1.5em;
|
||||
.fdpi-incentive-card {
|
||||
border-radius: 0;
|
||||
padding: 16px;
|
||||
|
||||
h4 {
|
||||
margin: 0 0 12px;
|
||||
font-size: 14px;
|
||||
font-weight: 600;
|
||||
color: #202124;
|
||||
}
|
||||
}
|
||||
|
||||
.margin-t {
|
||||
margin-top: 1em;
|
||||
}
|
||||
|
||||
.margin-v {
|
||||
margin: 1em 0;
|
||||
.fdpi-incentive-actions {
|
||||
margin-bottom: 12px;
|
||||
}
|
||||
|
||||
-5
@@ -36,7 +36,6 @@ import { MatTooltip } from '@angular/material/tooltip';
|
||||
import { MatButton, MatIconButton } from '@angular/material/button';
|
||||
import { FaIconComponent } from '@fortawesome/angular-fontawesome';
|
||||
|
||||
import { MatDivider } from '@angular/material/divider';
|
||||
import { MatCheckbox } from '@angular/material/checkbox';
|
||||
import {
|
||||
MatTable,
|
||||
@@ -50,7 +49,6 @@ import {
|
||||
MatRowDef,
|
||||
MatRow
|
||||
} from '@angular/material/table';
|
||||
import { MatStepperPrevious, MatStepperNext } from '@angular/material/stepper';
|
||||
import { FindPipe } from '../../../../pipes/find.pipe';
|
||||
import { STANDALONE_SHARED_IMPORTS } from 'app/standalone-shared.module';
|
||||
|
||||
@@ -69,7 +67,6 @@ import { STANDALONE_SHARED_IMPORTS } from 'app/standalone-shared.module';
|
||||
...STANDALONE_SHARED_IMPORTS,
|
||||
MatTooltip,
|
||||
FaIconComponent,
|
||||
MatDivider,
|
||||
MatIconButton,
|
||||
MatCheckbox,
|
||||
MatTable,
|
||||
@@ -82,8 +79,6 @@ import { STANDALONE_SHARED_IMPORTS } from 'app/standalone-shared.module';
|
||||
MatHeaderRow,
|
||||
MatRowDef,
|
||||
MatRow,
|
||||
MatStepperPrevious,
|
||||
MatStepperNext,
|
||||
FindPipe
|
||||
]
|
||||
})
|
||||
|
||||
+534
-504
File diff suppressed because it is too large
Load Diff
+124
-37
@@ -6,18 +6,106 @@
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
@use 'assets/styles/helper';
|
||||
@use 'assets/styles/colours' as *;
|
||||
|
||||
h2,
|
||||
h3,
|
||||
h4 {
|
||||
margin: 0;
|
||||
font-weight: 500;
|
||||
.fdpp-container {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 16px;
|
||||
}
|
||||
|
||||
table {
|
||||
width: 100%;
|
||||
.fdpp-title {
|
||||
margin: 0;
|
||||
font-size: 20px;
|
||||
font-weight: 600;
|
||||
color: #202124;
|
||||
}
|
||||
|
||||
.fdpp-section {
|
||||
border: 1px solid #e2e8f0;
|
||||
border-radius: 10px;
|
||||
overflow: hidden;
|
||||
background: #fff;
|
||||
|
||||
&__header {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 10px;
|
||||
padding: 12px 24px;
|
||||
background: #f8f9fa;
|
||||
border-bottom: 1px solid #e8eaed;
|
||||
|
||||
i {
|
||||
font-size: 14px;
|
||||
color: #0ea5e9;
|
||||
}
|
||||
|
||||
h3 {
|
||||
margin: 0;
|
||||
font-size: 14px;
|
||||
font-weight: 600;
|
||||
color: #202124;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.fdpp-section-body {
|
||||
padding: 16px 24px;
|
||||
}
|
||||
|
||||
.fdpp-preview-grid {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(2, 1fr);
|
||||
gap: 4px 16px;
|
||||
padding: 16px 24px;
|
||||
|
||||
@media (max-width: 600px) {
|
||||
grid-template-columns: 1fr;
|
||||
}
|
||||
}
|
||||
|
||||
.fdpp-row {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
padding: 6px 0;
|
||||
|
||||
&--full {
|
||||
grid-column: 1 / -1;
|
||||
}
|
||||
}
|
||||
|
||||
.fdpp-label {
|
||||
font-size: 12px;
|
||||
font-weight: 500;
|
||||
color: #5f6368;
|
||||
margin-bottom: 2px;
|
||||
}
|
||||
|
||||
.fdpp-value {
|
||||
font-size: 14px;
|
||||
font-weight: 500;
|
||||
color: #202124;
|
||||
}
|
||||
|
||||
.fdpp-chart-block {
|
||||
padding-bottom: 16px;
|
||||
border-bottom: 1px solid #e2e8f0;
|
||||
margin-bottom: 16px;
|
||||
|
||||
&:last-child {
|
||||
border-bottom: none;
|
||||
margin-bottom: 0;
|
||||
padding-bottom: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.fdpp-table-wrapper {
|
||||
border: 1px solid #e2e8f0;
|
||||
border-radius: 8px;
|
||||
overflow: hidden;
|
||||
margin-top: 8px;
|
||||
|
||||
table {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
tr.incentives-row {
|
||||
height: 0;
|
||||
@@ -25,40 +113,39 @@ table {
|
||||
> td {
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.incentives {
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.mat-card {
|
||||
border-radius: 0;
|
||||
|
||||
> h4 {
|
||||
font-weight: 500;
|
||||
margin: 0.5em 0 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.mat-h3 {
|
||||
margin-top: 10px !important;
|
||||
font-weight: 300;
|
||||
color: $status-approved;
|
||||
.fdpp-incentives-wrap {
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.mat-elevation-z1 {
|
||||
margin: 1em 0 1.5em;
|
||||
.fdpp-incentive-card {
|
||||
border-radius: 0;
|
||||
padding: 16px;
|
||||
|
||||
h4 {
|
||||
margin: 0 0 12px;
|
||||
font-size: 14px;
|
||||
font-weight: 600;
|
||||
color: #202124;
|
||||
}
|
||||
}
|
||||
|
||||
span {
|
||||
margin: 0.5em 0;
|
||||
.fdpp-subsection-title {
|
||||
margin: 16px 0 8px;
|
||||
font-size: 14px;
|
||||
font-weight: 600;
|
||||
color: #202124;
|
||||
|
||||
&:first-child {
|
||||
margin-top: 0;
|
||||
}
|
||||
}
|
||||
|
||||
mat-divider {
|
||||
margin: 0 0 0.5em;
|
||||
}
|
||||
|
||||
.margin-t {
|
||||
margin-top: 1em;
|
||||
.fdpp-actions {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 12px;
|
||||
margin-top: 16px;
|
||||
}
|
||||
|
||||
-4
@@ -10,7 +10,6 @@ import { Component, OnInit, Input, Output, EventEmitter, SimpleChanges, OnChange
|
||||
import { trigger, state, transition, animate, style } from '@angular/animations';
|
||||
import { Accounting } from 'app/core/utils/accounting';
|
||||
import { OptionData } from 'app/shared/models/option-data.model';
|
||||
import { MatDivider } from '@angular/material/divider';
|
||||
|
||||
import {
|
||||
MatTable,
|
||||
@@ -26,7 +25,6 @@ import {
|
||||
} from '@angular/material/table';
|
||||
import { FaIconComponent } from '@fortawesome/angular-fontawesome';
|
||||
import { ViewSavingsAccountingDetailsComponent } from '../../../../shared/accounting/view-savings-accounting-details/view-savings-accounting-details.component';
|
||||
import { MatStepperPrevious } from '@angular/material/stepper';
|
||||
import { FindPipe } from '../../../../pipes/find.pipe';
|
||||
import { DateFormatPipe } from '../../../../pipes/date-format.pipe';
|
||||
import { FormatNumberPipe } from '../../../../pipes/format-number.pipe';
|
||||
@@ -46,7 +44,6 @@ import { STANDALONE_SHARED_IMPORTS } from 'app/standalone-shared.module';
|
||||
],
|
||||
imports: [
|
||||
...STANDALONE_SHARED_IMPORTS,
|
||||
MatDivider,
|
||||
MatTable,
|
||||
MatColumnDef,
|
||||
MatHeaderCellDef,
|
||||
@@ -59,7 +56,6 @@ import { STANDALONE_SHARED_IMPORTS } from 'app/standalone-shared.module';
|
||||
MatRowDef,
|
||||
MatRow,
|
||||
ViewSavingsAccountingDetailsComponent,
|
||||
MatStepperPrevious,
|
||||
FindPipe,
|
||||
DateFormatPipe,
|
||||
FormatNumberPipe,
|
||||
|
||||
+184
-155
@@ -7,172 +7,201 @@
|
||||
-->
|
||||
|
||||
<form [formGroup]="fixedDepositProductSettingsForm">
|
||||
<div class="layout-row-wrap gap-2px responsive-column">
|
||||
<h4 class="mat-h4 flex-98">
|
||||
{{ 'labels.inputs.Lock-in Period' | translate }}
|
||||
<i
|
||||
class="fas fa-question"
|
||||
matTooltip="{{ 'tooltips.A period of time during which a fixed deposit account' | translate }}"
|
||||
></i>
|
||||
</h4>
|
||||
<div class="fdps-section">
|
||||
<div class="fdps-section__header">
|
||||
<i class="fas fa-lock"></i>
|
||||
<h3>{{ 'labels.inputs.Lock-in Period' | translate }}</h3>
|
||||
</div>
|
||||
<div class="fdps-grid">
|
||||
<mat-form-field appearance="outline" class="fdps-field">
|
||||
<mat-label>{{ 'labels.inputs.Frequency' | translate }}</mat-label>
|
||||
<input
|
||||
type="number"
|
||||
min="0"
|
||||
matInput
|
||||
formControlName="lockinPeriodFrequency"
|
||||
matTooltip="{{ 'tooltips.A period of time during which a fixed deposit account' | translate }}"
|
||||
/>
|
||||
</mat-form-field>
|
||||
|
||||
<mat-form-field class="flex-48">
|
||||
<mat-label>{{ 'labels.inputs.Frequency' | translate }}</mat-label>
|
||||
<input type="number" min="0" matInput formControlName="lockinPeriodFrequency" />
|
||||
</mat-form-field>
|
||||
<mat-form-field appearance="outline" class="fdps-field">
|
||||
<mat-label>{{ 'labels.inputs.Type' | translate }}</mat-label>
|
||||
<mat-select formControlName="lockinPeriodFrequencyType">
|
||||
@for (lockinPeriodFrequencyType of lockinPeriodFrequencyTypeData; track lockinPeriodFrequencyType) {
|
||||
<mat-option [value]="lockinPeriodFrequencyType.id">
|
||||
{{ lockinPeriodFrequencyType.value }}
|
||||
</mat-option>
|
||||
}
|
||||
</mat-select>
|
||||
</mat-form-field>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<mat-form-field class="flex-48">
|
||||
<mat-label>{{ 'labels.inputs.Type' | translate }}</mat-label>
|
||||
<mat-select formControlName="lockinPeriodFrequencyType">
|
||||
@for (lockinPeriodFrequencyType of lockinPeriodFrequencyTypeData; track lockinPeriodFrequencyType) {
|
||||
<mat-option [value]="lockinPeriodFrequencyType.id">
|
||||
{{ lockinPeriodFrequencyType.value }}
|
||||
</mat-option>
|
||||
}
|
||||
</mat-select>
|
||||
</mat-form-field>
|
||||
<div class="fdps-section">
|
||||
<div class="fdps-section__header">
|
||||
<i class="fas fa-calendar-check"></i>
|
||||
<h3>{{ 'labels.inputs.Minimum Deposit Term' | translate }}</h3>
|
||||
</div>
|
||||
<div class="fdps-grid">
|
||||
<mat-form-field appearance="outline" class="fdps-field">
|
||||
<mat-label>{{ 'labels.inputs.Frequency' | translate }}</mat-label>
|
||||
<input
|
||||
type="number"
|
||||
min="0"
|
||||
matInput
|
||||
formControlName="minDepositTerm"
|
||||
required
|
||||
matTooltip="{{ 'tooltips.The minimum length of time' | translate }}"
|
||||
/>
|
||||
<mat-error>
|
||||
{{ 'labels.inputs.Minimum Deposit Term Frequency' | translate }} {{ 'labels.commons.is' | translate }}
|
||||
<strong>{{ 'labels.commons.required' | translate }}</strong>
|
||||
</mat-error>
|
||||
</mat-form-field>
|
||||
|
||||
<h4 class="mat-h4 flex-98">
|
||||
{{ 'labels.inputs.Minimum Deposit Term' | translate }}
|
||||
<i class="fas fa-question" matTooltip="{{ 'tooltips.The minimum length of time' | translate }}"></i>
|
||||
</h4>
|
||||
|
||||
<mat-form-field class="flex-48">
|
||||
<mat-label>{{ 'labels.inputs.Frequency' | translate }}</mat-label>
|
||||
<input type="number" min="0" matInput formControlName="minDepositTerm" required />
|
||||
<mat-error>
|
||||
{{ 'labels.inputs.Minimum Deposit Term Frequency' | translate }} {{ 'labels.commons.is' | translate }}
|
||||
<strong>{{ 'labels.commons.required' | translate }}</strong>
|
||||
</mat-error>
|
||||
</mat-form-field>
|
||||
|
||||
<mat-form-field class="flex-48">
|
||||
<mat-label>{{ 'labels.inputs.Frequency Type' | translate }}</mat-label>
|
||||
<mat-select formControlName="minDepositTermTypeId" required>
|
||||
@for (periodFrequencyType of periodFrequencyTypeData; track periodFrequencyType) {
|
||||
<mat-option [value]="periodFrequencyType.id">
|
||||
{{ periodFrequencyType.value }}
|
||||
</mat-option>
|
||||
}
|
||||
</mat-select>
|
||||
<mat-error>
|
||||
{{ 'labels.inputs.Minimum Deposit Term Frequency Type' | translate }} {{ 'labels.commons.is' | translate }}
|
||||
<strong>{{ 'labels.commons.required' | translate }}</strong>
|
||||
</mat-error>
|
||||
</mat-form-field>
|
||||
|
||||
<h4 class="mat-h4 flex-98">
|
||||
{{ 'labels.heading.And thereafter, in Multiples of' | translate }}
|
||||
<i
|
||||
class="fas fa-question-circle"
|
||||
matTooltip="{{ 'tooltips.After the minimum deposit term has passed' | translate }}"
|
||||
></i>
|
||||
</h4>
|
||||
|
||||
<mat-form-field class="flex-48">
|
||||
<mat-label>{{ 'labels.inputs.Frequency' | translate }}</mat-label>
|
||||
<input type="number" min="0" matInput formControlName="inMultiplesOfDepositTerm" />
|
||||
</mat-form-field>
|
||||
|
||||
<mat-form-field class="flex-48">
|
||||
<mat-label>{{ 'labels.inputs.Type' | translate }}</mat-label>
|
||||
<mat-select formControlName="inMultiplesOfDepositTermTypeId">
|
||||
@for (periodFrequencyType of periodFrequencyTypeData; track periodFrequencyType) {
|
||||
<mat-option [value]="periodFrequencyType.id">
|
||||
{{ periodFrequencyType.value }}
|
||||
</mat-option>
|
||||
}
|
||||
</mat-select>
|
||||
</mat-form-field>
|
||||
|
||||
<h4 class="mat-h4 flex-98">
|
||||
{{ 'labels.inputs.Maximum Deposit Term' | translate }}
|
||||
<i class="fas fa-question-circle" matTooltip="{{ 'tooltips.The maximum length of time funds' | translate }}"></i>
|
||||
</h4>
|
||||
|
||||
<mat-form-field class="flex-48">
|
||||
<mat-label>{{ 'labels.inputs.Frequency' | translate }}</mat-label>
|
||||
<input type="number" min="0" matInput formControlName="maxDepositTerm" />
|
||||
</mat-form-field>
|
||||
|
||||
<mat-form-field class="flex-48">
|
||||
<mat-label>{{ 'labels.inputs.Type' | translate }}</mat-label>
|
||||
<mat-select formControlName="maxDepositTermTypeId">
|
||||
@for (periodFrequencyType of periodFrequencyTypeData; track periodFrequencyType) {
|
||||
<mat-option [value]="periodFrequencyType.id">
|
||||
{{ periodFrequencyType.value }}
|
||||
</mat-option>
|
||||
}
|
||||
</mat-select>
|
||||
</mat-form-field>
|
||||
|
||||
<mat-divider class="flex-98"></mat-divider>
|
||||
|
||||
<h4 class="mat-h4 flex-23">
|
||||
{{ 'labels.heading.For Pre-mature closure' | translate }}
|
||||
<i
|
||||
class="fas fa-question-circle"
|
||||
matTooltip="{{ 'tooltips.This sections defines an interest penalty' | translate }}"
|
||||
></i>
|
||||
</h4>
|
||||
|
||||
<mat-checkbox class="flex-73 margin-v" labelPosition="before" formControlName="preClosurePenalApplicable">
|
||||
{{ 'labels.inputs.Apply Penal Interest (less)' | translate }}
|
||||
</mat-checkbox>
|
||||
|
||||
<mat-form-field class="flex-48">
|
||||
<mat-label>{{ 'labels.inputs.Penal Interest' | translate }} (%)</mat-label>
|
||||
<input type="number" min="0" matInput formControlName="preClosurePenalInterest" />
|
||||
</mat-form-field>
|
||||
|
||||
<mat-form-field class="flex-48">
|
||||
<mat-label>{{ 'labels.inputs.Period' | translate }}</mat-label>
|
||||
<mat-select formControlName="preClosurePenalInterestOnTypeId">
|
||||
@for (preClosurePenalInterestOnType of preClosurePenalInterestOnTypeData; track preClosurePenalInterestOnType) {
|
||||
<mat-option [value]="preClosurePenalInterestOnType.id">
|
||||
{{ preClosurePenalInterestOnType.value }}
|
||||
</mat-option>
|
||||
}
|
||||
</mat-select>
|
||||
</mat-form-field>
|
||||
|
||||
<mat-divider class="flex-98"></mat-divider>
|
||||
|
||||
<mat-checkbox
|
||||
class="flex-48 margin-v"
|
||||
labelPosition="before"
|
||||
formControlName="withHoldTax"
|
||||
matTooltip="{{ 'tooltips.An boolean flag to attach' | translate }}"
|
||||
>
|
||||
{{ 'labels.inputs.Is Withhold Tax Applicable' | translate }}
|
||||
</mat-checkbox>
|
||||
|
||||
@if (fixedDepositProductSettingsForm.value.withHoldTax) {
|
||||
<mat-form-field class="flex-48">
|
||||
<mat-label>{{ 'labels.inputs.Tax Group' | translate }}</mat-label>
|
||||
<mat-select formControlName="taxGroupId" required>
|
||||
@for (taxGroup of taxGroupData; track taxGroup) {
|
||||
<mat-option [value]="taxGroup.id">
|
||||
{{ taxGroup.name }}
|
||||
<mat-form-field appearance="outline" class="fdps-field">
|
||||
<mat-label>{{ 'labels.inputs.Frequency Type' | translate }}</mat-label>
|
||||
<mat-select formControlName="minDepositTermTypeId" required>
|
||||
@for (periodFrequencyType of periodFrequencyTypeData; track periodFrequencyType) {
|
||||
<mat-option [value]="periodFrequencyType.id">
|
||||
{{ periodFrequencyType.value }}
|
||||
</mat-option>
|
||||
}
|
||||
</mat-select>
|
||||
<mat-error>
|
||||
{{ 'labels.inputs.Tax Group' | translate }} {{ 'labels.commons.is' | translate }}
|
||||
{{ 'labels.inputs.Minimum Deposit Term Frequency Type' | translate }} {{ 'labels.commons.is' | translate }}
|
||||
<strong>{{ 'labels.commons.required' | translate }}</strong>
|
||||
</mat-error>
|
||||
</mat-form-field>
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="layout-row align-center gap-2percent margin-t responsive-column">
|
||||
<button mat-raised-button matStepperPrevious>
|
||||
<fa-icon icon="arrow-left" class="m-r-10"></fa-icon>
|
||||
{{ 'labels.buttons.Previous' | translate }}
|
||||
</button>
|
||||
<button mat-raised-button matStepperNext>
|
||||
{{ 'labels.buttons.Next' | translate }}
|
||||
<fa-icon icon="arrow-right" class="m-l-10"></fa-icon>
|
||||
</button>
|
||||
<div class="fdps-section">
|
||||
<div class="fdps-section__header">
|
||||
<i class="fas fa-layer-group"></i>
|
||||
<h3>{{ 'labels.heading.And thereafter, in Multiples of' | translate }}</h3>
|
||||
</div>
|
||||
<div class="fdps-grid">
|
||||
<mat-form-field appearance="outline" class="fdps-field">
|
||||
<mat-label>{{ 'labels.inputs.Frequency' | translate }}</mat-label>
|
||||
<input
|
||||
type="number"
|
||||
min="0"
|
||||
matInput
|
||||
formControlName="inMultiplesOfDepositTerm"
|
||||
matTooltip="{{ 'tooltips.After the minimum deposit term has passed' | translate }}"
|
||||
/>
|
||||
</mat-form-field>
|
||||
|
||||
<mat-form-field appearance="outline" class="fdps-field">
|
||||
<mat-label>{{ 'labels.inputs.Type' | translate }}</mat-label>
|
||||
<mat-select formControlName="inMultiplesOfDepositTermTypeId">
|
||||
@for (periodFrequencyType of periodFrequencyTypeData; track periodFrequencyType) {
|
||||
<mat-option [value]="periodFrequencyType.id">
|
||||
{{ periodFrequencyType.value }}
|
||||
</mat-option>
|
||||
}
|
||||
</mat-select>
|
||||
</mat-form-field>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="fdps-section">
|
||||
<div class="fdps-section__header">
|
||||
<i class="fas fa-calendar-alt"></i>
|
||||
<h3>{{ 'labels.inputs.Maximum Deposit Term' | translate }}</h3>
|
||||
</div>
|
||||
<div class="fdps-grid">
|
||||
<mat-form-field appearance="outline" class="fdps-field">
|
||||
<mat-label>{{ 'labels.inputs.Frequency' | translate }}</mat-label>
|
||||
<input
|
||||
type="number"
|
||||
min="0"
|
||||
matInput
|
||||
formControlName="maxDepositTerm"
|
||||
matTooltip="{{ 'tooltips.The maximum length of time funds' | translate }}"
|
||||
/>
|
||||
</mat-form-field>
|
||||
|
||||
<mat-form-field appearance="outline" class="fdps-field">
|
||||
<mat-label>{{ 'labels.inputs.Type' | translate }}</mat-label>
|
||||
<mat-select formControlName="maxDepositTermTypeId">
|
||||
@for (periodFrequencyType of periodFrequencyTypeData; track periodFrequencyType) {
|
||||
<mat-option [value]="periodFrequencyType.id">
|
||||
{{ periodFrequencyType.value }}
|
||||
</mat-option>
|
||||
}
|
||||
</mat-select>
|
||||
</mat-form-field>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="fdps-section">
|
||||
<div class="fdps-section__header">
|
||||
<i class="fas fa-exclamation-triangle"></i>
|
||||
<h3>{{ 'labels.heading.For Pre-mature closure' | translate }}</h3>
|
||||
</div>
|
||||
<div class="fdps-grid">
|
||||
<div class="fdps-field fdps-field--full fdps-checkbox-row">
|
||||
<mat-checkbox
|
||||
labelPosition="before"
|
||||
formControlName="preClosurePenalApplicable"
|
||||
matTooltip="{{ 'tooltips.This sections defines an interest penalty' | translate }}"
|
||||
>
|
||||
{{ 'labels.inputs.Apply Penal Interest (less)' | translate }}
|
||||
</mat-checkbox>
|
||||
</div>
|
||||
|
||||
<mat-form-field appearance="outline" class="fdps-field">
|
||||
<mat-label>{{ 'labels.inputs.Penal Interest' | translate }} (%)</mat-label>
|
||||
<input type="number" min="0" matInput formControlName="preClosurePenalInterest" />
|
||||
</mat-form-field>
|
||||
|
||||
<mat-form-field appearance="outline" class="fdps-field">
|
||||
<mat-label>{{ 'labels.inputs.Period' | translate }}</mat-label>
|
||||
<mat-select formControlName="preClosurePenalInterestOnTypeId">
|
||||
@for (preClosurePenalInterestOnType of preClosurePenalInterestOnTypeData; track preClosurePenalInterestOnType) {
|
||||
<mat-option [value]="preClosurePenalInterestOnType.id">
|
||||
{{ preClosurePenalInterestOnType.value }}
|
||||
</mat-option>
|
||||
}
|
||||
</mat-select>
|
||||
</mat-form-field>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="fdps-section">
|
||||
<div class="fdps-section__header">
|
||||
<i class="fas fa-file-invoice-dollar"></i>
|
||||
<h3>{{ 'labels.inputs.Is Withhold Tax Applicable' | translate }}</h3>
|
||||
</div>
|
||||
<div class="fdps-grid">
|
||||
<div class="fdps-field fdps-field--full fdps-checkbox-row">
|
||||
<mat-checkbox
|
||||
labelPosition="before"
|
||||
formControlName="withHoldTax"
|
||||
matTooltip="{{ 'tooltips.An boolean flag to attach' | translate }}"
|
||||
>
|
||||
{{ 'labels.inputs.Is Withhold Tax Applicable' | translate }}
|
||||
</mat-checkbox>
|
||||
</div>
|
||||
|
||||
@if (fixedDepositProductSettingsForm.value.withHoldTax) {
|
||||
<mat-form-field appearance="outline" class="fdps-field">
|
||||
<mat-label>{{ 'labels.inputs.Tax Group' | translate }}</mat-label>
|
||||
<mat-select formControlName="taxGroupId" required>
|
||||
@for (taxGroup of taxGroupData; track taxGroup) {
|
||||
<mat-option [value]="taxGroup.id">
|
||||
{{ taxGroup.name }}
|
||||
</mat-option>
|
||||
}
|
||||
</mat-select>
|
||||
<mat-error>
|
||||
{{ 'labels.inputs.Tax Group' | translate }} {{ 'labels.commons.is' | translate }}
|
||||
<strong>{{ 'labels.commons.required' | translate }}</strong>
|
||||
</mat-error>
|
||||
</mat-form-field>
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
+49
-13
@@ -6,23 +6,59 @@
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
h4 {
|
||||
font-weight: 500;
|
||||
margin: 1em 0;
|
||||
.fdps-section {
|
||||
border: 1px solid #e2e8f0;
|
||||
border-radius: 10px;
|
||||
overflow: hidden;
|
||||
background: #fff;
|
||||
|
||||
& + & {
|
||||
margin-top: 16px;
|
||||
}
|
||||
|
||||
&__header {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 10px;
|
||||
padding: 12px 24px;
|
||||
background: #f8f9fa;
|
||||
border-bottom: 1px solid #e8eaed;
|
||||
|
||||
i {
|
||||
font-size: 14px;
|
||||
color: #0ea5e9;
|
||||
}
|
||||
|
||||
h3 {
|
||||
margin: 0;
|
||||
font-size: 14px;
|
||||
font-weight: 600;
|
||||
color: #202124;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
mat-divider {
|
||||
margin: 1em 0 2em;
|
||||
.fdps-grid {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(2, 1fr);
|
||||
gap: 4px 16px;
|
||||
padding: 16px 24px;
|
||||
|
||||
@media (max-width: 600px) {
|
||||
grid-template-columns: 1fr;
|
||||
}
|
||||
}
|
||||
|
||||
.margin-v {
|
||||
margin: 1em 0;
|
||||
.fdps-field {
|
||||
width: 100%;
|
||||
|
||||
&--full {
|
||||
grid-column: 1 / -1;
|
||||
}
|
||||
}
|
||||
|
||||
.margin-b {
|
||||
margin: 0 0 1em;
|
||||
}
|
||||
|
||||
.margin-t {
|
||||
margin-top: 1em;
|
||||
.fdps-checkbox-row {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding: 4px 0;
|
||||
}
|
||||
|
||||
+1
-8
@@ -15,10 +15,7 @@ import {
|
||||
ReactiveFormsModule
|
||||
} from '@angular/forms';
|
||||
import { MatTooltip } from '@angular/material/tooltip';
|
||||
import { MatDivider } from '@angular/material/divider';
|
||||
import { MatCheckbox } from '@angular/material/checkbox';
|
||||
import { MatStepperPrevious, MatStepperNext } from '@angular/material/stepper';
|
||||
import { FaIconComponent } from '@fortawesome/angular-fontawesome';
|
||||
import { STANDALONE_SHARED_IMPORTS } from 'app/standalone-shared.module';
|
||||
|
||||
@Component({
|
||||
@@ -28,11 +25,7 @@ import { STANDALONE_SHARED_IMPORTS } from 'app/standalone-shared.module';
|
||||
imports: [
|
||||
...STANDALONE_SHARED_IMPORTS,
|
||||
MatTooltip,
|
||||
MatDivider,
|
||||
MatCheckbox,
|
||||
MatStepperPrevious,
|
||||
FaIconComponent,
|
||||
MatStepperNext
|
||||
MatCheckbox
|
||||
]
|
||||
})
|
||||
export class FixedDepositProductSettingsStepComponent implements OnInit {
|
||||
|
||||
+127
-129
@@ -7,138 +7,136 @@
|
||||
-->
|
||||
|
||||
<form [formGroup]="fixedDepositProductTermsForm">
|
||||
<div class="layout-row-wrap gap-2px responsive-column">
|
||||
<h4 class="mat-h4 flex-98">{{ 'labels.inputs.Deposit Amount' | translate }}</h4>
|
||||
<div class="fdpt-section">
|
||||
<div class="fdpt-section__header">
|
||||
<i class="fas fa-wallet"></i>
|
||||
<h3>{{ 'labels.inputs.Deposit Amount' | translate }}</h3>
|
||||
</div>
|
||||
<div class="fdpt-grid">
|
||||
<mat-form-field appearance="outline" class="fdpt-field">
|
||||
<mat-label>{{ 'labels.inputs.Minimum' | translate }}</mat-label>
|
||||
<input
|
||||
type="number"
|
||||
min="0"
|
||||
matInput
|
||||
formControlName="minDepositAmount"
|
||||
matTooltip="{{ 'tooltips.The minimum deposit amount required to open a fixed deposit' | translate }}"
|
||||
/>
|
||||
</mat-form-field>
|
||||
|
||||
<mat-form-field class="flex-31">
|
||||
<mat-label>{{ 'labels.inputs.Minimum' | translate }}</mat-label>
|
||||
<input
|
||||
type="number"
|
||||
min="0"
|
||||
matInput
|
||||
formControlName="minDepositAmount"
|
||||
matTooltip="{{ 'tooltips.The minimum deposit amount required to open a fixed deposit' | translate }}"
|
||||
/>
|
||||
</mat-form-field>
|
||||
<mat-form-field appearance="outline" class="fdpt-field">
|
||||
<mat-label>{{ 'labels.inputs.Default' | translate }}</mat-label>
|
||||
<input
|
||||
type="number"
|
||||
min="0"
|
||||
matInput
|
||||
formControlName="depositAmount"
|
||||
matTooltip="{{ 'tooltips.The default deposit amount expected' | translate }}"
|
||||
required
|
||||
/>
|
||||
<mat-error>
|
||||
{{ 'labels.inputs.Default' | translate }} {{ 'labels.inputs.Deposit Amount' | translate }}
|
||||
{{ 'labels.commons.is' | translate }} <strong>{{ 'labels.commons.required' | translate }}</strong>
|
||||
</mat-error>
|
||||
</mat-form-field>
|
||||
|
||||
<mat-form-field class="flex-31">
|
||||
<mat-label>{{ 'labels.inputs.Default' | translate }}</mat-label>
|
||||
<input
|
||||
type="number"
|
||||
min="0"
|
||||
matInput
|
||||
formControlName="depositAmount"
|
||||
matTooltip="{{ 'tooltips.The default deposit amount expected' | translate }}"
|
||||
required
|
||||
/>
|
||||
<mat-error>
|
||||
{{ 'labels.inputs.Default' | translate }} {{ 'labels.inputs.Deposit Amount' | translate }}
|
||||
{{ 'labels.commons.is' | translate }} <strong>{{ 'labels.commons.required' | translate }}</strong>
|
||||
</mat-error>
|
||||
</mat-form-field>
|
||||
|
||||
<mat-form-field class="flex-31">
|
||||
<mat-label>{{ 'labels.inputs.Maximum' | translate }}</mat-label>
|
||||
|
||||
<input
|
||||
type="number"
|
||||
min="0"
|
||||
matInput
|
||||
formControlName="maxDepositAmount"
|
||||
matTooltip="{{ 'tooltips.The maximum deposit amount allowed when a fixed deposit' | translate }}"
|
||||
/>
|
||||
</mat-form-field>
|
||||
|
||||
<mat-divider class="flex-98"></mat-divider>
|
||||
|
||||
<mat-form-field class="flex-48">
|
||||
<mat-label>{{ 'labels.inputs.Interest Compounding Period' | translate }}</mat-label>
|
||||
<mat-select
|
||||
formControlName="interestCompoundingPeriodType"
|
||||
matTooltip="{{ 'tooltips.The period at which interest rate' | translate }}"
|
||||
required
|
||||
>
|
||||
@for (interestCompoundingPeriodType of interestCompoundingPeriodTypeData; track interestCompoundingPeriodType) {
|
||||
<mat-option [value]="interestCompoundingPeriodType.id">
|
||||
{{ interestCompoundingPeriodType.value }}
|
||||
</mat-option>
|
||||
}
|
||||
</mat-select>
|
||||
<mat-error>
|
||||
{{ 'labels.inputs.Interest Compounding Period' | translate }} {{ 'labels.commons.is' | translate }}
|
||||
<strong>{{ 'labels.commons.required' | translate }}</strong>
|
||||
</mat-error>
|
||||
</mat-form-field>
|
||||
|
||||
<mat-form-field class="flex-48">
|
||||
<mat-label>{{ 'labels.inputs.Interest Posting Period' | translate }}</mat-label>
|
||||
<mat-select
|
||||
formControlName="interestPostingPeriodType"
|
||||
matTooltip="{{ 'tooltips.The period at which interest rate is posted or credited' | translate }}"
|
||||
required
|
||||
>
|
||||
@for (interestPostingPeriodType of interestPostingPeriodTypeData; track interestPostingPeriodType) {
|
||||
<mat-option [value]="interestPostingPeriodType.id">
|
||||
{{ interestPostingPeriodType.value }}
|
||||
</mat-option>
|
||||
}
|
||||
</mat-select>
|
||||
<mat-error>
|
||||
{{ 'labels.inputs.Interest Posting Period' | translate }} {{ 'labels.commons.is' | translate }}
|
||||
<strong>{{ 'labels.commons.required' | translate }}</strong>
|
||||
</mat-error>
|
||||
</mat-form-field>
|
||||
|
||||
<mat-form-field class="flex-48">
|
||||
<mat-label>{{ 'labels.inputs.Interest Calculated using' | translate }}</mat-label>
|
||||
<mat-select
|
||||
formControlName="interestCalculationType"
|
||||
matTooltip="{{ 'tooltips.The method used to calculate interest' | translate }}"
|
||||
required
|
||||
>
|
||||
@for (interestCalculationType of interestCalculationTypeData; track interestCalculationType) {
|
||||
<mat-option [value]="interestCalculationType.id">
|
||||
{{ interestCalculationType.value }}
|
||||
</mat-option>
|
||||
}
|
||||
</mat-select>
|
||||
<mat-error>
|
||||
{{ 'labels.inputs.Interest Calculated using' | translate }} {{ 'labels.commons.is' | translate }}
|
||||
<strong>{{ 'labels.commons.required' | translate }}</strong>
|
||||
</mat-error>
|
||||
</mat-form-field>
|
||||
|
||||
<mat-form-field class="flex-48">
|
||||
<mat-label>{{ 'labels.inputs.Days in Year' | translate }}</mat-label>
|
||||
<mat-select
|
||||
formControlName="interestCalculationDaysInYearType"
|
||||
matTooltip="{{ 'tooltips.The setting for number of days' | translate }}"
|
||||
required
|
||||
>
|
||||
@for (
|
||||
interestCalculationDaysInYearType of interestCalculationDaysInYearTypeData;
|
||||
track interestCalculationDaysInYearType
|
||||
) {
|
||||
<mat-option [value]="interestCalculationDaysInYearType.id">
|
||||
{{ interestCalculationDaysInYearType.value }}
|
||||
</mat-option>
|
||||
}
|
||||
</mat-select>
|
||||
<mat-error>
|
||||
{{ 'labels.inputs.Days in Year' | translate }} {{ 'labels.commons.is' | translate }}
|
||||
<strong>{{ 'labels.commons.required' | translate }}</strong>
|
||||
</mat-error>
|
||||
</mat-form-field>
|
||||
<mat-form-field appearance="outline" class="fdpt-field">
|
||||
<mat-label>{{ 'labels.inputs.Maximum' | translate }}</mat-label>
|
||||
<input
|
||||
type="number"
|
||||
min="0"
|
||||
matInput
|
||||
formControlName="maxDepositAmount"
|
||||
matTooltip="{{ 'tooltips.The maximum deposit amount allowed when a fixed deposit' | translate }}"
|
||||
/>
|
||||
</mat-form-field>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="layout-row align-center gap-2percent margin-t responsive-column">
|
||||
<button mat-raised-button matStepperPrevious>
|
||||
<fa-icon icon="arrow-left" class="m-r-10"></fa-icon>
|
||||
{{ 'labels.buttons.Previous' | translate }}
|
||||
</button>
|
||||
<button mat-raised-button matStepperNext>
|
||||
{{ 'labels.buttons.Next' | translate }}
|
||||
<fa-icon icon="arrow-right" class="m-l-10"></fa-icon>
|
||||
</button>
|
||||
<div class="fdpt-section">
|
||||
<div class="fdpt-section__header">
|
||||
<i class="fas fa-percentage"></i>
|
||||
<h3>{{ 'labels.inputs.Interest Compounding Period' | translate }}</h3>
|
||||
</div>
|
||||
<div class="fdpt-grid">
|
||||
<mat-form-field appearance="outline" class="fdpt-field">
|
||||
<mat-label>{{ 'labels.inputs.Interest Compounding Period' | translate }}</mat-label>
|
||||
<mat-select
|
||||
formControlName="interestCompoundingPeriodType"
|
||||
matTooltip="{{ 'tooltips.The period at which interest rate' | translate }}"
|
||||
required
|
||||
>
|
||||
@for (interestCompoundingPeriodType of interestCompoundingPeriodTypeData; track interestCompoundingPeriodType) {
|
||||
<mat-option [value]="interestCompoundingPeriodType.id">
|
||||
{{ interestCompoundingPeriodType.value }}
|
||||
</mat-option>
|
||||
}
|
||||
</mat-select>
|
||||
<mat-error>
|
||||
{{ 'labels.inputs.Interest Compounding Period' | translate }} {{ 'labels.commons.is' | translate }}
|
||||
<strong>{{ 'labels.commons.required' | translate }}</strong>
|
||||
</mat-error>
|
||||
</mat-form-field>
|
||||
|
||||
<mat-form-field appearance="outline" class="fdpt-field">
|
||||
<mat-label>{{ 'labels.inputs.Interest Posting Period' | translate }}</mat-label>
|
||||
<mat-select
|
||||
formControlName="interestPostingPeriodType"
|
||||
matTooltip="{{ 'tooltips.The period at which interest rate is posted or credited' | translate }}"
|
||||
required
|
||||
>
|
||||
@for (interestPostingPeriodType of interestPostingPeriodTypeData; track interestPostingPeriodType) {
|
||||
<mat-option [value]="interestPostingPeriodType.id">
|
||||
{{ interestPostingPeriodType.value }}
|
||||
</mat-option>
|
||||
}
|
||||
</mat-select>
|
||||
<mat-error>
|
||||
{{ 'labels.inputs.Interest Posting Period' | translate }} {{ 'labels.commons.is' | translate }}
|
||||
<strong>{{ 'labels.commons.required' | translate }}</strong>
|
||||
</mat-error>
|
||||
</mat-form-field>
|
||||
|
||||
<mat-form-field appearance="outline" class="fdpt-field">
|
||||
<mat-label>{{ 'labels.inputs.Interest Calculated using' | translate }}</mat-label>
|
||||
<mat-select
|
||||
formControlName="interestCalculationType"
|
||||
matTooltip="{{ 'tooltips.The method used to calculate interest' | translate }}"
|
||||
required
|
||||
>
|
||||
@for (interestCalculationType of interestCalculationTypeData; track interestCalculationType) {
|
||||
<mat-option [value]="interestCalculationType.id">
|
||||
{{ interestCalculationType.value }}
|
||||
</mat-option>
|
||||
}
|
||||
</mat-select>
|
||||
<mat-error>
|
||||
{{ 'labels.inputs.Interest Calculated using' | translate }} {{ 'labels.commons.is' | translate }}
|
||||
<strong>{{ 'labels.commons.required' | translate }}</strong>
|
||||
</mat-error>
|
||||
</mat-form-field>
|
||||
|
||||
<mat-form-field appearance="outline" class="fdpt-field">
|
||||
<mat-label>{{ 'labels.inputs.Days in Year' | translate }}</mat-label>
|
||||
<mat-select
|
||||
formControlName="interestCalculationDaysInYearType"
|
||||
matTooltip="{{ 'tooltips.The setting for number of days' | translate }}"
|
||||
required
|
||||
>
|
||||
@for (
|
||||
interestCalculationDaysInYearType of interestCalculationDaysInYearTypeData;
|
||||
track interestCalculationDaysInYearType
|
||||
) {
|
||||
<mat-option [value]="interestCalculationDaysInYearType.id">
|
||||
{{ interestCalculationDaysInYearType.value }}
|
||||
</mat-option>
|
||||
}
|
||||
</mat-select>
|
||||
<mat-error>
|
||||
{{ 'labels.inputs.Days in Year' | translate }} {{ 'labels.commons.is' | translate }}
|
||||
<strong>{{ 'labels.commons.required' | translate }}</strong>
|
||||
</mat-error>
|
||||
</mat-form-field>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
+45
-7
@@ -6,15 +6,53 @@
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
h4 {
|
||||
font-weight: 500;
|
||||
margin: 1em 0;
|
||||
.fdpt-section {
|
||||
border: 1px solid #e2e8f0;
|
||||
border-radius: 10px;
|
||||
overflow: hidden;
|
||||
background: #fff;
|
||||
|
||||
& + & {
|
||||
margin-top: 16px;
|
||||
}
|
||||
|
||||
&__header {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 10px;
|
||||
padding: 12px 24px;
|
||||
background: #f8f9fa;
|
||||
border-bottom: 1px solid #e8eaed;
|
||||
|
||||
i {
|
||||
font-size: 14px;
|
||||
color: #0ea5e9;
|
||||
}
|
||||
|
||||
h3 {
|
||||
margin: 0;
|
||||
font-size: 14px;
|
||||
font-weight: 600;
|
||||
color: #202124;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
mat-divider {
|
||||
margin: 1em 0 2em;
|
||||
.fdpt-grid {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(2, 1fr);
|
||||
gap: 4px 16px;
|
||||
padding: 16px 24px;
|
||||
|
||||
@media (max-width: 600px) {
|
||||
grid-template-columns: 1fr;
|
||||
}
|
||||
}
|
||||
|
||||
.margin-t {
|
||||
margin-top: 1em;
|
||||
.fdpt-field {
|
||||
width: 100%;
|
||||
|
||||
&--full {
|
||||
grid-column: 1 / -1;
|
||||
}
|
||||
}
|
||||
|
||||
+1
-8
@@ -9,9 +9,6 @@
|
||||
import { Component, OnInit, Input, inject } from '@angular/core';
|
||||
import { UntypedFormGroup, UntypedFormBuilder, Validators, ReactiveFormsModule } from '@angular/forms';
|
||||
import { MatTooltip } from '@angular/material/tooltip';
|
||||
import { MatDivider } from '@angular/material/divider';
|
||||
import { MatStepperPrevious, MatStepperNext } from '@angular/material/stepper';
|
||||
import { FaIconComponent } from '@fortawesome/angular-fontawesome';
|
||||
import { STANDALONE_SHARED_IMPORTS } from 'app/standalone-shared.module';
|
||||
|
||||
@Component({
|
||||
@@ -20,11 +17,7 @@ import { STANDALONE_SHARED_IMPORTS } from 'app/standalone-shared.module';
|
||||
styleUrls: ['./fixed-deposit-product-terms-step.component.scss'],
|
||||
imports: [
|
||||
...STANDALONE_SHARED_IMPORTS,
|
||||
MatTooltip,
|
||||
MatDivider,
|
||||
MatStepperPrevious,
|
||||
FaIconComponent,
|
||||
MatStepperNext
|
||||
MatTooltip
|
||||
]
|
||||
})
|
||||
export class FixedDepositProductTermsStepComponent implements OnInit {
|
||||
|
||||
@@ -22,8 +22,9 @@
|
||||
|
||||
<div class="container">
|
||||
<div #filter class="layout-row gap-20px">
|
||||
<mat-form-field class="flex-fill">
|
||||
<mat-form-field appearance="outline" class="flex-fill">
|
||||
<mat-label>{{ 'labels.inputs.Filter' | translate }}</mat-label>
|
||||
<i matPrefix class="fas fa-search"></i>
|
||||
<input matInput (keyup)="applyFilter($event.target.value)" />
|
||||
</mat-form-field>
|
||||
</div>
|
||||
|
||||
+155
-157
@@ -6,173 +6,171 @@
|
||||
file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
-->
|
||||
|
||||
<div class="container">
|
||||
<mat-card>
|
||||
<form [formGroup]="floatingRateForm" (ngSubmit)="submit()">
|
||||
<mat-card-content>
|
||||
<div class="layout-row-wrap responsive-column gap-4percent">
|
||||
<mat-form-field class="flex-30">
|
||||
<mat-label>{{ 'labels.inputs.Floating Rate Name' | translate }}</mat-label>
|
||||
<input
|
||||
matInput
|
||||
required
|
||||
matTooltip="{{ 'tooltips.Unique name for the floating rate scheme' | translate }}"
|
||||
formControlName="name"
|
||||
/>
|
||||
@if (floatingRateForm.controls.name.hasError('required')) {
|
||||
<mat-error>
|
||||
{{ 'labels.inputs.Floating Rate Name' | translate }} {{ 'labels.commons.is' | translate }}
|
||||
<strong>{{ 'labels.commons.required' | translate }}</strong>
|
||||
</mat-error>
|
||||
}
|
||||
</mat-form-field>
|
||||
<div class="cfr-container">
|
||||
<div class="cfr-page-header">
|
||||
<i class="fas fa-percentage cfr-page-header__icon"></i>
|
||||
<h2 class="cfr-page-header__title">{{ 'labels.buttons.Create Floating Rate' | translate }}</h2>
|
||||
</div>
|
||||
|
||||
<div class="checkbox-wrapper flex-30">
|
||||
<mat-checkbox
|
||||
formControlName="isBaseLendingRate"
|
||||
matTooltip="{{ 'tooltips.Base lending rate for the organisation' | translate }}"
|
||||
class="checkbox"
|
||||
labelPosition="before"
|
||||
>{{ 'labels.inputs.Is Base Lending Rate' | translate }}?</mat-checkbox
|
||||
>
|
||||
</div>
|
||||
<form [formGroup]="floatingRateForm" (ngSubmit)="submit()">
|
||||
<!-- Rate Details Section -->
|
||||
<div class="cfr-section">
|
||||
<div class="cfr-section__header">
|
||||
<i class="fas fa-info-circle"></i>
|
||||
<h3>{{ 'labels.heading.Rate Details' | translate }}</h3>
|
||||
</div>
|
||||
<div class="cfr-section__body">
|
||||
<mat-form-field appearance="outline" class="cfr-field-full">
|
||||
<mat-label>{{ 'labels.inputs.Floating Rate Name' | translate }}</mat-label>
|
||||
<input
|
||||
matInput
|
||||
required
|
||||
matTooltip="{{ 'tooltips.Unique name for the floating rate scheme' | translate }}"
|
||||
formControlName="name"
|
||||
/>
|
||||
@if (floatingRateForm.controls.name.hasError('required')) {
|
||||
<mat-error>
|
||||
{{ 'labels.inputs.Floating Rate Name' | translate }} {{ 'labels.commons.is' | translate }}
|
||||
<strong>{{ 'labels.commons.required' | translate }}</strong>
|
||||
</mat-error>
|
||||
}
|
||||
</mat-form-field>
|
||||
|
||||
<div class="checkbox-wrapper flex-30">
|
||||
<mat-checkbox
|
||||
formControlName="isActive"
|
||||
matTooltip="{{ 'tooltips.Floating rate scheme to be activated' | translate }}"
|
||||
class="checkbox"
|
||||
labelPosition="before"
|
||||
>{{ 'labels.inputs.Active' | translate }}</mat-checkbox
|
||||
>
|
||||
</div>
|
||||
<div class="cfr-checkbox-row">
|
||||
<mat-checkbox
|
||||
formControlName="isBaseLendingRate"
|
||||
matTooltip="{{ 'tooltips.Base lending rate for the organisation' | translate }}"
|
||||
>
|
||||
{{ 'labels.inputs.Is Base Lending Rate' | translate }}?
|
||||
</mat-checkbox>
|
||||
|
||||
<mat-checkbox
|
||||
formControlName="isActive"
|
||||
matTooltip="{{ 'tooltips.Floating rate scheme to be activated' | translate }}"
|
||||
>
|
||||
{{ 'labels.inputs.Active' | translate }}
|
||||
</mat-checkbox>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<br />
|
||||
<!-- Floating Rate Periods Section -->
|
||||
<div class="cfr-section">
|
||||
<div class="cfr-section__header">
|
||||
<i class="fas fa-calendar-alt"></i>
|
||||
<h3>{{ 'labels.inputs.Floating Rate Periods' | translate }}</h3>
|
||||
<button mat-flat-button type="button" color="primary" class="cfr-add-btn" (click)="addFloatingRatePeriod()">
|
||||
<fa-icon icon="plus"></fa-icon>
|
||||
{{ 'labels.buttons.Add' | translate }}
|
||||
</button>
|
||||
</div>
|
||||
<div class="cfr-section__body cfr-section__body--no-padding">
|
||||
<div class="cfr-table-wrapper">
|
||||
<table mat-table [dataSource]="dataSource" matSort class="cfr-table">
|
||||
<ng-container matColumnDef="fromDate">
|
||||
<th
|
||||
mat-header-cell
|
||||
*matHeaderCellDef
|
||||
matTooltip="{{ 'tooltips.Interest effective from date' | translate }}"
|
||||
mat-sort-header
|
||||
>
|
||||
{{ 'labels.inputs.From Date' | translate }}
|
||||
</th>
|
||||
<td mat-cell *matCellDef="let floatingRatePeriod">{{ floatingRatePeriod.fromDate | dateFormat }}</td>
|
||||
</ng-container>
|
||||
|
||||
<mat-divider [inset]="true"></mat-divider>
|
||||
<ng-container matColumnDef="interestRate">
|
||||
<th
|
||||
mat-header-cell
|
||||
*matHeaderCellDef
|
||||
matTooltip="{{ 'tooltips.Annualised Interest rate' | translate }}"
|
||||
mat-sort-header
|
||||
>
|
||||
{{ 'labels.inputs.Interest Rate' | translate }}
|
||||
</th>
|
||||
<td mat-cell *matCellDef="let floatingRatePeriod">{{ floatingRatePeriod.interestRate | formatNumber }}</td>
|
||||
</ng-container>
|
||||
|
||||
<br />
|
||||
<ng-container matColumnDef="isDifferential">
|
||||
<th
|
||||
mat-header-cell
|
||||
*matHeaderCellDef
|
||||
matTooltip="{{ 'tooltips.Interest rate mentioned is added to base lending rate' | translate }}"
|
||||
mat-sort-header
|
||||
>
|
||||
{{ 'labels.inputs.Is Differential' | translate }}?
|
||||
</th>
|
||||
<td mat-cell *matCellDef="let floatingRate">
|
||||
@if (floatingRate.isDifferentialToBaseLendingRate) {
|
||||
<fa-icon
|
||||
icon="check-circle"
|
||||
size="lg"
|
||||
class="cfr-icon-yes"
|
||||
matTooltip="{{ 'tooltips.Yes' | translate }}"
|
||||
matTooltipPosition="right"
|
||||
></fa-icon>
|
||||
}
|
||||
@if (!floatingRate.isDifferentialToBaseLendingRate) {
|
||||
<fa-icon
|
||||
icon="times-circle"
|
||||
size="lg"
|
||||
class="cfr-icon-no"
|
||||
matTooltip="{{ 'tooltips.No' | translate }}"
|
||||
matTooltipPosition="right"
|
||||
></fa-icon>
|
||||
}
|
||||
</td>
|
||||
</ng-container>
|
||||
|
||||
<div class="layout-row-wrap gap-70percent m-b-10 layout-lt-md-column">
|
||||
<p class="mat-title flex-25">
|
||||
{{ 'labels.inputs.Floating Rate Periods' | translate }}
|
||||
<i
|
||||
class="fas fa-question"
|
||||
matTooltip="{{ 'tooltips.Floating interest rate and start date' | translate }}"
|
||||
></i>
|
||||
</p>
|
||||
<ng-container matColumnDef="actions">
|
||||
<th mat-header-cell *matHeaderCellDef>{{ 'labels.inputs.Actions' | translate }}</th>
|
||||
<td mat-cell *matCellDef="let floatingRatePeriod">
|
||||
<button
|
||||
type="button"
|
||||
color="primary"
|
||||
mat-icon-button
|
||||
matTooltip="{{ 'tooltips.Edit Period' | translate }}"
|
||||
matTooltipPosition="left"
|
||||
(click)="editFloatingRatePeriod(floatingRatePeriod)"
|
||||
>
|
||||
<fa-icon icon="edit" size="lg"></fa-icon>
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
color="warn"
|
||||
mat-icon-button
|
||||
matTooltip="{{ 'tooltips.Remove Period' | translate }}"
|
||||
matTooltipPosition="right"
|
||||
(click)="deleteFloatingRatePeriod(floatingRatePeriod)"
|
||||
>
|
||||
<fa-icon icon="trash" size="lg"></fa-icon>
|
||||
</button>
|
||||
</td>
|
||||
</ng-container>
|
||||
|
||||
<button mat-mini-fab type="button" color="primary" (click)="addFloatingRatePeriod()">
|
||||
<fa-icon icon="plus"></fa-icon>
|
||||
</button>
|
||||
<tr mat-header-row *matHeaderRowDef="displayedColumns"></tr>
|
||||
<tr mat-row *matRowDef="let row; columns: displayedColumns"></tr>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
<table mat-table [dataSource]="dataSource" matSort>
|
||||
<ng-container matColumnDef="fromDate">
|
||||
<th
|
||||
mat-header-cell
|
||||
*matHeaderCellDef
|
||||
matTooltip="{{ 'tooltips.Interest effective from date' | translate }}"
|
||||
mat-sort-header
|
||||
>
|
||||
{{ 'labels.inputs.From Date' | translate }}
|
||||
</th>
|
||||
<td mat-cell *matCellDef="let floatingRatePeriod">{{ floatingRatePeriod.fromDate | dateFormat }}</td>
|
||||
</ng-container>
|
||||
|
||||
<ng-container matColumnDef="interestRate">
|
||||
<th
|
||||
mat-header-cell
|
||||
*matHeaderCellDef
|
||||
matTooltip="{{ 'tooltips.Annualised Interest rate' | translate }}"
|
||||
mat-sort-header
|
||||
>
|
||||
{{ 'labels.inputs.Interest Rate' | translate }}
|
||||
</th>
|
||||
<td mat-cell *matCellDef="let floatingRatePeriod">{{ floatingRatePeriod.interestRate | formatNumber }}</td>
|
||||
</ng-container>
|
||||
|
||||
<ng-container matColumnDef="isDifferential">
|
||||
<th
|
||||
mat-header-cell
|
||||
*matHeaderCellDef
|
||||
matTooltip="{{ 'tooltips.Interest rate mentioned is added to base lending rate' | translate }}"
|
||||
mat-sort-header
|
||||
>
|
||||
{{ 'labels.inputs.Is Differential' | translate }}?
|
||||
</th>
|
||||
<td mat-cell *matCellDef="let floatingRate">
|
||||
@if (floatingRate.isDifferentialToBaseLendingRate) {
|
||||
<fa-icon
|
||||
icon="check-circle"
|
||||
size="lg"
|
||||
class="is-differential"
|
||||
matTooltip="{{ 'tooltips.Yes' | translate }}"
|
||||
matTooltipPosition="right"
|
||||
></fa-icon>
|
||||
}
|
||||
@if (!floatingRate.isDifferentialToBaseLendingRate) {
|
||||
<fa-icon
|
||||
icon="times-circle"
|
||||
size="lg"
|
||||
class="not-is-differential"
|
||||
matTooltip="{{ 'tooltips.No' | translate }}"
|
||||
matTooltipPosition="right"
|
||||
></fa-icon>
|
||||
}
|
||||
</td>
|
||||
</ng-container>
|
||||
|
||||
<ng-container matColumnDef="actions">
|
||||
<th mat-header-cell *matHeaderCellDef>{{ 'labels.inputs.Actions' | translate }}</th>
|
||||
<td mat-cell *matCellDef="let floatingRatePeriod" class="gap-15percent">
|
||||
<button
|
||||
type="button"
|
||||
class="flex-8"
|
||||
color="primary"
|
||||
mat-icon-button
|
||||
matTooltip="{{ 'tooltips.Edit Period' | translate }}"
|
||||
matTooltipPosition="left"
|
||||
(click)="editFloatingRatePeriod(floatingRatePeriod)"
|
||||
>
|
||||
<fa-icon icon="edit" size="lg"></fa-icon>
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
class="flex-8"
|
||||
color="warn"
|
||||
mat-icon-button
|
||||
matTooltip="{{ 'tooltips.Remove Period' | translate }}"
|
||||
matTooltipPosition="right"
|
||||
(click)="deleteFloatingRatePeriod(floatingRatePeriod)"
|
||||
>
|
||||
<fa-icon icon="trash" size="lg"></fa-icon>
|
||||
</button>
|
||||
</td>
|
||||
</ng-container>
|
||||
|
||||
<tr mat-header-row *matHeaderRowDef="displayedColumns"></tr>
|
||||
<tr mat-row *matRowDef="let row; columns: displayedColumns"></tr>
|
||||
</table>
|
||||
|
||||
<mat-paginator [pageSizeOptions]="[10, 25, 50, 100]" showFirstLastButtons></mat-paginator>
|
||||
</mat-card-content>
|
||||
</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
|
||||
type="submit"
|
||||
color="primary"
|
||||
[disabled]="!floatingRateForm.valid"
|
||||
*mifosxHasPermission="'CREATE_FLOATINGRATE'"
|
||||
>
|
||||
{{ 'labels.buttons.Submit' | translate }}
|
||||
</button>
|
||||
</mat-card-actions>
|
||||
</form>
|
||||
</mat-card>
|
||||
<!-- Action Bar -->
|
||||
<div class="cfr-action-bar">
|
||||
<button type="button" mat-stroked-button [routerLink]="['../']">
|
||||
{{ 'labels.buttons.Cancel' | translate }}
|
||||
</button>
|
||||
<button
|
||||
mat-flat-button
|
||||
type="submit"
|
||||
color="primary"
|
||||
[disabled]="!floatingRateForm.valid"
|
||||
*mifosxHasPermission="'CREATE_FLOATINGRATE'"
|
||||
>
|
||||
{{ 'labels.buttons.Submit' | translate }}
|
||||
</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
+166
-10
@@ -6,25 +6,181 @@
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
@media (width >=992px) {
|
||||
.checkbox-wrapper {
|
||||
margin-top: 8px;
|
||||
.cfr-container {
|
||||
max-width: 960px;
|
||||
margin: 0 auto;
|
||||
padding: 24px 16px;
|
||||
}
|
||||
|
||||
.checkbox {
|
||||
padding: 0 0 17.5px;
|
||||
.cfr-page-header {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 10px;
|
||||
margin-bottom: 24px;
|
||||
|
||||
&__icon {
|
||||
font-size: 20px;
|
||||
color: #1353a0;
|
||||
}
|
||||
|
||||
&__title {
|
||||
font-size: 20px;
|
||||
font-weight: 600;
|
||||
color: #202124;
|
||||
margin: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.cfr-section {
|
||||
border: 1px solid #e2e8f0;
|
||||
border-radius: 10px;
|
||||
overflow: hidden;
|
||||
background: #fff;
|
||||
margin-bottom: 20px;
|
||||
|
||||
&__header {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
padding: 12px 24px;
|
||||
background: #f8f9fa;
|
||||
border-bottom: 1px solid #e8eaed;
|
||||
|
||||
i {
|
||||
font-size: 14px;
|
||||
color: #0ea5e9;
|
||||
}
|
||||
|
||||
h3 {
|
||||
font-size: 14px;
|
||||
font-weight: 600;
|
||||
color: #202124;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.cfr-add-btn {
|
||||
margin-left: auto;
|
||||
font-size: 12px;
|
||||
height: 32px;
|
||||
padding: 0 14px;
|
||||
border-radius: 6px;
|
||||
|
||||
fa-icon {
|
||||
margin-right: 4px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&__body {
|
||||
padding: 20px 24px;
|
||||
|
||||
&--no-padding {
|
||||
padding: 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: CONFIGURE THESE CLASSES GLOBALLY
|
||||
.is-differential {
|
||||
.cfr-field-full {
|
||||
width: 100%;
|
||||
max-width: 480px;
|
||||
}
|
||||
|
||||
.cfr-checkbox-row {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 24px;
|
||||
flex-wrap: wrap;
|
||||
margin-top: 4px;
|
||||
}
|
||||
|
||||
.cfr-table-wrapper {
|
||||
border-bottom: 1px solid #e2e8f0;
|
||||
overflow: auto;
|
||||
}
|
||||
|
||||
.cfr-table {
|
||||
width: 100%;
|
||||
|
||||
::ng-deep {
|
||||
.mat-mdc-header-row {
|
||||
background: #f8fafc;
|
||||
min-height: 38px;
|
||||
height: 38px;
|
||||
}
|
||||
|
||||
.mat-mdc-header-cell {
|
||||
font-size: 11px;
|
||||
font-weight: 600;
|
||||
text-transform: uppercase;
|
||||
letter-spacing: 0.04em;
|
||||
color: #64748b;
|
||||
border-bottom: 1px solid #e2e8f0;
|
||||
padding: 0 14px;
|
||||
}
|
||||
|
||||
.mat-mdc-row {
|
||||
min-height: 40px;
|
||||
height: 40px;
|
||||
border-bottom: 1px solid #f1f5f9;
|
||||
|
||||
&:last-child {
|
||||
border-bottom: none;
|
||||
}
|
||||
}
|
||||
|
||||
.mat-mdc-cell {
|
||||
font-size: 13px;
|
||||
color: #202124;
|
||||
padding: 0 14px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.cfr-icon-yes {
|
||||
color: #32cd32;
|
||||
}
|
||||
|
||||
.not-is-differential {
|
||||
.cfr-icon-no {
|
||||
color: #f44366;
|
||||
}
|
||||
|
||||
table {
|
||||
width: 100%;
|
||||
.cfr-action-bar {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 10px;
|
||||
justify-content: flex-end;
|
||||
padding-top: 8px;
|
||||
}
|
||||
|
||||
@media (max-width: 600px) {
|
||||
.cfr-container {
|
||||
padding: 16px 10px;
|
||||
}
|
||||
|
||||
.cfr-field-full {
|
||||
max-width: 100%;
|
||||
}
|
||||
|
||||
.cfr-checkbox-row {
|
||||
flex-direction: column;
|
||||
align-items: flex-start;
|
||||
gap: 12px;
|
||||
}
|
||||
|
||||
.cfr-section__header {
|
||||
padding: 10px 16px;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
|
||||
.cfr-section__body {
|
||||
padding: 16px;
|
||||
}
|
||||
|
||||
.cfr-action-bar {
|
||||
flex-direction: column;
|
||||
|
||||
button {
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -38,7 +38,6 @@ import { DeleteDialogComponent } from 'app/shared/delete-dialog/delete-dialog.co
|
||||
import { FloatingRatePeriodDialogComponent } from '../floating-rate-period-dialog/floating-rate-period-dialog.component';
|
||||
import { MatTooltip } from '@angular/material/tooltip';
|
||||
import { MatCheckbox } from '@angular/material/checkbox';
|
||||
import { MatDivider } from '@angular/material/divider';
|
||||
import { MatMiniFabButton, MatIconButton, MatButton } from '@angular/material/button';
|
||||
import { FaIconComponent } from '@fortawesome/angular-fontawesome';
|
||||
import { DateFormatPipe } from '../../../pipes/date-format.pipe';
|
||||
@@ -56,7 +55,6 @@ import { STANDALONE_SHARED_IMPORTS } from 'app/standalone-shared.module';
|
||||
...STANDALONE_SHARED_IMPORTS,
|
||||
MatTooltip,
|
||||
MatCheckbox,
|
||||
MatDivider,
|
||||
MatMiniFabButton,
|
||||
FaIconComponent,
|
||||
MatTable,
|
||||
|
||||
+157
-152
@@ -6,165 +6,170 @@
|
||||
file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
-->
|
||||
|
||||
<div class="container">
|
||||
<mat-card>
|
||||
<form [formGroup]="floatingRateForm" (ngSubmit)="submit()">
|
||||
<mat-card-content>
|
||||
<div class="layout-row-wrap responsive-column gap-15percent">
|
||||
<mat-form-field class="flex-25">
|
||||
<mat-label>{{ 'labels.inputs.Floating Rate Name' | translate }}</mat-label>
|
||||
<input
|
||||
matInput
|
||||
required
|
||||
matTooltip="{{ 'tooltips.Unique name for the floating rate scheme' | translate }}"
|
||||
formControlName="name"
|
||||
/>
|
||||
@if (floatingRateForm.controls.name.hasError('required')) {
|
||||
<mat-error>
|
||||
{{ 'labels.inputs.Floating Rate Name' | translate }} {{ 'labels.commons.is' | translate }}
|
||||
<strong>{{ 'labels.commons.required' | translate }}</strong>
|
||||
</mat-error>
|
||||
}
|
||||
</mat-form-field>
|
||||
<div class="efr-container">
|
||||
<div class="efr-page-header">
|
||||
<i class="fas fa-percentage efr-page-header__icon"></i>
|
||||
<h2 class="efr-page-header__title">{{ 'labels.buttons.Edit Floating Rate' | translate }}</h2>
|
||||
</div>
|
||||
|
||||
<div class="checkbox-wrapper flex-25">
|
||||
<mat-checkbox
|
||||
formControlName="isBaseLendingRate"
|
||||
matTooltip="{{ 'tooltips.Base lending rate for the organisation' | translate }}"
|
||||
class="checkbox"
|
||||
labelPosition="before"
|
||||
>
|
||||
{{ 'labels.inputs.Is Base Lending Rate' | translate }}?
|
||||
</mat-checkbox>
|
||||
</div>
|
||||
<form [formGroup]="floatingRateForm" (ngSubmit)="submit()">
|
||||
<!-- Rate Details Section -->
|
||||
<div class="efr-section">
|
||||
<div class="efr-section__header">
|
||||
<i class="fas fa-info-circle"></i>
|
||||
<h3>{{ 'labels.heading.Rate Details' | translate }}</h3>
|
||||
</div>
|
||||
<div class="efr-section__body">
|
||||
<mat-form-field appearance="outline" class="efr-field-full">
|
||||
<mat-label>{{ 'labels.inputs.Floating Rate Name' | translate }}</mat-label>
|
||||
<input
|
||||
matInput
|
||||
required
|
||||
matTooltip="{{ 'tooltips.Unique name for the floating rate scheme' | translate }}"
|
||||
formControlName="name"
|
||||
/>
|
||||
@if (floatingRateForm.controls.name.hasError('required')) {
|
||||
<mat-error>
|
||||
{{ 'labels.inputs.Floating Rate Name' | translate }} {{ 'labels.commons.is' | translate }}
|
||||
<strong>{{ 'labels.commons.required' | translate }}</strong>
|
||||
</mat-error>
|
||||
}
|
||||
</mat-form-field>
|
||||
|
||||
<div class="checkbox-wrapper flex-15">
|
||||
<mat-checkbox
|
||||
formControlName="isActive"
|
||||
matTooltip="{{ 'tooltips.Floating rate scheme to be activated' | translate }}"
|
||||
class="checkbox"
|
||||
labelPosition="before"
|
||||
>
|
||||
{{ 'labels.inputs.Active' | translate }}
|
||||
</mat-checkbox>
|
||||
</div>
|
||||
<div class="efr-checkbox-row">
|
||||
<mat-checkbox
|
||||
formControlName="isBaseLendingRate"
|
||||
matTooltip="{{ 'tooltips.Base lending rate for the organisation' | translate }}"
|
||||
>
|
||||
{{ 'labels.inputs.Is Base Lending Rate' | translate }}?
|
||||
</mat-checkbox>
|
||||
|
||||
<mat-checkbox
|
||||
formControlName="isActive"
|
||||
matTooltip="{{ 'tooltips.Floating rate scheme to be activated' | translate }}"
|
||||
>
|
||||
{{ 'labels.inputs.Active' | translate }}
|
||||
</mat-checkbox>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<br />
|
||||
|
||||
<mat-divider [inset]="true"></mat-divider>
|
||||
|
||||
<br />
|
||||
|
||||
<div class="layout-row-wrap gap-70percent m-b-10 layout-lt-md-column">
|
||||
<p class="mat-title flex-25">
|
||||
{{ 'labels.inputs.Floating Rate Periods' | translate }}
|
||||
<i
|
||||
class="fas fa-question"
|
||||
matTooltip="{{
|
||||
'tooltips.Floating interest rate and start date for this floating rate scheme' | translate
|
||||
}}"
|
||||
></i>
|
||||
</p>
|
||||
|
||||
<button mat-mini-fab type="button" color="primary" (click)="addFloatingRatePeriod()">
|
||||
<fa-icon icon="plus"></fa-icon>
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<table mat-table [dataSource]="dataSource" matSort>
|
||||
<ng-container matColumnDef="fromDate">
|
||||
<th
|
||||
mat-header-cell
|
||||
*matHeaderCellDef
|
||||
matTooltip="{{ 'tooltips.Interest effective from date' | translate }}"
|
||||
mat-sort-header
|
||||
>
|
||||
{{ 'labels.inputs.From Date' | translate }}
|
||||
</th>
|
||||
<td mat-cell *matCellDef="let floatingRatePeriod">{{ floatingRatePeriod.fromDate | dateFormat }}</td>
|
||||
</ng-container>
|
||||
|
||||
<ng-container matColumnDef="interestRate">
|
||||
<th
|
||||
mat-header-cell
|
||||
*matHeaderCellDef
|
||||
matTooltip="{{ 'tooltips.Annualised Interest rate' | translate }}"
|
||||
mat-sort-header
|
||||
>
|
||||
{{ 'labels.inputs.Interest Rate' | translate }}
|
||||
</th>
|
||||
<td mat-cell *matCellDef="let floatingRatePeriod">{{ floatingRatePeriod.interestRate }}</td>
|
||||
</ng-container>
|
||||
|
||||
<ng-container matColumnDef="isDifferential">
|
||||
<th
|
||||
mat-header-cell
|
||||
*matHeaderCellDef
|
||||
matTooltip="{{ 'tooltips.Interest rate mentioned is added to base lending rate' | translate }}"
|
||||
mat-sort-header
|
||||
>
|
||||
{{ 'labels.inputs.Is Differential' | translate }}?
|
||||
</th>
|
||||
<td mat-cell *matCellDef="let floatingRate">
|
||||
@if (floatingRate.isDifferentialToBaseLendingRate) {
|
||||
<fa-icon
|
||||
icon="check-circle"
|
||||
size="lg"
|
||||
class="is-differential"
|
||||
matTooltip="{{ 'tooltips.Yes' | translate }}"
|
||||
matTooltipPosition="right"
|
||||
></fa-icon>
|
||||
}
|
||||
@if (!floatingRate.isDifferentialToBaseLendingRate) {
|
||||
<fa-icon
|
||||
icon="times-circle"
|
||||
size="lg"
|
||||
class="not-is-differential"
|
||||
matTooltip="{{ 'tooltips.No' | translate }}"
|
||||
matTooltipPosition="right"
|
||||
></fa-icon>
|
||||
}
|
||||
</td>
|
||||
</ng-container>
|
||||
|
||||
<ng-container matColumnDef="actions">
|
||||
<th mat-header-cell *matHeaderCellDef>{{ 'labels.inputs.Actions' | translate }}</th>
|
||||
<td mat-cell *matCellDef="let floatingRatePeriod">
|
||||
<button
|
||||
type="button"
|
||||
color="primary"
|
||||
mat-icon-button
|
||||
(click)="editFloatingRatePeriod(floatingRatePeriod)"
|
||||
<!-- Floating Rate Periods Section -->
|
||||
<div class="efr-section">
|
||||
<div class="efr-section__header">
|
||||
<i class="fas fa-calendar-alt"></i>
|
||||
<h3>{{ 'labels.inputs.Floating Rate Periods' | translate }}</h3>
|
||||
<button mat-flat-button type="button" color="primary" class="efr-add-btn" (click)="addFloatingRatePeriod()">
|
||||
<fa-icon icon="plus"></fa-icon>
|
||||
{{ 'labels.buttons.Add' | translate }}
|
||||
</button>
|
||||
</div>
|
||||
<div class="efr-section__body efr-section__body--no-padding">
|
||||
<div class="efr-table-wrapper">
|
||||
<table mat-table [dataSource]="dataSource" matSort class="efr-table">
|
||||
<ng-container matColumnDef="fromDate">
|
||||
<th
|
||||
mat-header-cell
|
||||
*matHeaderCellDef
|
||||
matTooltip="{{ 'tooltips.Interest effective from date' | translate }}"
|
||||
mat-sort-header
|
||||
>
|
||||
<fa-icon icon="edit" size="lg"></fa-icon>
|
||||
</button>
|
||||
<button type="button" color="warn" mat-icon-button (click)="deleteFloatingRatePeriod(floatingRatePeriod)">
|
||||
<fa-icon icon="trash" size="lg"></fa-icon>
|
||||
</button>
|
||||
</td>
|
||||
</ng-container>
|
||||
{{ 'labels.inputs.From Date' | translate }}
|
||||
</th>
|
||||
<td mat-cell *matCellDef="let floatingRatePeriod">{{ floatingRatePeriod.fromDate | dateFormat }}</td>
|
||||
</ng-container>
|
||||
|
||||
<tr mat-header-row *matHeaderRowDef="displayedColumns"></tr>
|
||||
<tr mat-row *matRowDef="let row; columns: displayedColumns"></tr>
|
||||
</table>
|
||||
<ng-container matColumnDef="interestRate">
|
||||
<th
|
||||
mat-header-cell
|
||||
*matHeaderCellDef
|
||||
matTooltip="{{ 'tooltips.Annualised Interest rate' | translate }}"
|
||||
mat-sort-header
|
||||
>
|
||||
{{ 'labels.inputs.Interest Rate' | translate }}
|
||||
</th>
|
||||
<td mat-cell *matCellDef="let floatingRatePeriod">{{ floatingRatePeriod.interestRate }}</td>
|
||||
</ng-container>
|
||||
|
||||
<ng-container matColumnDef="isDifferential">
|
||||
<th
|
||||
mat-header-cell
|
||||
*matHeaderCellDef
|
||||
matTooltip="{{ 'tooltips.Interest rate mentioned is added to base lending rate' | translate }}"
|
||||
mat-sort-header
|
||||
>
|
||||
{{ 'labels.inputs.Is Differential' | translate }}?
|
||||
</th>
|
||||
<td mat-cell *matCellDef="let floatingRate">
|
||||
@if (floatingRate.isDifferentialToBaseLendingRate) {
|
||||
<fa-icon
|
||||
icon="check-circle"
|
||||
size="lg"
|
||||
class="efr-icon-yes"
|
||||
matTooltip="{{ 'tooltips.Yes' | translate }}"
|
||||
matTooltipPosition="right"
|
||||
></fa-icon>
|
||||
}
|
||||
@if (!floatingRate.isDifferentialToBaseLendingRate) {
|
||||
<fa-icon
|
||||
icon="times-circle"
|
||||
size="lg"
|
||||
class="efr-icon-no"
|
||||
matTooltip="{{ 'tooltips.No' | translate }}"
|
||||
matTooltipPosition="right"
|
||||
></fa-icon>
|
||||
}
|
||||
</td>
|
||||
</ng-container>
|
||||
|
||||
<ng-container matColumnDef="actions">
|
||||
<th mat-header-cell *matHeaderCellDef>{{ 'labels.inputs.Actions' | translate }}</th>
|
||||
<td mat-cell *matCellDef="let floatingRatePeriod">
|
||||
<button
|
||||
type="button"
|
||||
color="primary"
|
||||
mat-icon-button
|
||||
matTooltip="{{ 'tooltips.Edit Period' | translate }}"
|
||||
matTooltipPosition="left"
|
||||
(click)="editFloatingRatePeriod(floatingRatePeriod)"
|
||||
>
|
||||
<fa-icon icon="edit" size="lg"></fa-icon>
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
color="warn"
|
||||
mat-icon-button
|
||||
matTooltip="{{ 'tooltips.Remove Period' | translate }}"
|
||||
matTooltipPosition="right"
|
||||
(click)="deleteFloatingRatePeriod(floatingRatePeriod)"
|
||||
>
|
||||
<fa-icon icon="trash" size="lg"></fa-icon>
|
||||
</button>
|
||||
</td>
|
||||
</ng-container>
|
||||
|
||||
<tr mat-header-row *matHeaderRowDef="displayedColumns"></tr>
|
||||
<tr mat-row *matRowDef="let row; columns: displayedColumns"></tr>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
<mat-paginator [pageSizeOptions]="[10, 25, 50, 100]" showFirstLastButtons></mat-paginator>
|
||||
</mat-card-content>
|
||||
</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
|
||||
type="submit"
|
||||
color="primary"
|
||||
[disabled]="!floatingRateForm.valid || (floatingRateForm.pristine && isFloatingRateFormPristine)"
|
||||
>
|
||||
{{ 'labels.buttons.Submit' | translate }}
|
||||
</button>
|
||||
</mat-card-actions>
|
||||
</form>
|
||||
</mat-card>
|
||||
<!-- Action Bar -->
|
||||
<div class="efr-action-bar">
|
||||
<button type="button" mat-stroked-button [routerLink]="['../']">
|
||||
{{ 'labels.buttons.Cancel' | translate }}
|
||||
</button>
|
||||
<button
|
||||
mat-flat-button
|
||||
type="submit"
|
||||
color="primary"
|
||||
[disabled]="!floatingRateForm.valid || (floatingRateForm.pristine && isFloatingRateFormPristine)"
|
||||
>
|
||||
{{ 'labels.buttons.Submit' | translate }}
|
||||
</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
+166
-12
@@ -6,27 +6,181 @@
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
@media (width >= 992px) {
|
||||
.checkbox-wrapper {
|
||||
position: relative;
|
||||
.efr-container {
|
||||
max-width: 960px;
|
||||
margin: 0 auto;
|
||||
padding: 24px 16px;
|
||||
}
|
||||
|
||||
.checkbox {
|
||||
padding: 0 0 17.5px;
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
.efr-page-header {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 10px;
|
||||
margin-bottom: 24px;
|
||||
|
||||
&__icon {
|
||||
font-size: 20px;
|
||||
color: #1353a0;
|
||||
}
|
||||
|
||||
&__title {
|
||||
font-size: 20px;
|
||||
font-weight: 600;
|
||||
color: #202124;
|
||||
margin: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.efr-section {
|
||||
border: 1px solid #e2e8f0;
|
||||
border-radius: 10px;
|
||||
overflow: hidden;
|
||||
background: #fff;
|
||||
margin-bottom: 20px;
|
||||
|
||||
&__header {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
padding: 12px 24px;
|
||||
background: #f8f9fa;
|
||||
border-bottom: 1px solid #e8eaed;
|
||||
|
||||
i {
|
||||
font-size: 14px;
|
||||
color: #0ea5e9;
|
||||
}
|
||||
|
||||
h3 {
|
||||
font-size: 14px;
|
||||
font-weight: 600;
|
||||
color: #202124;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.efr-add-btn {
|
||||
margin-left: auto;
|
||||
font-size: 12px;
|
||||
height: 32px;
|
||||
padding: 0 14px;
|
||||
border-radius: 6px;
|
||||
|
||||
fa-icon {
|
||||
margin-right: 4px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&__body {
|
||||
padding: 20px 24px;
|
||||
|
||||
&--no-padding {
|
||||
padding: 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: CONFIGURE THESE CLASSES GLOBALLY
|
||||
.is-differential {
|
||||
.efr-field-full {
|
||||
width: 100%;
|
||||
max-width: 480px;
|
||||
}
|
||||
|
||||
.efr-checkbox-row {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 24px;
|
||||
flex-wrap: wrap;
|
||||
margin-top: 4px;
|
||||
}
|
||||
|
||||
.efr-table-wrapper {
|
||||
border-bottom: 1px solid #e2e8f0;
|
||||
overflow: auto;
|
||||
}
|
||||
|
||||
.efr-table {
|
||||
width: 100%;
|
||||
|
||||
::ng-deep {
|
||||
.mat-mdc-header-row {
|
||||
background: #f8fafc;
|
||||
min-height: 38px;
|
||||
height: 38px;
|
||||
}
|
||||
|
||||
.mat-mdc-header-cell {
|
||||
font-size: 11px;
|
||||
font-weight: 600;
|
||||
text-transform: uppercase;
|
||||
letter-spacing: 0.04em;
|
||||
color: #64748b;
|
||||
border-bottom: 1px solid #e2e8f0;
|
||||
padding: 0 14px;
|
||||
}
|
||||
|
||||
.mat-mdc-row {
|
||||
min-height: 40px;
|
||||
height: 40px;
|
||||
border-bottom: 1px solid #f1f5f9;
|
||||
|
||||
&:last-child {
|
||||
border-bottom: none;
|
||||
}
|
||||
}
|
||||
|
||||
.mat-mdc-cell {
|
||||
font-size: 13px;
|
||||
color: #202124;
|
||||
padding: 0 14px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.efr-icon-yes {
|
||||
color: #32cd32;
|
||||
}
|
||||
|
||||
.not-is-differential {
|
||||
.efr-icon-no {
|
||||
color: #f44366;
|
||||
}
|
||||
|
||||
table {
|
||||
width: 100%;
|
||||
.efr-action-bar {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 10px;
|
||||
justify-content: flex-end;
|
||||
padding-top: 8px;
|
||||
}
|
||||
|
||||
@media (max-width: 600px) {
|
||||
.efr-container {
|
||||
padding: 16px 10px;
|
||||
}
|
||||
|
||||
.efr-field-full {
|
||||
max-width: 100%;
|
||||
}
|
||||
|
||||
.efr-checkbox-row {
|
||||
flex-direction: column;
|
||||
align-items: flex-start;
|
||||
gap: 12px;
|
||||
}
|
||||
|
||||
.efr-section__header {
|
||||
padding: 10px 16px;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
|
||||
.efr-section__body {
|
||||
padding: 16px;
|
||||
}
|
||||
|
||||
.efr-action-bar {
|
||||
flex-direction: column;
|
||||
|
||||
button {
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -38,7 +38,6 @@ import { DeleteDialogComponent } from 'app/shared/delete-dialog/delete-dialog.co
|
||||
import { FloatingRatePeriodDialogComponent } from '../floating-rate-period-dialog/floating-rate-period-dialog.component';
|
||||
import { MatTooltip } from '@angular/material/tooltip';
|
||||
import { MatCheckbox } from '@angular/material/checkbox';
|
||||
import { MatDivider } from '@angular/material/divider';
|
||||
import { MatMiniFabButton, MatIconButton, MatButton } from '@angular/material/button';
|
||||
import { FaIconComponent } from '@fortawesome/angular-fontawesome';
|
||||
import { DateFormatPipe } from '../../../pipes/date-format.pipe';
|
||||
@@ -55,7 +54,6 @@ import { STANDALONE_SHARED_IMPORTS } from 'app/standalone-shared.module';
|
||||
...STANDALONE_SHARED_IMPORTS,
|
||||
MatTooltip,
|
||||
MatCheckbox,
|
||||
MatDivider,
|
||||
MatMiniFabButton,
|
||||
FaIconComponent,
|
||||
MatTable,
|
||||
|
||||
+34
-23
@@ -6,12 +6,17 @@
|
||||
file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
-->
|
||||
|
||||
<h1 mat-dialog-title>{{ 'labels.inputs.Floating Rate Periods' | translate }}</h1>
|
||||
<div class="frpd-dialog">
|
||||
<div class="frpd-header">
|
||||
<div class="frpd-header__icon-wrap">
|
||||
<i class="fas fa-calendar-alt"></i>
|
||||
</div>
|
||||
<h2 mat-dialog-title class="frpd-header__title">{{ 'labels.inputs.Floating Rate Periods' | translate }}</h2>
|
||||
</div>
|
||||
|
||||
<mat-dialog-content>
|
||||
<form [formGroup]="floatingRatePeriodForm">
|
||||
<div class="layout-column">
|
||||
<mat-form-field (click)="fromDatePicker.open()">
|
||||
<mat-dialog-content>
|
||||
<form [formGroup]="floatingRatePeriodForm" class="frpd-form">
|
||||
<mat-form-field appearance="outline" class="frpd-field" (click)="fromDatePicker.open()">
|
||||
<mat-label>{{ 'labels.inputs.From Date' | translate }}</mat-label>
|
||||
<input required matInput formControlName="fromDate" [min]="minDate" [matDatepicker]="fromDatePicker" />
|
||||
<mat-datepicker-toggle matSuffix [for]="fromDatePicker"></mat-datepicker-toggle>
|
||||
@@ -24,9 +29,10 @@
|
||||
}
|
||||
</mat-form-field>
|
||||
|
||||
<mat-form-field>
|
||||
<mat-form-field appearance="outline" class="frpd-field">
|
||||
<mat-label>{{ 'labels.inputs.Interest Rate' | translate }}</mat-label>
|
||||
<input matInput type="number" required formControlName="interestRate" min="0" />
|
||||
<span matSuffix class="frpd-suffix">%</span>
|
||||
@if (floatingRatePeriodForm.controls.interestRate.hasError('required')) {
|
||||
<mat-error>
|
||||
{{ 'labels.inputs.Interest Rate' | translate }} {{ 'labels.commons.is' | translate }}
|
||||
@@ -35,21 +41,26 @@
|
||||
}
|
||||
</mat-form-field>
|
||||
|
||||
<mat-checkbox class="is-differential" formControlName="isDifferentialToBaseLendingRate" labelPosition="after">
|
||||
{{ 'labels.inputs.Is Differential' | translate }}?
|
||||
</mat-checkbox>
|
||||
</div>
|
||||
</form>
|
||||
</mat-dialog-content>
|
||||
<div class="frpd-checkbox-row">
|
||||
<mat-checkbox formControlName="isDifferentialToBaseLendingRate" labelPosition="after">
|
||||
{{ 'labels.inputs.Is Differential' | translate }}?
|
||||
</mat-checkbox>
|
||||
</div>
|
||||
</form>
|
||||
</mat-dialog-content>
|
||||
|
||||
<mat-dialog-actions align="end">
|
||||
<button mat-button mat-dialog-close>{{ 'labels.buttons.Cancel' | translate }}</button>
|
||||
<button
|
||||
mat-raised-button
|
||||
color="primary"
|
||||
[disabled]="!floatingRatePeriodForm.valid || floatingRatePeriodForm.pristine"
|
||||
(click)="submit()"
|
||||
>
|
||||
{{ 'labels.buttons.Submit' | translate }}
|
||||
</button>
|
||||
</mat-dialog-actions>
|
||||
<mat-dialog-actions align="end" class="frpd-actions">
|
||||
<button mat-stroked-button mat-dialog-close class="frpd-actions__cancel">
|
||||
{{ 'labels.buttons.Cancel' | translate }}
|
||||
</button>
|
||||
<button
|
||||
mat-flat-button
|
||||
color="primary"
|
||||
class="frpd-actions__submit"
|
||||
[disabled]="!floatingRatePeriodForm.valid || floatingRatePeriodForm.pristine"
|
||||
(click)="submit()"
|
||||
>
|
||||
{{ 'labels.buttons.Submit' | translate }}
|
||||
</button>
|
||||
</mat-dialog-actions>
|
||||
</div>
|
||||
|
||||
+68
@@ -5,3 +5,71 @@
|
||||
* 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/.
|
||||
*/
|
||||
|
||||
.frpd-dialog {
|
||||
min-width: 380px;
|
||||
}
|
||||
|
||||
.frpd-header {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 12px;
|
||||
padding: 20px 24px 12px;
|
||||
|
||||
&__icon-wrap {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
width: 36px;
|
||||
height: 36px;
|
||||
border-radius: 8px;
|
||||
background: #f0f9ff;
|
||||
color: #0ea5e9;
|
||||
font-size: 15px;
|
||||
}
|
||||
|
||||
&__title {
|
||||
margin: 0 !important;
|
||||
padding: 0 !important;
|
||||
font-size: 17px;
|
||||
font-weight: 600;
|
||||
color: #202124;
|
||||
}
|
||||
}
|
||||
|
||||
.frpd-form {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 4px;
|
||||
padding: 8px 0;
|
||||
}
|
||||
|
||||
.frpd-field {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.frpd-suffix {
|
||||
font-size: 13px;
|
||||
font-weight: 500;
|
||||
color: #5f6368;
|
||||
padding-right: 4px;
|
||||
}
|
||||
|
||||
.frpd-checkbox-row {
|
||||
padding: 4px 0 8px;
|
||||
}
|
||||
|
||||
.frpd-actions {
|
||||
padding: 12px 24px 20px !important;
|
||||
gap: 10px;
|
||||
|
||||
&__cancel {
|
||||
border-radius: 8px;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
&__submit {
|
||||
border-radius: 8px;
|
||||
font-weight: 600;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,23 +6,34 @@
|
||||
file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
-->
|
||||
|
||||
<div class="container m-b-20 layout-row align-end gap-20px">
|
||||
<button mat-raised-button color="primary" [routerLink]="['create']" *mifosxHasPermission="'CREATE_FLOATINGRATE'">
|
||||
<fa-icon icon="plus" class="m-r-10"></fa-icon>
|
||||
{{ 'labels.buttons.Create Floating Rate' | translate }}
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<div class="container">
|
||||
<div class="layout-row gap-20px">
|
||||
<mat-form-field class="flex-fill">
|
||||
<mat-label>{{ 'labels.inputs.Filter' | translate }}</mat-label>
|
||||
<input matInput (keyup)="applyFilter($event.target.value)" />
|
||||
</mat-form-field>
|
||||
<div class="table-header">
|
||||
<div class="table-title-group">
|
||||
<h2 class="table-title">
|
||||
<i class="fas fa-percentage title-icon"></i>
|
||||
{{ 'labels.inputs.Floating Rates' | translate }}
|
||||
</h2>
|
||||
<span class="table-count">{{ dataSource?.filteredData?.length || 0 }}</span>
|
||||
</div>
|
||||
|
||||
<div class="table-actions">
|
||||
<mat-form-field appearance="outline" class="table-search">
|
||||
<i matPrefix class="fas fa-search"></i>
|
||||
<mat-label>{{ 'labels.inputs.Filter' | translate }}</mat-label>
|
||||
<input matInput (keyup)="applyFilter($event.target.value)" />
|
||||
</mat-form-field>
|
||||
|
||||
<div class="table-buttons">
|
||||
<button mat-flat-button color="primary" class="btn-create" [routerLink]="['create']" *mifosxHasPermission="'CREATE_FLOATINGRATE'">
|
||||
<fa-icon icon="plus" class="m-r-10"></fa-icon>
|
||||
{{ 'labels.buttons.Create Floating Rate' | translate }}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="mat-elevation-z8">
|
||||
<table mat-table [dataSource]="dataSource" matSort>
|
||||
<div class="table-container">
|
||||
<table mat-table [dataSource]="dataSource" matSort class="modern-table">
|
||||
<ng-container matColumnDef="name">
|
||||
<th mat-header-cell *matHeaderCellDef mat-sort-header>{{ 'labels.inputs.Name' | translate }}</th>
|
||||
<td mat-cell *matCellDef="let floatingRate">{{ floatingRate.name }}</td>
|
||||
@@ -84,7 +95,7 @@
|
||||
</ng-container>
|
||||
|
||||
<tr mat-header-row *matHeaderRowDef="displayedColumns"></tr>
|
||||
<tr mat-row *matRowDef="let row; columns: displayedColumns" class="select-row" [routerLink]="[row.id]"></tr>
|
||||
<tr mat-row *matRowDef="let row; columns: displayedColumns" class="table-row" [routerLink]="[row.id]"></tr>
|
||||
</table>
|
||||
|
||||
<mat-paginator [pageSizeOptions]="[10, 25, 50, 100]" showFirstLastButtons></mat-paginator>
|
||||
|
||||
@@ -6,15 +6,8 @@
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
table {
|
||||
width: 100%;
|
||||
@use '../../shared/styles/list-layout' as *;
|
||||
|
||||
.select-row:hover {
|
||||
cursor: pointer;
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: CONFIGURE THESE CLASSES GLOBALLY
|
||||
.is-base-lending-rate-or-active {
|
||||
color: #32cd32;
|
||||
}
|
||||
|
||||
+46
-43
@@ -6,46 +6,49 @@
|
||||
file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
-->
|
||||
|
||||
<div class="container m-b-20 layout-row align-end gap-20px">
|
||||
<button mat-raised-button color="primary" [routerLink]="['edit']" *mifosxHasPermission="'UPDATE_FLOATINGRATE'">
|
||||
<fa-icon icon="edit" class="m-r-10"></fa-icon>
|
||||
{{ 'labels.buttons.Edit' | translate }}
|
||||
</button>
|
||||
</div>
|
||||
<div class="vfr-container">
|
||||
<div class="vfr-top-bar">
|
||||
<div class="vfr-top-bar__title-group">
|
||||
<i class="fas fa-percentage vfr-top-bar__icon"></i>
|
||||
<h2 class="vfr-top-bar__title">{{ floatingRateData.name }}</h2>
|
||||
</div>
|
||||
<button mat-flat-button color="primary" [routerLink]="['edit']" *mifosxHasPermission="'UPDATE_FLOATINGRATE'">
|
||||
<fa-icon icon="edit" class="m-r-10"></fa-icon>
|
||||
{{ 'labels.buttons.Edit' | translate }}
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<div class="container">
|
||||
<mat-card>
|
||||
<mat-card-content>
|
||||
<div class="layout-row-wrap layout-lt-md-column">
|
||||
<div class="mat-body-strong flex-18">{{ 'labels.inputs.Floating Rate Name' | translate }}:</div>
|
||||
|
||||
<div class="flex-18">
|
||||
{{ floatingRateData.name }}
|
||||
</div>
|
||||
|
||||
<div class="mat-body-strong flex-20">{{ 'labels.inputs.Is Base Lending Rate' | translate }}:</div>
|
||||
|
||||
<div class="flex-10">
|
||||
{{ floatingRateData.isBaseLendingRate | yesNo }}
|
||||
</div>
|
||||
|
||||
<div class="mat-body-strong flex-14">{{ 'labels.inputs.Is Active' | translate }}:</div>
|
||||
|
||||
<div class="flex-10">
|
||||
{{ floatingRateData.isActive | yesNo }}
|
||||
</div>
|
||||
<!-- Rate Details Section -->
|
||||
<div class="vfr-section">
|
||||
<div class="vfr-section__header">
|
||||
<i class="fas fa-info-circle"></i>
|
||||
<h3>{{ 'labels.heading.Rate Details' | translate }}</h3>
|
||||
</div>
|
||||
<div class="vfr-section__body">
|
||||
<div class="vfr-detail-row">
|
||||
<span class="vfr-detail-row__label">{{ 'labels.inputs.Floating Rate Name' | translate }}</span>
|
||||
<span class="vfr-detail-row__value">{{ floatingRateData.name }}</span>
|
||||
</div>
|
||||
<div class="vfr-detail-row">
|
||||
<span class="vfr-detail-row__label">{{ 'labels.inputs.Is Base Lending Rate' | translate }}</span>
|
||||
<span class="vfr-detail-row__value">{{ floatingRateData.isBaseLendingRate | yesNo }}</span>
|
||||
</div>
|
||||
<div class="vfr-detail-row">
|
||||
<span class="vfr-detail-row__label">{{ 'labels.inputs.Is Active' | translate }}</span>
|
||||
<span class="vfr-detail-row__value">{{ floatingRateData.isActive | yesNo }}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<br />
|
||||
|
||||
<mat-divider [inset]="true"></mat-divider>
|
||||
|
||||
<br />
|
||||
|
||||
<p class="mat-title">{{ 'labels.inputs.Floating Rate Periods' | translate }}</p>
|
||||
|
||||
<div class="mat-elevation-z8">
|
||||
<table mat-table [dataSource]="dataSource" matSort>
|
||||
<!-- Floating Rate Periods Section -->
|
||||
<div class="vfr-section">
|
||||
<div class="vfr-section__header">
|
||||
<i class="fas fa-calendar-alt"></i>
|
||||
<h3>{{ 'labels.inputs.Floating Rate Periods' | translate }}</h3>
|
||||
</div>
|
||||
<div class="vfr-section__body vfr-section__body--no-padding">
|
||||
<div class="vfr-table-wrapper">
|
||||
<table mat-table [dataSource]="dataSource" matSort class="vfr-table">
|
||||
<ng-container matColumnDef="fromDate">
|
||||
<th mat-header-cell *matHeaderCellDef mat-sort-header>{{ 'labels.inputs.From Date' | translate }}</th>
|
||||
<td mat-cell *matCellDef="let floatingRate">{{ floatingRate.fromDate | dateFormat }}</td>
|
||||
@@ -65,7 +68,7 @@
|
||||
<fa-icon
|
||||
icon="check-circle"
|
||||
size="lg"
|
||||
class="is-differential"
|
||||
class="vfr-icon-yes"
|
||||
matTooltip="{{ 'tooltips.Yes' | translate }}"
|
||||
matTooltipPosition="right"
|
||||
></fa-icon>
|
||||
@@ -74,7 +77,7 @@
|
||||
<fa-icon
|
||||
icon="times-circle"
|
||||
size="lg"
|
||||
class="not-is-differential"
|
||||
class="vfr-icon-no"
|
||||
matTooltip="{{ 'tooltips.No' | translate }}"
|
||||
matTooltipPosition="right"
|
||||
></fa-icon>
|
||||
@@ -85,9 +88,9 @@
|
||||
<tr mat-header-row *matHeaderRowDef="displayedColumns"></tr>
|
||||
<tr mat-row *matRowDef="let row; columns: displayedColumns"></tr>
|
||||
</table>
|
||||
|
||||
<mat-paginator [pageSizeOptions]="[10, 25, 50, 100]" showFirstLastButtons></mat-paginator>
|
||||
</div>
|
||||
</mat-card-content>
|
||||
</mat-card>
|
||||
|
||||
<mat-paginator [pageSizeOptions]="[10, 25, 50, 100]" showFirstLastButtons></mat-paginator>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
+160
-9
@@ -6,22 +6,173 @@
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
table {
|
||||
width: 100%;
|
||||
.vfr-container {
|
||||
max-width: 960px;
|
||||
margin: 0 auto;
|
||||
padding: 24px 16px;
|
||||
}
|
||||
|
||||
// TODO: CONFIGURE THESE CLASSES GLOBALLY
|
||||
.is-differential {
|
||||
.vfr-top-bar {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
margin-bottom: 24px;
|
||||
flex-wrap: wrap;
|
||||
gap: 12px;
|
||||
|
||||
&__title-group {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 10px;
|
||||
}
|
||||
|
||||
&__icon {
|
||||
font-size: 20px;
|
||||
color: #1353a0;
|
||||
}
|
||||
|
||||
&__title {
|
||||
font-size: 20px;
|
||||
font-weight: 600;
|
||||
color: #202124;
|
||||
margin: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.vfr-section {
|
||||
border: 1px solid #e2e8f0;
|
||||
border-radius: 10px;
|
||||
overflow: hidden;
|
||||
background: #fff;
|
||||
margin-bottom: 20px;
|
||||
|
||||
&__header {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
padding: 12px 24px;
|
||||
background: #f8f9fa;
|
||||
border-bottom: 1px solid #e8eaed;
|
||||
|
||||
i {
|
||||
font-size: 14px;
|
||||
color: #0ea5e9;
|
||||
}
|
||||
|
||||
h3 {
|
||||
font-size: 14px;
|
||||
font-weight: 600;
|
||||
color: #202124;
|
||||
margin: 0;
|
||||
}
|
||||
}
|
||||
|
||||
&__body {
|
||||
padding: 16px 24px;
|
||||
|
||||
&--no-padding {
|
||||
padding: 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.vfr-detail-row {
|
||||
display: flex;
|
||||
padding: 6px 0;
|
||||
border-bottom: 1px solid #f1f3f4;
|
||||
|
||||
&:last-child {
|
||||
border-bottom: none;
|
||||
}
|
||||
|
||||
&__label {
|
||||
flex: 0 0 40%;
|
||||
font-size: 13px;
|
||||
font-weight: 500;
|
||||
color: #5f6368;
|
||||
}
|
||||
|
||||
&__value {
|
||||
flex: 1;
|
||||
font-size: 13px;
|
||||
color: #202124;
|
||||
}
|
||||
}
|
||||
|
||||
.vfr-table-wrapper {
|
||||
border-bottom: 1px solid #e2e8f0;
|
||||
overflow: auto;
|
||||
}
|
||||
|
||||
.vfr-table {
|
||||
width: 100%;
|
||||
|
||||
::ng-deep {
|
||||
.mat-mdc-header-row {
|
||||
background: #f8fafc;
|
||||
min-height: 38px;
|
||||
height: 38px;
|
||||
}
|
||||
|
||||
.mat-mdc-header-cell {
|
||||
font-size: 11px;
|
||||
font-weight: 600;
|
||||
text-transform: uppercase;
|
||||
letter-spacing: 0.04em;
|
||||
color: #64748b;
|
||||
border-bottom: 1px solid #e2e8f0;
|
||||
padding: 0 14px;
|
||||
}
|
||||
|
||||
.mat-mdc-row {
|
||||
min-height: 40px;
|
||||
height: 40px;
|
||||
border-bottom: 1px solid #f1f5f9;
|
||||
|
||||
&:last-child {
|
||||
border-bottom: none;
|
||||
}
|
||||
}
|
||||
|
||||
.mat-mdc-cell {
|
||||
font-size: 13px;
|
||||
color: #202124;
|
||||
padding: 0 14px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.vfr-icon-yes {
|
||||
color: #32cd32;
|
||||
}
|
||||
|
||||
.not-is-differential {
|
||||
.vfr-icon-no {
|
||||
color: #f44366;
|
||||
}
|
||||
|
||||
.content {
|
||||
div {
|
||||
margin: 1rem 0;
|
||||
word-wrap: break-word;
|
||||
.m-r-10 {
|
||||
margin-right: 10px;
|
||||
}
|
||||
|
||||
@media (max-width: 600px) {
|
||||
.vfr-container {
|
||||
padding: 16px 10px;
|
||||
}
|
||||
|
||||
.vfr-detail-row {
|
||||
flex-direction: column;
|
||||
gap: 2px;
|
||||
|
||||
&__label {
|
||||
flex: none;
|
||||
}
|
||||
}
|
||||
|
||||
.vfr-section__header {
|
||||
padding: 10px 16px;
|
||||
}
|
||||
|
||||
.vfr-section__body {
|
||||
padding: 12px 16px;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -25,7 +25,6 @@ import {
|
||||
MatRow
|
||||
} from '@angular/material/table';
|
||||
import { FaIconComponent } from '@fortawesome/angular-fontawesome';
|
||||
import { MatDivider } from '@angular/material/divider';
|
||||
import { DecimalPipe } from '@angular/common';
|
||||
import { MatTooltip } from '@angular/material/tooltip';
|
||||
import { DateFormatPipe } from '../../../pipes/date-format.pipe';
|
||||
@@ -42,7 +41,6 @@ import { STANDALONE_SHARED_IMPORTS } from 'app/standalone-shared.module';
|
||||
imports: [
|
||||
...STANDALONE_SHARED_IMPORTS,
|
||||
FaIconComponent,
|
||||
MatDivider,
|
||||
MatTable,
|
||||
MatSort,
|
||||
MatColumnDef,
|
||||
|
||||
+168
-131
@@ -6,149 +6,186 @@
|
||||
file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
-->
|
||||
|
||||
<div class="container">
|
||||
<mat-stepper
|
||||
orientation="vertical"
|
||||
[linear]="false"
|
||||
class="mat-elevation-z8"
|
||||
labelPosition="bottom"
|
||||
#loanProductStepper
|
||||
>
|
||||
<ng-template matStepperIcon="number">
|
||||
<fa-icon icon="pencil-alt" size="sm"></fa-icon>
|
||||
</ng-template>
|
||||
<div class="lp-container">
|
||||
<div class="lp-header">
|
||||
<i class="fas fa-hand-holding-usd lp-header__icon"></i>
|
||||
<h2 class="lp-header__title">{{ 'labels.heading.Create Loan Product' | translate }}</h2>
|
||||
</div>
|
||||
|
||||
<ng-template matStepperIcon="edit">
|
||||
<fa-icon icon="pencil-alt" size="sm"></fa-icon>
|
||||
</ng-template>
|
||||
|
||||
<ng-template matStepperIcon="done">
|
||||
<fa-icon icon="check" size="sm"></fa-icon>
|
||||
</ng-template>
|
||||
|
||||
<ng-template matStepperIcon="error">
|
||||
<fa-icon icon="exclamation-triangle" size="lg"></fa-icon>
|
||||
</ng-template>
|
||||
|
||||
<ng-template matStepperIcon="preview">
|
||||
<fa-icon icon="eye" size="sm"></fa-icon>
|
||||
</ng-template>
|
||||
|
||||
<mat-step [stepControl]="loanProductDetailsForm">
|
||||
<ng-template matStepLabel>{{ 'labels.inputs.DETAILS' | translate }}</ng-template>
|
||||
|
||||
<mifosx-loan-product-details-step
|
||||
[loanProductsTemplate]="loanProductsTemplate"
|
||||
></mifosx-loan-product-details-step>
|
||||
</mat-step>
|
||||
|
||||
<mat-step [stepControl]="loanProductCurrencyForm">
|
||||
<ng-template matStepLabel>{{ 'labels.inputs.CURRENCY' | translate }}</ng-template>
|
||||
|
||||
<mifosx-loan-product-currency-step
|
||||
[loanProductsTemplate]="loanProductsTemplate"
|
||||
></mifosx-loan-product-currency-step>
|
||||
</mat-step>
|
||||
|
||||
<mat-step [stepControl]="loanProductSettingsForm">
|
||||
<ng-template matStepLabel>{{ 'labels.inputs.SETTINGS' | translate }}</ng-template>
|
||||
|
||||
<mifosx-loan-product-settings-step
|
||||
[loanProductsTemplate]="loanProductsTemplate"
|
||||
[isLinkedToFloatingInterestRates]="loanProductTermsForm.get('isLinkedToFloatingInterestRates')"
|
||||
(advancePaymentStrategy)="advancePaymentStrategy($event)"
|
||||
>
|
||||
</mifosx-loan-product-settings-step>
|
||||
</mat-step>
|
||||
|
||||
@if (isAdvancedPaymentStrategy) {
|
||||
<mat-step [stepControl]="loanProductInterestRefundForm">
|
||||
<ng-template matStepLabel>{{ 'labels.inputs.INTEREST REFUND' | translate }}</ng-template>
|
||||
<mifosx-loan-product-interest-refund-step
|
||||
<mat-tab-group class="lp-tabs" animationDuration="200ms" [preserveContent]="true" [(selectedIndex)]="selectedTabIndex">
|
||||
<mat-tab>
|
||||
<ng-template mat-tab-label>
|
||||
<i class="fas fa-info-circle lp-tab-icon"></i>
|
||||
{{ 'labels.inputs.DETAILS' | translate }}
|
||||
</ng-template>
|
||||
<div class="lp-tab-content">
|
||||
<mifosx-loan-product-details-step
|
||||
[loanProductsTemplate]="loanProductsTemplate"
|
||||
(supportedInterestRefundTypes)="setSupportedInterestRefundTypes($event)"
|
||||
>
|
||||
</mifosx-loan-product-interest-refund-step>
|
||||
<mifosx-stepper-buttons></mifosx-stepper-buttons>
|
||||
</mat-step>
|
||||
}
|
||||
></mifosx-loan-product-details-step>
|
||||
</div>
|
||||
</mat-tab>
|
||||
|
||||
<mat-tab>
|
||||
<ng-template mat-tab-label>
|
||||
<i class="fas fa-coins lp-tab-icon"></i>
|
||||
{{ 'labels.inputs.CURRENCY' | translate }}
|
||||
</ng-template>
|
||||
<div class="lp-tab-content">
|
||||
<mifosx-loan-product-currency-step
|
||||
[loanProductsTemplate]="loanProductsTemplate"
|
||||
></mifosx-loan-product-currency-step>
|
||||
</div>
|
||||
</mat-tab>
|
||||
|
||||
<mat-tab>
|
||||
<ng-template mat-tab-label>
|
||||
<i class="fas fa-cog lp-tab-icon"></i>
|
||||
{{ 'labels.inputs.SETTINGS' | translate }}
|
||||
</ng-template>
|
||||
<div class="lp-tab-content">
|
||||
<mifosx-loan-product-settings-step
|
||||
[loanProductsTemplate]="loanProductsTemplate"
|
||||
[isLinkedToFloatingInterestRates]="loanProductTermsForm.get('isLinkedToFloatingInterestRates')"
|
||||
(advancePaymentStrategy)="advancePaymentStrategy($event)"
|
||||
></mifosx-loan-product-settings-step>
|
||||
</div>
|
||||
</mat-tab>
|
||||
|
||||
@if (isAdvancedPaymentStrategy) {
|
||||
<mat-step>
|
||||
<ng-template matStepLabel>{{ 'labels.inputs.PAYMENT ALLOCATION' | translate }}</ng-template>
|
||||
<mifosx-loan-product-payment-strategy-step
|
||||
[advancedPaymentAllocations]="advancedPaymentAllocations"
|
||||
[advancedCreditAllocations]="advancedCreditAllocations"
|
||||
[advancedPaymentAllocationTransactionTypes]="loanProductsTemplate.advancedPaymentAllocationTransactionTypes"
|
||||
[paymentAllocationOrderDefault]="loanProductsTemplate.advancedPaymentAllocationTypes"
|
||||
[advancedCreditAllocationTransactionTypes]="loanProductsTemplate.creditAllocationTransactionTypes"
|
||||
[creditAllocationOrderDefault]="loanProductsTemplate.creditAllocationAllocationTypes"
|
||||
(setPaymentAllocation)="setPaymentAllocation($event)"
|
||||
(setCreditAllocation)="setCreditAllocation($event)"
|
||||
>
|
||||
</mifosx-loan-product-payment-strategy-step>
|
||||
<mifosx-stepper-buttons></mifosx-stepper-buttons>
|
||||
</mat-step>
|
||||
<mat-tab>
|
||||
<ng-template mat-tab-label>
|
||||
<i class="fas fa-undo lp-tab-icon"></i>
|
||||
{{ 'labels.inputs.INTEREST REFUND' | translate }}
|
||||
</ng-template>
|
||||
<div class="lp-tab-content">
|
||||
<mifosx-loan-product-interest-refund-step
|
||||
[loanProductsTemplate]="loanProductsTemplate"
|
||||
(supportedInterestRefundTypes)="setSupportedInterestRefundTypes($event)"
|
||||
></mifosx-loan-product-interest-refund-step>
|
||||
</div>
|
||||
</mat-tab>
|
||||
|
||||
<mat-tab>
|
||||
<ng-template mat-tab-label>
|
||||
<i class="fas fa-exchange-alt lp-tab-icon"></i>
|
||||
{{ 'labels.inputs.PAYMENT ALLOCATION' | translate }}
|
||||
</ng-template>
|
||||
<div class="lp-tab-content">
|
||||
<mifosx-loan-product-payment-strategy-step
|
||||
[advancedPaymentAllocations]="advancedPaymentAllocations"
|
||||
[advancedCreditAllocations]="advancedCreditAllocations"
|
||||
[advancedPaymentAllocationTransactionTypes]="loanProductsTemplate.advancedPaymentAllocationTransactionTypes"
|
||||
[paymentAllocationOrderDefault]="loanProductsTemplate.advancedPaymentAllocationTypes"
|
||||
[advancedCreditAllocationTransactionTypes]="loanProductsTemplate.creditAllocationTransactionTypes"
|
||||
[creditAllocationOrderDefault]="loanProductsTemplate.creditAllocationAllocationTypes"
|
||||
(setPaymentAllocation)="setPaymentAllocation($event)"
|
||||
(setCreditAllocation)="setCreditAllocation($event)"
|
||||
></mifosx-loan-product-payment-strategy-step>
|
||||
</div>
|
||||
</mat-tab>
|
||||
}
|
||||
|
||||
<mat-step [stepControl]="loanProductTermsForm">
|
||||
<ng-template matStepLabel>{{ 'labels.inputs.TERMS' | translate }}</ng-template>
|
||||
<mat-tab>
|
||||
<ng-template mat-tab-label>
|
||||
<i class="fas fa-sliders-h lp-tab-icon"></i>
|
||||
{{ 'labels.inputs.TERMS' | translate }}
|
||||
</ng-template>
|
||||
<div class="lp-tab-content">
|
||||
<mifosx-loan-product-terms-step [loanProductsTemplate]="loanProductsTemplate"></mifosx-loan-product-terms-step>
|
||||
</div>
|
||||
</mat-tab>
|
||||
|
||||
<mifosx-loan-product-terms-step [loanProductsTemplate]="loanProductsTemplate"></mifosx-loan-product-terms-step>
|
||||
</mat-step>
|
||||
|
||||
<mat-step>
|
||||
<ng-template matStepLabel>{{ 'labels.inputs.CHARGES' | translate }}</ng-template>
|
||||
|
||||
<mifosx-loan-product-charges-step
|
||||
[loanProductsTemplate]="loanProductsTemplate"
|
||||
[currencyCode]="loanProductCurrencyForm.get('currencyCode')"
|
||||
[multiDisburseLoan]="loanProductSettingsForm.get('multiDisburseLoan')"
|
||||
>
|
||||
</mifosx-loan-product-charges-step>
|
||||
</mat-step>
|
||||
<mat-tab>
|
||||
<ng-template mat-tab-label>
|
||||
<i class="fas fa-receipt lp-tab-icon"></i>
|
||||
{{ 'labels.inputs.CHARGES' | translate }}
|
||||
</ng-template>
|
||||
<div class="lp-tab-content">
|
||||
<mifosx-loan-product-charges-step
|
||||
[loanProductsTemplate]="loanProductsTemplate"
|
||||
[currencyCode]="loanProductCurrencyForm.get('currencyCode')"
|
||||
[multiDisburseLoan]="loanProductSettingsForm.get('multiDisburseLoan')"
|
||||
></mifosx-loan-product-charges-step>
|
||||
</div>
|
||||
</mat-tab>
|
||||
|
||||
@if (isAdvancedPaymentStrategy) {
|
||||
<mat-step [stepControl]="loanIncomeCapitalizationForm">
|
||||
<ng-template matStepLabel>{{ 'labels.inputs.DEFERRED INCOME RECOGNITION' | translate }}</ng-template>
|
||||
<mifosx-loan-product-capitalized-income-step
|
||||
[deferredIncomeRecognition]="deferredIncomeRecognition"
|
||||
[capitalizedIncomeCalculationTypeOptions]="loanProductsTemplate.capitalizedIncomeCalculationTypeOptions"
|
||||
[capitalizedIncomeStrategyOptions]="loanProductsTemplate.capitalizedIncomeStrategyOptions"
|
||||
[capitalizedIncomeTypeOptions]="loanProductsTemplate.capitalizedIncomeTypeOptions"
|
||||
[buyDownFeeCalculationTypeOptions]="loanProductsTemplate.buyDownFeeCalculationTypeOptions"
|
||||
[buyDownFeeStrategyOptions]="loanProductsTemplate.buyDownFeeStrategyOptions"
|
||||
[buyDownFeeIncomeTypeOptions]="loanProductsTemplate.buyDownFeeIncomeTypeOptions"
|
||||
(setViewChildForm)="setViewChildForm($event)"
|
||||
>
|
||||
</mifosx-loan-product-capitalized-income-step>
|
||||
<mifosx-stepper-buttons></mifosx-stepper-buttons>
|
||||
</mat-step>
|
||||
<mat-tab>
|
||||
<ng-template mat-tab-label>
|
||||
<i class="fas fa-clock lp-tab-icon"></i>
|
||||
{{ 'labels.inputs.DEFERRED INCOME RECOGNITION' | translate }}
|
||||
</ng-template>
|
||||
<div class="lp-tab-content">
|
||||
<mifosx-loan-product-capitalized-income-step
|
||||
[deferredIncomeRecognition]="deferredIncomeRecognition"
|
||||
[capitalizedIncomeCalculationTypeOptions]="loanProductsTemplate.capitalizedIncomeCalculationTypeOptions"
|
||||
[capitalizedIncomeStrategyOptions]="loanProductsTemplate.capitalizedIncomeStrategyOptions"
|
||||
[capitalizedIncomeTypeOptions]="loanProductsTemplate.capitalizedIncomeTypeOptions"
|
||||
[buyDownFeeCalculationTypeOptions]="loanProductsTemplate.buyDownFeeCalculationTypeOptions"
|
||||
[buyDownFeeStrategyOptions]="loanProductsTemplate.buyDownFeeStrategyOptions"
|
||||
[buyDownFeeIncomeTypeOptions]="loanProductsTemplate.buyDownFeeIncomeTypeOptions"
|
||||
(setViewChildForm)="setViewChildForm($event)"
|
||||
></mifosx-loan-product-capitalized-income-step>
|
||||
</div>
|
||||
</mat-tab>
|
||||
}
|
||||
|
||||
<mat-step [stepControl]="loanProductAccountingForm">
|
||||
<ng-template matStepLabel>{{ 'labels.inputs.ACCOUNTING' | translate }}</ng-template>
|
||||
|
||||
<mifosx-loan-product-accounting-step
|
||||
[loanProductsTemplate]="loanProductsTemplate"
|
||||
[accountingRuleData]="accountingRuleData"
|
||||
[loanProductFormValid]="loanProductFormValid"
|
||||
[deferredIncomeRecognition]="deferredIncomeRecognition"
|
||||
>
|
||||
</mifosx-loan-product-accounting-step>
|
||||
</mat-step>
|
||||
|
||||
@if (loanProductFormValid) {
|
||||
<mat-step state="preview" completed>
|
||||
<ng-template matStepLabel>{{ 'labels.inputs.PREVIEW' | translate }}</ng-template>
|
||||
<mifosx-loan-product-preview-step
|
||||
<mat-tab>
|
||||
<ng-template mat-tab-label>
|
||||
<i class="fas fa-book lp-tab-icon"></i>
|
||||
{{ 'labels.inputs.ACCOUNTING' | translate }}
|
||||
</ng-template>
|
||||
<div class="lp-tab-content">
|
||||
<mifosx-loan-product-accounting-step
|
||||
[loanProductsTemplate]="loanProductsTemplate"
|
||||
[accountingRuleData]="accountingRuleData"
|
||||
[loanProduct]="loanProduct"
|
||||
(submitEvent)="submit()"
|
||||
>
|
||||
</mifosx-loan-product-preview-step>
|
||||
</mat-step>
|
||||
[loanProductFormValid]="loanProductFormValid"
|
||||
[deferredIncomeRecognition]="deferredIncomeRecognition"
|
||||
></mifosx-loan-product-accounting-step>
|
||||
</div>
|
||||
</mat-tab>
|
||||
|
||||
@if (loanProductFormValid) {
|
||||
<mat-tab>
|
||||
<ng-template mat-tab-label>
|
||||
<i class="fas fa-eye lp-tab-icon"></i>
|
||||
{{ 'labels.inputs.PREVIEW' | translate }}
|
||||
</ng-template>
|
||||
<div class="lp-tab-content">
|
||||
<mifosx-loan-product-preview-step
|
||||
[loanProductsTemplate]="loanProductsTemplate"
|
||||
[accountingRuleData]="accountingRuleData"
|
||||
[loanProduct]="loanProduct"
|
||||
(submitEvent)="submit()"
|
||||
></mifosx-loan-product-preview-step>
|
||||
</div>
|
||||
</mat-tab>
|
||||
}
|
||||
</mat-stepper>
|
||||
</mat-tab-group>
|
||||
|
||||
<div class="lp-action-bar">
|
||||
<button mat-raised-button [routerLink]="['../']" class="lp-action-bar__cancel">
|
||||
{{ 'labels.buttons.Cancel' | translate }}
|
||||
</button>
|
||||
<div class="lp-action-bar__right">
|
||||
@if (selectedTabIndex > 0) {
|
||||
<button mat-raised-button (click)="selectedTabIndex = selectedTabIndex - 1">
|
||||
<i class="fas fa-arrow-left" style="margin-right: 8px;"></i>
|
||||
{{ 'labels.buttons.Previous' | translate }}
|
||||
</button>
|
||||
}
|
||||
@if (selectedTabIndex < totalTabs - 1) {
|
||||
<button mat-raised-button color="primary" (click)="selectedTabIndex = selectedTabIndex + 1">
|
||||
{{ 'labels.buttons.Next' | translate }}
|
||||
<i class="fas fa-arrow-right" style="margin-left: 8px;"></i>
|
||||
</button>
|
||||
}
|
||||
@if (loanProductFormValid && selectedTabIndex === totalTabs - 1) {
|
||||
<button mat-raised-button color="primary" (click)="submit()">
|
||||
<i class="fas fa-check" style="margin-right: 8px;"></i>
|
||||
{{ 'labels.buttons.Submit' | translate }}
|
||||
</button>
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
+79
-7
@@ -6,13 +6,85 @@
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
.container {
|
||||
max-width: 86rem;
|
||||
width: 96%;
|
||||
padding-bottom: 30px;
|
||||
$primary: #1353a0;
|
||||
|
||||
.lp-container {
|
||||
max-width: 960px;
|
||||
margin: 0 auto;
|
||||
padding: 24px 16px;
|
||||
}
|
||||
|
||||
fa-icon {
|
||||
position: relative;
|
||||
left: 5%;
|
||||
.lp-header {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 10px;
|
||||
margin-bottom: 20px;
|
||||
|
||||
&__icon {
|
||||
font-size: 20px;
|
||||
color: $primary;
|
||||
}
|
||||
|
||||
&__title {
|
||||
margin: 0;
|
||||
font-size: 22px;
|
||||
font-weight: 500;
|
||||
}
|
||||
}
|
||||
|
||||
.lp-tabs {
|
||||
background: var(--md-sys-color-surface, #fff);
|
||||
border-radius: 8px;
|
||||
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.08);
|
||||
|
||||
::ng-deep {
|
||||
.mat-mdc-tab-header {
|
||||
border-bottom: 1px solid rgba(0, 0, 0, 0.08);
|
||||
}
|
||||
|
||||
.mat-mdc-tab {
|
||||
min-width: 100px;
|
||||
padding: 0 12px;
|
||||
height: 52px;
|
||||
}
|
||||
|
||||
.mat-mdc-tab-body-wrapper {
|
||||
min-height: 200px;
|
||||
}
|
||||
|
||||
.mat-mdc-tab-body {
|
||||
overflow: visible !important;
|
||||
}
|
||||
|
||||
.mat-mdc-tab-body-content {
|
||||
overflow: visible !important;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.lp-tab-icon {
|
||||
margin-right: 8px;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.lp-tab-content {
|
||||
padding: 24px 16px;
|
||||
}
|
||||
|
||||
.lp-action-bar {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
margin-top: 20px;
|
||||
padding: 16px 0;
|
||||
border-top: 1px solid rgba(0, 0, 0, 0.08);
|
||||
|
||||
&__cancel {
|
||||
color: rgba(0, 0, 0, 0.6);
|
||||
}
|
||||
|
||||
&__right {
|
||||
display: flex;
|
||||
gap: 12px;
|
||||
}
|
||||
}
|
||||
|
||||
+10
-7
@@ -34,11 +34,10 @@ import { Accounting } from 'app/core/utils/accounting';
|
||||
import { StringEnumOptionData } from '../../../shared/models/option-data.model';
|
||||
import { LoanProductDeferredIncomeRecognitionStepComponent } from '../loan-product-stepper/loan-product-capitalized-income-step/loan-product-deferred-income-recognition-step.component';
|
||||
import { UntypedFormGroup } from '@angular/forms';
|
||||
import { MatStepper, MatStepperIcon, MatStep, MatStepLabel } from '@angular/material/stepper';
|
||||
import { FaIconComponent } from '@fortawesome/angular-fontawesome';
|
||||
import { LoanProductPaymentStrategyStepComponent } from '../loan-product-stepper/loan-product-payment-strategy-step/loan-product-payment-strategy-step.component';
|
||||
import { StepperButtonsComponent } from '../../../shared/steppers/stepper-buttons/stepper-buttons.component';
|
||||
import { LoanProductPreviewStepComponent } from '../loan-product-stepper/loan-product-preview-step/loan-product-preview-step.component';
|
||||
import { MatTabsModule } from '@angular/material/tabs';
|
||||
import { STANDALONE_SHARED_IMPORTS } from 'app/standalone-shared.module';
|
||||
|
||||
@Component({
|
||||
@@ -47,17 +46,13 @@ import { STANDALONE_SHARED_IMPORTS } from 'app/standalone-shared.module';
|
||||
styleUrls: ['./create-loan-product.component.scss'],
|
||||
imports: [
|
||||
...STANDALONE_SHARED_IMPORTS,
|
||||
MatStepper,
|
||||
MatStepperIcon,
|
||||
MatTabsModule,
|
||||
FaIconComponent,
|
||||
MatStep,
|
||||
MatStepLabel,
|
||||
LoanProductDetailsStepComponent,
|
||||
LoanProductCurrencyStepComponent,
|
||||
LoanProductSettingsStepComponent,
|
||||
LoanProductInterestRefundStepComponent,
|
||||
LoanProductPaymentStrategyStepComponent,
|
||||
StepperButtonsComponent,
|
||||
LoanProductTermsStepComponent,
|
||||
LoanProductChargesStepComponent,
|
||||
LoanProductDeferredIncomeRecognitionStepComponent,
|
||||
@@ -90,6 +85,7 @@ export class CreateLoanProductComponent implements OnInit {
|
||||
loanProductsTemplate: any;
|
||||
accountingRuleData: string[] = [];
|
||||
itemsByDefault: any[] = [];
|
||||
selectedTabIndex = 0;
|
||||
|
||||
isAdvancedPaymentStrategy = false;
|
||||
paymentAllocation: PaymentAllocation[] = [];
|
||||
@@ -240,6 +236,13 @@ export class CreateLoanProductComponent implements OnInit {
|
||||
return this.loanProductAccountingStep.loanProductAccountingForm;
|
||||
}
|
||||
|
||||
get totalTabs(): number {
|
||||
let tabs = 6; // details, currency, settings, terms, charges, accounting
|
||||
if (this.isAdvancedPaymentStrategy) tabs += 3; // interest refund, payment allocation, deferred income
|
||||
if (this.loanProductFormValid) tabs += 1; // preview
|
||||
return tabs;
|
||||
}
|
||||
|
||||
get loanProductFormValid() {
|
||||
if (this.isAdvancedPaymentStrategy) {
|
||||
return (
|
||||
|
||||
+235
-191
@@ -7,41 +7,63 @@
|
||||
-->
|
||||
|
||||
<form [formGroup]="loanProductAccountingForm">
|
||||
<div class="layout-row-wrap gap-2px responsive-column">
|
||||
<mat-radio-group
|
||||
class="flex-98 layout-row gap-5percent layout-lt-md-column radio-group-spacing"
|
||||
formControlName="accountingRule"
|
||||
>
|
||||
@for (accountingRule of accountingRuleData; track accountingRule; let i = $index) {
|
||||
<mat-radio-button [value]="i + 1">
|
||||
{{ 'labels.accounting.' + accountingRule | translate }}
|
||||
</mat-radio-button>
|
||||
}
|
||||
</mat-radio-group>
|
||||
|
||||
<mat-divider class="flex-98"></mat-divider>
|
||||
|
||||
@if (loanProductAccountingForm.value.accountingRule >= 2 && loanProductAccountingForm.value.accountingRule <= 4) {
|
||||
<div class="flex-100 layout-row-wrap responsive-column">
|
||||
@if (isAccountingAccrualBased) {
|
||||
<mat-checkbox class="flex-73" formControlName="enableAccrualActivityPosting">{{
|
||||
<!-- Accounting Rule Section -->
|
||||
<div class="lpa-section">
|
||||
<div class="lpa-section-header">
|
||||
<i class="fas fa-book lpa-section-icon"></i>
|
||||
<h3>{{ 'labels.heading.Accounting Rule' | translate }}</h3>
|
||||
</div>
|
||||
<div class="lpa-section-body">
|
||||
<div class="lpa-full-width">
|
||||
<mat-radio-group
|
||||
class="lpa-radio-group"
|
||||
formControlName="accountingRule"
|
||||
>
|
||||
@for (accountingRule of accountingRuleData; track accountingRule; let i = $index) {
|
||||
<mat-radio-button [value]="i + 1">
|
||||
{{ 'labels.accounting.' + accountingRule | translate }}
|
||||
</mat-radio-button>
|
||||
}
|
||||
</mat-radio-group>
|
||||
</div>
|
||||
@if (isAccountingAccrualBased) {
|
||||
<div class="lpa-full-width lpa-checkbox-row">
|
||||
<mat-checkbox formControlName="enableAccrualActivityPosting">{{
|
||||
'labels.inputs.Enable Accrual Activity Posting on Installment Due Date' | translate
|
||||
}}</mat-checkbox>
|
||||
}
|
||||
<h4 class="mat-h4 flex-98">
|
||||
{{ 'labels.heading.Assets' | translate }} / {{ 'labels.heading.Liabilities' | translate }}
|
||||
</h4>
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@if (loanProductAccountingForm.value.accountingRule >= 2 && loanProductAccountingForm.value.accountingRule <= 4) {
|
||||
|
||||
<!-- Assets / Liabilities Section -->
|
||||
<div class="lpa-section">
|
||||
<div class="lpa-section-header">
|
||||
<i class="fas fa-university lpa-section-icon"></i>
|
||||
<h3>{{ 'labels.heading.Assets' | translate }} / {{ 'labels.heading.Liabilities' | translate }}</h3>
|
||||
</div>
|
||||
<div class="lpa-section-body lpa-grid">
|
||||
<mifosx-gl-account-selector
|
||||
class="flex-48"
|
||||
[inputFormControl]="loanProductAccountingForm.controls.fundSourceAccountId"
|
||||
[glAccountList]="assetAndLiabilityAccountData"
|
||||
[required]="true"
|
||||
[inputLabel]="'Fund source'"
|
||||
>
|
||||
</mifosx-gl-account-selector>
|
||||
<h4 class="mat-h4 flex-98">{{ 'labels.heading.Assets' | translate }}</h4>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Assets Section -->
|
||||
<div class="lpa-section">
|
||||
<div class="lpa-section-header">
|
||||
<i class="fas fa-university lpa-section-icon"></i>
|
||||
<h3>{{ 'labels.heading.Assets' | translate }}</h3>
|
||||
</div>
|
||||
<div class="lpa-section-body lpa-grid">
|
||||
<mifosx-gl-account-selector
|
||||
class="flex-48"
|
||||
[inputFormControl]="loanProductAccountingForm.controls.loanPortfolioAccountId"
|
||||
[glAccountList]="assetAccountData"
|
||||
[required]="true"
|
||||
@@ -49,7 +71,6 @@
|
||||
>
|
||||
</mifosx-gl-account-selector>
|
||||
<mifosx-gl-account-selector
|
||||
class="flex-48"
|
||||
[inputFormControl]="loanProductAccountingForm.controls.transfersInSuspenseAccountId"
|
||||
[glAccountList]="assetAccountData"
|
||||
[required]="true"
|
||||
@@ -59,37 +80,39 @@
|
||||
@if (
|
||||
loanProductAccountingForm.value.accountingRule === 3 || loanProductAccountingForm.value.accountingRule === 4
|
||||
) {
|
||||
<div class="flex-100 layout-row-wrap responsive-column">
|
||||
<mifosx-gl-account-selector
|
||||
class="flex-48"
|
||||
[inputFormControl]="loanProductAccountingForm.controls.receivableInterestAccountId"
|
||||
[glAccountList]="assetAccountData"
|
||||
[required]="true"
|
||||
[inputLabel]="'Interest Receivable'"
|
||||
>
|
||||
</mifosx-gl-account-selector>
|
||||
<mifosx-gl-account-selector
|
||||
class="flex-48"
|
||||
[inputFormControl]="loanProductAccountingForm.controls.receivableFeeAccountId"
|
||||
[glAccountList]="assetAccountData"
|
||||
[required]="true"
|
||||
[inputLabel]="'Fees Receivable'"
|
||||
>
|
||||
</mifosx-gl-account-selector>
|
||||
<mifosx-gl-account-selector
|
||||
class="flex-48"
|
||||
[inputFormControl]="loanProductAccountingForm.controls.receivablePenaltyAccountId"
|
||||
[glAccountList]="assetAccountData"
|
||||
[required]="true"
|
||||
[inputLabel]="'Penalties Receivable'"
|
||||
>
|
||||
</mifosx-gl-account-selector>
|
||||
</div>
|
||||
<mifosx-gl-account-selector
|
||||
[inputFormControl]="loanProductAccountingForm.controls.receivableInterestAccountId"
|
||||
[glAccountList]="assetAccountData"
|
||||
[required]="true"
|
||||
[inputLabel]="'Interest Receivable'"
|
||||
>
|
||||
</mifosx-gl-account-selector>
|
||||
<mifosx-gl-account-selector
|
||||
[inputFormControl]="loanProductAccountingForm.controls.receivableFeeAccountId"
|
||||
[glAccountList]="assetAccountData"
|
||||
[required]="true"
|
||||
[inputLabel]="'Fees Receivable'"
|
||||
>
|
||||
</mifosx-gl-account-selector>
|
||||
<mifosx-gl-account-selector
|
||||
[inputFormControl]="loanProductAccountingForm.controls.receivablePenaltyAccountId"
|
||||
[glAccountList]="assetAccountData"
|
||||
[required]="true"
|
||||
[inputLabel]="'Penalties Receivable'"
|
||||
>
|
||||
</mifosx-gl-account-selector>
|
||||
}
|
||||
<mat-divider class="flex-98"></mat-divider>
|
||||
<h4 class="mat-h4 flex-98">{{ 'labels.heading.Income' | translate }}</h4>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Income Section -->
|
||||
<div class="lpa-section">
|
||||
<div class="lpa-section-header">
|
||||
<i class="fas fa-chart-line lpa-section-icon"></i>
|
||||
<h3>{{ 'labels.heading.Income' | translate }}</h3>
|
||||
</div>
|
||||
<div class="lpa-section-body lpa-grid">
|
||||
<mifosx-gl-account-selector
|
||||
class="flex-48"
|
||||
[inputFormControl]="loanProductAccountingForm.controls.interestOnLoanAccountId"
|
||||
[glAccountList]="incomeAccountData"
|
||||
[required]="true"
|
||||
@@ -97,7 +120,6 @@
|
||||
>
|
||||
</mifosx-gl-account-selector>
|
||||
<mifosx-gl-account-selector
|
||||
class="flex-48"
|
||||
[inputFormControl]="loanProductAccountingForm.controls.incomeFromFeeAccountId"
|
||||
[glAccountList]="incomeAccountData"
|
||||
[required]="true"
|
||||
@@ -105,7 +127,6 @@
|
||||
>
|
||||
</mifosx-gl-account-selector>
|
||||
<mifosx-gl-account-selector
|
||||
class="flex-48"
|
||||
[inputFormControl]="loanProductAccountingForm.controls.incomeFromPenaltyAccountId"
|
||||
[glAccountList]="incomeAccountData"
|
||||
[required]="true"
|
||||
@@ -113,7 +134,6 @@
|
||||
>
|
||||
</mifosx-gl-account-selector>
|
||||
<mifosx-gl-account-selector
|
||||
class="flex-48"
|
||||
[inputFormControl]="loanProductAccountingForm.controls.incomeFromRecoveryAccountId"
|
||||
[glAccountList]="incomeAccountData"
|
||||
[required]="true"
|
||||
@@ -121,7 +141,6 @@
|
||||
>
|
||||
</mifosx-gl-account-selector>
|
||||
<mifosx-gl-account-selector
|
||||
class="flex-48"
|
||||
[inputFormControl]="loanProductAccountingForm.controls.incomeFromChargeOffInterestAccountId"
|
||||
[glAccountList]="incomeAccountData"
|
||||
[required]="true"
|
||||
@@ -129,7 +148,6 @@
|
||||
>
|
||||
</mifosx-gl-account-selector>
|
||||
<mifosx-gl-account-selector
|
||||
class="flex-48"
|
||||
[inputFormControl]="loanProductAccountingForm.controls.incomeFromChargeOffFeesAccountId"
|
||||
[glAccountList]="incomeAccountData"
|
||||
[required]="true"
|
||||
@@ -137,7 +155,6 @@
|
||||
>
|
||||
</mifosx-gl-account-selector>
|
||||
<mifosx-gl-account-selector
|
||||
class="flex-48"
|
||||
[inputFormControl]="loanProductAccountingForm.controls.incomeFromChargeOffPenaltyAccountId"
|
||||
[glAccountList]="incomeAccountData"
|
||||
[required]="true"
|
||||
@@ -145,7 +162,6 @@
|
||||
>
|
||||
</mifosx-gl-account-selector>
|
||||
<mifosx-gl-account-selector
|
||||
class="flex-48"
|
||||
[inputFormControl]="loanProductAccountingForm.controls.incomeFromGoodwillCreditInterestAccountId"
|
||||
[glAccountList]="incomeAccountData"
|
||||
[required]="true"
|
||||
@@ -153,7 +169,6 @@
|
||||
>
|
||||
</mifosx-gl-account-selector>
|
||||
<mifosx-gl-account-selector
|
||||
class="flex-48"
|
||||
[inputFormControl]="loanProductAccountingForm.controls.incomeFromGoodwillCreditFeesAccountId"
|
||||
[glAccountList]="incomeAccountData"
|
||||
[required]="true"
|
||||
@@ -161,7 +176,6 @@
|
||||
>
|
||||
</mifosx-gl-account-selector>
|
||||
<mifosx-gl-account-selector
|
||||
class="flex-48"
|
||||
[inputFormControl]="loanProductAccountingForm.controls.incomeFromGoodwillCreditPenaltyAccountId"
|
||||
[glAccountList]="incomeAccountData"
|
||||
[required]="true"
|
||||
@@ -170,7 +184,6 @@
|
||||
</mifosx-gl-account-selector>
|
||||
@if (deferredIncomeRecognition?.capitalizedIncome?.enableIncomeCapitalization) {
|
||||
<mifosx-gl-account-selector
|
||||
class="flex-48"
|
||||
[inputFormControl]="loanProductAccountingForm.controls.incomeFromCapitalizationAccountId"
|
||||
[glAccountList]="incomeAccountData"
|
||||
[required]="true"
|
||||
@@ -180,7 +193,6 @@
|
||||
}
|
||||
@if (deferredIncomeRecognition?.buyDownFee?.enableBuyDownFee) {
|
||||
<mifosx-gl-account-selector
|
||||
class="flex-48"
|
||||
[inputFormControl]="loanProductAccountingForm.controls.incomeFromBuyDownAccountId"
|
||||
[glAccountList]="incomeAccountData"
|
||||
[required]="true"
|
||||
@@ -188,10 +200,17 @@
|
||||
>
|
||||
</mifosx-gl-account-selector>
|
||||
}
|
||||
<mat-divider class="flex-98"></mat-divider>
|
||||
<h4 class="mat-h4 flex-98">{{ 'labels.heading.Expenses' | translate }}</h4>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Expenses Section -->
|
||||
<div class="lpa-section">
|
||||
<div class="lpa-section-header">
|
||||
<i class="fas fa-money-bill-wave lpa-section-icon"></i>
|
||||
<h3>{{ 'labels.heading.Expenses' | translate }}</h3>
|
||||
</div>
|
||||
<div class="lpa-section-body lpa-grid">
|
||||
<mifosx-gl-account-selector
|
||||
class="flex-48"
|
||||
[inputFormControl]="loanProductAccountingForm.controls.writeOffAccountId"
|
||||
[glAccountList]="expenseAccountData"
|
||||
[required]="true"
|
||||
@@ -199,7 +218,6 @@
|
||||
>
|
||||
</mifosx-gl-account-selector>
|
||||
<mifosx-gl-account-selector
|
||||
class="flex-48"
|
||||
[inputFormControl]="loanProductAccountingForm.controls.goodwillCreditAccountId"
|
||||
[glAccountList]="expenseAccountData"
|
||||
[required]="true"
|
||||
@@ -207,7 +225,6 @@
|
||||
>
|
||||
</mifosx-gl-account-selector>
|
||||
<mifosx-gl-account-selector
|
||||
class="flex-48"
|
||||
[inputFormControl]="loanProductAccountingForm.controls.chargeOffExpenseAccountId"
|
||||
[glAccountList]="expenseAccountData"
|
||||
[required]="true"
|
||||
@@ -215,7 +232,6 @@
|
||||
>
|
||||
</mifosx-gl-account-selector>
|
||||
<mifosx-gl-account-selector
|
||||
class="flex-48"
|
||||
[inputFormControl]="loanProductAccountingForm.controls.chargeOffFraudExpenseAccountId"
|
||||
[glAccountList]="expenseAccountData"
|
||||
[required]="true"
|
||||
@@ -227,7 +243,6 @@
|
||||
deferredIncomeRecognition?.buyDownFee?.merchantBuyDownFee
|
||||
) {
|
||||
<mifosx-gl-account-selector
|
||||
class="flex-48"
|
||||
[inputFormControl]="loanProductAccountingForm.controls.buyDownExpenseAccountId"
|
||||
[glAccountList]="expenseAccountData"
|
||||
[required]="true"
|
||||
@@ -235,10 +250,17 @@
|
||||
>
|
||||
</mifosx-gl-account-selector>
|
||||
}
|
||||
<mat-divider class="flex-98"></mat-divider>
|
||||
<h4 class="mat-h4 flex-98">{{ 'labels.heading.Liabilities' | translate }}</h4>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Liabilities Section -->
|
||||
<div class="lpa-section">
|
||||
<div class="lpa-section-header">
|
||||
<i class="fas fa-file-invoice-dollar lpa-section-icon"></i>
|
||||
<h3>{{ 'labels.heading.Liabilities' | translate }}</h3>
|
||||
</div>
|
||||
<div class="lpa-section-body lpa-grid">
|
||||
<mifosx-gl-account-selector
|
||||
class="flex-48"
|
||||
[inputFormControl]="loanProductAccountingForm.controls.overpaymentLiabilityAccountId"
|
||||
[glAccountList]="liabilityAccountData"
|
||||
[required]="true"
|
||||
@@ -250,7 +272,6 @@
|
||||
deferredIncomeRecognition?.buyDownFee?.enableBuyDownFee
|
||||
) {
|
||||
<mifosx-gl-account-selector
|
||||
class="flex-48"
|
||||
[inputFormControl]="loanProductAccountingForm.controls.deferredIncomeLiabilityAccountId"
|
||||
[glAccountList]="liabilityAccountData"
|
||||
[required]="true"
|
||||
@@ -258,28 +279,42 @@
|
||||
>
|
||||
</mifosx-gl-account-selector>
|
||||
}
|
||||
<mat-divider fxFlex="flex-98"></mat-divider>
|
||||
<mat-checkbox class="flex-73" formControlName="advancedAccountingRules">{{
|
||||
'labels.heading.Advanced Accounting Rules' | translate
|
||||
}}</mat-checkbox>
|
||||
@if (loanProductAccountingForm.value.advancedAccountingRules) {
|
||||
<div class="flex-100 layout-row-wrap responsive-column">
|
||||
<h4 class="mat-h4 flex-33">
|
||||
{{ 'labels.heading.Configure Fund Sources for Payment Channels' | translate }}
|
||||
</h4>
|
||||
<div class="flex-63">
|
||||
<button
|
||||
type="button"
|
||||
mat-raised-button
|
||||
color="primary"
|
||||
(click)="add('PaymentFundSource', paymentChannelToFundSourceMappings)"
|
||||
>
|
||||
<fa-icon icon="plus" class="m-r-10"></fa-icon>
|
||||
{{ 'labels.buttons.Add' | translate }}
|
||||
</button>
|
||||
</div>
|
||||
@if (paymentChannelToFundSourceMappings.value.length !== 0) {
|
||||
<table class="flex-98 mat-elevation-z1" mat-table [dataSource]="paymentChannelToFundSourceMappings.value">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Advanced Accounting Rules Section -->
|
||||
<div class="lpa-section">
|
||||
<div class="lpa-section-header">
|
||||
<i class="fas fa-cogs lpa-section-icon"></i>
|
||||
<h3>{{ 'labels.heading.Advanced Accounting Rules' | translate }}</h3>
|
||||
</div>
|
||||
<div class="lpa-section-body">
|
||||
<div class="lpa-full-width lpa-checkbox-row">
|
||||
<mat-checkbox formControlName="advancedAccountingRules">{{
|
||||
'labels.heading.Advanced Accounting Rules' | translate
|
||||
}}</mat-checkbox>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@if (loanProductAccountingForm.value.advancedAccountingRules) {
|
||||
<!-- Payment Fund Sources -->
|
||||
<div class="lpa-subsection">
|
||||
<div class="lpa-subsection-header">
|
||||
<h4>{{ 'labels.heading.Configure Fund Sources for Payment Channels' | translate }}</h4>
|
||||
<button
|
||||
type="button"
|
||||
mat-raised-button
|
||||
color="primary"
|
||||
class="lpa-add-btn"
|
||||
(click)="add('PaymentFundSource', paymentChannelToFundSourceMappings)"
|
||||
>
|
||||
<fa-icon icon="plus" class="m-r-10"></fa-icon>
|
||||
{{ 'labels.buttons.Add' | translate }}
|
||||
</button>
|
||||
</div>
|
||||
@if (paymentChannelToFundSourceMappings.value.length !== 0) {
|
||||
<div class="lpa-table-wrapper">
|
||||
<table mat-table [dataSource]="paymentChannelToFundSourceMappings.value">
|
||||
<ng-container matColumnDef="paymentTypeId">
|
||||
<th mat-header-cell *matHeaderCellDef>{{ 'labels.inputs.Payment Type' | translate }}</th>
|
||||
<td mat-cell *matCellDef="let paymentFundSource">
|
||||
@@ -314,21 +349,28 @@
|
||||
<tr mat-header-row *matHeaderRowDef="paymentFundSourceDisplayedColumns"></tr>
|
||||
<tr mat-row *matRowDef="let row; columns: paymentFundSourceDisplayedColumns"></tr>
|
||||
</table>
|
||||
}
|
||||
<h4 class="mat-h4 flex-33">{{ 'labels.heading.Map Fees to Specific Income Accounts' | translate }}</h4>
|
||||
<div class="flex-63">
|
||||
<button
|
||||
type="button"
|
||||
mat-raised-button
|
||||
color="primary"
|
||||
(click)="add('FeesIncome', feeToIncomeAccountMappings)"
|
||||
>
|
||||
<fa-icon icon="plus" class="m-r-10"></fa-icon>
|
||||
{{ 'labels.buttons.Add' | translate }}
|
||||
</button>
|
||||
</div>
|
||||
@if (feeToIncomeAccountMappings.value.length !== 0) {
|
||||
<table class="flex-98 mat-elevation-z1" mat-table [dataSource]="feeToIncomeAccountMappings.value">
|
||||
}
|
||||
</div>
|
||||
|
||||
<!-- Fees to Income -->
|
||||
<div class="lpa-subsection">
|
||||
<div class="lpa-subsection-header">
|
||||
<h4>{{ 'labels.heading.Map Fees to Specific Income Accounts' | translate }}</h4>
|
||||
<button
|
||||
type="button"
|
||||
mat-raised-button
|
||||
color="primary"
|
||||
class="lpa-add-btn"
|
||||
(click)="add('FeesIncome', feeToIncomeAccountMappings)"
|
||||
>
|
||||
<fa-icon icon="plus" class="m-r-10"></fa-icon>
|
||||
{{ 'labels.buttons.Add' | translate }}
|
||||
</button>
|
||||
</div>
|
||||
@if (feeToIncomeAccountMappings.value.length !== 0) {
|
||||
<div class="lpa-table-wrapper">
|
||||
<table mat-table [dataSource]="feeToIncomeAccountMappings.value">
|
||||
<ng-container matColumnDef="chargeId">
|
||||
<th mat-header-cell *matHeaderCellDef>{{ 'labels.inputs.Fees' | translate }}</th>
|
||||
<td mat-cell *matCellDef="let feesIncome">
|
||||
@@ -355,23 +397,28 @@
|
||||
<tr mat-header-row *matHeaderRowDef="feesPenaltyIncomeDisplayedColumns"></tr>
|
||||
<tr mat-row *matRowDef="let row; columns: feesPenaltyIncomeDisplayedColumns"></tr>
|
||||
</table>
|
||||
}
|
||||
<h4 class="mat-h4 flex-33">
|
||||
{{ 'labels.heading.Map Penalties to Specific Income Accounts' | translate }}
|
||||
</h4>
|
||||
<div class="flex-63">
|
||||
<button
|
||||
type="button"
|
||||
mat-raised-button
|
||||
color="primary"
|
||||
(click)="add('PenaltyIncome', penaltyToIncomeAccountMappings)"
|
||||
>
|
||||
<fa-icon icon="plus" class="m-r-10"></fa-icon>
|
||||
{{ 'labels.buttons.Add' | translate }}
|
||||
</button>
|
||||
</div>
|
||||
@if (penaltyToIncomeAccountMappings.value.length !== 0) {
|
||||
<table class="flex-98 mat-elevation-z1" mat-table [dataSource]="penaltyToIncomeAccountMappings.value">
|
||||
}
|
||||
</div>
|
||||
|
||||
<!-- Penalties to Income -->
|
||||
<div class="lpa-subsection">
|
||||
<div class="lpa-subsection-header">
|
||||
<h4>{{ 'labels.heading.Map Penalties to Specific Income Accounts' | translate }}</h4>
|
||||
<button
|
||||
type="button"
|
||||
mat-raised-button
|
||||
color="primary"
|
||||
class="lpa-add-btn"
|
||||
(click)="add('PenaltyIncome', penaltyToIncomeAccountMappings)"
|
||||
>
|
||||
<fa-icon icon="plus" class="m-r-10"></fa-icon>
|
||||
{{ 'labels.buttons.Add' | translate }}
|
||||
</button>
|
||||
</div>
|
||||
@if (penaltyToIncomeAccountMappings.value.length !== 0) {
|
||||
<div class="lpa-table-wrapper">
|
||||
<table mat-table [dataSource]="penaltyToIncomeAccountMappings.value">
|
||||
<ng-container matColumnDef="chargeId">
|
||||
<th mat-header-cell *matHeaderCellDef>{{ 'labels.inputs.Penalty' | translate }}</th>
|
||||
<td mat-cell *matCellDef="let penaltyIncome">
|
||||
@@ -406,25 +453,29 @@
|
||||
<tr mat-header-row *matHeaderRowDef="feesPenaltyIncomeDisplayedColumns"></tr>
|
||||
<tr mat-row *matRowDef="let row; columns: feesPenaltyIncomeDisplayedColumns"></tr>
|
||||
</table>
|
||||
}
|
||||
<h4 class="mat-h4 flex-33">
|
||||
{{ 'labels.heading.Map Charge-off reasons to Expense accounts' | translate }}
|
||||
</h4>
|
||||
<div class="flex-63">
|
||||
<button
|
||||
type="button"
|
||||
mat-raised-button
|
||||
color="primary"
|
||||
[disabled]="!allowAddChargeOffReasonExpense"
|
||||
(click)="add('ChargeOffReasonExpense', chargeOffReasonToExpenseAccountMappings)"
|
||||
>
|
||||
<fa-icon icon="plus" class="m-r-10"></fa-icon>
|
||||
{{ 'labels.buttons.Add' | translate }}
|
||||
</button>
|
||||
</div>
|
||||
@if (chargeOffReasonToExpenseAccountMappings.value.length !== 0) {
|
||||
}
|
||||
</div>
|
||||
|
||||
<!-- Charge-off Reasons to Expense -->
|
||||
<div class="lpa-subsection">
|
||||
<div class="lpa-subsection-header">
|
||||
<h4>{{ 'labels.heading.Map Charge-off reasons to Expense accounts' | translate }}</h4>
|
||||
<button
|
||||
type="button"
|
||||
mat-raised-button
|
||||
color="primary"
|
||||
class="lpa-add-btn"
|
||||
[disabled]="!allowAddChargeOffReasonExpense"
|
||||
(click)="add('ChargeOffReasonExpense', chargeOffReasonToExpenseAccountMappings)"
|
||||
>
|
||||
<fa-icon icon="plus" class="m-r-10"></fa-icon>
|
||||
{{ 'labels.buttons.Add' | translate }}
|
||||
</button>
|
||||
</div>
|
||||
@if (chargeOffReasonToExpenseAccountMappings.value.length !== 0) {
|
||||
<div class="lpa-table-wrapper">
|
||||
<table
|
||||
class="flex-98 mat-elevation-z1"
|
||||
mat-table
|
||||
[dataSource]="chargeOffReasonToExpenseAccountMappings.value"
|
||||
>
|
||||
@@ -464,51 +515,44 @@
|
||||
<tr mat-header-row *matHeaderRowDef="chargeOffReasonExpenseDisplayedColumns"></tr>
|
||||
<tr mat-row *matRowDef="let row; columns: chargeOffReasonExpenseDisplayedColumns"></tr>
|
||||
</table>
|
||||
}
|
||||
<mifosx-advanced-accounting-mapping-rule
|
||||
class="flex-100 m-t-10"
|
||||
[textField]="'Classification'"
|
||||
[formType]="'BuydownFeeClassificationToIncome'"
|
||||
[formArray]="buydownfeeClassificationToIncomeAccountMappings"
|
||||
[textHeading]="'Buydown Fee classifications to Income accounts'"
|
||||
[incomeAccountData]="incomeAccountData"
|
||||
[accountingMappingOptions]="buydownFeeClassificationOptions"
|
||||
(formChangeEvent)="formChangeEvent($event)"
|
||||
></mifosx-advanced-accounting-mapping-rule>
|
||||
<mifosx-advanced-accounting-mapping-rule
|
||||
class="flex-100 m-t-10"
|
||||
[textField]="'Classification'"
|
||||
[formType]="'CapitalizedIncomeClassificationToIncome'"
|
||||
[formArray]="capitalizedIncomeClassificationToIncomeAccountMappings"
|
||||
[textHeading]="'Capitalized Income classifications to Income accounts'"
|
||||
[incomeAccountData]="incomeAccountData"
|
||||
[accountingMappingOptions]="capitalizedIncomeClassificationOptions"
|
||||
(formChangeEvent)="formChangeEvent($event)"
|
||||
></mifosx-advanced-accounting-mapping-rule>
|
||||
<mifosx-advanced-accounting-mapping-rule
|
||||
class="flex-100 m-t-10"
|
||||
[textField]="'WriteOff Reason'"
|
||||
[formType]="'WriteOffReasonToExpense'"
|
||||
[formArray]="writeOffReasonsToExpenseMappings"
|
||||
[textHeading]="'WriteOff reasons to Expense accounts'"
|
||||
[expenseAccountData]="expenseAccountData"
|
||||
[accountingMappingOptions]="writeOffReasonOptions"
|
||||
(formChangeEvent)="formChangeEvent($event)"
|
||||
></mifosx-advanced-accounting-mapping-rule>
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
|
||||
<!-- Advanced Mapping Rule Components -->
|
||||
<mifosx-advanced-accounting-mapping-rule
|
||||
class="lpa-full-width"
|
||||
[textField]="'Classification'"
|
||||
[formType]="'BuydownFeeClassificationToIncome'"
|
||||
[formArray]="buydownfeeClassificationToIncomeAccountMappings"
|
||||
[textHeading]="'Buydown Fee classifications to Income accounts'"
|
||||
[incomeAccountData]="incomeAccountData"
|
||||
[accountingMappingOptions]="buydownFeeClassificationOptions"
|
||||
(formChangeEvent)="formChangeEvent($event)"
|
||||
></mifosx-advanced-accounting-mapping-rule>
|
||||
<mifosx-advanced-accounting-mapping-rule
|
||||
class="lpa-full-width"
|
||||
[textField]="'Classification'"
|
||||
[formType]="'CapitalizedIncomeClassificationToIncome'"
|
||||
[formArray]="capitalizedIncomeClassificationToIncomeAccountMappings"
|
||||
[textHeading]="'Capitalized Income classifications to Income accounts'"
|
||||
[incomeAccountData]="incomeAccountData"
|
||||
[accountingMappingOptions]="capitalizedIncomeClassificationOptions"
|
||||
(formChangeEvent)="formChangeEvent($event)"
|
||||
></mifosx-advanced-accounting-mapping-rule>
|
||||
<mifosx-advanced-accounting-mapping-rule
|
||||
class="lpa-full-width"
|
||||
[textField]="'WriteOff Reason'"
|
||||
[formType]="'WriteOffReasonToExpense'"
|
||||
[formArray]="writeOffReasonsToExpenseMappings"
|
||||
[textHeading]="'WriteOff reasons to Expense accounts'"
|
||||
[expenseAccountData]="expenseAccountData"
|
||||
[accountingMappingOptions]="writeOffReasonOptions"
|
||||
(formChangeEvent)="formChangeEvent($event)"
|
||||
></mifosx-advanced-accounting-mapping-rule>
|
||||
}
|
||||
</div>
|
||||
|
||||
}
|
||||
|
||||
<div class="layout-row align-center margin-t responsive-column gap-2percent">
|
||||
<button mat-raised-button matStepperPrevious>
|
||||
<fa-icon icon="arrow-left" class="m-r-10"></fa-icon>
|
||||
{{ 'labels.buttons.Previous' | translate }}
|
||||
</button>
|
||||
<button mat-raised-button matStepperNext [disabled]="!loanProductFormValid">
|
||||
{{ 'labels.buttons.Next' | translate }}
|
||||
<fa-icon icon="arrow-right" class="m-l-10"></fa-icon>
|
||||
</button>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
+104
-20
@@ -6,40 +6,124 @@
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
table {
|
||||
width: 100%;
|
||||
}
|
||||
// Section cards
|
||||
.lpa-section {
|
||||
border: 1px solid #e2e8f0;
|
||||
border-radius: 10px;
|
||||
overflow: hidden;
|
||||
background: #fff;
|
||||
|
||||
.mat-elevation-z1 {
|
||||
margin: 1em 0 1.5em;
|
||||
& + & {
|
||||
margin-top: 16px;
|
||||
}
|
||||
}
|
||||
|
||||
h3,
|
||||
h4 {
|
||||
font-weight: 500;
|
||||
// Section header
|
||||
.lpa-section-header {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 10px;
|
||||
padding: 12px 24px;
|
||||
background: #f8f9fa;
|
||||
border-bottom: 1px solid #e8eaed;
|
||||
|
||||
h3 {
|
||||
font-size: 14px;
|
||||
font-weight: 600;
|
||||
color: #202124;
|
||||
margin: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.lpa-section-icon {
|
||||
color: #0ea5e9;
|
||||
font-size: 15px;
|
||||
}
|
||||
|
||||
mat-radio-group,
|
||||
h4 {
|
||||
margin: 1em 0;
|
||||
// Section body
|
||||
.lpa-section-body {
|
||||
padding: 16px 24px;
|
||||
}
|
||||
|
||||
mat-divider {
|
||||
margin: 1em 0 2em;
|
||||
// 2-column grid
|
||||
.lpa-grid {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(2, 1fr);
|
||||
gap: 4px 16px;
|
||||
}
|
||||
|
||||
.margin-t {
|
||||
margin-top: 1em;
|
||||
// Full width utility
|
||||
.lpa-full-width {
|
||||
grid-column: 1 / -1;
|
||||
}
|
||||
|
||||
.radio-group-spacing {
|
||||
// Radio group
|
||||
.lpa-radio-group {
|
||||
display: flex;
|
||||
gap: 2rem;
|
||||
flex-direction: row;
|
||||
gap: 24px;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
|
||||
// Checkbox row
|
||||
.lpa-checkbox-row {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding: 4px 0;
|
||||
}
|
||||
|
||||
// Subsections inside advanced rules
|
||||
.lpa-subsection {
|
||||
padding: 16px 24px;
|
||||
border-top: 1px solid #e8eaed;
|
||||
}
|
||||
|
||||
.lpa-subsection-header {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
margin-bottom: 12px;
|
||||
|
||||
h4 {
|
||||
font-size: 13px;
|
||||
font-weight: 600;
|
||||
color: #202124;
|
||||
margin: 0;
|
||||
}
|
||||
}
|
||||
|
||||
// Add buttons
|
||||
.lpa-add-btn {
|
||||
height: 32px;
|
||||
border-radius: 8px;
|
||||
font-size: 12px;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
// Table wrapper
|
||||
.lpa-table-wrapper {
|
||||
border: 1px solid #e2e8f0;
|
||||
border-radius: 8px;
|
||||
overflow: hidden;
|
||||
margin-top: 8px;
|
||||
|
||||
table {
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
// Responsive
|
||||
@media (max-width: 600px) {
|
||||
.lpa-grid {
|
||||
grid-template-columns: 1fr;
|
||||
}
|
||||
|
||||
.lpa-radio-group {
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
@media (width <= 768px) {
|
||||
.radio-group-spacing {
|
||||
.lpa-subsection-header {
|
||||
flex-direction: column;
|
||||
align-items: flex-start;
|
||||
gap: 8px;
|
||||
}
|
||||
}
|
||||
|
||||
-5
@@ -22,7 +22,6 @@ import {
|
||||
} from 'app/shared/models/general.model';
|
||||
import { DeferredIncomeRecognition } from '../loan-product-payment-strategy-step/payment-allocation-model';
|
||||
import { MatRadioGroup, MatRadioButton } from '@angular/material/radio';
|
||||
import { MatDivider } from '@angular/material/divider';
|
||||
import { MatCheckbox } from '@angular/material/checkbox';
|
||||
import { GlAccountSelectorComponent } from '../../../../shared/accounting/gl-account-selector/gl-account-selector.component';
|
||||
import { MatIconButton } from '@angular/material/button';
|
||||
@@ -39,7 +38,6 @@ import {
|
||||
MatRowDef,
|
||||
MatRow
|
||||
} from '@angular/material/table';
|
||||
import { MatStepperPrevious, MatStepperNext } from '@angular/material/stepper';
|
||||
import { FindPipe } from '../../../../pipes/find.pipe';
|
||||
import { STANDALONE_SHARED_IMPORTS } from 'app/standalone-shared.module';
|
||||
import { AdvancedAccountingMappingRuleComponent } from './advanced-accounting-mapping-rule/advanced-accounting-mapping-rule.component';
|
||||
@@ -53,7 +51,6 @@ import { AccountingMappingDTO, AdvancedMappingDTO } from '../../models/loan-prod
|
||||
...STANDALONE_SHARED_IMPORTS,
|
||||
MatRadioGroup,
|
||||
MatRadioButton,
|
||||
MatDivider,
|
||||
MatCheckbox,
|
||||
GlAccountSelectorComponent,
|
||||
FaIconComponent,
|
||||
@@ -68,8 +65,6 @@ import { AccountingMappingDTO, AdvancedMappingDTO } from '../../models/loan-prod
|
||||
MatHeaderRow,
|
||||
MatRowDef,
|
||||
MatRow,
|
||||
MatStepperPrevious,
|
||||
MatStepperNext,
|
||||
FindPipe,
|
||||
AdvancedAccountingMappingRuleComponent
|
||||
]
|
||||
|
||||
+103
-88
@@ -7,97 +7,112 @@
|
||||
-->
|
||||
|
||||
<form [formGroup]="loanDeferredIncomeRecognitionForm">
|
||||
<div class="layout-row-wrap gap-2percent layout-column-lt-md">
|
||||
<mat-checkbox class="flex-98" labelPosition="before" formControlName="enableIncomeCapitalization">
|
||||
{{ 'labels.inputs.Enable income capitalization' | translate }}
|
||||
</mat-checkbox>
|
||||
<!-- Income Capitalization -->
|
||||
<div class="lpdi-section">
|
||||
<div class="lpdi-section__header">
|
||||
<i class="fas fa-chart-bar"></i>
|
||||
<h3>{{ 'labels.inputs.Income Capitalization' | translate }}</h3>
|
||||
</div>
|
||||
<div class="lpdi-grid">
|
||||
<div class="lpdi-field--full lpdi-checkbox-row">
|
||||
<mat-checkbox labelPosition="before" formControlName="enableIncomeCapitalization">
|
||||
{{ 'labels.inputs.Enable income capitalization' | translate }}
|
||||
</mat-checkbox>
|
||||
</div>
|
||||
|
||||
@if (enableIncomeCapitalization) {
|
||||
<mat-form-field class="flex-48">
|
||||
<mat-label>{{ 'labels.inputs.Income capitalization calculation type' | translate }}</mat-label>
|
||||
<mat-select formControlName="capitalizedIncomeCalculationType" required>
|
||||
@for (
|
||||
capitalizedIncomeCalculationType of capitalizedIncomeCalculationTypeOptions;
|
||||
track capitalizedIncomeCalculationType
|
||||
) {
|
||||
<mat-option [value]="capitalizedIncomeCalculationType.id">
|
||||
{{ capitalizedIncomeCalculationType.value | translateKey: 'catalogs' }}
|
||||
</mat-option>
|
||||
}
|
||||
</mat-select>
|
||||
</mat-form-field>
|
||||
}
|
||||
@if (enableIncomeCapitalization) {
|
||||
<mat-form-field class="flex-48">
|
||||
<mat-label>{{ 'labels.inputs.Income capitalization strategy' | translate }}</mat-label>
|
||||
<mat-select formControlName="capitalizedIncomeStrategy" required>
|
||||
@for (capitalizedIncomeStrategy of capitalizedIncomeStrategyOptions; track capitalizedIncomeStrategy) {
|
||||
<mat-option [value]="capitalizedIncomeStrategy.id">
|
||||
{{ capitalizedIncomeStrategy.value | translateKey: 'catalogs' }}
|
||||
</mat-option>
|
||||
}
|
||||
</mat-select>
|
||||
</mat-form-field>
|
||||
}
|
||||
@if (enableIncomeCapitalization) {
|
||||
<mat-form-field class="flex-48">
|
||||
<mat-label>{{ 'labels.inputs.Income type' | translate }}</mat-label>
|
||||
<mat-select formControlName="capitalizedIncomeType" required>
|
||||
@for (capitalizedIncomeType of capitalizedIncomeTypeOptions; track capitalizedIncomeType) {
|
||||
<mat-option [value]="capitalizedIncomeType.id">
|
||||
{{ capitalizedIncomeType.value | translateKey: 'catalogs' }}
|
||||
</mat-option>
|
||||
}
|
||||
</mat-select>
|
||||
</mat-form-field>
|
||||
}
|
||||
@if (enableIncomeCapitalization) {
|
||||
<mat-form-field appearance="outline" class="lpdi-field">
|
||||
<mat-label>{{ 'labels.inputs.Income capitalization calculation type' | translate }}</mat-label>
|
||||
<mat-select formControlName="capitalizedIncomeCalculationType" required>
|
||||
@for (
|
||||
capitalizedIncomeCalculationType of capitalizedIncomeCalculationTypeOptions;
|
||||
track capitalizedIncomeCalculationType
|
||||
) {
|
||||
<mat-option [value]="capitalizedIncomeCalculationType.id">
|
||||
{{ capitalizedIncomeCalculationType.value | translateKey: 'catalogs' }}
|
||||
</mat-option>
|
||||
}
|
||||
</mat-select>
|
||||
</mat-form-field>
|
||||
|
||||
<mat-form-field appearance="outline" class="lpdi-field">
|
||||
<mat-label>{{ 'labels.inputs.Income capitalization strategy' | translate }}</mat-label>
|
||||
<mat-select formControlName="capitalizedIncomeStrategy" required>
|
||||
@for (capitalizedIncomeStrategy of capitalizedIncomeStrategyOptions; track capitalizedIncomeStrategy) {
|
||||
<mat-option [value]="capitalizedIncomeStrategy.id">
|
||||
{{ capitalizedIncomeStrategy.value | translateKey: 'catalogs' }}
|
||||
</mat-option>
|
||||
}
|
||||
</mat-select>
|
||||
</mat-form-field>
|
||||
|
||||
<mat-form-field appearance="outline" class="lpdi-field">
|
||||
<mat-label>{{ 'labels.inputs.Income type' | translate }}</mat-label>
|
||||
<mat-select formControlName="capitalizedIncomeType" required>
|
||||
@for (capitalizedIncomeType of capitalizedIncomeTypeOptions; track capitalizedIncomeType) {
|
||||
<mat-option [value]="capitalizedIncomeType.id">
|
||||
{{ capitalizedIncomeType.value | translateKey: 'catalogs' }}
|
||||
</mat-option>
|
||||
}
|
||||
</mat-select>
|
||||
</mat-form-field>
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
<div class="layout-row-wrap gap-2percent layout-column-lt-md">
|
||||
<mat-checkbox class="flex-98" labelPosition="before" formControlName="enableBuyDownFee">
|
||||
{{ 'labels.inputs.Enable Buy down fee' | translate }}
|
||||
</mat-checkbox>
|
||||
|
||||
@if (enableBuyDownFee) {
|
||||
<mat-form-field class="flex-48">
|
||||
<mat-label>{{ 'labels.inputs.Buy down fee calculation type' | translate }}</mat-label>
|
||||
<mat-select formControlName="buyDownFeeCalculationType" required>
|
||||
@for (buyDownFeeCalculationType of buyDownFeeCalculationTypeOptions; track buyDownFeeCalculationType) {
|
||||
<mat-option [value]="buyDownFeeCalculationType.id">
|
||||
{{ buyDownFeeCalculationType.value | translateKey: 'catalogs' }}
|
||||
</mat-option>
|
||||
}
|
||||
</mat-select>
|
||||
</mat-form-field>
|
||||
}
|
||||
@if (enableBuyDownFee) {
|
||||
<mat-form-field class="flex-48">
|
||||
<mat-label>{{ 'labels.inputs.Buy down fee strategy' | translate }}</mat-label>
|
||||
<mat-select formControlName="buyDownFeeStrategy" required>
|
||||
@for (buyDownFeeStrategy of buyDownFeeStrategyOptions; track buyDownFeeStrategy) {
|
||||
<mat-option [value]="buyDownFeeStrategy.id">
|
||||
{{ buyDownFeeStrategy.value | translateKey: 'catalogs' }}
|
||||
</mat-option>
|
||||
}
|
||||
</mat-select>
|
||||
</mat-form-field>
|
||||
}
|
||||
@if (enableBuyDownFee) {
|
||||
<mat-form-field class="flex-48">
|
||||
<mat-label>{{ 'labels.inputs.Buy down fee income type' | translate }}</mat-label>
|
||||
<mat-select formControlName="buyDownFeeIncomeType" required>
|
||||
@for (buyDownFeeIncomeType of buyDownFeeIncomeTypeOptions; track buyDownFeeIncomeType) {
|
||||
<mat-option [value]="buyDownFeeIncomeType.id">
|
||||
{{ buyDownFeeIncomeType.value | translateKey: 'catalogs' }}
|
||||
</mat-option>
|
||||
}
|
||||
</mat-select>
|
||||
</mat-form-field>
|
||||
}
|
||||
<!-- Buy Down Fee -->
|
||||
<div class="lpdi-section">
|
||||
<div class="lpdi-section__header">
|
||||
<i class="fas fa-tag"></i>
|
||||
<h3>{{ 'labels.inputs.Buy Down Fee' | translate }}</h3>
|
||||
</div>
|
||||
<div class="lpdi-grid">
|
||||
<div class="lpdi-field--full lpdi-checkbox-row">
|
||||
<mat-checkbox labelPosition="before" formControlName="enableBuyDownFee">
|
||||
{{ 'labels.inputs.Enable Buy down fee' | translate }}
|
||||
</mat-checkbox>
|
||||
</div>
|
||||
|
||||
@if (enableBuyDownFee) {
|
||||
<mat-checkbox class="flex-48" labelPosition="before" formControlName="merchantBuyDownFee">
|
||||
{{ 'labels.inputs.Merchant Buy down fee' | translate }}
|
||||
</mat-checkbox>
|
||||
}
|
||||
@if (enableBuyDownFee) {
|
||||
<mat-form-field appearance="outline" class="lpdi-field">
|
||||
<mat-label>{{ 'labels.inputs.Buy down fee calculation type' | translate }}</mat-label>
|
||||
<mat-select formControlName="buyDownFeeCalculationType" required>
|
||||
@for (buyDownFeeCalculationType of buyDownFeeCalculationTypeOptions; track buyDownFeeCalculationType) {
|
||||
<mat-option [value]="buyDownFeeCalculationType.id">
|
||||
{{ buyDownFeeCalculationType.value | translateKey: 'catalogs' }}
|
||||
</mat-option>
|
||||
}
|
||||
</mat-select>
|
||||
</mat-form-field>
|
||||
|
||||
<mat-form-field appearance="outline" class="lpdi-field">
|
||||
<mat-label>{{ 'labels.inputs.Buy down fee strategy' | translate }}</mat-label>
|
||||
<mat-select formControlName="buyDownFeeStrategy" required>
|
||||
@for (buyDownFeeStrategy of buyDownFeeStrategyOptions; track buyDownFeeStrategy) {
|
||||
<mat-option [value]="buyDownFeeStrategy.id">
|
||||
{{ buyDownFeeStrategy.value | translateKey: 'catalogs' }}
|
||||
</mat-option>
|
||||
}
|
||||
</mat-select>
|
||||
</mat-form-field>
|
||||
|
||||
<mat-form-field appearance="outline" class="lpdi-field">
|
||||
<mat-label>{{ 'labels.inputs.Buy down fee income type' | translate }}</mat-label>
|
||||
<mat-select formControlName="buyDownFeeIncomeType" required>
|
||||
@for (buyDownFeeIncomeType of buyDownFeeIncomeTypeOptions; track buyDownFeeIncomeType) {
|
||||
<mat-option [value]="buyDownFeeIncomeType.id">
|
||||
{{ buyDownFeeIncomeType.value | translateKey: 'catalogs' }}
|
||||
</mat-option>
|
||||
}
|
||||
</mat-select>
|
||||
</mat-form-field>
|
||||
|
||||
<div class="lpdi-field lpdi-checkbox-row">
|
||||
<mat-checkbox labelPosition="before" formControlName="merchantBuyDownFee">
|
||||
{{ 'labels.inputs.Merchant Buy down fee' | translate }}
|
||||
</mat-checkbox>
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
+45
-2
@@ -6,6 +6,49 @@
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
.margin-t {
|
||||
margin-top: 1em;
|
||||
$accent: #0ea5e9;
|
||||
$border: #e2e8f0;
|
||||
$gray-50: #f8f9fa;
|
||||
$gray-200: #e8eaed;
|
||||
$gray-900: #202124;
|
||||
|
||||
.lpdi-section {
|
||||
border: 1px solid $border;
|
||||
border-radius: 10px;
|
||||
overflow: hidden;
|
||||
background: #fff;
|
||||
|
||||
& + & { margin-top: 16px; }
|
||||
|
||||
&__header {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 10px;
|
||||
padding: 12px 24px;
|
||||
background: $gray-50;
|
||||
border-bottom: 1px solid $gray-200;
|
||||
|
||||
i { font-size: 14px; color: $accent; }
|
||||
h3 { margin: 0; font-size: 14px; font-weight: 600; color: $gray-900; }
|
||||
}
|
||||
}
|
||||
|
||||
.lpdi-grid {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(2, 1fr);
|
||||
gap: 4px 16px;
|
||||
padding: 16px 24px;
|
||||
|
||||
@media (max-width: 600px) { grid-template-columns: 1fr; }
|
||||
}
|
||||
|
||||
.lpdi-field {
|
||||
width: 100%;
|
||||
&--full { grid-column: 1 / -1; }
|
||||
}
|
||||
|
||||
.lpdi-checkbox-row {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding: 4px 0;
|
||||
}
|
||||
|
||||
+161
-150
@@ -6,165 +6,176 @@
|
||||
file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
-->
|
||||
|
||||
<div class="layout-row-wrap gap-2px responsive-column">
|
||||
<mat-form-field class="flex-48">
|
||||
<mat-label>{{ 'labels.inputs.Charge' | translate }}</mat-label>
|
||||
<mat-select #charge>
|
||||
@for (
|
||||
charge of chargeData | chargesFilter: chargesDataSource : currencyCode.value : multiDisburseLoan.value;
|
||||
track charge
|
||||
) {
|
||||
<mat-option [value]="charge">
|
||||
{{ charge.name }}
|
||||
</mat-option>
|
||||
}
|
||||
</mat-select>
|
||||
</mat-form-field>
|
||||
|
||||
<div class="flex-48 align-center">
|
||||
<button type="button" mat-raised-button color="primary" (click)="addCharge(charge)" [disabled]="!charge.value">
|
||||
<fa-icon icon="plus" class="m-r-10"></fa-icon>
|
||||
{{ 'labels.buttons.Add' | translate }}
|
||||
</button>
|
||||
<!-- Charges -->
|
||||
<div class="lpch-section">
|
||||
<div class="lpch-section__header">
|
||||
<i class="fas fa-receipt"></i>
|
||||
<h3>{{ 'labels.inputs.Charges' | translate }}</h3>
|
||||
</div>
|
||||
<div class="lpch-body">
|
||||
<div class="lpch-add-row">
|
||||
<mat-form-field appearance="outline" class="lpch-add-row__select">
|
||||
<mat-label>{{ 'labels.inputs.Charge' | translate }}</mat-label>
|
||||
<mat-select #charge>
|
||||
@for (
|
||||
charge of chargeData | chargesFilter: chargesDataSource : currencyCode.value : multiDisburseLoan.value;
|
||||
track charge
|
||||
) {
|
||||
<mat-option [value]="charge">
|
||||
{{ charge.name }}
|
||||
</mat-option>
|
||||
}
|
||||
</mat-select>
|
||||
</mat-form-field>
|
||||
|
||||
<table
|
||||
class="flex-98 mat-elevation-z1"
|
||||
mat-table
|
||||
[dataSource]="chargesDataSource | chargesPenaltyFilter: false"
|
||||
#chargesTable
|
||||
[hidden]="chargesTable.dataSource.length === 0"
|
||||
>
|
||||
<ng-container matColumnDef="name">
|
||||
<th mat-header-cell *matHeaderCellDef>{{ 'labels.inputs.Name' | translate }}</th>
|
||||
<td mat-cell *matCellDef="let charge">
|
||||
{{ charge.name + ', ' + charge.currency.displaySymbol }}
|
||||
</td>
|
||||
</ng-container>
|
||||
<button
|
||||
type="button"
|
||||
mat-flat-button
|
||||
color="primary"
|
||||
(click)="addCharge(charge)"
|
||||
[disabled]="!charge.value"
|
||||
class="lpch-add-row__btn"
|
||||
>
|
||||
<fa-icon icon="plus" class="m-r-10"></fa-icon>
|
||||
{{ 'labels.buttons.Add' | translate }}
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<ng-container matColumnDef="chargeCalculationType">
|
||||
<th mat-header-cell *matHeaderCellDef>{{ 'labels.inputs.Type' | translate }}</th>
|
||||
<td mat-cell *matCellDef="let charge">
|
||||
{{ charge.chargeCalculationType.value | translateKey: 'catalogs' }}
|
||||
</td>
|
||||
</ng-container>
|
||||
@if ((chargesDataSource | chargesPenaltyFilter: false).length > 0) {
|
||||
<div class="lpch-table-wrap">
|
||||
<table
|
||||
mat-table
|
||||
[dataSource]="chargesDataSource | chargesPenaltyFilter: false"
|
||||
class="lpch-table"
|
||||
>
|
||||
<ng-container matColumnDef="name">
|
||||
<th mat-header-cell *matHeaderCellDef>{{ 'labels.inputs.Name' | translate }}</th>
|
||||
<td mat-cell *matCellDef="let charge">
|
||||
{{ charge.name + ', ' + charge.currency.displaySymbol }}
|
||||
</td>
|
||||
</ng-container>
|
||||
|
||||
<ng-container matColumnDef="amount">
|
||||
<th mat-header-cell *matHeaderCellDef>{{ 'labels.inputs.Amount' | translate }}</th>
|
||||
<td mat-cell *matCellDef="let charge">
|
||||
{{ charge.amount | formatNumber }}
|
||||
</td>
|
||||
</ng-container>
|
||||
<ng-container matColumnDef="chargeCalculationType">
|
||||
<th mat-header-cell *matHeaderCellDef>{{ 'labels.inputs.Type' | translate }}</th>
|
||||
<td mat-cell *matCellDef="let charge">
|
||||
{{ charge.chargeCalculationType.value | translateKey: 'catalogs' }}
|
||||
</td>
|
||||
</ng-container>
|
||||
|
||||
<ng-container matColumnDef="chargeTimeType">
|
||||
<th mat-header-cell *matHeaderCellDef>{{ 'labels.inputs.Collected On' | translate }}</th>
|
||||
<td mat-cell *matCellDef="let charge">
|
||||
{{ charge.chargeTimeType.value | translateKey: 'catalogs' }}
|
||||
</td>
|
||||
</ng-container>
|
||||
<ng-container matColumnDef="amount">
|
||||
<th mat-header-cell *matHeaderCellDef>{{ 'labels.inputs.Amount' | translate }}</th>
|
||||
<td mat-cell *matCellDef="let charge">
|
||||
{{ charge.amount | formatNumber }}
|
||||
</td>
|
||||
</ng-container>
|
||||
|
||||
<ng-container matColumnDef="action">
|
||||
<th mat-header-cell *matHeaderCellDef>{{ 'labels.inputs.Actions' | translate }}</th>
|
||||
<td mat-cell *matCellDef="let charge">
|
||||
<button mat-icon-button color="warn" (click)="deleteCharge(charge)">
|
||||
<fa-icon icon="trash"></fa-icon>
|
||||
</button>
|
||||
</td>
|
||||
</ng-container>
|
||||
<ng-container matColumnDef="chargeTimeType">
|
||||
<th mat-header-cell *matHeaderCellDef>{{ 'labels.inputs.Collected On' | translate }}</th>
|
||||
<td mat-cell *matCellDef="let charge">
|
||||
{{ charge.chargeTimeType.value | translateKey: 'catalogs' }}
|
||||
</td>
|
||||
</ng-container>
|
||||
|
||||
<tr mat-header-row *matHeaderRowDef="displayedColumns"></tr>
|
||||
<tr mat-row *matRowDef="let row; columns: displayedColumns"></tr>
|
||||
</table>
|
||||
<ng-container matColumnDef="action">
|
||||
<th mat-header-cell *matHeaderCellDef>{{ 'labels.inputs.Actions' | translate }}</th>
|
||||
<td mat-cell *matCellDef="let charge">
|
||||
<button mat-icon-button color="warn" (click)="deleteCharge(charge)">
|
||||
<fa-icon icon="trash"></fa-icon>
|
||||
</button>
|
||||
</td>
|
||||
</ng-container>
|
||||
|
||||
<mat-divider class="flex-98"></mat-divider>
|
||||
|
||||
<div class="flex-98">
|
||||
<h3 class="mat-h3">{{ 'labels.inputs.Overdue Charges' | translate }}</h3>
|
||||
<tr mat-header-row *matHeaderRowDef="displayedColumns"></tr>
|
||||
<tr mat-row *matRowDef="let row; columns: displayedColumns"></tr>
|
||||
</table>
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
|
||||
<mat-form-field class="flex-48">
|
||||
<mat-label>{{ 'labels.inputs.Overdue Charge' | translate }}</mat-label>
|
||||
<mat-select #overdueCharge>
|
||||
@for (
|
||||
overdueCharge of overdueChargeData | chargesFilter: chargesDataSource : currencyCode.value;
|
||||
track overdueCharge
|
||||
) {
|
||||
<mat-option [value]="overdueCharge">
|
||||
{{ overdueCharge.name }}
|
||||
</mat-option>
|
||||
}
|
||||
</mat-select>
|
||||
</mat-form-field>
|
||||
|
||||
<div class="flex-48 align-center">
|
||||
<button
|
||||
type="button"
|
||||
mat-raised-button
|
||||
color="primary"
|
||||
(click)="addCharge(overdueCharge)"
|
||||
[disabled]="!overdueCharge.value"
|
||||
>
|
||||
<fa-icon icon="plus" class="m-r-10"></fa-icon>
|
||||
{{ 'labels.buttons.Add' | translate }}
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<table
|
||||
class="flex-98 mat-elevation-z1"
|
||||
mat-table
|
||||
[dataSource]="chargesDataSource | chargesPenaltyFilter: true"
|
||||
#overdueChargesTable
|
||||
[hidden]="overdueChargesTable.dataSource.length === 0"
|
||||
>
|
||||
<ng-container matColumnDef="name">
|
||||
<th mat-header-cell *matHeaderCellDef>{{ 'labels.inputs.Name' | translate }}</th>
|
||||
<td mat-cell *matCellDef="let overdueCharge">
|
||||
{{ overdueCharge.name + ', ' + overdueCharge.currency.displaySymbol }}
|
||||
</td>
|
||||
</ng-container>
|
||||
|
||||
<ng-container matColumnDef="chargeCalculationType">
|
||||
<th mat-header-cell *matHeaderCellDef>{{ 'labels.inputs.Type' | translate }}</th>
|
||||
<td mat-cell *matCellDef="let overdueCharge">
|
||||
{{ overdueCharge.chargeCalculationType.value | translateKey: 'catalogs' }}
|
||||
</td>
|
||||
</ng-container>
|
||||
|
||||
<ng-container matColumnDef="amount">
|
||||
<th mat-header-cell *matHeaderCellDef>{{ 'labels.inputs.Amount' | translate }}</th>
|
||||
<td mat-cell *matCellDef="let overdueCharge">
|
||||
{{ overdueCharge.amount | formatNumber }}
|
||||
</td>
|
||||
</ng-container>
|
||||
|
||||
<ng-container matColumnDef="chargeTimeType">
|
||||
<th mat-header-cell *matHeaderCellDef>{{ 'labels.inputs.Collected On' | translate }}</th>
|
||||
<td mat-cell *matCellDef="let overdueCharge">
|
||||
{{ overdueCharge.chargeTimeType.value | translateKey: 'catalogs' }}
|
||||
</td>
|
||||
</ng-container>
|
||||
|
||||
<ng-container matColumnDef="action">
|
||||
<th mat-header-cell *matHeaderCellDef>{{ 'labels.inputs.Actions' | translate }}</th>
|
||||
<td mat-cell *matCellDef="let overdueCharge">
|
||||
<button mat-icon-button color="warn" (click)="deleteCharge(overdueCharge)">
|
||||
<fa-icon icon="trash"></fa-icon>
|
||||
</button>
|
||||
</td>
|
||||
</ng-container>
|
||||
|
||||
<tr mat-header-row *matHeaderRowDef="displayedColumns"></tr>
|
||||
<tr mat-row *matRowDef="let row; columns: displayedColumns"></tr>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
<div class="layout-row responsive-column align-center gap-2px margin-t">
|
||||
<button mat-raised-button matStepperPrevious>
|
||||
<fa-icon icon="arrow-left" class="m-r-10"></fa-icon>
|
||||
{{ 'labels.buttons.Previous' | translate }}
|
||||
</button>
|
||||
<button mat-raised-button matStepperNext>
|
||||
{{ 'labels.buttons.Next' | translate }}
|
||||
<fa-icon icon="arrow-right" class="m-l-10"></fa-icon>
|
||||
</button>
|
||||
<!-- Overdue Charges -->
|
||||
<div class="lpch-section">
|
||||
<div class="lpch-section__header">
|
||||
<i class="fas fa-exclamation-circle"></i>
|
||||
<h3>{{ 'labels.inputs.Overdue Charges' | translate }}</h3>
|
||||
</div>
|
||||
<div class="lpch-body">
|
||||
<div class="lpch-add-row">
|
||||
<mat-form-field appearance="outline" class="lpch-add-row__select">
|
||||
<mat-label>{{ 'labels.inputs.Overdue Charge' | translate }}</mat-label>
|
||||
<mat-select #overdueCharge>
|
||||
@for (
|
||||
overdueCharge of overdueChargeData | chargesFilter: chargesDataSource : currencyCode.value;
|
||||
track overdueCharge
|
||||
) {
|
||||
<mat-option [value]="overdueCharge">
|
||||
{{ overdueCharge.name }}
|
||||
</mat-option>
|
||||
}
|
||||
</mat-select>
|
||||
</mat-form-field>
|
||||
|
||||
<button
|
||||
type="button"
|
||||
mat-flat-button
|
||||
color="primary"
|
||||
(click)="addCharge(overdueCharge)"
|
||||
[disabled]="!overdueCharge.value"
|
||||
class="lpch-add-row__btn"
|
||||
>
|
||||
<fa-icon icon="plus" class="m-r-10"></fa-icon>
|
||||
{{ 'labels.buttons.Add' | translate }}
|
||||
</button>
|
||||
</div>
|
||||
|
||||
@if ((chargesDataSource | chargesPenaltyFilter: true).length > 0) {
|
||||
<div class="lpch-table-wrap">
|
||||
<table
|
||||
mat-table
|
||||
[dataSource]="chargesDataSource | chargesPenaltyFilter: true"
|
||||
class="lpch-table"
|
||||
>
|
||||
<ng-container matColumnDef="name">
|
||||
<th mat-header-cell *matHeaderCellDef>{{ 'labels.inputs.Name' | translate }}</th>
|
||||
<td mat-cell *matCellDef="let overdueCharge">
|
||||
{{ overdueCharge.name + ', ' + overdueCharge.currency.displaySymbol }}
|
||||
</td>
|
||||
</ng-container>
|
||||
|
||||
<ng-container matColumnDef="chargeCalculationType">
|
||||
<th mat-header-cell *matHeaderCellDef>{{ 'labels.inputs.Type' | translate }}</th>
|
||||
<td mat-cell *matCellDef="let overdueCharge">
|
||||
{{ overdueCharge.chargeCalculationType.value | translateKey: 'catalogs' }}
|
||||
</td>
|
||||
</ng-container>
|
||||
|
||||
<ng-container matColumnDef="amount">
|
||||
<th mat-header-cell *matHeaderCellDef>{{ 'labels.inputs.Amount' | translate }}</th>
|
||||
<td mat-cell *matCellDef="let overdueCharge">
|
||||
{{ overdueCharge.amount | formatNumber }}
|
||||
</td>
|
||||
</ng-container>
|
||||
|
||||
<ng-container matColumnDef="chargeTimeType">
|
||||
<th mat-header-cell *matHeaderCellDef>{{ 'labels.inputs.Collected On' | translate }}</th>
|
||||
<td mat-cell *matCellDef="let overdueCharge">
|
||||
{{ overdueCharge.chargeTimeType.value | translateKey: 'catalogs' }}
|
||||
</td>
|
||||
</ng-container>
|
||||
|
||||
<ng-container matColumnDef="action">
|
||||
<th mat-header-cell *matHeaderCellDef>{{ 'labels.inputs.Actions' | translate }}</th>
|
||||
<td mat-cell *matCellDef="let overdueCharge">
|
||||
<button mat-icon-button color="warn" (click)="deleteCharge(overdueCharge)">
|
||||
<fa-icon icon="trash"></fa-icon>
|
||||
</button>
|
||||
</td>
|
||||
</ng-container>
|
||||
|
||||
<tr mat-header-row *matHeaderRowDef="displayedColumns"></tr>
|
||||
<tr mat-row *matRowDef="let row; columns: displayedColumns"></tr>
|
||||
</table>
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
+65
-17
@@ -6,22 +6,70 @@
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
table {
|
||||
$primary: #1353a0;
|
||||
$accent: #0ea5e9;
|
||||
$border: #e2e8f0;
|
||||
$gray-50: #f8f9fa;
|
||||
$gray-200: #e8eaed;
|
||||
$gray-900: #202124;
|
||||
|
||||
.lpch-section {
|
||||
border: 1px solid $border;
|
||||
border-radius: 10px;
|
||||
overflow: hidden;
|
||||
background: #fff;
|
||||
|
||||
& + & { margin-top: 16px; }
|
||||
|
||||
&__header {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 10px;
|
||||
padding: 12px 24px;
|
||||
background: $gray-50;
|
||||
border-bottom: 1px solid $gray-200;
|
||||
|
||||
i { font-size: 14px; color: $accent; }
|
||||
h3 { margin: 0; font-size: 14px; font-weight: 600; color: $gray-900; }
|
||||
}
|
||||
}
|
||||
|
||||
.lpch-body {
|
||||
padding: 16px 24px;
|
||||
}
|
||||
|
||||
.lpch-add-row {
|
||||
display: flex;
|
||||
align-items: flex-start;
|
||||
gap: 12px;
|
||||
|
||||
&__select {
|
||||
flex: 1;
|
||||
max-width: 400px;
|
||||
}
|
||||
|
||||
&__btn {
|
||||
margin-top: 4px;
|
||||
height: 36px !important;
|
||||
border-radius: 8px !important;
|
||||
font-size: 13px !important;
|
||||
font-weight: 600 !important;
|
||||
box-shadow: 0 1px 3px rgba($primary, 0.3) !important;
|
||||
}
|
||||
|
||||
@media (max-width: 600px) {
|
||||
flex-direction: column;
|
||||
&__select { max-width: 100%; width: 100%; }
|
||||
}
|
||||
}
|
||||
|
||||
.lpch-table-wrap {
|
||||
margin-top: 8px;
|
||||
border: 1px solid $border;
|
||||
border-radius: 8px;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.lpch-table {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.mat-elevation-z1 {
|
||||
margin: 1em 0 1.5em;
|
||||
}
|
||||
|
||||
h3 {
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
mat-divider {
|
||||
margin: 1em 0 2em;
|
||||
}
|
||||
|
||||
.margin-t {
|
||||
margin-top: 1em;
|
||||
}
|
||||
|
||||
-5
@@ -26,8 +26,6 @@ import {
|
||||
MatRowDef,
|
||||
MatRow
|
||||
} from '@angular/material/table';
|
||||
import { MatDivider } from '@angular/material/divider';
|
||||
import { MatStepperPrevious, MatStepperNext } from '@angular/material/stepper';
|
||||
import { ChargesFilterPipe } from '../../../../pipes/charges-filter.pipe';
|
||||
import { ChargesPenaltyFilterPipe } from '../../../../pipes/charges-penalty-filter.pipe';
|
||||
import { FormatNumberPipe } from '../../../../pipes/format-number.pipe';
|
||||
@@ -51,9 +49,6 @@ import { STANDALONE_SHARED_IMPORTS } from 'app/standalone-shared.module';
|
||||
MatHeaderRow,
|
||||
MatRowDef,
|
||||
MatRow,
|
||||
MatDivider,
|
||||
MatStepperPrevious,
|
||||
MatStepperNext,
|
||||
ChargesFilterPipe,
|
||||
ChargesPenaltyFilterPipe,
|
||||
FormatNumberPipe
|
||||
|
||||
+97
-80
@@ -7,94 +7,111 @@
|
||||
-->
|
||||
|
||||
<form [formGroup]="loanProductCurrencyForm">
|
||||
<div class="layout-row-wrap gap-2px responsive-column">
|
||||
<mat-form-field class="flex-48">
|
||||
<mat-label>{{ 'labels.inputs.Currency' | translate }}</mat-label>
|
||||
<mat-select
|
||||
formControlName="currencyCode"
|
||||
matTooltip="{{ 'tooltips.The currency in which the loan will be disbursed' | translate }}"
|
||||
required
|
||||
>
|
||||
@for (currency of currencyData; track currency) {
|
||||
<mat-option [value]="currency.code">
|
||||
{{ currency.name }}
|
||||
</mat-option>
|
||||
}
|
||||
</mat-select>
|
||||
<mat-error>
|
||||
{{ 'labels.inputs.Currency' | translate }} {{ 'labels.commons.is' | translate }}
|
||||
<strong>{{ 'labels.commons.required' | translate }}</strong>
|
||||
</mat-error>
|
||||
</mat-form-field>
|
||||
<div class="lpc-section">
|
||||
<div class="lpc-section__header">
|
||||
<i class="fas fa-coins"></i>
|
||||
<h3>{{ 'labels.inputs.Currency' | translate }}</h3>
|
||||
</div>
|
||||
<div class="lpc-grid">
|
||||
<mat-form-field appearance="outline" class="lpc-field">
|
||||
<mat-label>{{ 'labels.inputs.Currency' | translate }}</mat-label>
|
||||
<mat-select
|
||||
formControlName="currencyCode"
|
||||
matTooltip="{{ 'tooltips.The currency in which the loan will be disbursed' | translate }}"
|
||||
required
|
||||
>
|
||||
@for (currency of currencyData; track currency) {
|
||||
<mat-option [value]="currency.code">
|
||||
{{ currency.name }}
|
||||
</mat-option>
|
||||
}
|
||||
</mat-select>
|
||||
<mat-error>
|
||||
{{ 'labels.inputs.Currency' | translate }} {{ 'labels.commons.is' | translate }}
|
||||
<strong>{{ 'labels.commons.required' | translate }}</strong>
|
||||
</mat-error>
|
||||
</mat-form-field>
|
||||
|
||||
<mat-form-field class="flex-48">
|
||||
<mat-label>{{ 'labels.inputs.Decimal Places' | translate }}</mat-label>
|
||||
<input
|
||||
type="number"
|
||||
min="0"
|
||||
matTooltip="{{ 'tooltips.Number of decimal places to be used to track and report' | translate }}"
|
||||
matInput
|
||||
formControlName="digitsAfterDecimal"
|
||||
required
|
||||
/>
|
||||
<mat-error *ngIf="loanProductCurrencyForm.get('digitsAfterDecimal')?.hasError('required')">
|
||||
{{ 'labels.inputs.Decimal Places' | translate }} {{ 'labels.commons.is' | translate }}
|
||||
<strong>{{ 'labels.commons.required' | translate }}</strong>
|
||||
</mat-error>
|
||||
<mat-error *ngIf="loanProductCurrencyForm.get('digitsAfterDecimal')?.hasError('min')">
|
||||
{{ 'labels.inputs.Decimal Places' | translate }} {{ 'labels.commons.Minimum Value must be' | translate }}
|
||||
<strong>0</strong>
|
||||
</mat-error>
|
||||
</mat-form-field>
|
||||
|
||||
<mat-checkbox labelPosition="before" formControlName="setMultiples" class="flex-98 margin-t align-center">
|
||||
{{ 'labels.inputs.Set the multiples of the loan and its installment' | translate }}
|
||||
</mat-checkbox>
|
||||
|
||||
@if (loanProductCurrencyForm.value.setMultiples) {
|
||||
<mat-form-field class="flex-48">
|
||||
<mat-label>{{ 'labels.inputs.Currency in multiples of' | translate }}</mat-label>
|
||||
<mat-form-field appearance="outline" class="lpc-field">
|
||||
<mat-label>{{ 'labels.inputs.Decimal Places' | translate }}</mat-label>
|
||||
<input
|
||||
type="number"
|
||||
min="1"
|
||||
min="0"
|
||||
matTooltip="{{ 'tooltips.Number of decimal places to be used to track and report' | translate }}"
|
||||
matInput
|
||||
matTooltip="{{ 'tooltips.Enter multiples of currency value' | translate }}"
|
||||
formControlName="inMultiplesOf"
|
||||
formControlName="digitsAfterDecimal"
|
||||
required
|
||||
/>
|
||||
<mat-error *ngIf="loanProductCurrencyForm.get('inMultiplesOf')?.hasError('required')">
|
||||
{{ 'labels.inputs.Currency in multiples of' | translate }} {{ 'labels.commons.is' | translate }}
|
||||
<strong>{{ 'labels.commons.required' | translate }}</strong>
|
||||
</mat-error>
|
||||
<mat-error *ngIf="loanProductCurrencyForm.get('inMultiplesOf')?.hasError('min')">
|
||||
{{ 'labels.inputs.Currency in multiples of' | translate }}
|
||||
{{ 'labels.commons.Minimum Value must be' | translate }} <strong>1</strong>
|
||||
</mat-error>
|
||||
@if (loanProductCurrencyForm.get('digitsAfterDecimal')?.hasError('required')) {
|
||||
<mat-error>
|
||||
{{ 'labels.inputs.Decimal Places' | translate }} {{ 'labels.commons.is' | translate }}
|
||||
<strong>{{ 'labels.commons.required' | translate }}</strong>
|
||||
</mat-error>
|
||||
}
|
||||
@if (loanProductCurrencyForm.get('digitsAfterDecimal')?.hasError('min')) {
|
||||
<mat-error>
|
||||
{{ 'labels.inputs.Decimal Places' | translate }} {{ 'labels.commons.Minimum Value must be' | translate }}
|
||||
<strong>0</strong>
|
||||
</mat-error>
|
||||
}
|
||||
</mat-form-field>
|
||||
|
||||
<mat-form-field class="flex-48">
|
||||
<mat-label>{{ 'labels.inputs.Installment in multiples of' | translate }}</mat-label>
|
||||
<input type="number" min="1" matInput formControlName="installmentAmountInMultiplesOf" required />
|
||||
<mat-error *ngIf="loanProductCurrencyForm.get('installmentAmountInMultiplesOf')?.hasError('required')">
|
||||
{{ 'labels.inputs.Installment in multiples of' | translate }} {{ 'labels.commons.is' | translate }}
|
||||
<strong>{{ 'labels.commons.required' | translate }}</strong>
|
||||
</mat-error>
|
||||
<mat-error *ngIf="loanProductCurrencyForm.get('installmentAmountInMultiplesOf')?.hasError('min')">
|
||||
{{ 'labels.inputs.Installment in multiples of' | translate }}
|
||||
{{ 'labels.commons.Minimum Value must be' | translate }} <strong>1</strong>
|
||||
</mat-error>
|
||||
</mat-form-field>
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="layout-row align-center gap-2percent margin-t responsive-column">
|
||||
<button mat-raised-button matStepperPrevious>
|
||||
<fa-icon icon="arrow-left" class="m-r-10"></fa-icon>
|
||||
{{ 'labels.buttons.Previous' | translate }}
|
||||
</button>
|
||||
<button mat-raised-button matStepperNext>
|
||||
{{ 'labels.buttons.Next' | translate }}
|
||||
<fa-icon icon="arrow-right" class="m-l-10"></fa-icon>
|
||||
</button>
|
||||
<div class="lpc-section">
|
||||
<div class="lpc-section__header">
|
||||
<i class="fas fa-calculator"></i>
|
||||
<h3>{{ 'labels.inputs.Multiples' | translate }}</h3>
|
||||
</div>
|
||||
<div class="lpc-grid">
|
||||
<div class="lpc-field--full lpc-checkbox-row">
|
||||
<mat-checkbox labelPosition="before" formControlName="setMultiples">
|
||||
{{ 'labels.inputs.Set the multiples of the loan and its installment' | translate }}
|
||||
</mat-checkbox>
|
||||
</div>
|
||||
|
||||
@if (loanProductCurrencyForm.value.setMultiples) {
|
||||
<mat-form-field appearance="outline" class="lpc-field">
|
||||
<mat-label>{{ 'labels.inputs.Currency in multiples of' | translate }}</mat-label>
|
||||
<input
|
||||
type="number"
|
||||
min="1"
|
||||
matInput
|
||||
matTooltip="{{ 'tooltips.Enter multiples of currency value' | translate }}"
|
||||
formControlName="inMultiplesOf"
|
||||
required
|
||||
/>
|
||||
@if (loanProductCurrencyForm.get('inMultiplesOf')?.hasError('required')) {
|
||||
<mat-error>
|
||||
{{ 'labels.inputs.Currency in multiples of' | translate }} {{ 'labels.commons.is' | translate }}
|
||||
<strong>{{ 'labels.commons.required' | translate }}</strong>
|
||||
</mat-error>
|
||||
}
|
||||
@if (loanProductCurrencyForm.get('inMultiplesOf')?.hasError('min')) {
|
||||
<mat-error>
|
||||
{{ 'labels.inputs.Currency in multiples of' | translate }}
|
||||
{{ 'labels.commons.Minimum Value must be' | translate }} <strong>1</strong>
|
||||
</mat-error>
|
||||
}
|
||||
</mat-form-field>
|
||||
|
||||
<mat-form-field appearance="outline" class="lpc-field">
|
||||
<mat-label>{{ 'labels.inputs.Installment in multiples of' | translate }}</mat-label>
|
||||
<input type="number" min="1" matInput formControlName="installmentAmountInMultiplesOf" required />
|
||||
@if (loanProductCurrencyForm.get('installmentAmountInMultiplesOf')?.hasError('required')) {
|
||||
<mat-error>
|
||||
{{ 'labels.inputs.Installment in multiples of' | translate }} {{ 'labels.commons.is' | translate }}
|
||||
<strong>{{ 'labels.commons.required' | translate }}</strong>
|
||||
</mat-error>
|
||||
}
|
||||
@if (loanProductCurrencyForm.get('installmentAmountInMultiplesOf')?.hasError('min')) {
|
||||
<mat-error>
|
||||
{{ 'labels.inputs.Installment in multiples of' | translate }}
|
||||
{{ 'labels.commons.Minimum Value must be' | translate }} <strong>1</strong>
|
||||
</mat-error>
|
||||
}
|
||||
</mat-form-field>
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
+42
-3
@@ -6,10 +6,49 @@
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
.margin-t {
|
||||
margin-top: 1em;
|
||||
$accent: #0ea5e9;
|
||||
$border: #e2e8f0;
|
||||
$gray-50: #f8f9fa;
|
||||
$gray-200: #e8eaed;
|
||||
$gray-900: #202124;
|
||||
|
||||
.lpc-section {
|
||||
border: 1px solid $border;
|
||||
border-radius: 10px;
|
||||
overflow: hidden;
|
||||
background: #fff;
|
||||
|
||||
& + & { margin-top: 16px; }
|
||||
|
||||
&__header {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 10px;
|
||||
padding: 12px 24px;
|
||||
background: $gray-50;
|
||||
border-bottom: 1px solid $gray-200;
|
||||
|
||||
i { font-size: 14px; color: $accent; }
|
||||
h3 { margin: 0; font-size: 14px; font-weight: 600; color: $gray-900; }
|
||||
}
|
||||
}
|
||||
|
||||
.align-center {
|
||||
.lpc-grid {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(2, 1fr);
|
||||
gap: 4px 16px;
|
||||
padding: 16px 24px;
|
||||
|
||||
@media (max-width: 600px) { grid-template-columns: 1fr; }
|
||||
}
|
||||
|
||||
.lpc-field {
|
||||
width: 100%;
|
||||
&--full { grid-column: 1 / -1; }
|
||||
}
|
||||
|
||||
.lpc-checkbox-row {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding: 4px 0;
|
||||
}
|
||||
|
||||
+1
-4
@@ -10,7 +10,6 @@ import { Component, OnInit, Input, inject } from '@angular/core';
|
||||
import { UntypedFormGroup, UntypedFormBuilder, Validators, ReactiveFormsModule } from '@angular/forms';
|
||||
import { MatTooltip } from '@angular/material/tooltip';
|
||||
import { MatCheckbox } from '@angular/material/checkbox';
|
||||
import { MatStepperPrevious, MatStepperNext } from '@angular/material/stepper';
|
||||
import { FaIconComponent } from '@fortawesome/angular-fontawesome';
|
||||
import { STANDALONE_SHARED_IMPORTS } from 'app/standalone-shared.module';
|
||||
|
||||
@@ -22,9 +21,7 @@ import { STANDALONE_SHARED_IMPORTS } from 'app/standalone-shared.module';
|
||||
...STANDALONE_SHARED_IMPORTS,
|
||||
MatTooltip,
|
||||
MatCheckbox,
|
||||
MatStepperPrevious,
|
||||
FaIconComponent,
|
||||
MatStepperNext
|
||||
FaIconComponent
|
||||
]
|
||||
})
|
||||
export class LoanProductCurrencyStepComponent implements OnInit {
|
||||
|
||||
+106
-102
@@ -7,113 +7,117 @@
|
||||
-->
|
||||
|
||||
<form [formGroup]="loanProductDetailsForm">
|
||||
<div class="layout-row-wrap gap-2percent responsive-column align-start-center">
|
||||
<mat-form-field class="flex-98">
|
||||
<mat-label>{{ 'labels.inputs.Product Name' | translate }}</mat-label>
|
||||
<input
|
||||
matInput
|
||||
formControlName="name"
|
||||
matTooltip="{{ 'tooltips.Product name is a unique identifier' | translate }}"
|
||||
required
|
||||
/>
|
||||
<mat-error>
|
||||
{{ 'labels.inputs.Product Name' | translate }} {{ 'labels.commons.is' | translate }}
|
||||
<strong>{{ 'labels.commons.required' | translate }}</strong>
|
||||
</mat-error>
|
||||
</mat-form-field>
|
||||
<div class="lpd-section">
|
||||
<div class="lpd-section__header">
|
||||
<i class="fas fa-info-circle"></i>
|
||||
<h3>{{ 'labels.inputs.Product Name' | translate }} & {{ 'labels.inputs.Description' | translate }}</h3>
|
||||
</div>
|
||||
<div class="lpd-grid">
|
||||
<mat-form-field appearance="outline" class="lpd-field lpd-field--full">
|
||||
<mat-label>{{ 'labels.inputs.Product Name' | translate }}</mat-label>
|
||||
<input
|
||||
matInput
|
||||
formControlName="name"
|
||||
matTooltip="{{ 'tooltips.Product name is a unique identifier' | translate }}"
|
||||
required
|
||||
/>
|
||||
<mat-error>
|
||||
{{ 'labels.inputs.Product Name' | translate }} {{ 'labels.commons.is' | translate }}
|
||||
<strong>{{ 'labels.commons.required' | translate }}</strong>
|
||||
</mat-error>
|
||||
</mat-form-field>
|
||||
|
||||
<mat-form-field class="flex-48">
|
||||
<mat-label>{{ 'labels.inputs.Short Name' | translate }}</mat-label>
|
||||
<input
|
||||
matInput
|
||||
formControlName="shortName"
|
||||
maxlength="4"
|
||||
matTooltip="{{ 'tooltips.Short name is a unique identifier' | translate }}"
|
||||
required
|
||||
/>
|
||||
<mat-error>
|
||||
{{ 'labels.inputs.Short Name' | translate }} {{ 'labels.commons.is' | translate }}
|
||||
<strong>{{ 'labels.commons.required' | translate }}</strong>
|
||||
</mat-error>
|
||||
</mat-form-field>
|
||||
<mat-form-field appearance="outline" class="lpd-field">
|
||||
<mat-label>{{ 'labels.inputs.Short Name' | translate }}</mat-label>
|
||||
<input
|
||||
matInput
|
||||
formControlName="shortName"
|
||||
maxlength="4"
|
||||
matTooltip="{{ 'tooltips.Short name is a unique identifier' | translate }}"
|
||||
required
|
||||
/>
|
||||
<mat-error>
|
||||
{{ 'labels.inputs.Short Name' | translate }} {{ 'labels.commons.is' | translate }}
|
||||
<strong>{{ 'labels.commons.required' | translate }}</strong>
|
||||
</mat-error>
|
||||
</mat-form-field>
|
||||
|
||||
<mat-form-field class="flex-48">
|
||||
<mat-label>{{ 'labels.inputs.External Id' | translate }}</mat-label>
|
||||
<input
|
||||
matInput
|
||||
formControlName="externalId"
|
||||
matTooltip="{{ 'tooltips.External Id is a unique identifier' | translate }}"
|
||||
/>
|
||||
</mat-form-field>
|
||||
<mat-form-field appearance="outline" class="lpd-field">
|
||||
<mat-label>{{ 'labels.inputs.External Id' | translate }}</mat-label>
|
||||
<input
|
||||
matInput
|
||||
formControlName="externalId"
|
||||
matTooltip="{{ 'tooltips.External Id is a unique identifier' | translate }}"
|
||||
/>
|
||||
</mat-form-field>
|
||||
|
||||
<mat-form-field class="flex-48">
|
||||
<mat-label>{{ 'labels.inputs.Fund' | translate }}</mat-label>
|
||||
<mat-select matTooltip="{{ 'tooltips.Loan products may be assigned' | translate }}" formControlName="fundId">
|
||||
@for (fund of fundData; track fund) {
|
||||
<mat-option [value]="fund.id">
|
||||
{{ fund.name }}
|
||||
</mat-option>
|
||||
}
|
||||
</mat-select>
|
||||
</mat-form-field>
|
||||
<mat-form-field appearance="outline" class="lpd-field">
|
||||
<mat-label>{{ 'labels.inputs.Fund' | translate }}</mat-label>
|
||||
<mat-select matTooltip="{{ 'tooltips.Loan products may be assigned' | translate }}" formControlName="fundId">
|
||||
@for (fund of fundData; track fund) {
|
||||
<mat-option [value]="fund.id">
|
||||
{{ fund.name }}
|
||||
</mat-option>
|
||||
}
|
||||
</mat-select>
|
||||
</mat-form-field>
|
||||
|
||||
<mat-checkbox
|
||||
labelPosition="before"
|
||||
matTooltip="{{ 'tooltips.A borrower loan counter (cycle)' | translate }}"
|
||||
formControlName="includeInBorrowerCycle"
|
||||
class="flex-48"
|
||||
>
|
||||
{{ 'labels.inputs.Include in Customer Loan Counter' | translate }}
|
||||
</mat-checkbox>
|
||||
|
||||
<mat-form-field class="flex-48" (click)="startDatePicker.open()">
|
||||
<mat-label>{{ 'labels.inputs.Start Date' | translate }}</mat-label>
|
||||
<input
|
||||
matInput
|
||||
[min]="minDate"
|
||||
[max]="maxDate"
|
||||
[matDatepicker]="startDatePicker"
|
||||
matTooltip="{{ 'tooltips.loan product will be active and available to clients' | translate }}"
|
||||
formControlName="startDate"
|
||||
/>
|
||||
<mat-datepicker-toggle matSuffix [for]="startDatePicker"></mat-datepicker-toggle>
|
||||
<mat-datepicker #startDatePicker></mat-datepicker>
|
||||
</mat-form-field>
|
||||
|
||||
<mat-form-field class="flex-48" (click)="closeDatePicker.open()">
|
||||
<mat-label>{{ 'labels.inputs.Close Date' | translate }}</mat-label>
|
||||
<input
|
||||
matInput
|
||||
[min]="minDate"
|
||||
[max]="maxDate"
|
||||
[matDatepicker]="closeDatePicker"
|
||||
matTooltip="{{ 'tooltips.loan product will become inactive and unavailable to clients' | translate }}"
|
||||
formControlName="closeDate"
|
||||
/>
|
||||
<mat-datepicker-toggle matSuffix [for]="closeDatePicker"></mat-datepicker-toggle>
|
||||
<mat-datepicker #closeDatePicker></mat-datepicker>
|
||||
</mat-form-field>
|
||||
|
||||
<mat-form-field class="flex-98">
|
||||
<mat-label>{{ 'labels.inputs.Description' | translate }}</mat-label>
|
||||
<textarea
|
||||
matInput
|
||||
matTooltip="{{ 'tooltips.Provide additional information' | translate }}"
|
||||
formControlName="description"
|
||||
cdkTextareaAutosize
|
||||
cdkAutosizeMinRows="2"
|
||||
></textarea>
|
||||
</mat-form-field>
|
||||
<div class="lpd-field lpd-checkbox-row">
|
||||
<mat-checkbox
|
||||
labelPosition="before"
|
||||
matTooltip="{{ 'tooltips.A borrower loan counter (cycle)' | translate }}"
|
||||
formControlName="includeInBorrowerCycle"
|
||||
>
|
||||
{{ 'labels.inputs.Include in Customer Loan Counter' | translate }}
|
||||
</mat-checkbox>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="layout-row align-center gap-2percent margin-t responsive-column">
|
||||
<button mat-raised-button matStepperPrevious disabled>
|
||||
<fa-icon icon="arrow-left" class="m-r-10"></fa-icon>
|
||||
{{ 'labels.buttons.Previous' | translate }}
|
||||
</button>
|
||||
<button mat-raised-button matStepperNext>
|
||||
{{ 'labels.buttons.Next' | translate }}
|
||||
<fa-icon icon="arrow-right" class="m-l-10"></fa-icon>
|
||||
</button>
|
||||
<div class="lpd-section">
|
||||
<div class="lpd-section__header">
|
||||
<i class="fas fa-calendar-alt"></i>
|
||||
<h3>{{ 'labels.inputs.Availability' | translate }}</h3>
|
||||
</div>
|
||||
<div class="lpd-grid">
|
||||
<mat-form-field appearance="outline" class="lpd-field" (click)="startDatePicker.open()">
|
||||
<mat-label>{{ 'labels.inputs.Start Date' | translate }}</mat-label>
|
||||
<input
|
||||
matInput
|
||||
[min]="minDate"
|
||||
[max]="maxDate"
|
||||
[matDatepicker]="startDatePicker"
|
||||
matTooltip="{{ 'tooltips.loan product will be active and available to clients' | translate }}"
|
||||
formControlName="startDate"
|
||||
/>
|
||||
<mat-datepicker-toggle matSuffix [for]="startDatePicker"></mat-datepicker-toggle>
|
||||
<mat-datepicker #startDatePicker></mat-datepicker>
|
||||
</mat-form-field>
|
||||
|
||||
<mat-form-field appearance="outline" class="lpd-field" (click)="closeDatePicker.open()">
|
||||
<mat-label>{{ 'labels.inputs.Close Date' | translate }}</mat-label>
|
||||
<input
|
||||
matInput
|
||||
[min]="minDate"
|
||||
[max]="maxDate"
|
||||
[matDatepicker]="closeDatePicker"
|
||||
matTooltip="{{ 'tooltips.loan product will become inactive and unavailable to clients' | translate }}"
|
||||
formControlName="closeDate"
|
||||
/>
|
||||
<mat-datepicker-toggle matSuffix [for]="closeDatePicker"></mat-datepicker-toggle>
|
||||
<mat-datepicker #closeDatePicker></mat-datepicker>
|
||||
</mat-form-field>
|
||||
|
||||
<mat-form-field appearance="outline" class="lpd-field lpd-field--full">
|
||||
<mat-label>{{ 'labels.inputs.Description' | translate }}</mat-label>
|
||||
<textarea
|
||||
matInput
|
||||
matTooltip="{{ 'tooltips.Provide additional information' | translate }}"
|
||||
formControlName="description"
|
||||
cdkTextareaAutosize
|
||||
cdkAutosizeMinRows="2"
|
||||
></textarea>
|
||||
</mat-form-field>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
+45
-2
@@ -6,6 +6,49 @@
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
.margin-t {
|
||||
margin-top: 1em;
|
||||
$accent: #0ea5e9;
|
||||
$border: #e2e8f0;
|
||||
$gray-50: #f8f9fa;
|
||||
$gray-200: #e8eaed;
|
||||
$gray-900: #202124;
|
||||
|
||||
.lpd-section {
|
||||
border: 1px solid $border;
|
||||
border-radius: 10px;
|
||||
overflow: hidden;
|
||||
background: #fff;
|
||||
|
||||
& + & { margin-top: 16px; }
|
||||
|
||||
&__header {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 10px;
|
||||
padding: 12px 24px;
|
||||
background: $gray-50;
|
||||
border-bottom: 1px solid $gray-200;
|
||||
|
||||
i { font-size: 14px; color: $accent; }
|
||||
h3 { margin: 0; font-size: 14px; font-weight: 600; color: $gray-900; }
|
||||
}
|
||||
}
|
||||
|
||||
.lpd-grid {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(2, 1fr);
|
||||
gap: 4px 16px;
|
||||
padding: 16px 24px;
|
||||
|
||||
@media (max-width: 600px) { grid-template-columns: 1fr; }
|
||||
}
|
||||
|
||||
.lpd-field {
|
||||
width: 100%;
|
||||
&--full { grid-column: 1 / -1; }
|
||||
}
|
||||
|
||||
.lpd-checkbox-row {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding: 4px 0;
|
||||
}
|
||||
|
||||
+1
-4
@@ -16,7 +16,6 @@ import { SettingsService } from 'app/settings/settings.service';
|
||||
import { MatTooltip } from '@angular/material/tooltip';
|
||||
import { MatCheckbox } from '@angular/material/checkbox';
|
||||
import { CdkTextareaAutosize } from '@angular/cdk/text-field';
|
||||
import { MatStepperPrevious, MatStepperNext } from '@angular/material/stepper';
|
||||
import { FaIconComponent } from '@fortawesome/angular-fontawesome';
|
||||
import { STANDALONE_SHARED_IMPORTS } from 'app/standalone-shared.module';
|
||||
|
||||
@@ -29,9 +28,7 @@ import { STANDALONE_SHARED_IMPORTS } from 'app/standalone-shared.module';
|
||||
MatTooltip,
|
||||
MatCheckbox,
|
||||
CdkTextareaAutosize,
|
||||
MatStepperPrevious,
|
||||
FaIconComponent,
|
||||
MatStepperNext
|
||||
FaIconComponent
|
||||
]
|
||||
})
|
||||
export class LoanProductDetailsStepComponent implements OnInit {
|
||||
|
||||
+23
-17
@@ -7,22 +7,28 @@
|
||||
-->
|
||||
|
||||
<form [formGroup]="loanProductInterestRefundForm">
|
||||
<div class="layout-row-wrap gap-2px responsive-column">
|
||||
<mat-form-field class="flex-48">
|
||||
<mat-label>{{ 'labels.inputs.Supported Interest Refund Types' | translate }}</mat-label>
|
||||
<mat-select
|
||||
multiple
|
||||
formControlName="supportedInterestRefundTypes"
|
||||
matTooltip="{{
|
||||
'tooltips.Refund transactions where interest refund will automatically be calculated' | translate
|
||||
}}"
|
||||
>
|
||||
@for (supportedTransaction of supportedInterestRefundTypesOptions; track supportedTransaction) {
|
||||
<mat-option [value]="supportedTransaction.id">
|
||||
{{ supportedTransaction.value | translateKey: 'catalogs' }}
|
||||
</mat-option>
|
||||
}
|
||||
</mat-select>
|
||||
</mat-form-field>
|
||||
<div class="lpir-section">
|
||||
<div class="lpir-section__header">
|
||||
<i class="fas fa-undo"></i>
|
||||
<h3>{{ 'labels.inputs.Supported Interest Refund Types' | translate }}</h3>
|
||||
</div>
|
||||
<div class="lpir-grid">
|
||||
<mat-form-field appearance="outline" class="lpir-field">
|
||||
<mat-label>{{ 'labels.inputs.Supported Interest Refund Types' | translate }}</mat-label>
|
||||
<mat-select
|
||||
multiple
|
||||
formControlName="supportedInterestRefundTypes"
|
||||
matTooltip="{{
|
||||
'tooltips.Refund transactions where interest refund will automatically be calculated' | translate
|
||||
}}"
|
||||
>
|
||||
@for (supportedTransaction of supportedInterestRefundTypesOptions; track supportedTransaction) {
|
||||
<mat-option [value]="supportedTransaction.id">
|
||||
{{ supportedTransaction.value | translateKey: 'catalogs' }}
|
||||
</mat-option>
|
||||
}
|
||||
</mat-select>
|
||||
</mat-form-field>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
+36
-2
@@ -6,6 +6,40 @@
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
.margin-t {
|
||||
margin-top: 1em;
|
||||
$accent: #0ea5e9;
|
||||
$border: #e2e8f0;
|
||||
$gray-50: #f8f9fa;
|
||||
$gray-200: #e8eaed;
|
||||
$gray-900: #202124;
|
||||
|
||||
.lpir-section {
|
||||
border: 1px solid $border;
|
||||
border-radius: 10px;
|
||||
overflow: hidden;
|
||||
background: #fff;
|
||||
|
||||
&__header {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 10px;
|
||||
padding: 12px 24px;
|
||||
background: $gray-50;
|
||||
border-bottom: 1px solid $gray-200;
|
||||
|
||||
i { font-size: 14px; color: $accent; }
|
||||
h3 { margin: 0; font-size: 14px; font-weight: 600; color: $gray-900; }
|
||||
}
|
||||
}
|
||||
|
||||
.lpir-grid {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(2, 1fr);
|
||||
gap: 4px 16px;
|
||||
padding: 16px 24px;
|
||||
|
||||
@media (max-width: 600px) { grid-template-columns: 1fr; }
|
||||
}
|
||||
|
||||
.lpir-field {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
-13
@@ -16,16 +16,3 @@
|
||||
[supportedInterestRefundTypes]="loanProduct.supportedInterestRefundTypes"
|
||||
>
|
||||
</mifosx-loan-product-summary>
|
||||
|
||||
<div class="layout-row responsive-column align-center gap-2px margin-t">
|
||||
<button mat-raised-button matStepperPrevious>
|
||||
<fa-icon icon="arrow-left" class="m-r-10"></fa-icon>
|
||||
{{ 'labels.buttons.Previous' | translate }}
|
||||
</button>
|
||||
<button mat-raised-button [routerLink]="['../']">
|
||||
{{ 'labels.buttons.Cancel' | translate }}
|
||||
</button>
|
||||
<button mat-raised-button color="primary" [disabled]="!isValid" (click)="submitEvent.emit()">
|
||||
{{ 'labels.buttons.Submit' | translate }}
|
||||
</button>
|
||||
</div>
|
||||
|
||||
-2
@@ -9,7 +9,6 @@
|
||||
import { Component, OnInit, Input, Output, EventEmitter, OnChanges, SimpleChanges } from '@angular/core';
|
||||
import { LoanProducts } from '../../loan-products';
|
||||
import { LoanProductSummaryComponent } from '../../common/loan-product-summary/loan-product-summary.component';
|
||||
import { MatStepperPrevious } from '@angular/material/stepper';
|
||||
import { FaIconComponent } from '@fortawesome/angular-fontawesome';
|
||||
import { STANDALONE_SHARED_IMPORTS } from 'app/standalone-shared.module';
|
||||
|
||||
@@ -20,7 +19,6 @@ import { STANDALONE_SHARED_IMPORTS } from 'app/standalone-shared.module';
|
||||
imports: [
|
||||
...STANDALONE_SHARED_IMPORTS,
|
||||
LoanProductSummaryComponent,
|
||||
MatStepperPrevious,
|
||||
FaIconComponent
|
||||
]
|
||||
})
|
||||
|
||||
+660
-605
File diff suppressed because it is too large
Load Diff
+72
-25
@@ -8,32 +8,79 @@
|
||||
|
||||
@use 'assets/styles/colours' as *;
|
||||
|
||||
h3,
|
||||
h4 {
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
h4 {
|
||||
margin: 1em 0;
|
||||
}
|
||||
|
||||
mat-divider {
|
||||
margin: 1em 0 2em;
|
||||
}
|
||||
|
||||
.margin-v {
|
||||
margin: 1em 0;
|
||||
}
|
||||
|
||||
.margin-b {
|
||||
margin: 0 0 1em;
|
||||
}
|
||||
|
||||
.margin-t {
|
||||
margin-top: 1em;
|
||||
}
|
||||
|
||||
.by-default {
|
||||
color: rgba($status-approved, 0.7);
|
||||
font-weight: 700;
|
||||
}
|
||||
|
||||
.lps-section {
|
||||
border: 1px solid #e2e8f0;
|
||||
border-radius: 10px;
|
||||
overflow: hidden;
|
||||
background: #fff;
|
||||
|
||||
& + & {
|
||||
margin-top: 16px;
|
||||
}
|
||||
|
||||
&__header {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 10px;
|
||||
padding: 12px 24px;
|
||||
background: #f8f9fa;
|
||||
border-bottom: 1px solid #e8eaed;
|
||||
}
|
||||
|
||||
&__icon {
|
||||
color: #0ea5e9;
|
||||
font-size: 16px;
|
||||
}
|
||||
|
||||
&__title {
|
||||
font-size: 14px;
|
||||
font-weight: 600;
|
||||
color: #202124;
|
||||
margin: 0;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
}
|
||||
|
||||
&__body {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(2, 1fr);
|
||||
gap: 4px 16px;
|
||||
padding: 16px 24px;
|
||||
|
||||
@media (max-width: 600px) {
|
||||
grid-template-columns: 1fr;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.lps-full-width {
|
||||
grid-column: 1 / -1;
|
||||
}
|
||||
|
||||
.lps-checkbox-row {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding: 4px 0;
|
||||
}
|
||||
|
||||
.lps-question-icon {
|
||||
font-size: 12px;
|
||||
color: #9aa0a6;
|
||||
cursor: help;
|
||||
}
|
||||
|
||||
.lps-overrides-grid {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(2, 1fr);
|
||||
gap: 4px 16px;
|
||||
|
||||
@media (max-width: 600px) {
|
||||
grid-template-columns: 1fr;
|
||||
}
|
||||
}
|
||||
|
||||
+2
-7
@@ -21,10 +21,8 @@ import { CodeName, OptionData, StringEnumOptionData } from 'app/shared/models/op
|
||||
import { ProcessingStrategyService } from '../../services/processing-strategy.service';
|
||||
import { MatTooltip } from '@angular/material/tooltip';
|
||||
import { MatCheckbox } from '@angular/material/checkbox';
|
||||
import { MatDivider } from '@angular/material/divider';
|
||||
import { MatButton, MatIconButton } from '@angular/material/button';
|
||||
import { MatIconButton } from '@angular/material/button';
|
||||
import { FaIconComponent } from '@fortawesome/angular-fontawesome';
|
||||
import { MatStepperPrevious, MatStepperNext } from '@angular/material/stepper';
|
||||
import { STANDALONE_SHARED_IMPORTS } from 'app/standalone-shared.module';
|
||||
|
||||
@Component({
|
||||
@@ -35,11 +33,8 @@ import { STANDALONE_SHARED_IMPORTS } from 'app/standalone-shared.module';
|
||||
...STANDALONE_SHARED_IMPORTS,
|
||||
MatTooltip,
|
||||
MatCheckbox,
|
||||
MatDivider,
|
||||
MatIconButton,
|
||||
FaIconComponent,
|
||||
MatStepperPrevious,
|
||||
MatStepperNext
|
||||
FaIconComponent
|
||||
]
|
||||
})
|
||||
export class LoanProductSettingsStepComponent implements OnInit {
|
||||
|
||||
+524
-489
File diff suppressed because it is too large
Load Diff
+121
-18
@@ -6,27 +6,130 @@
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
table {
|
||||
width: 100%;
|
||||
.lpt-section {
|
||||
border: 1px solid #e2e8f0;
|
||||
border-radius: 10px;
|
||||
overflow: hidden;
|
||||
background: #fff;
|
||||
|
||||
& + & {
|
||||
margin-top: 16px;
|
||||
}
|
||||
}
|
||||
|
||||
.mat-elevation-z1 {
|
||||
margin: 1em 0 1.5em;
|
||||
.lpt-section-header {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 10px;
|
||||
padding: 12px 24px;
|
||||
background: #f8f9fa;
|
||||
border-bottom: 1px solid #e8eaed;
|
||||
|
||||
h3 {
|
||||
font-size: 14px;
|
||||
font-weight: 600;
|
||||
color: #202124;
|
||||
margin: 0;
|
||||
}
|
||||
}
|
||||
|
||||
h3,
|
||||
h4 {
|
||||
.lpt-section-icon {
|
||||
color: #0ea5e9;
|
||||
font-size: 15px;
|
||||
}
|
||||
|
||||
.lpt-help-icon {
|
||||
color: #9aa0a6;
|
||||
font-size: 13px;
|
||||
cursor: help;
|
||||
}
|
||||
|
||||
.lpt-grid {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(2, 1fr);
|
||||
gap: 4px 16px;
|
||||
padding: 16px 24px;
|
||||
|
||||
@media (max-width: 600px) {
|
||||
grid-template-columns: 1fr;
|
||||
}
|
||||
}
|
||||
|
||||
.lpt-grid-3 {
|
||||
grid-template-columns: repeat(3, 1fr);
|
||||
|
||||
@media (max-width: 600px) {
|
||||
grid-template-columns: 1fr;
|
||||
}
|
||||
}
|
||||
|
||||
.lpt-grid-4 {
|
||||
grid-template-columns: repeat(4, 1fr);
|
||||
|
||||
@media (max-width: 900px) {
|
||||
grid-template-columns: repeat(2, 1fr);
|
||||
}
|
||||
|
||||
@media (max-width: 600px) {
|
||||
grid-template-columns: 1fr;
|
||||
}
|
||||
}
|
||||
|
||||
.lpt-full-width {
|
||||
grid-column: 1 / -1;
|
||||
}
|
||||
|
||||
.lpt-checkbox-row {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding: 4px 0;
|
||||
}
|
||||
|
||||
.lpt-subsection {
|
||||
padding: 0 24px 16px;
|
||||
|
||||
&:first-of-type {
|
||||
padding-top: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.lpt-subsection-title {
|
||||
font-size: 13px;
|
||||
font-weight: 600;
|
||||
color: #3c4043;
|
||||
margin: 8px 0 12px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
}
|
||||
|
||||
.lpt-subsection-header {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
margin-bottom: 12px;
|
||||
|
||||
.lpt-subsection-title {
|
||||
margin: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.lpt-table-wrapper {
|
||||
border: 1px solid #e2e8f0;
|
||||
border-radius: 8px;
|
||||
overflow: hidden;
|
||||
margin-bottom: 16px;
|
||||
|
||||
table {
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
.lpt-label-field {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
font-size: 14px;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
h4 {
|
||||
margin: 1em 0;
|
||||
}
|
||||
|
||||
mat-divider {
|
||||
margin: 1em 0 2em;
|
||||
}
|
||||
|
||||
.margin-t {
|
||||
margin-top: 1em;
|
||||
color: #3c4043;
|
||||
padding: 8px 0;
|
||||
}
|
||||
|
||||
-5
@@ -27,7 +27,6 @@ import { ProcessingStrategyService } from '../../services/processing-strategy.se
|
||||
import { TranslateService } from '@ngx-translate/core';
|
||||
import { MatTooltip } from '@angular/material/tooltip';
|
||||
import { MatCheckbox } from '@angular/material/checkbox';
|
||||
import { MatDivider } from '@angular/material/divider';
|
||||
import { MatButton, MatIconButton } from '@angular/material/button';
|
||||
import { FaIconComponent } from '@fortawesome/angular-fontawesome';
|
||||
import {
|
||||
@@ -42,7 +41,6 @@ import {
|
||||
MatRowDef,
|
||||
MatRow
|
||||
} from '@angular/material/table';
|
||||
import { MatStepperPrevious, MatStepperNext } from '@angular/material/stepper';
|
||||
import { FindPipe } from '../../../../pipes/find.pipe';
|
||||
import { STANDALONE_SHARED_IMPORTS } from 'app/standalone-shared.module';
|
||||
|
||||
@@ -54,7 +52,6 @@ import { STANDALONE_SHARED_IMPORTS } from 'app/standalone-shared.module';
|
||||
...STANDALONE_SHARED_IMPORTS,
|
||||
MatTooltip,
|
||||
MatCheckbox,
|
||||
MatDivider,
|
||||
FaIconComponent,
|
||||
MatTable,
|
||||
MatColumnDef,
|
||||
@@ -67,8 +64,6 @@ import { STANDALONE_SHARED_IMPORTS } from 'app/standalone-shared.module';
|
||||
MatHeaderRow,
|
||||
MatRowDef,
|
||||
MatRow,
|
||||
MatStepperPrevious,
|
||||
MatStepperNext,
|
||||
FindPipe
|
||||
]
|
||||
})
|
||||
|
||||
@@ -23,8 +23,9 @@
|
||||
|
||||
<div class="container">
|
||||
<div #filter class="layout-row">
|
||||
<mat-form-field class="flex-fill">
|
||||
<mat-form-field appearance="outline" class="flex-fill">
|
||||
<mat-label>{{ 'labels.inputs.Filter' | translate }}</mat-label>
|
||||
<i matPrefix class="fas fa-search"></i>
|
||||
<input matInput (keyup)="applyFilter($event.target.value)" />
|
||||
</mat-form-field>
|
||||
</div>
|
||||
|
||||
+51
-23
@@ -6,12 +6,26 @@
|
||||
file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
-->
|
||||
|
||||
<div class="container">
|
||||
<mat-card>
|
||||
<div class="db-container">
|
||||
<!-- Header -->
|
||||
<div class="db-header">
|
||||
<button mat-stroked-button [routerLink]="['../']" class="db-back">
|
||||
<i class="fas fa-arrow-left"></i> {{ 'labels.heading.Delinquency Buckets' | translate }}
|
||||
</button>
|
||||
<h2 class="db-header__title">{{ 'labels.buttons.Create Delinquency Bucket' | translate }}</h2>
|
||||
</div>
|
||||
|
||||
<!-- Form Card -->
|
||||
<div class="db-card">
|
||||
<form [formGroup]="bucketForm" (ngSubmit)="submit()">
|
||||
<mat-card-content>
|
||||
<div class="layout-row-wrap gap-2px responsive-column">
|
||||
<mat-form-field class="flex-100">
|
||||
<!-- Bucket Details Section -->
|
||||
<div class="db-section">
|
||||
<div class="db-section__header">
|
||||
<i class="fas fa-layer-group"></i>
|
||||
<h3>{{ 'labels.heading.Delinquency Buckets' | translate }}</h3>
|
||||
</div>
|
||||
<div class="db-grid">
|
||||
<mat-form-field appearance="outline" class="db-field db-field--full">
|
||||
<mat-label>{{ 'labels.inputs.Name' | translate }}</mat-label>
|
||||
<input matInput required formControlName="name" />
|
||||
@if (bucketForm.controls.name.hasError('required')) {
|
||||
@@ -21,17 +35,21 @@
|
||||
</mat-error>
|
||||
}
|
||||
</mat-form-field>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<h3 class="mat-h3 flex-40">{{ 'labels.heading.Delinquency Ranges' | translate }}</h3>
|
||||
|
||||
<div class="flex-40 layout-row align-start-center">
|
||||
<button type="button" mat-raised-button color="primary" (click)="addDelinquencyRange()">
|
||||
<fa-icon icon="plus" class="m-r-10"></fa-icon>
|
||||
{{ 'labels.buttons.Add' | translate }}
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<table mat-table [dataSource]="rangesDataSource" [hidden]="rangesDataSource.length === 0">
|
||||
<!-- Delinquency Ranges Section -->
|
||||
<div class="db-section">
|
||||
<div class="db-section__header">
|
||||
<i class="fas fa-sliders-h"></i>
|
||||
<h3>{{ 'labels.heading.Delinquency Ranges' | translate }}</h3>
|
||||
<button type="button" mat-flat-button color="primary" class="db-add-btn" (click)="addDelinquencyRange()">
|
||||
<fa-icon icon="plus"></fa-icon>
|
||||
{{ 'labels.buttons.Add' | translate }}
|
||||
</button>
|
||||
</div>
|
||||
<div class="db-ranges-body">
|
||||
<table mat-table [dataSource]="rangesDataSource" [hidden]="rangesDataSource.length === 0" class="db-ranges-table">
|
||||
<ng-container matColumnDef="classification">
|
||||
<th mat-header-cell *matHeaderCellDef>{{ 'labels.inputs.Classification' | translate }}</th>
|
||||
<td mat-cell *matCellDef="let row">
|
||||
@@ -72,22 +90,32 @@
|
||||
<tr mat-header-row *matHeaderRowDef="displayedColumns"></tr>
|
||||
<tr mat-row *matRowDef="let row; columns: displayedColumns"></tr>
|
||||
</table>
|
||||
</div>
|
||||
</mat-card-content>
|
||||
|
||||
<mat-card-actions class="layout-row align-center gap-5px responsive-column">
|
||||
<button type="button" mat-raised-button [routerLink]="['../']">
|
||||
@if (rangesDataSource.length === 0) {
|
||||
<div class="db-empty">
|
||||
<i class="fas fa-inbox"></i>
|
||||
<p>No delinquency ranges added yet</p>
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Actions -->
|
||||
<div class="db-actions">
|
||||
<button type="button" mat-stroked-button [routerLink]="['../']" class="db-actions__cancel">
|
||||
{{ 'labels.buttons.Cancel' | translate }}
|
||||
</button>
|
||||
<button
|
||||
mat-raised-button
|
||||
type="submit"
|
||||
mat-flat-button
|
||||
color="primary"
|
||||
[disabled]="!bucketForm.valid"
|
||||
*mifosxHasPermission="'CREATE_DELINQUENCY_BUCKET'"
|
||||
class="db-actions__submit"
|
||||
>
|
||||
{{ 'labels.buttons.Submit' | translate }}
|
||||
<i class="fas fa-check"></i> {{ 'labels.buttons.Submit' | translate }}
|
||||
</button>
|
||||
</mat-card-actions>
|
||||
</div>
|
||||
</form>
|
||||
</mat-card>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
+201
-6
@@ -6,13 +6,208 @@
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
.container {
|
||||
max-width: 37rem;
|
||||
$primary: #1353a0;
|
||||
$accent: #0ea5e9;
|
||||
$border: #e2e8f0;
|
||||
$gray-50: #f8f9fa;
|
||||
$gray-200: #e8eaed;
|
||||
$gray-500: #9aa0a6;
|
||||
$gray-700: #5f6368;
|
||||
$gray-900: #202124;
|
||||
|
||||
.content {
|
||||
div {
|
||||
margin: 0.8rem 0;
|
||||
word-wrap: break-word;
|
||||
.db-container {
|
||||
max-width: 960px;
|
||||
margin: 0 auto;
|
||||
padding: 20px 16px;
|
||||
}
|
||||
|
||||
// Header
|
||||
.db-header {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 14px;
|
||||
margin-bottom: 20px;
|
||||
|
||||
&__title {
|
||||
font-size: 18px;
|
||||
font-weight: 600;
|
||||
color: $gray-900;
|
||||
margin: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.db-back {
|
||||
border-radius: 8px !important;
|
||||
font-size: 12px !important;
|
||||
font-weight: 600 !important;
|
||||
height: 32px !important;
|
||||
border-color: $border !important;
|
||||
color: $gray-500 !important;
|
||||
|
||||
i { margin-right: 6px; }
|
||||
|
||||
&:hover { color: $primary !important; border-color: $primary !important; }
|
||||
}
|
||||
|
||||
// Card
|
||||
.db-card {
|
||||
background: #fff;
|
||||
border: 1px solid $border;
|
||||
border-radius: 10px;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
// Section
|
||||
.db-section {
|
||||
&__header {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 10px;
|
||||
padding: 12px 24px;
|
||||
background: $gray-50;
|
||||
border-bottom: 1px solid $gray-200;
|
||||
|
||||
i {
|
||||
font-size: 14px;
|
||||
color: $accent;
|
||||
}
|
||||
|
||||
h3 {
|
||||
margin: 0;
|
||||
font-size: 14px;
|
||||
font-weight: 600;
|
||||
color: $gray-900;
|
||||
}
|
||||
}
|
||||
|
||||
& + & {
|
||||
border-top: 1px solid $gray-200;
|
||||
}
|
||||
}
|
||||
|
||||
// Grid
|
||||
.db-grid {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(2, 1fr);
|
||||
gap: 4px 16px;
|
||||
padding: 16px 24px;
|
||||
|
||||
@media (max-width: 600px) { grid-template-columns: 1fr; }
|
||||
}
|
||||
|
||||
.db-field {
|
||||
width: 100%;
|
||||
|
||||
&--full {
|
||||
grid-column: 1 / -1;
|
||||
}
|
||||
}
|
||||
|
||||
// Add button in section header
|
||||
.db-add-btn {
|
||||
margin-left: auto !important;
|
||||
border-radius: 8px !important;
|
||||
font-size: 12px !important;
|
||||
font-weight: 600 !important;
|
||||
height: 30px !important;
|
||||
padding: 0 14px !important;
|
||||
box-shadow: 0 1px 3px rgba($primary, 0.25) !important;
|
||||
|
||||
fa-icon { margin-right: 6px; font-size: 11px; }
|
||||
}
|
||||
|
||||
// Ranges table
|
||||
.db-ranges-body {
|
||||
padding: 16px 24px;
|
||||
}
|
||||
|
||||
.db-ranges-table {
|
||||
width: 100%;
|
||||
border: 1px solid $border;
|
||||
border-radius: 8px;
|
||||
overflow: hidden;
|
||||
|
||||
::ng-deep {
|
||||
.mat-mdc-header-row {
|
||||
background: #f8fafc;
|
||||
min-height: 36px;
|
||||
height: 36px;
|
||||
}
|
||||
|
||||
.mat-mdc-header-cell {
|
||||
font-size: 10px;
|
||||
font-weight: 600;
|
||||
text-transform: uppercase;
|
||||
letter-spacing: 0.06em;
|
||||
color: #64748b;
|
||||
border-bottom: 1px solid $border;
|
||||
padding: 0 14px;
|
||||
}
|
||||
|
||||
.mat-mdc-row {
|
||||
min-height: 40px;
|
||||
height: 40px;
|
||||
border-bottom: 1px solid #f1f5f9;
|
||||
|
||||
&:last-child { border-bottom: none; }
|
||||
}
|
||||
|
||||
.mat-mdc-cell {
|
||||
font-size: 13px;
|
||||
font-weight: 400;
|
||||
color: $gray-900;
|
||||
padding: 0 14px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Empty state
|
||||
.db-empty {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
padding: 32px 16px;
|
||||
text-align: center;
|
||||
|
||||
i {
|
||||
font-size: 28px;
|
||||
color: #cbd5e1;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
p {
|
||||
font-size: 13px;
|
||||
color: #94a3b8;
|
||||
margin: 0;
|
||||
}
|
||||
}
|
||||
|
||||
// Actions
|
||||
.db-actions {
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
gap: 10px;
|
||||
padding: 14px 24px;
|
||||
border-top: 1px solid $gray-200;
|
||||
background: $gray-50;
|
||||
|
||||
&__cancel {
|
||||
border-radius: 8px !important;
|
||||
font-size: 13px !important;
|
||||
font-weight: 600 !important;
|
||||
height: 36px !important;
|
||||
border-color: $border !important;
|
||||
color: $gray-700 !important;
|
||||
}
|
||||
|
||||
&__submit {
|
||||
border-radius: 8px !important;
|
||||
font-size: 13px !important;
|
||||
font-weight: 600 !important;
|
||||
height: 36px !important;
|
||||
box-shadow: 0 1px 3px rgba($primary, 0.3) !important;
|
||||
|
||||
i { margin-right: 6px; font-size: 12px; }
|
||||
}
|
||||
}
|
||||
|
||||
+31
-21
@@ -6,37 +6,47 @@
|
||||
file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
-->
|
||||
|
||||
<div class="container m-b-20 layout-row align-end gap-20px">
|
||||
<button
|
||||
mat-raised-button
|
||||
color="primary"
|
||||
[routerLink]="['create']"
|
||||
*mifosxHasPermission="'CREATE_DELINQUENCY_BUCKET'"
|
||||
>
|
||||
<fa-icon icon="plus" class="m-r-10"></fa-icon>
|
||||
{{ 'labels.buttons.Create Delinquency Bucket' | translate }}
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<div class="container">
|
||||
<div class="layout-row">
|
||||
<mat-form-field class="flex-fill">
|
||||
<mat-label>{{ 'labels.inputs.Filter' | translate }}</mat-label>
|
||||
<input matInput (keyup)="applyFilter($event.target.value)" />
|
||||
</mat-form-field>
|
||||
<div class="table-header">
|
||||
<div class="table-title-group">
|
||||
<h2 class="table-title">
|
||||
<i class="fas fa-layer-group title-icon"></i>
|
||||
{{ 'labels.heading.Delinquency Buckets' | translate }}
|
||||
</h2>
|
||||
</div>
|
||||
<div class="table-actions">
|
||||
<div class="table-search">
|
||||
<mat-form-field appearance="outline">
|
||||
<i matPrefix class="fas fa-search"></i>
|
||||
<mat-label>{{ 'labels.inputs.Filter' | translate }}</mat-label>
|
||||
<input matInput (keyup)="applyFilter($event.target.value)" />
|
||||
</mat-form-field>
|
||||
</div>
|
||||
<div class="table-buttons">
|
||||
<button
|
||||
mat-flat-button
|
||||
color="primary"
|
||||
class="btn-create"
|
||||
[routerLink]="['create']"
|
||||
*mifosxHasPermission="'CREATE_DELINQUENCY_BUCKET'"
|
||||
>
|
||||
<fa-icon icon="plus" class="m-r-10"></fa-icon>
|
||||
{{ 'labels.buttons.Create Delinquency Bucket' | translate }}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="mat-elevation-z8">
|
||||
<table mat-table [dataSource]="dataSource" matSort>
|
||||
<div class="table-container">
|
||||
<table mat-table [dataSource]="dataSource" matSort class="modern-table">
|
||||
<ng-container matColumnDef="name">
|
||||
<th mat-header-cell *matHeaderCellDef mat-sort-header>{{ 'labels.inputs.Name' | translate }}</th>
|
||||
<td mat-cell *matCellDef="let delinquencyBucket">{{ delinquencyBucket.name }}</td>
|
||||
</ng-container>
|
||||
|
||||
<tr mat-header-row *matHeaderRowDef="displayedColumns"></tr>
|
||||
<tr mat-row *matRowDef="let row; columns: displayedColumns" [routerLink]="[row.id]" class="select-row"></tr>
|
||||
<tr mat-row *matRowDef="let row; columns: displayedColumns" [routerLink]="[row.id]" class="table-row"></tr>
|
||||
</table>
|
||||
|
||||
<mat-paginator [pageSizeOptions]="[10, 25, 50, 100]" showFirstLastButtons></mat-paginator>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
+1
-20
@@ -6,23 +6,4 @@
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
.container {
|
||||
.action-button {
|
||||
margin-left: auto;
|
||||
}
|
||||
|
||||
.search-button {
|
||||
min-width: 30px;
|
||||
margin: 4px;
|
||||
}
|
||||
}
|
||||
|
||||
table {
|
||||
tr.select-row:hover {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
tr:nth-child(odd).td {
|
||||
color: black;
|
||||
}
|
||||
}
|
||||
@use '../../../shared/styles/list-layout' as *;
|
||||
|
||||
+51
-32
@@ -6,12 +6,26 @@
|
||||
file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
-->
|
||||
|
||||
<div class="container">
|
||||
<mat-card>
|
||||
<div class="db-container">
|
||||
<!-- Header -->
|
||||
<div class="db-header">
|
||||
<button mat-stroked-button [routerLink]="['../']" class="db-back">
|
||||
<i class="fas fa-arrow-left"></i> {{ 'labels.heading.Delinquency Buckets' | translate }}
|
||||
</button>
|
||||
<h2 class="db-header__title">{{ 'labels.buttons.Edit' | translate }} {{ delinquencyBucketData.name }}</h2>
|
||||
</div>
|
||||
|
||||
<!-- Form Card -->
|
||||
<div class="db-card">
|
||||
<form [formGroup]="bucketForm" (ngSubmit)="submit()">
|
||||
<mat-card-content>
|
||||
<div class="layout-row-wrap gap-2px responsive-column">
|
||||
<mat-form-field class="flex-100">
|
||||
<!-- Bucket Details Section -->
|
||||
<div class="db-section">
|
||||
<div class="db-section__header">
|
||||
<i class="fas fa-layer-group"></i>
|
||||
<h3>{{ 'labels.heading.Delinquency Buckets' | translate }}</h3>
|
||||
</div>
|
||||
<div class="db-grid">
|
||||
<mat-form-field appearance="outline" class="db-field db-field--full">
|
||||
<mat-label>{{ 'labels.inputs.Name' | translate }}</mat-label>
|
||||
<input matInput required formControlName="name" />
|
||||
@if (bucketForm.controls.name.hasError('required')) {
|
||||
@@ -21,39 +35,34 @@
|
||||
</mat-error>
|
||||
}
|
||||
</mat-form-field>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<h3 class="mat-h3 flex-40">{{ 'labels.heading.Delinquency Ranges' | translate }}</h3>
|
||||
|
||||
<div class="flex-40 layout-row align-start-center">
|
||||
<button type="button" mat-raised-button color="primary" (click)="addDelinquencyRange()">
|
||||
<fa-icon icon="plus" class="m-r-10"></fa-icon>
|
||||
{{ 'labels.buttons.Add' | translate }}
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<table mat-table [dataSource]="rangesDataSource" [hidden]="rangesDataSource.length === 0">
|
||||
<!-- Delinquency Ranges Section -->
|
||||
<div class="db-section">
|
||||
<div class="db-section__header">
|
||||
<i class="fas fa-sliders-h"></i>
|
||||
<h3>{{ 'labels.heading.Delinquency Ranges' | translate }}</h3>
|
||||
<button type="button" mat-flat-button color="primary" class="db-add-btn" (click)="addDelinquencyRange()">
|
||||
<fa-icon icon="plus"></fa-icon>
|
||||
{{ 'labels.buttons.Add' | translate }}
|
||||
</button>
|
||||
</div>
|
||||
<div class="db-ranges-body">
|
||||
<table mat-table [dataSource]="rangesDataSource" [hidden]="rangesDataSource.length === 0" class="db-ranges-table">
|
||||
<ng-container matColumnDef="classification">
|
||||
<th mat-header-cell *matHeaderCellDef>{{ 'labels.inputs.Classification' | translate }}</th>
|
||||
<td mat-cell *matCellDef="let row">{{ row.classification }}</td>
|
||||
<td mat-cell *matCellDef="let row">
|
||||
{{ row.rangeId | find: delinquencyRangesData : 'id' : 'classification' }}
|
||||
</td>
|
||||
</ng-container>
|
||||
|
||||
<ng-container matColumnDef="minimumAgeDays">
|
||||
<th mat-header-cell *matHeaderCellDef>{{ 'labels.inputs.Days From' | translate }}</th>
|
||||
<td mat-cell *matCellDef="let row">{{ row.minimumAgeDays }}</td>
|
||||
<td mat-cell *matCellDef="let row">
|
||||
{{ row.rangeId | find: delinquencyRangesData : 'id' : 'minimumAgeDays' }}
|
||||
</td>
|
||||
</ng-container>
|
||||
|
||||
<ng-container matColumnDef="maximumAgeDays">
|
||||
<th mat-header-cell *matHeaderCellDef>{{ 'labels.inputs.Days Till' | translate }}</th>
|
||||
<td mat-cell *matCellDef="let row">{{ row.maximumAgeDays }}</td>
|
||||
<td mat-cell *matCellDef="let row">
|
||||
{{ row.rangeId | find: delinquencyRangesData : 'id' : 'maximumAgeDays' }}
|
||||
</td>
|
||||
</ng-container>
|
||||
|
||||
<ng-container matColumnDef="actions">
|
||||
@@ -75,22 +84,32 @@
|
||||
<tr mat-header-row *matHeaderRowDef="displayedColumns"></tr>
|
||||
<tr mat-row *matRowDef="let row; columns: displayedColumns"></tr>
|
||||
</table>
|
||||
</div>
|
||||
</mat-card-content>
|
||||
|
||||
<mat-card-actions class="layout-row align-center gap-5px responsive-column">
|
||||
<button type="button" mat-raised-button [routerLink]="['../']">
|
||||
@if (rangesDataSource.length === 0) {
|
||||
<div class="db-empty">
|
||||
<i class="fas fa-inbox"></i>
|
||||
<p>No delinquency ranges added yet</p>
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Actions -->
|
||||
<div class="db-actions">
|
||||
<button type="button" mat-stroked-button [routerLink]="['../']" class="db-actions__cancel">
|
||||
{{ 'labels.buttons.Cancel' | translate }}
|
||||
</button>
|
||||
<button
|
||||
mat-raised-button
|
||||
type="submit"
|
||||
mat-flat-button
|
||||
color="primary"
|
||||
[disabled]="!dataWasChanged"
|
||||
*mifosxHasPermission="'UPDATE_DELINQUENCY_BUCKET'"
|
||||
class="db-actions__submit"
|
||||
>
|
||||
{{ 'labels.buttons.Submit' | translate }}
|
||||
<i class="fas fa-check"></i> {{ 'labels.buttons.Submit' | translate }}
|
||||
</button>
|
||||
</mat-card-actions>
|
||||
</div>
|
||||
</form>
|
||||
</mat-card>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
+201
-6
@@ -6,13 +6,208 @@
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
.container {
|
||||
max-width: 37rem;
|
||||
$primary: #1353a0;
|
||||
$accent: #0ea5e9;
|
||||
$border: #e2e8f0;
|
||||
$gray-50: #f8f9fa;
|
||||
$gray-200: #e8eaed;
|
||||
$gray-500: #9aa0a6;
|
||||
$gray-700: #5f6368;
|
||||
$gray-900: #202124;
|
||||
|
||||
.content {
|
||||
div {
|
||||
margin: 0.8rem 0;
|
||||
word-wrap: break-word;
|
||||
.db-container {
|
||||
max-width: 960px;
|
||||
margin: 0 auto;
|
||||
padding: 20px 16px;
|
||||
}
|
||||
|
||||
// Header
|
||||
.db-header {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 14px;
|
||||
margin-bottom: 20px;
|
||||
|
||||
&__title {
|
||||
font-size: 18px;
|
||||
font-weight: 600;
|
||||
color: $gray-900;
|
||||
margin: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.db-back {
|
||||
border-radius: 8px !important;
|
||||
font-size: 12px !important;
|
||||
font-weight: 600 !important;
|
||||
height: 32px !important;
|
||||
border-color: $border !important;
|
||||
color: $gray-500 !important;
|
||||
|
||||
i { margin-right: 6px; }
|
||||
|
||||
&:hover { color: $primary !important; border-color: $primary !important; }
|
||||
}
|
||||
|
||||
// Card
|
||||
.db-card {
|
||||
background: #fff;
|
||||
border: 1px solid $border;
|
||||
border-radius: 10px;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
// Section
|
||||
.db-section {
|
||||
&__header {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 10px;
|
||||
padding: 12px 24px;
|
||||
background: $gray-50;
|
||||
border-bottom: 1px solid $gray-200;
|
||||
|
||||
i {
|
||||
font-size: 14px;
|
||||
color: $accent;
|
||||
}
|
||||
|
||||
h3 {
|
||||
margin: 0;
|
||||
font-size: 14px;
|
||||
font-weight: 600;
|
||||
color: $gray-900;
|
||||
}
|
||||
}
|
||||
|
||||
& + & {
|
||||
border-top: 1px solid $gray-200;
|
||||
}
|
||||
}
|
||||
|
||||
// Grid
|
||||
.db-grid {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(2, 1fr);
|
||||
gap: 4px 16px;
|
||||
padding: 16px 24px;
|
||||
|
||||
@media (max-width: 600px) { grid-template-columns: 1fr; }
|
||||
}
|
||||
|
||||
.db-field {
|
||||
width: 100%;
|
||||
|
||||
&--full {
|
||||
grid-column: 1 / -1;
|
||||
}
|
||||
}
|
||||
|
||||
// Add button in section header
|
||||
.db-add-btn {
|
||||
margin-left: auto !important;
|
||||
border-radius: 8px !important;
|
||||
font-size: 12px !important;
|
||||
font-weight: 600 !important;
|
||||
height: 30px !important;
|
||||
padding: 0 14px !important;
|
||||
box-shadow: 0 1px 3px rgba($primary, 0.25) !important;
|
||||
|
||||
fa-icon { margin-right: 6px; font-size: 11px; }
|
||||
}
|
||||
|
||||
// Ranges table
|
||||
.db-ranges-body {
|
||||
padding: 16px 24px;
|
||||
}
|
||||
|
||||
.db-ranges-table {
|
||||
width: 100%;
|
||||
border: 1px solid $border;
|
||||
border-radius: 8px;
|
||||
overflow: hidden;
|
||||
|
||||
::ng-deep {
|
||||
.mat-mdc-header-row {
|
||||
background: #f8fafc;
|
||||
min-height: 36px;
|
||||
height: 36px;
|
||||
}
|
||||
|
||||
.mat-mdc-header-cell {
|
||||
font-size: 10px;
|
||||
font-weight: 600;
|
||||
text-transform: uppercase;
|
||||
letter-spacing: 0.06em;
|
||||
color: #64748b;
|
||||
border-bottom: 1px solid $border;
|
||||
padding: 0 14px;
|
||||
}
|
||||
|
||||
.mat-mdc-row {
|
||||
min-height: 40px;
|
||||
height: 40px;
|
||||
border-bottom: 1px solid #f1f5f9;
|
||||
|
||||
&:last-child { border-bottom: none; }
|
||||
}
|
||||
|
||||
.mat-mdc-cell {
|
||||
font-size: 13px;
|
||||
font-weight: 400;
|
||||
color: $gray-900;
|
||||
padding: 0 14px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Empty state
|
||||
.db-empty {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
padding: 32px 16px;
|
||||
text-align: center;
|
||||
|
||||
i {
|
||||
font-size: 28px;
|
||||
color: #cbd5e1;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
p {
|
||||
font-size: 13px;
|
||||
color: #94a3b8;
|
||||
margin: 0;
|
||||
}
|
||||
}
|
||||
|
||||
// Actions
|
||||
.db-actions {
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
gap: 10px;
|
||||
padding: 14px 24px;
|
||||
border-top: 1px solid $gray-200;
|
||||
background: $gray-50;
|
||||
|
||||
&__cancel {
|
||||
border-radius: 8px !important;
|
||||
font-size: 13px !important;
|
||||
font-weight: 600 !important;
|
||||
height: 36px !important;
|
||||
border-color: $border !important;
|
||||
color: $gray-700 !important;
|
||||
}
|
||||
|
||||
&__submit {
|
||||
border-radius: 8px !important;
|
||||
font-size: 13px !important;
|
||||
font-weight: 600 !important;
|
||||
height: 36px !important;
|
||||
box-shadow: 0 1px 3px rgba($primary, 0.3) !important;
|
||||
|
||||
i { margin-right: 6px; font-size: 12px; }
|
||||
}
|
||||
}
|
||||
|
||||
+68
-53
@@ -6,63 +6,78 @@
|
||||
file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
-->
|
||||
|
||||
<div class="container m-b-20 layout-row layout-lt-md-column align-end gap-2percent">
|
||||
<button mat-raised-button color="primary" [routerLink]="['edit']" *mifosxHasPermission="'UPDATE_DELINQUENCY_BUCKET'">
|
||||
<fa-icon icon="edit" class="m-r-10"></fa-icon>
|
||||
{{ 'labels.buttons.Edit' | translate }}
|
||||
</button>
|
||||
<button
|
||||
mat-raised-button
|
||||
color="warn"
|
||||
(click)="deleteDelinquencyBucket()"
|
||||
*mifosxHasPermission="'DELETE_DELINQUENCY_BUCKET'"
|
||||
>
|
||||
<fa-icon icon="trash" class="m-r-10"></fa-icon>
|
||||
{{ 'labels.buttons.Delete' | translate }}
|
||||
</button>
|
||||
</div>
|
||||
<div class="vb-container">
|
||||
<!-- Header -->
|
||||
<div class="vb-header">
|
||||
<div class="vb-header__left">
|
||||
<button mat-stroked-button [routerLink]="['../']" class="vb-back">
|
||||
<i class="fas fa-arrow-left"></i> {{ 'labels.heading.Delinquency Buckets' | translate }}
|
||||
</button>
|
||||
<h2 class="vb-header__title">{{ delinquencyBucketData.name }}</h2>
|
||||
</div>
|
||||
<div class="vb-header__actions">
|
||||
<button mat-flat-button color="primary" [routerLink]="['edit']" *mifosxHasPermission="'UPDATE_DELINQUENCY_BUCKET'" class="vb-header__edit">
|
||||
<fa-icon icon="edit" class="m-r-10"></fa-icon>
|
||||
{{ 'labels.buttons.Edit' | translate }}
|
||||
</button>
|
||||
<button
|
||||
mat-stroked-button
|
||||
color="warn"
|
||||
(click)="deleteDelinquencyBucket()"
|
||||
*mifosxHasPermission="'DELETE_DELINQUENCY_BUCKET'"
|
||||
class="vb-header__delete"
|
||||
>
|
||||
<fa-icon icon="trash" class="m-r-10"></fa-icon>
|
||||
{{ 'labels.buttons.Delete' | translate }}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="container">
|
||||
<mat-card>
|
||||
<mat-card-content>
|
||||
<div class="layout-row-wrap">
|
||||
<div class="flex-100 layout-row m-b-10">
|
||||
<div class="flex-30 mat-body-strong">
|
||||
{{ 'labels.inputs.Name' | translate }}
|
||||
</div>
|
||||
|
||||
<div class="flex-70">
|
||||
{{ delinquencyBucketData.name }}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="flex-60 mat-body-strong">
|
||||
{{ 'labels.inputs.Classification' | translate }}
|
||||
{{ 'labels.inputs.Name' | translate }}
|
||||
</div>
|
||||
|
||||
<div class="mat-body-strong flex-20">
|
||||
{{ 'labels.inputs.Days From' | translate }}
|
||||
</div>
|
||||
|
||||
<div class="mat-body-strong flex-20">
|
||||
{{ 'labels.inputs.Days Till' | translate }}
|
||||
<!-- Detail Card -->
|
||||
<div class="vb-card">
|
||||
<!-- Bucket Info Section -->
|
||||
<div class="vb-section">
|
||||
<div class="vb-section__header">
|
||||
<i class="fas fa-layer-group"></i>
|
||||
<h3>{{ 'labels.heading.Delinquency Buckets' | translate }}</h3>
|
||||
</div>
|
||||
<div class="vb-section__body">
|
||||
<div class="vb-row">
|
||||
<span class="vb-row__label">{{ 'labels.inputs.Name' | translate }}</span>
|
||||
<span class="vb-row__value">{{ delinquencyBucketData.name }}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@for (range of delinquencyBucketData.ranges; track range) {
|
||||
<div class="layout-row-wrap bucket-range">
|
||||
<div class="flex-60">
|
||||
{{ range.classification }}
|
||||
<!-- Ranges Section -->
|
||||
<div class="vb-section">
|
||||
<div class="vb-section__header">
|
||||
<i class="fas fa-sliders-h"></i>
|
||||
<h3>{{ 'labels.heading.Delinquency Ranges' | translate }}</h3>
|
||||
</div>
|
||||
<div class="vb-section__body vb-section__body--no-pad">
|
||||
@if (delinquencyBucketData.ranges && delinquencyBucketData.ranges.length > 0) {
|
||||
<div class="vb-ranges-table">
|
||||
<div class="vb-ranges-header">
|
||||
<span class="vb-ranges-cell vb-ranges-cell--name">{{ 'labels.inputs.Classification' | translate }} {{ 'labels.inputs.Name' | translate }}</span>
|
||||
<span class="vb-ranges-cell vb-ranges-cell--num">{{ 'labels.inputs.Days From' | translate }}</span>
|
||||
<span class="vb-ranges-cell vb-ranges-cell--num">{{ 'labels.inputs.Days Till' | translate }}</span>
|
||||
</div>
|
||||
@for (range of delinquencyBucketData.ranges; track range) {
|
||||
<div class="vb-ranges-row">
|
||||
<span class="vb-ranges-cell vb-ranges-cell--name">{{ range.classification }}</span>
|
||||
<span class="vb-ranges-cell vb-ranges-cell--num">{{ range.minimumAgeDays }}</span>
|
||||
<span class="vb-ranges-cell vb-ranges-cell--num">{{ range.maximumAgeDays }}</span>
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
<div class="flex-20 r-value">
|
||||
{{ range.minimumAgeDays }}
|
||||
} @else {
|
||||
<div class="vb-empty">
|
||||
<i class="fas fa-inbox"></i>
|
||||
<p>No delinquency ranges configured</p>
|
||||
</div>
|
||||
<div class="flex-20 r-value">
|
||||
{{ range.maximumAgeDays }}
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
</mat-card-content>
|
||||
</mat-card>
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
+200
-15
@@ -6,25 +6,210 @@
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
.container {
|
||||
max-width: 37rem;
|
||||
$primary: #1353a0;
|
||||
$accent: #0ea5e9;
|
||||
$border: #e2e8f0;
|
||||
$gray-50: #f8f9fa;
|
||||
$gray-200: #e8eaed;
|
||||
$gray-500: #9aa0a6;
|
||||
$gray-700: #5f6368;
|
||||
$gray-900: #202124;
|
||||
|
||||
.content {
|
||||
div {
|
||||
margin: 0.8rem 0;
|
||||
word-wrap: break-word;
|
||||
}
|
||||
.vb-container {
|
||||
max-width: 800px;
|
||||
margin: 0 auto;
|
||||
padding: 20px 16px;
|
||||
}
|
||||
|
||||
// Header
|
||||
.vb-header {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
gap: 14px;
|
||||
margin-bottom: 20px;
|
||||
flex-wrap: wrap;
|
||||
|
||||
&__left {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 14px;
|
||||
}
|
||||
|
||||
&__title {
|
||||
font-size: 18px;
|
||||
font-weight: 600;
|
||||
color: $gray-900;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
&__actions {
|
||||
display: flex;
|
||||
gap: 8px;
|
||||
}
|
||||
|
||||
&__edit {
|
||||
border-radius: 8px !important;
|
||||
font-size: 13px !important;
|
||||
font-weight: 600 !important;
|
||||
height: 36px !important;
|
||||
box-shadow: 0 1px 3px rgba($primary, 0.3) !important;
|
||||
}
|
||||
|
||||
&__delete {
|
||||
border-radius: 8px !important;
|
||||
font-size: 13px !important;
|
||||
font-weight: 600 !important;
|
||||
height: 36px !important;
|
||||
}
|
||||
}
|
||||
|
||||
.bucket-range {
|
||||
height: 2rem;
|
||||
vertical-align: middle;
|
||||
.vb-back {
|
||||
border-radius: 8px !important;
|
||||
font-size: 12px !important;
|
||||
font-weight: 600 !important;
|
||||
height: 32px !important;
|
||||
border-color: $border !important;
|
||||
color: $gray-500 !important;
|
||||
|
||||
i { margin-right: 6px; }
|
||||
|
||||
&:hover { color: $primary !important; border-color: $primary !important; }
|
||||
}
|
||||
|
||||
.r-value {
|
||||
margin: 0 !important;
|
||||
padding: 0 !important;
|
||||
text-align: right !important;
|
||||
padding-right: 35px !important;
|
||||
// Card
|
||||
.vb-card {
|
||||
background: #fff;
|
||||
border: 1px solid $border;
|
||||
border-radius: 10px;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
// Section
|
||||
.vb-section {
|
||||
&__header {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 10px;
|
||||
padding: 12px 24px;
|
||||
background: $gray-50;
|
||||
border-bottom: 1px solid $gray-200;
|
||||
|
||||
i {
|
||||
font-size: 14px;
|
||||
color: $accent;
|
||||
}
|
||||
|
||||
h3 {
|
||||
margin: 0;
|
||||
font-size: 14px;
|
||||
font-weight: 600;
|
||||
color: $gray-900;
|
||||
}
|
||||
}
|
||||
|
||||
&__body {
|
||||
padding: 16px 24px;
|
||||
|
||||
&--no-pad {
|
||||
padding: 0;
|
||||
}
|
||||
}
|
||||
|
||||
& + & {
|
||||
border-top: 1px solid $gray-200;
|
||||
}
|
||||
}
|
||||
|
||||
// Detail rows
|
||||
.vb-row {
|
||||
display: flex;
|
||||
padding: 10px 0;
|
||||
border-bottom: 1px solid #f1f3f4;
|
||||
|
||||
&:last-child { border-bottom: none; }
|
||||
|
||||
&__label {
|
||||
flex: 0 0 40%;
|
||||
font-weight: 500;
|
||||
font-size: 13px;
|
||||
color: $gray-700;
|
||||
}
|
||||
|
||||
&__value {
|
||||
flex: 1;
|
||||
font-size: 14px;
|
||||
font-weight: 600;
|
||||
color: $gray-900;
|
||||
}
|
||||
}
|
||||
|
||||
// Ranges table
|
||||
.vb-ranges-table {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.vb-ranges-header {
|
||||
display: flex;
|
||||
background: #f8fafc;
|
||||
border-bottom: 1px solid $border;
|
||||
padding: 8px 24px;
|
||||
|
||||
.vb-ranges-cell {
|
||||
font-size: 10px;
|
||||
font-weight: 600;
|
||||
text-transform: uppercase;
|
||||
letter-spacing: 0.06em;
|
||||
color: #64748b;
|
||||
}
|
||||
}
|
||||
|
||||
.vb-ranges-row {
|
||||
display: flex;
|
||||
padding: 10px 24px;
|
||||
border-bottom: 1px solid #f1f5f9;
|
||||
transition: background 0.1s;
|
||||
|
||||
&:last-child { border-bottom: none; }
|
||||
|
||||
&:hover { background: #f8fafc; }
|
||||
|
||||
.vb-ranges-cell {
|
||||
font-size: 13px;
|
||||
font-weight: 400;
|
||||
color: $gray-900;
|
||||
}
|
||||
}
|
||||
|
||||
.vb-ranges-cell {
|
||||
&--name {
|
||||
flex: 3;
|
||||
}
|
||||
|
||||
&--num {
|
||||
flex: 1;
|
||||
text-align: right;
|
||||
}
|
||||
}
|
||||
|
||||
// Empty state
|
||||
.vb-empty {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
padding: 32px 16px;
|
||||
text-align: center;
|
||||
|
||||
i {
|
||||
font-size: 28px;
|
||||
color: #cbd5e1;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
p {
|
||||
font-size: 13px;
|
||||
color: #94a3b8;
|
||||
margin: 0;
|
||||
}
|
||||
}
|
||||
|
||||
+56
-49
@@ -6,56 +6,63 @@
|
||||
file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
-->
|
||||
|
||||
<div class="container">
|
||||
<mat-card>
|
||||
<form [formGroup]="delinquencyRangeForm" (ngSubmit)="submit()">
|
||||
<mat-card-content>
|
||||
<div class="layout-column">
|
||||
<mat-form-field>
|
||||
<mat-label>{{ 'labels.inputs.Classification' | translate }}</mat-label>
|
||||
<input matInput required formControlName="classification" />
|
||||
@if (delinquencyRangeForm.controls.classification.hasError('required')) {
|
||||
<mat-error>
|
||||
{{ 'labels.inputs.Classification' | translate }} {{ 'labels.commons.is' | translate }}
|
||||
<strong>{{ 'labels.commons.required' | translate }}</strong>
|
||||
</mat-error>
|
||||
}
|
||||
</mat-form-field>
|
||||
<div class="cr-container">
|
||||
<div class="cr-header">
|
||||
<i class="fas fa-plus-circle cr-header__icon"></i>
|
||||
<h2 class="cr-header__title">{{ 'labels.text.Create Delinquency Range' | translate }}</h2>
|
||||
</div>
|
||||
|
||||
<mat-form-field>
|
||||
<mat-label>{{ 'labels.inputs.Days From' | translate }}</mat-label>
|
||||
<input matInput type="number" required formControlName="minimumAgeDays" min="0" />
|
||||
@if (delinquencyRangeForm.controls.minimumAgeDays.hasError('required')) {
|
||||
<mat-error>
|
||||
{{ 'labels.inputs.Days From' | translate }} {{ 'labels.commons.is' | translate }}
|
||||
<strong>{{ 'labels.commons.required' | translate }}</strong>
|
||||
</mat-error>
|
||||
}
|
||||
@if (delinquencyRangeForm.controls.minimumAgeDays.hasError('pattern')) {
|
||||
<mat-error> {{ 'labels.inputs.Days From' | translate }} must be a positive number. </mat-error>
|
||||
}
|
||||
</mat-form-field>
|
||||
<form [formGroup]="delinquencyRangeForm" (ngSubmit)="submit()">
|
||||
<div class="cr-section">
|
||||
<div class="cr-section__header">
|
||||
<i class="fa fa-layer-group"></i>
|
||||
<h3>{{ 'labels.inputs.Range Details' | translate }}</h3>
|
||||
</div>
|
||||
<div class="cr-grid">
|
||||
<mat-form-field appearance="outline">
|
||||
<mat-label>{{ 'labels.inputs.Classification' | translate }}</mat-label>
|
||||
<input matInput required formControlName="classification" />
|
||||
@if (delinquencyRangeForm.controls.classification.hasError('required')) {
|
||||
<mat-error>
|
||||
{{ 'labels.inputs.Classification' | translate }} {{ 'labels.commons.is' | translate }}
|
||||
<strong>{{ 'labels.commons.required' | translate }}</strong>
|
||||
</mat-error>
|
||||
}
|
||||
</mat-form-field>
|
||||
|
||||
<mat-form-field>
|
||||
<mat-label>{{ 'labels.inputs.Days Till' | translate }}</mat-label>
|
||||
<input matInput type="number" required formControlName="maximumAgeDays" min="1" />
|
||||
</mat-form-field>
|
||||
</div>
|
||||
</mat-card-content>
|
||||
<mat-form-field appearance="outline">
|
||||
<mat-label>{{ 'labels.inputs.Days From' | translate }}</mat-label>
|
||||
<input matInput type="number" required formControlName="minimumAgeDays" min="0" />
|
||||
@if (delinquencyRangeForm.controls.minimumAgeDays.hasError('required')) {
|
||||
<mat-error>
|
||||
{{ 'labels.inputs.Days From' | translate }} {{ 'labels.commons.is' | translate }}
|
||||
<strong>{{ 'labels.commons.required' | translate }}</strong>
|
||||
</mat-error>
|
||||
}
|
||||
@if (delinquencyRangeForm.controls.minimumAgeDays.hasError('pattern')) {
|
||||
<mat-error> {{ 'labels.inputs.Days From' | translate }} must be a positive number. </mat-error>
|
||||
}
|
||||
</mat-form-field>
|
||||
|
||||
<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]="!delinquencyRangeForm.valid"
|
||||
*mifosxHasPermission="'CREATE_DELINQUENCY_RANGE'"
|
||||
>
|
||||
{{ 'labels.buttons.Submit' | translate }}
|
||||
</button>
|
||||
</mat-card-actions>
|
||||
</form>
|
||||
</mat-card>
|
||||
<mat-form-field appearance="outline">
|
||||
<mat-label>{{ 'labels.inputs.Days Till' | translate }}</mat-label>
|
||||
<input matInput type="number" required formControlName="maximumAgeDays" min="1" />
|
||||
</mat-form-field>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="cr-action-bar">
|
||||
<button type="button" mat-raised-button [routerLink]="['../']">
|
||||
{{ 'labels.buttons.Cancel' | translate }}
|
||||
</button>
|
||||
<button
|
||||
mat-raised-button
|
||||
color="primary"
|
||||
[disabled]="!delinquencyRangeForm.valid"
|
||||
*mifosxHasPermission="'CREATE_DELINQUENCY_RANGE'"
|
||||
>
|
||||
{{ 'labels.buttons.Submit' | translate }}
|
||||
</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
+28
-7
@@ -6,13 +6,34 @@
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
.container {
|
||||
max-width: 37rem;
|
||||
.cr-container { max-width: 960px; margin: 0 auto; padding: 24px 16px; }
|
||||
|
||||
.content {
|
||||
div {
|
||||
margin: 0.8rem 0;
|
||||
word-wrap: break-word;
|
||||
}
|
||||
.cr-header {
|
||||
display: flex; align-items: center; gap: 10px; margin-bottom: 20px;
|
||||
&__icon { font-size: 20px; color: #1353a0; }
|
||||
&__title { margin: 0; font-size: 22px; font-weight: 500; }
|
||||
}
|
||||
|
||||
.cr-section {
|
||||
border: 1px solid #e2e8f0; border-radius: 10px; overflow: hidden; background: #fff;
|
||||
|
||||
&__header {
|
||||
display: flex; align-items: center; gap: 10px; padding: 12px 24px;
|
||||
background: #f8f9fa; border-bottom: 1px solid #e8eaed;
|
||||
i { font-size: 14px; color: #0ea5e9; }
|
||||
h3 { margin: 0; font-size: 14px; font-weight: 600; color: #202124; }
|
||||
}
|
||||
}
|
||||
|
||||
.cr-grid {
|
||||
display: grid; grid-template-columns: repeat(2, 1fr); gap: 4px 16px; padding: 16px 24px;
|
||||
}
|
||||
|
||||
.cr-action-bar {
|
||||
display: flex; justify-content: flex-end; gap: 12px; margin-top: 20px; padding: 16px 0;
|
||||
border-top: 1px solid rgba(0, 0, 0, 0.08);
|
||||
}
|
||||
|
||||
@media (max-width: 600px) {
|
||||
.cr-grid { grid-template-columns: 1fr; }
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user