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
@@ -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