fix(clients): block Alternate Mobile No from matching Mobile No

Same number in both fields defeats the point of having a second contact
route, and re-running DIP on an identical number is pointless. Added a
cross-field validator on alternateMobileNo, re-checked whenever mobileNo
changes, with a matching error message and the Verify-with-DIP button
disabled while the clash exists.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
2026-09-14 11:49:36 +05:30
co-authored by Claude Sonnet 5
parent 31e99b1363
commit 45a337915e
2 changed files with 30 additions and 3 deletions
@@ -969,6 +969,11 @@
createClientForm.get('alternateMobileNo')?.touched
) {
<mat-error>Enter valid 10-digit number (starts with 6-9)</mat-error>
} @else if (
createClientForm.get('alternateMobileNo')?.hasError('sameAsMobile') &&
createClientForm.get('alternateMobileNo')?.touched
) {
<mat-error>Alternate number can't be the same as Mobile No</mat-error>
}
</mat-form-field>
@@ -979,7 +984,11 @@
color="primary"
type="button"
class="verify-btn"
[disabled]="readOnly || createClientForm.get('alternateMobileNo')?.value?.length !== 10"
[disabled]="
readOnly ||
createClientForm.get('alternateMobileNo')?.value?.length !== 10 ||
createClientForm.get('alternateMobileNo')?.hasError('sameAsMobile')
"
(click)="verifyAlternateDIP()"
>
<fa-icon icon="shield-alt" class="m-r-10"></fa-icon>
@@ -25,7 +25,10 @@ import {
UntypedFormGroup,
Validators,
UntypedFormControl,
ReactiveFormsModule
ReactiveFormsModule,
ValidatorFn,
AbstractControl,
ValidationErrors
} from '@angular/forms';
import { Subject, Subscription, merge } from 'rxjs';
import { filter, switchMap, takeUntil } from 'rxjs/operators';
@@ -922,6 +925,16 @@ export class ClientGeneralStepComponent implements OnInit, OnDestroy, OnChanges
}
}
/** Alternate Mobile No must differ from Mobile No — the same number saved in both fields is
* meaningless (there's no second contact route) and the DIP checks would just repeat. */
private notSameAsMobileNoValidator(): ValidatorFn {
return (control: AbstractControl): ValidationErrors | null => {
const value = control.value;
const mobileNo = control.parent?.get('mobileNo')?.value;
return value && mobileNo && value === mobileNo ? { sameAsMobile: true } : null;
};
}
/**
* Creates the client form.
*/
@@ -961,7 +974,8 @@ export class ClientGeneralStepComponent implements OnInit, OnDestroy, OnChanges
'',
[
Validators.pattern(/^[6-9]\d{9}$/),
Validators.maxLength(10)
Validators.maxLength(10),
this.notSameAsMobileNoValidator()
]
],
emailAddress: [
@@ -1334,6 +1348,10 @@ export class ClientGeneralStepComponent implements OnInit, OnDestroy, OnChanges
// invalid) and its own reset never had a chance to run.
this.mobileOtpVerified = false;
this.mobileNewOtpId = null;
// Alternate Mobile No's "not same as Mobile No" validator reads mobileNo's current
// value, so re-run it here too — otherwise fixing mobileNo away from a clash leaves
// the alternate field's error stuck until the user also edits that field.
this.createClientForm.get('alternateMobileNo')?.updateValueAndValidity({ emitEvent: false });
});
this.createClientForm