update some logic show option

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Nitesh Yadav
2026-04-21 17:38:07 +05:30
co-authored by Claude Sonnet 4.6
parent e212bf7d79
commit e9a9377148
39 changed files with 2215 additions and 287 deletions
@@ -1,4 +1,4 @@
<!--
<!--
Copyright since 2025 Mifos Initiative
This Source Code Form is subject to the terms of the Mozilla Public
@@ -7,63 +7,119 @@
-->
<form [formGroup]="savingsAccountDetailsForm">
<div class="layout-row-wrap gap-2px responsive-column">
<mat-form-field class="flex-48">
<mat-label>{{ 'labels.inputs.Product Name' | translate }}</mat-label>
<mat-select formControlName="productId" required>
@for (product of productData; track product) {
<mat-option [value]="product.id">
{{ product.name }}
</mat-option>
}
</mat-select>
<mat-error>
{{ 'labels.inputs.Product Name' | translate }} {{ 'labels.commons.is' | translate }}
<strong>{{ 'labels.commons.required' | translate }}</strong>
</mat-error>
</mat-form-field>
@if (savingsProductSelected) {
<mat-form-field class="flex-48" (click)="submittedOnDatePicker.open()">
<mat-label>{{ 'labels.inputs.Submitted On' | translate }}</mat-label>
<input
matInput
[min]="minDate"
[max]="maxDate"
[matDatepicker]="submittedOnDatePicker"
formControlName="submittedOnDate"
required
/>
<mat-datepicker-toggle matSuffix [for]="submittedOnDatePicker"></mat-datepicker-toggle>
<mat-datepicker #submittedOnDatePicker></mat-datepicker>
<!-- Account Details -->
<div class="sad-section">
<div class="sad-section__header">
<i class="fas fa-info-circle"></i>
<h3>Account Details</h3>
</div>
<div class="sad-grid">
<mat-form-field appearance="outline" class="sad-field">
<mat-label>{{ 'labels.inputs.Product Name' | translate }}</mat-label>
<mat-select formControlName="productId" required>
@for (product of productData; track product) {
<mat-option [value]="product.id">{{ product.name }}</mat-option>
}
</mat-select>
<mat-error>
{{ 'labels.inputs.Submitted On' | translate }} {{ 'labels.commons.is' | translate }}
{{ 'labels.inputs.Product Name' | translate }} {{ 'labels.commons.is' | translate }}
<strong>{{ 'labels.commons.required' | translate }}</strong>
</mat-error>
</mat-form-field>
}
@if (savingsProductSelected) {
<mat-form-field class="flex-48">
<mat-label>{{ 'labels.inputs.Field Officer' | translate }}</mat-label>
<mat-select formControlName="fieldOfficerId">
@for (officer of fieldOfficerData; track officer) {
<mat-option [value]="officer.id">
{{ officer.displayName }}
</mat-option>
}
</mat-select>
</mat-form-field>
}
@if (savingsProductSelected) {
<mat-form-field appearance="outline" class="sad-field" (click)="submittedOnDatePicker.open()">
<mat-label>{{ 'labels.inputs.Submitted On' | translate }}</mat-label>
<input
matInput
[min]="minDate"
[max]="maxDate"
[matDatepicker]="submittedOnDatePicker"
formControlName="submittedOnDate"
required
/>
<mat-datepicker-toggle matSuffix [for]="submittedOnDatePicker"></mat-datepicker-toggle>
<mat-datepicker #submittedOnDatePicker></mat-datepicker>
<mat-error>
{{ 'labels.inputs.Submitted On' | translate }} {{ 'labels.commons.is' | translate }}
<strong>{{ 'labels.commons.required' | translate }}</strong>
</mat-error>
</mat-form-field>
}
@if (savingsProductSelected) {
<mat-form-field class="flex-48">
<mat-label>{{ 'labels.inputs.External ID' | translate }}</mat-label>
<input matInput formControlName="externalId" />
</mat-form-field>
}
@if (savingsProductSelected) {
<mat-form-field appearance="outline" class="sad-field">
<mat-label>{{ 'labels.inputs.Field Officer' | translate }}</mat-label>
<mat-select formControlName="fieldOfficerId">
@for (officer of fieldOfficerData; track officer) {
<mat-option [value]="officer.id">{{ officer.displayName }}</mat-option>
}
</mat-select>
</mat-form-field>
}
@if (savingsProductSelected) {
<mat-form-field appearance="outline" class="sad-field">
<mat-label>{{ 'labels.inputs.External ID' | translate }}</mat-label>
<input matInput formControlName="externalId" />
</mat-form-field>
}
</div>
</div>
<!-- Product Classification (read-only, shown after product is selected) -->
@if (savingsProductSelected) {
<div class="sad-section sad-section--mt">
<div class="sad-section__header">
<i class="fas fa-tags"></i>
<h3>Product Classification</h3>
<span class="sad-badge">From Product</span>
</div>
<div class="sad-grid sad-grid--classification">
<mat-form-field appearance="outline" class="sad-field">
<mat-label>Account Type</mat-label>
<input matInput [value]="productTemplate.accountType || ''" readonly />
</mat-form-field>
<mat-form-field appearance="outline" class="sad-field">
<mat-label>Customer Segment</mat-label>
<input matInput [value]="productTemplate.customerSegment || ''" readonly />
</mat-form-field>
<mat-form-field appearance="outline" class="sad-field">
<mat-label>Product Code</mat-label>
<input matInput [value]="productTemplate.productCode || ''" readonly />
</mat-form-field>
@if (productTemplate.effectiveDate) {
<mat-form-field appearance="outline" class="sad-field">
<mat-label>Effective Date</mat-label>
<input matInput [value]="formatTemplateDate(productTemplate.effectiveDate)" readonly />
</mat-form-field>
}
@if (productTemplate.endDate) {
<mat-form-field appearance="outline" class="sad-field">
<mat-label>End Date</mat-label>
<input matInput [value]="formatTemplateDate(productTemplate.endDate)" readonly />
</mat-form-field>
}
<mat-form-field appearance="outline" class="sad-field">
<mat-label>Introducer Required</mat-label>
<input matInput [value]="productTemplate.introducerRequired ? 'Yes' : 'No'" readonly />
</mat-form-field>
<div class="sad-field sad-info-row">
<span class="sad-info-label">Share Linking Enabled</span>
<span class="sad-badge" [class.sad-badge--yes]="productTemplate.shareLinkingEnabled">
{{ productTemplate.shareLinkingEnabled ? 'Yes' : 'No' }}
</span>
</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>
@@ -5,3 +5,101 @@
* 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/.
*/
$accent: #0ea5e9;
$border: #e2e8f0;
$gray-50: #f8f9fa;
$gray-200: #e8eaed;
$gray-900: #202124;
.sad-section {
border: 1px solid $border;
border-radius: 10px;
overflow: hidden;
background: #fff;
&--mt {
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;
flex: 1;
}
}
}
.sad-grid {
display: grid;
grid-template-columns: repeat(2, 1fr);
gap: 4px 16px;
padding: 16px 24px;
@media (width <= 600px) {
grid-template-columns: 1fr;
}
}
.sad-grid--classification {
grid-template-columns: repeat(3, 1fr);
@media (width <= 900px) {
grid-template-columns: repeat(2, 1fr);
}
@media (width <= 600px) {
grid-template-columns: 1fr;
}
}
.sad-field {
width: 100%;
}
.sad-info-row {
display: flex;
align-items: center;
gap: 12px;
min-height: 56px;
}
.sad-info-label {
font-size: 14px;
color: $gray-900;
font-weight: 500;
}
.sad-badge {
display: inline-flex;
align-items: center;
justify-content: center;
padding: 3px 12px;
border-radius: 999px;
font-size: 11px;
font-weight: 700;
background: #dbeafe;
color: #1d4ed8;
border: 1px solid #bfdbfe;
&--yes {
background: #dcfce7;
color: #15803d;
border-color: #bbf7d0;
}
}
@@ -1,4 +1,4 @@
/**
/**
* Copyright since 2025 Mifos Initiative
*
* This Source Code Form is subject to the terms of the Mozilla Public
@@ -7,12 +7,13 @@
*/
/** Angular Imports */
import { Component, OnInit, Input, Output, EventEmitter, inject } from '@angular/core';
import { Component, OnInit, Input, Output, EventEmitter, inject, ChangeDetectorRef } from '@angular/core';
import { UntypedFormGroup, UntypedFormBuilder, Validators, ReactiveFormsModule } from '@angular/forms';
import { Dates } from 'app/core/utils/dates';
import { SettingsService } from 'app/settings/settings.service';
/** Custom Services */
import { SavingsService } from 'app/savings/savings.service';
import { SettingsService } from 'app/settings/settings.service';
import { MatStepperPrevious, MatStepperNext } from '@angular/material/stepper';
import { FaIconComponent } from '@fortawesome/angular-fontawesome';
import { STANDALONE_SHARED_IMPORTS } from 'app/standalone-shared.module';
@@ -35,6 +36,8 @@ export class SavingsAccountDetailsStepComponent implements OnInit {
private formBuilder = inject(UntypedFormBuilder);
private savingsService = inject(SavingsService);
private settingsService = inject(SettingsService);
private dateUtils = inject(Dates);
private cdr = inject(ChangeDetectorRef);
/** Savings Account Template */
@Input() savingsAccountTemplate: any;
@@ -57,6 +60,9 @@ export class SavingsAccountDetailsStepComponent implements OnInit {
/** Savings Account Template with product data */
@Output() savingsAccountProductTemplate = new EventEmitter();
/** Local copy of product template for displaying classification info */
productTemplate: any = null;
/**
* Sets share account details form.
* @param {FormBuilder} formBuilder Form Builder.
@@ -115,9 +121,11 @@ export class SavingsAccountDetailsStepComponent implements OnInit {
this.savingsService
.getSavingsAccountTemplate(entityId, productId, this.savingsAccountTemplate.groupId ? true : false)
.subscribe((response: any) => {
this.productTemplate = response;
this.savingsAccountProductTemplate.emit(response);
this.fieldOfficerData = response.fieldOfficerOptions;
this.savingsProductSelected = true;
this.cdr.detectChanges();
if (!this.isFieldOfficerPatched && this.savingsAccountTemplate.fieldOfficerId) {
this.savingsAccountDetailsForm.get('fieldOfficerId').patchValue(this.savingsAccountTemplate.fieldOfficerId);
this.isFieldOfficerPatched = true;
@@ -128,6 +136,32 @@ export class SavingsAccountDetailsStepComponent implements OnInit {
});
}
/**
* Formats template dates into the current CBS date format.
* Handles backend date arrays like [2026, 4, 20] as well as strings and Date objects.
*/
formatTemplateDate(value: any): string {
if (!value) {
return '';
}
let dateValue: Date | null = null;
if (value instanceof Date) {
dateValue = value;
} else if (Array.isArray(value) && value.length >= 3) {
dateValue = new Date(value[0], value[1] - 1, value[2]);
} else {
dateValue = new Date(value);
}
if (!dateValue || Number.isNaN(dateValue.getTime())) {
return Array.isArray(value) ? value.join('/') : String(value);
}
return this.dateUtils.formatDate(dateValue, 'M/d/yyyy') || '';
}
/**
* Returns savings account form value.
*/