Merge pull request #2994 from AnvayKharb/web-573-update-ui-of-password-preference

WEB-573: Improve UI of Password Preferences
This commit is contained in:
Jose Alberto Hernandez
2026-01-15 13:20:42 -05:00
committed by GitHub
3 changed files with 80 additions and 15 deletions
@@ -1,6 +1,5 @@
<!-- <!--
Copyright since 2025 Mifos Initiative Copyright since 2025 Mifos Initiative
This Source Code Form is subject to the terms of the Mozilla Public 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 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/. file, You can obtain one at http://mozilla.org/MPL/2.0/.
@@ -10,14 +9,25 @@
<mat-card> <mat-card>
<form [formGroup]="passwordPreferencesForm" (ngSubmit)="submit()"> <form [formGroup]="passwordPreferencesForm" (ngSubmit)="submit()">
<mat-card-content> <mat-card-content>
<mat-radio-group class="layout-column gap-10px radio-group-spacing" formControlName="validationPolicyId"> <mat-radio-group class="password-cards-container" formControlName="validationPolicyId">
@for (passwordPreference of passwordPreferencesData; track passwordPreference) { <div
<mat-radio-button [value]="passwordPreference.id"> *ngFor="let passwordPreference of passwordPreferencesData; trackBy: trackByPasswordPreference"
<span class="description-wrap">{{ class="password-card"
passwordPreference.description | translateKey: 'passwordPreferences' [class.selected]="passwordPreferencesForm.get('validationPolicyId')?.value === passwordPreference.id"
}}</span> >
</mat-radio-button> <div class="card-header">
} <div class="card-heading">
{{ getPasswordLabel(passwordPreference) | translate }}
</div>
<mat-radio-button [value]="passwordPreference.id"></mat-radio-button>
</div>
<div class="card-description">
<span class="description-wrap">
{{ passwordPreference.description | translateKey: 'passwordPreferences' }}
</span>
</div>
</div>
</mat-radio-group> </mat-radio-group>
</mat-card-content> </mat-card-content>
@@ -10,14 +10,44 @@
white-space: normal; white-space: normal;
} }
.radio-group-spacing { .password-cards-container {
display: flex; display: flex;
gap: 2rem; flex-direction: column;
flex-direction: row; gap: 1.5rem;
width: 100%;
} }
@media (width <= 768px) { .password-card {
.radio-group-spacing { width: 100%;
flex-direction: column; border: 1px solid rgb(0 0 0 / 12%);
border-radius: 4px;
padding: 1.5rem;
box-sizing: border-box;
&.selected {
border-color: currentcolor;
border-width: 2px;
}
.card-header {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 1rem;
}
.card-heading {
font-weight: 500;
font-size: 1rem;
}
.card-description {
padding-left: 0;
.description-wrap {
white-space: normal;
display: block;
line-height: 1.5;
}
} }
} }
@@ -81,6 +81,31 @@ export class PasswordPreferencesComponent implements OnInit {
} }
} }
/**
* TrackBy function for ngFor optimization.
* @param index Index of the item.
* @param item Password preference item.
* @returns Unique identifier for the item.
*/
trackByPasswordPreference(index: number, item: any): any {
return item.id || index;
}
/**
* Gets the password preference label based on ID.
* @param preference Password preference object.
* @returns Translation key for the password preference label.
*/
getPasswordLabel(preference: any): string {
// Map based on ID to ensure robustness
const labelMap: { [key: number]: string } = {
1: 'labels.inputs.Basic',
2: 'labels.inputs.Standard',
3: 'labels.inputs.Strong'
};
return labelMap[preference.id] || 'labels.inputs.Unknown';
}
/** /**
* Submits the password preferences form and updates password preferences, * Submits the password preferences form and updates password preferences,
* if successful redirects to organization view. * if successful redirects to organization view.