-
Notifications
You must be signed in to change notification settings - Fork 938
fe: landing page UI #3665
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
fe: landing page UI #3665
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -8,7 +8,8 @@ | |
|
|
||
| <form [formGroup]="createClientForm"> | ||
| <div class="layout-row-wrap gap-2px responsive-column"> | ||
| <mat-form-field class="flex-fill flex-23"> | ||
| <!-- Row 1: Office, Legal Form, External Id, First Name / Middle Name (or Full Name for Entity) --> | ||
| <mat-form-field class="flex-20"> | ||
| <mat-label>{{ 'labels.inputs.Office' | translate }}</mat-label> | ||
| <mat-select required formControlName="officeId"> | ||
| @for (office of officeOptions; track office) { | ||
|
|
@@ -25,7 +26,7 @@ | |
| } | ||
| </mat-form-field> | ||
|
|
||
| <mat-form-field class="flex-fill flex-23"> | ||
| <mat-form-field class="flex-15"> | ||
| <mat-label>{{ 'labels.inputs.Legal Form' | translate }}</mat-label> | ||
| <mat-select required formControlName="legalFormId"> | ||
| @for (legalForm of legalFormOptions; track legalForm) { | ||
|
|
@@ -36,7 +37,7 @@ | |
| </mat-select> | ||
| </mat-form-field> | ||
|
|
||
| <mat-form-field class="flex-fill flex-23"> | ||
| <mat-form-field class="flex-20"> | ||
| <mat-label>{{ 'labels.inputs.External Id' | translate }}</mat-label> | ||
| <input matInput formControlName="externalId" /> | ||
| @if (!externalNationalIdService.isLoading && externalNationalIdService.statusMessageKey) { | ||
|
|
@@ -55,7 +56,7 @@ | |
| </mat-form-field> | ||
|
|
||
| @if (createClientForm.get('fullname')) { | ||
| <mat-form-field class="flex-48"> | ||
| <mat-form-field class="flex-40"> | ||
| <mat-label> | ||
| {{ 'labels.inputs.' + getDateLabel(createClientForm.value.legalFormId, ['Name', 'Entity Name']) | translate }} | ||
| </mat-label> | ||
|
|
@@ -75,65 +76,62 @@ | |
| </mat-form-field> | ||
| } | ||
|
|
||
| @if (createClientForm.get('firstname') || createClientForm.get('middlename') || createClientForm.get('lastname')) { | ||
| <div class="name-fields-row"> | ||
| @if (createClientForm.get('firstname')) { | ||
| <mat-form-field class="name-field first-name"> | ||
| <mat-label>{{ 'labels.inputs.First Name' | translate }}</mat-label> | ||
| <input matInput required formControlName="firstname" /> | ||
| @if (createClientForm.controls.firstname.hasError('required')) { | ||
| <mat-error> | ||
| {{ 'labels.inputs.Client first name' | translate }} {{ 'labels.commons.is' | translate }} | ||
| <strong>{{ 'labels.commons.required' | translate }}</strong> | ||
| </mat-error> | ||
| } | ||
| @if (createClientForm.controls.firstname.hasError('pattern')) { | ||
| <mat-error> | ||
| {{ 'labels.inputs.Client first name' | translate }} | ||
| <strong>{{ 'labels.inputs.cannot' | translate }}</strong> | ||
| {{ 'labels.commons.begin with a special character or number' | translate }} | ||
| </mat-error> | ||
| } | ||
| </mat-form-field> | ||
| @if (createClientForm.get('firstname')) { | ||
| <mat-form-field class="flex-20"> | ||
| <mat-label>{{ 'labels.inputs.First Name' | translate }}</mat-label> | ||
| <input matInput required formControlName="firstname" /> | ||
| @if (createClientForm.controls.firstname.hasError('required')) { | ||
| <mat-error> | ||
| {{ 'labels.inputs.Client first name' | translate }} {{ 'labels.commons.is' | translate }} | ||
| <strong>{{ 'labels.commons.required' | translate }}</strong> | ||
| </mat-error> | ||
| } | ||
| @if (createClientForm.get('middlename')) { | ||
| <mat-form-field class="name-field middle-name"> | ||
| <mat-label>{{ 'labels.inputs.Middle Name' | translate }}</mat-label> | ||
| <input matInput formControlName="middlename" /> | ||
| @if (createClientForm.controls.middlename.hasError('pattern')) { | ||
| <mat-error> | ||
| {{ 'labels.inputs.Client middle name' | translate }} | ||
| <strong>{{ 'labels.inputs.cannot' | translate }}</strong> | ||
| {{ 'labels.commons.begin with a special character or number' | translate }} | ||
| </mat-error> | ||
| } | ||
| </mat-form-field> | ||
| @if (createClientForm.controls.firstname.hasError('pattern')) { | ||
| <mat-error> | ||
| {{ 'labels.inputs.Client first name' | translate }} | ||
| <strong>{{ 'labels.inputs.cannot' | translate }}</strong> | ||
| {{ 'labels.commons.begin with a special character or number' | translate }} | ||
| </mat-error> | ||
| } | ||
| @if (createClientForm.get('lastname')) { | ||
| <mat-form-field class="name-field last-name"> | ||
| <mat-label>{{ 'labels.inputs.Last Name' | translate }}</mat-label> | ||
| <input matInput required formControlName="lastname" /> | ||
| @if (createClientForm.controls.lastname.hasError('required')) { | ||
| <mat-error> | ||
| {{ 'labels.inputs.Client last name' | translate }} {{ 'labels.commons.is' | translate }} | ||
| <strong>{{ 'labels.commons.required' | translate }}</strong> | ||
| </mat-error> | ||
| } | ||
| @if (createClientForm.controls.lastname.hasError('pattern')) { | ||
| <mat-error> | ||
| {{ 'labels.inputs.Client last name' | translate }} | ||
| <strong>{{ 'labels.inputs.cannot' | translate }}</strong> | ||
| {{ 'labels.commons.begin with a special character or number' | translate }} | ||
| </mat-error> | ||
| } | ||
| </mat-form-field> | ||
| </mat-form-field> | ||
| } | ||
|
|
||
| @if (createClientForm.get('middlename')) { | ||
| <mat-form-field class="flex-20"> | ||
| <mat-label>{{ 'labels.inputs.Middle Name' | translate }}</mat-label> | ||
| <input matInput formControlName="middlename" /> | ||
| @if (createClientForm.controls.middlename.hasError('pattern')) { | ||
| <mat-error> | ||
| {{ 'labels.inputs.Client middle name' | translate }} | ||
| <strong>{{ 'labels.inputs.cannot' | translate }}</strong> | ||
| {{ 'labels.commons.begin with a special character or number' | translate }} | ||
| </mat-error> | ||
| } | ||
| </div> | ||
| </mat-form-field> | ||
| } | ||
|
|
||
| <mat-divider></mat-divider> | ||
| <!-- Row 2: Last Name, Date of Birth, Gender, Staff, Is Staff? --> | ||
| @if (createClientForm.get('lastname')) { | ||
| <mat-form-field class="flex-20"> | ||
| <mat-label>{{ 'labels.inputs.Last Name' | translate }}</mat-label> | ||
| <input matInput required formControlName="lastname" /> | ||
| @if (createClientForm.controls.lastname.hasError('required')) { | ||
| <mat-error> | ||
| {{ 'labels.inputs.Client last name' | translate }} {{ 'labels.commons.is' | translate }} | ||
| <strong>{{ 'labels.commons.required' | translate }}</strong> | ||
| </mat-error> | ||
| } | ||
| @if (createClientForm.controls.lastname.hasError('pattern')) { | ||
| <mat-error> | ||
| {{ 'labels.inputs.Client last name' | translate }} | ||
| <strong>{{ 'labels.inputs.cannot' | translate }}</strong> | ||
| {{ 'labels.commons.begin with a special character or number' | translate }} | ||
| </mat-error> | ||
| } | ||
| </mat-form-field> | ||
| } | ||
|
Comment on lines
+79
to
+132
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🧩 Analysis chain🏁 Script executed: #!/bin/bash
# Description: Verify TypeScript component manages firstname/middlename/lastname form controls based on legalFormId
echo "=== Checking component form control management ==="
ast-grep --pattern $'addControl($$$) {
$$$
}'
echo -e "\n=== Checking for legalFormId-based control logic ==="
rg -n "legalFormId|firstname|middlename|lastname" src/app/clients/client-stepper/client-general-step/client-general-step.component.ts -A3 -B3
echo -e "\n=== Checking if name-fields-row CSS was removed ==="
rg -n "name-fields-row" --type=scssRepository: openMF/web-app Length of output: 2271 🏁 Script executed: #!/bin/bash
# Find and check CSS/SCSS files for name-fields-row and flex-20 definitions
echo "=== Searching for name-fields-row in CSS/SCSS files ==="
find src -type f \( -name "*.scss" -o -name "*.css" \) -exec grep -l "name-fields-row\|flex-20" {} \;
echo -e "\n=== Checking component-specific SCSS file ==="
ls -la src/app/clients/client-stepper/client-general-step/ | grep -E "\.(scss|css)$"
echo -e "\n=== Checking for flex-20 definition in theme files ==="
grep -r "flex-20" src/theme/ src/main.scss 2>/dev/null || echo "Not found in theme files"
echo -e "\n=== Checking for grid/flex utilities in main styles ==="
rg "flex-20|name-fields-row" src/main.scss src/styles.scss 2>/dev/null || echo "Pattern not found"Repository: openMF/web-app Length of output: 527 🏁 Script executed: #!/bin/bash
# Check the actual CSS definitions for name-fields-row and related styling
echo "=== Checking name-fields-row definition in component SCSS ==="
cat -n src/app/clients/client-stepper/client-general-step/client-general-step.component.scss
echo -e "\n=== Checking name-fields-row definition in main.scss ==="
rg -A5 "\.name-fields-row" src/main.scss
echo -e "\n=== Checking flex-20 definition ==="
rg -A3 "\.flex-20" src/main.scssRepository: openMF/web-app Length of output: 3441 Fix CSS layout issues caused by removing the name-fields-row wrapper container. The refactoring removed the
While the TypeScript component correctly manages the form control lifecycle (adding/removing firstname, middlename, lastname based on legalFormId), the HTML refactoring breaks the responsive design and flex layout. Either restore the wrapper container with its CSS or apply equivalent styling directly to the individual 🤖 Prompt for AI Agents |
||
|
|
||
| <mat-form-field class="flex-48" (click)="dateOfBirthDatePicker.open()"> | ||
| <mat-form-field class="flex-20" (click)="dateOfBirthDatePicker.open()"> | ||
| <mat-label> | ||
| {{ | ||
| 'labels.inputs.' + getDateLabel(createClientForm.value.legalFormId, ['Date of Birth', 'Incorporation Date']) | ||
|
|
@@ -191,7 +189,7 @@ | |
| } | ||
|
|
||
| @if (createClientForm.value.legalFormId === LegalFormId.PERSON) { | ||
| <mat-form-field class="flex-48"> | ||
| <mat-form-field class="flex-15"> | ||
| <mat-label>{{ 'labels.inputs.Gender' | translate }}</mat-label> | ||
| <mat-select formControlName="genderId"> | ||
| @for (gender of genderOptions; track gender) { | ||
|
|
@@ -203,7 +201,7 @@ | |
| </mat-form-field> | ||
| } | ||
|
|
||
| <mat-form-field class="flex-48"> | ||
| <mat-form-field class="flex-23"> | ||
| <mat-label>{{ 'labels.inputs.Staff' | translate }}</mat-label> | ||
| <mat-select formControlName="staffId"> | ||
| @for (staff of staffOptions; track staff) { | ||
|
|
@@ -215,19 +213,20 @@ | |
| </mat-form-field> | ||
|
|
||
| @if (createClientForm.value.legalFormId === LegalFormId.PERSON) { | ||
| <mat-checkbox class="flex-48 margin-v" labelPosition="before" formControlName="isStaff"> | ||
| <mat-checkbox class="flex-15 margin-v" labelPosition="before" formControlName="isStaff"> | ||
| {{ 'labels.inputs.Is staff' | translate }}? | ||
| </mat-checkbox> | ||
| } | ||
|
|
||
| <mat-divider class="flex-98"></mat-divider> | ||
|
|
||
| <mat-form-field class="flex-48"> | ||
| <!-- Row 3: Mobile No, Email Address, Client Type, Client Classification --> | ||
| <mat-form-field class="flex-20"> | ||
| <mat-label>{{ 'labels.inputs.Mobile No' | translate }}</mat-label> | ||
| <input matInput type="text" formControlName="mobileNo" /> | ||
| </mat-form-field> | ||
|
|
||
| <mat-form-field class="flex-48"> | ||
| <mat-form-field class="flex-30"> | ||
| <mat-label>{{ 'labels.inputs.Email Address' | translate }}</mat-label> | ||
| <input matInput formControlName="emailAddress" /> | ||
| @if (createClientForm.controls.emailAddress.errors?.email) { | ||
|
|
@@ -237,7 +236,7 @@ | |
| } | ||
| </mat-form-field> | ||
|
|
||
| <mat-form-field class="flex-48"> | ||
| <mat-form-field class="flex-23"> | ||
| <mat-label>{{ 'labels.inputs.Client Type' | translate }}</mat-label> | ||
| <mat-select formControlName="clientTypeId"> | ||
| @for (clientType of clientTypeOptions; track clientType) { | ||
|
|
@@ -248,7 +247,7 @@ | |
| </mat-select> | ||
| </mat-form-field> | ||
|
|
||
| <mat-form-field class="flex-48"> | ||
| <mat-form-field class="flex-23"> | ||
| <mat-label>{{ 'labels.inputs.Client Classification' | translate }}</mat-label> | ||
| <mat-select formControlName="clientClassificationId"> | ||
| @for (clientClassification of clientClassificationTypeOptions; track clientClassification) { | ||
|
|
@@ -259,7 +258,8 @@ | |
| </mat-select> | ||
| </mat-form-field> | ||
|
|
||
| <mat-form-field class="flex-48" (click)="submittedOnDatePicker.open()"> | ||
| <!-- Row 4: Submitted On, Active?, Activation Date, Open Savings Account?, Savings Product --> | ||
| <mat-form-field class="flex-20" (click)="submittedOnDatePicker.open()"> | ||
| <mat-label>{{ 'labels.inputs.Submitted On' | translate }}</mat-label> | ||
| <input | ||
| matInput | ||
|
|
@@ -273,14 +273,12 @@ | |
| <mat-datepicker #submittedOnDatePicker></mat-datepicker> | ||
| </mat-form-field> | ||
|
|
||
| <br /> | ||
|
|
||
| <mat-checkbox labelPosition="before" formControlName="active" class="margin-v flex-48"> | ||
| <mat-checkbox labelPosition="before" formControlName="active" class="margin-v flex-10"> | ||
| {{ 'labels.inputs.Active' | translate }}? | ||
| </mat-checkbox> | ||
|
|
||
| @if (createClientForm.contains('activationDate')) { | ||
| <mat-form-field class="flex-48" (click)="activatedOnDatePicker.open()"> | ||
| <mat-form-field class="flex-20" (click)="activatedOnDatePicker.open()"> | ||
| <mat-label>{{ 'labels.inputs.Activation Date' | translate }}</mat-label> | ||
| <input | ||
| matInput | ||
|
|
@@ -301,12 +299,12 @@ | |
| </mat-form-field> | ||
| } | ||
|
|
||
| <mat-checkbox labelPosition="before" formControlName="addSavings" class="margin-v flex-48"> | ||
| <mat-checkbox labelPosition="before" formControlName="addSavings" class="margin-v flex-10"> | ||
| {{ 'labels.inputs.Open Savings Account' | translate }}? | ||
| </mat-checkbox> | ||
|
|
||
| @if (createClientForm.contains('savingsProductId')) { | ||
| <mat-form-field class="flex-48"> | ||
| <mat-form-field class="flex-20"> | ||
| <mat-label>{{ 'labels.inputs.Savings Product' | translate }}</mat-label> | ||
| <mat-select required formControlName="savingsProductId"> | ||
| @for (product of savingProductOptions; track product) { | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -68,7 +68,7 @@ const routes: Routes = [ | |
| }, | ||
| { | ||
| path: 'create', | ||
| data: { title: 'Create Client', breadcrumb: 'Create Client', routeParamBreadcrumb: false }, | ||
| data: { title: 'Create Member', breadcrumb: 'Create Member', routeParamBreadcrumb: false }, | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🧩 Analysis chain🏁 Script executed: #!/bin/bash
# Check if "Create Member" translation key exists in translation files
rg -n "Create Member" src/assets/translations/ --type jsonRepository: openMF/web-app Length of output: 40 🏁 Script executed: # First, check the exact content of the routing file around line 71
sed -n '65,85p' src/app/clients/clients-routing.module.tsRepository: openMF/web-app Length of output: 832 🏁 Script executed: # List translation files to understand structure
find src/assets/translations/ -type f -name "*.json" | head -20Repository: openMF/web-app Length of output: 513 🏁 Script executed: # Search for both "Create Member" and "Create Client" to understand the pattern
rg "Create (Member|Client)" src/assets/translations/ -t json --max-count 20Repository: openMF/web-app Length of output: 2038 🏁 Script executed: # Check if "Members View" translation key exists
rg "Members View" src/assets/translations/ -t jsonRepository: openMF/web-app Length of output: 131 🏁 Script executed: # Check if there are any "Member" keys at all in translation files
rg "Member" src/assets/translations/ -t json | head -20Repository: openMF/web-app Length of output: 1673 🏁 Script executed: # Check one translation file to understand the structure
cat src/assets/translations/en-US.json | grep -A2 -B2 "Create Client"Repository: openMF/web-app Length of output: 463 Use the correct i18n translation keys for route metadata. The route data uses string literals that don't exist as translation keys. Replace 🤖 Prompt for AI AgentsSource: Learnings |
||
| component: CreateClientComponent, | ||
| resolve: { | ||
| clientAddressFieldConfig: ClientAddressFieldConfigurationResolver, | ||
|
|
@@ -78,7 +78,7 @@ const routes: Routes = [ | |
| { | ||
| path: ':clientId', | ||
| component: ClientsViewComponent, | ||
| data: { title: 'Clients View', routeParamBreadcrumb: 'clientId' }, | ||
| data: { title: 'Members View', routeParamBreadcrumb: 'clientId' }, | ||
| resolve: { | ||
| clientViewData: ClientViewResolver, | ||
| clientTemplateData: ClientTemplateResolver, | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🧩 Analysis chain
🏁 Script executed:
Repository: openMF/web-app
Length of output: 3511
🏁 Script executed:
Repository: openMF/web-app
Length of output: 50371
🏁 Script executed:
Repository: openMF/web-app
Length of output: 1145
Verify responsive sizing classes use SCSS variables instead of hardcoded values.
Multiple form fields use responsive sizing classes (
flex-20,flex-15,flex-40,flex-23,flex-30,flex-98,flex-10) that currently contain hardcoded percentage values (e.g.,flex: 0 0 20%) insrc/main.scss. Per coding guidelines, these should leverage SCSS variables fromsrc/main.scssorsrc/theme/mifosx-theme.scssrather than explicit hardcoded values.🤖 Prompt for AI Agents
Source: Coding guidelines