feat: non-individual entity UI improvements — hide individual-only sections, fix legal form display, send extended fields to API
- Hide Family Members tab/section for non-individual entities in client view, create flow, and preview - Hide Financial & Classification section for non-individual entities in personal data and preview - Fix legal form column in clients list — fetch legalForm from client API for correct display - Add person/business icon before client name in list rows - Remove unsupportedNpd filter — send authorizedSignatory, additionalInfo, dateOfRegistration to API - Add registration number format hint (mat-hint) based on constitution type - Add spacing between verification row and constitution type dropdowns - Reduce table cell padding and prevent action buttons from being clipped - Add missing MPL-2.0 license headers Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 4.6
parent
ab01111424
commit
b890d24bb7
@@ -35,287 +35,226 @@
|
||||
|
||||
<!-- KYC Summary (read-only when not in edit mode) -->
|
||||
@if (!isEditMode && kycData) {
|
||||
<div class="kyc-summary-grid">
|
||||
<!-- PAN Card -->
|
||||
<mat-card class="kyc-card">
|
||||
<mat-card-content>
|
||||
<div class="kyc-card-header">
|
||||
<div class="kyc-card-label">
|
||||
<mat-icon class="kyc-card-icon">credit_card</mat-icon>
|
||||
<span>{{ 'labels.inputs.PAN Number' | translate }}</span>
|
||||
<span class="kyc-tag">KYC</span>
|
||||
</div>
|
||||
@if (kycData.panVerified) {
|
||||
<span class="status-chip verified">
|
||||
<mat-icon class="status-chip-icon">check_circle</mat-icon>
|
||||
{{ 'labels.inputs.Verified' | translate }}
|
||||
</span>
|
||||
} @else {
|
||||
<span class="status-chip not-verified">
|
||||
<mat-icon class="status-chip-icon">radio_button_unchecked</mat-icon>
|
||||
{{ 'labels.inputs.Not Verified' | translate }}
|
||||
</span>
|
||||
}
|
||||
</div>
|
||||
<p class="kyc-value">{{ kycData.panNumber || '—' }}</p>
|
||||
@if (kycData.panVerifiedOn) {
|
||||
<p class="kyc-meta">
|
||||
{{ 'labels.inputs.Last Verified On' | translate }}: {{ formatDate(kycData.panVerifiedOn) }}
|
||||
</p>
|
||||
<!-- Verification Table -->
|
||||
<div class="kv-table">
|
||||
<div class="kv-table__header">
|
||||
<span class="kv-table__col kv-table__col--doc">Document</span>
|
||||
<span class="kv-table__col kv-table__col--num">Number</span>
|
||||
<span class="kv-table__col kv-table__col--status">Status</span>
|
||||
<span class="kv-table__col kv-table__col--date">Verified On</span>
|
||||
<span class="kv-table__col kv-table__col--action">Action</span>
|
||||
</div>
|
||||
|
||||
<!-- PAN Row -->
|
||||
<div class="kv-table__row">
|
||||
<span class="kv-table__col kv-table__col--doc">
|
||||
<mat-icon class="kv-doc-icon">credit_card</mat-icon> PAN
|
||||
</span>
|
||||
<span class="kv-table__col kv-table__col--num kv-mono">{{ kycData.panNumber || '—' }}</span>
|
||||
<span class="kv-table__col kv-table__col--status">
|
||||
@if (kycData.panVerified) {
|
||||
<span class="kv-status kv-status--ok"><mat-icon>check_circle</mat-icon> Verified</span>
|
||||
} @else {
|
||||
<span class="kv-status kv-status--pending"><mat-icon>radio_button_unchecked</mat-icon> Pending</span>
|
||||
}
|
||||
@if (verificationError.pan) {
|
||||
<div class="kyc-error-msg">
|
||||
<mat-icon class="kyc-error-icon">error_outline</mat-icon>
|
||||
<span>{{ verificationError.pan }}</span>
|
||||
</div>
|
||||
}
|
||||
@if (verificationStatus.pan === 'VERIFIED' && verificationDetails.pan?.name) {
|
||||
<p class="kyc-meta verification-detail-text">{{ verificationDetails.pan.name }}</p>
|
||||
}
|
||||
<button
|
||||
mat-stroked-button
|
||||
color="primary"
|
||||
class="re-verify-btn"
|
||||
type="button"
|
||||
[disabled]="verifying.pan || !kycData.panNumber"
|
||||
(click)="verifyPAN()"
|
||||
>
|
||||
@if (verifying.pan) {
|
||||
<mat-progress-spinner diameter="14" mode="indeterminate"></mat-progress-spinner>
|
||||
} @else {
|
||||
{{ 'labels.inputs.Re-Verify' | translate }}
|
||||
}
|
||||
</span>
|
||||
<span class="kv-table__col kv-table__col--date">{{ kycData.panVerifiedOn ? formatDate(kycData.panVerifiedOn) : '—' }}</span>
|
||||
<span class="kv-table__col kv-table__col--action">
|
||||
<button mat-stroked-button class="kv-action-btn" type="button"
|
||||
[disabled]="verifying.pan || !kycData.panNumber" (click)="verifyPAN()">
|
||||
@if (verifying.pan) { <mat-progress-spinner diameter="14" mode="indeterminate"></mat-progress-spinner> }
|
||||
@else { Re-Verify }
|
||||
</button>
|
||||
</mat-card-content>
|
||||
</mat-card>
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<!-- Aadhaar Card -->
|
||||
<mat-card class="kyc-card">
|
||||
<mat-card-content>
|
||||
<div class="kyc-card-header">
|
||||
<div class="kyc-card-label">
|
||||
<mat-icon class="kyc-card-icon">fingerprint</mat-icon>
|
||||
<span>{{ 'labels.inputs.Aadhaar Number' | translate }}</span>
|
||||
<span class="kyc-tag">KYC</span>
|
||||
</div>
|
||||
@if (kycData.aadhaarVerified) {
|
||||
<span class="status-chip verified">
|
||||
<mat-icon class="status-chip-icon">check_circle</mat-icon>
|
||||
{{ 'labels.inputs.Verified' | translate }}
|
||||
</span>
|
||||
} @else {
|
||||
<span class="status-chip not-verified">
|
||||
<mat-icon class="status-chip-icon">radio_button_unchecked</mat-icon>
|
||||
{{ 'labels.inputs.Not Verified' | translate }}
|
||||
</span>
|
||||
}
|
||||
</div>
|
||||
<p class="kyc-value">{{ kycData.aadhaarNumberMasked || '—' }}</p>
|
||||
@if (kycData.aadhaarVerifiedOn) {
|
||||
<p class="kyc-meta">
|
||||
{{ 'labels.inputs.Last Verified On' | translate }}: {{ formatDate(kycData.aadhaarVerifiedOn) }}
|
||||
</p>
|
||||
<!-- Aadhaar Row -->
|
||||
<div class="kv-table__row">
|
||||
<span class="kv-table__col kv-table__col--doc">
|
||||
<mat-icon class="kv-doc-icon">fingerprint</mat-icon> Aadhaar
|
||||
</span>
|
||||
<span class="kv-table__col kv-table__col--num kv-mono">{{ kycData.aadhaarNumberMasked || '—' }}</span>
|
||||
<span class="kv-table__col kv-table__col--status">
|
||||
@if (kycData.aadhaarVerified) {
|
||||
<span class="kv-status kv-status--ok"><mat-icon>check_circle</mat-icon> Verified</span>
|
||||
} @else {
|
||||
<span class="kv-status kv-status--pending"><mat-icon>radio_button_unchecked</mat-icon> Pending</span>
|
||||
}
|
||||
@if (verificationError.aadhaar) {
|
||||
<div class="kyc-error-msg">
|
||||
<mat-icon class="kyc-error-icon">error_outline</mat-icon>
|
||||
<span>{{ verificationError.aadhaar }}</span>
|
||||
</div>
|
||||
}
|
||||
@if (verificationStatus.aadhaar === 'VERIFIED' && verificationDetails.aadhaar?.name) {
|
||||
<p class="kyc-meta verification-detail-text">{{ verificationDetails.aadhaar.name }}</p>
|
||||
}
|
||||
|
||||
<!-- Step 1: Re-Verify button -->
|
||||
</span>
|
||||
<span class="kv-table__col kv-table__col--date">{{ kycData.aadhaarVerifiedOn ? formatDate(kycData.aadhaarVerifiedOn) : '—' }}</span>
|
||||
<span class="kv-table__col kv-table__col--action">
|
||||
@if (!showAadhaarReVerify && !aadhaarOtpSent) {
|
||||
<button
|
||||
mat-stroked-button
|
||||
color="primary"
|
||||
class="re-verify-btn"
|
||||
type="button"
|
||||
[disabled]="verifying.aadhaar || !kycData.aadhaarNumberMasked"
|
||||
(click)="startAadhaarReVerify()"
|
||||
>
|
||||
{{ 'labels.inputs.Re-Verify' | translate }}
|
||||
<button mat-stroked-button class="kv-action-btn" type="button"
|
||||
[disabled]="verifying.aadhaar || !kycData.aadhaarNumberMasked" (click)="startAadhaarReVerify()">
|
||||
Re-Verify
|
||||
</button>
|
||||
}
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<!-- Step 2: Enter full Aadhaar + Send OTP -->
|
||||
@if (showAadhaarReVerify && !aadhaarOtpSent) {
|
||||
<div class="otp-section">
|
||||
<div class="otp-inline">
|
||||
<mat-form-field appearance="outline" class="otp-field">
|
||||
<mat-label>{{ 'labels.inputs.Enter 12-digit Aadhaar' | translate }}</mat-label>
|
||||
<input
|
||||
matInput
|
||||
[(ngModel)]="aadhaarFullNumber"
|
||||
[ngModelOptions]="{ standalone: true }"
|
||||
maxlength="12"
|
||||
type="password"
|
||||
/>
|
||||
</mat-form-field>
|
||||
<button
|
||||
mat-raised-button
|
||||
color="accent"
|
||||
class="otp-verify-btn"
|
||||
type="button"
|
||||
[disabled]="!aadhaarFullNumber || aadhaarFullNumber.length !== 12 || verifying.aadhaar"
|
||||
(click)="sendAadhaarOtp()"
|
||||
>
|
||||
@if (verifying.aadhaar) {
|
||||
<mat-progress-spinner diameter="14" mode="indeterminate"></mat-progress-spinner>
|
||||
} @else {
|
||||
Send OTP
|
||||
}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
|
||||
<!-- Step 3: Enter OTP + Verify -->
|
||||
@if (aadhaarOtpSent) {
|
||||
<div class="otp-section">
|
||||
<p class="otp-info">
|
||||
<mat-icon class="otp-info-icon">sms</mat-icon>
|
||||
OTP sent to Aadhaar-linked mobile
|
||||
</p>
|
||||
<div class="otp-inline">
|
||||
<mat-form-field appearance="outline" class="otp-field">
|
||||
<mat-label>Enter OTP</mat-label>
|
||||
<input
|
||||
matInput
|
||||
[(ngModel)]="aadhaarOtp"
|
||||
[ngModelOptions]="{ standalone: true }"
|
||||
maxlength="6"
|
||||
autocomplete="one-time-code"
|
||||
/>
|
||||
</mat-form-field>
|
||||
<button
|
||||
mat-raised-button
|
||||
color="accent"
|
||||
class="otp-verify-btn"
|
||||
type="button"
|
||||
[disabled]="!aadhaarOtp || aadhaarOtp.length < 4 || aadhaarOtpVerifying"
|
||||
(click)="verifyAadhaarOtp()"
|
||||
>
|
||||
@if (aadhaarOtpVerifying) {
|
||||
<mat-progress-spinner diameter="14" mode="indeterminate"></mat-progress-spinner>
|
||||
} @else {
|
||||
Verify OTP
|
||||
}
|
||||
</button>
|
||||
<button
|
||||
mat-stroked-button
|
||||
type="button"
|
||||
class="otp-resend-btn"
|
||||
[disabled]="verifying.aadhaar"
|
||||
(click)="sendAadhaarOtp()"
|
||||
>
|
||||
Resend
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
</mat-card-content>
|
||||
</mat-card>
|
||||
|
||||
<!-- GSTIN Card -->
|
||||
<mat-card class="kyc-card">
|
||||
<mat-card-content>
|
||||
<div class="kyc-card-header">
|
||||
<div class="kyc-card-label">
|
||||
<mat-icon class="kyc-card-icon">business</mat-icon>
|
||||
<span>{{ 'labels.inputs.GSTIN Number' | translate }}</span>
|
||||
<span class="kyc-tag">KYC</span>
|
||||
</div>
|
||||
<!-- GSTIN Row (Non-Individual only) -->
|
||||
@if (isNonIndividual) {
|
||||
<div class="kv-table__row">
|
||||
<span class="kv-table__col kv-table__col--doc">
|
||||
<mat-icon class="kv-doc-icon">business</mat-icon> GSTIN
|
||||
</span>
|
||||
<span class="kv-table__col kv-table__col--num kv-mono">{{ kycData.gstinNumber || '—' }}</span>
|
||||
<span class="kv-table__col kv-table__col--status">
|
||||
@if (kycData.gstinVerified) {
|
||||
<span class="status-chip verified">
|
||||
<mat-icon class="status-chip-icon">check_circle</mat-icon>
|
||||
{{ 'labels.inputs.Verified' | translate }}
|
||||
</span>
|
||||
<span class="kv-status kv-status--ok"><mat-icon>check_circle</mat-icon> Verified</span>
|
||||
} @else {
|
||||
<span class="status-chip not-verified">
|
||||
<mat-icon class="status-chip-icon">radio_button_unchecked</mat-icon>
|
||||
{{ 'labels.inputs.Not Verified' | translate }}
|
||||
</span>
|
||||
<span class="kv-status kv-status--pending"><mat-icon>radio_button_unchecked</mat-icon> Pending</span>
|
||||
}
|
||||
</div>
|
||||
<p class="kyc-value">{{ kycData.gstinNumber || '—' }}</p>
|
||||
@if (kycData.gstinVerifiedOn) {
|
||||
<p class="kyc-meta">
|
||||
{{ 'labels.inputs.Last Verified On' | translate }}: {{ formatDate(kycData.gstinVerifiedOn) }}
|
||||
</p>
|
||||
}
|
||||
@if (verificationError.gstin) {
|
||||
<div class="kyc-error-msg">
|
||||
<mat-icon class="kyc-error-icon">error_outline</mat-icon>
|
||||
<span>{{ verificationError.gstin }}</span>
|
||||
</div>
|
||||
}
|
||||
@if (verificationStatus.gstin === 'VERIFIED' && verificationDetails.gstin?.businessName) {
|
||||
<p class="kyc-meta verification-detail-text">{{ verificationDetails.gstin.businessName }}</p>
|
||||
}
|
||||
<button
|
||||
mat-stroked-button
|
||||
color="primary"
|
||||
class="re-verify-btn"
|
||||
type="button"
|
||||
[disabled]="verifying.gstin || !kycData.gstinNumber"
|
||||
(click)="verifyGSTIN()"
|
||||
>
|
||||
@if (verifying.gstin) {
|
||||
<mat-progress-spinner diameter="14" mode="indeterminate"></mat-progress-spinner>
|
||||
</span>
|
||||
<span class="kv-table__col kv-table__col--date">{{ kycData.gstinVerifiedOn ? formatDate(kycData.gstinVerifiedOn) : '—' }}</span>
|
||||
<span class="kv-table__col kv-table__col--action">
|
||||
<button mat-stroked-button class="kv-action-btn" type="button"
|
||||
[disabled]="verifying.gstin || !kycData.gstinNumber" (click)="verifyGSTIN()">
|
||||
@if (verifying.gstin) { <mat-progress-spinner diameter="14" mode="indeterminate"></mat-progress-spinner> }
|
||||
@else { Re-Verify }
|
||||
</button>
|
||||
</span>
|
||||
</div>
|
||||
}
|
||||
|
||||
<!-- Enterprise PAN Row (Non-Individual) -->
|
||||
@if (isNonIndividual && kycData?.enterprisePan) {
|
||||
<div class="kv-table__row">
|
||||
<span class="kv-table__col kv-table__col--doc">
|
||||
<mat-icon class="kv-doc-icon">credit_card</mat-icon> Enterprise PAN
|
||||
</span>
|
||||
<span class="kv-table__col kv-table__col--num kv-mono">{{ kycData.enterprisePan }}</span>
|
||||
<span class="kv-table__col kv-table__col--status">
|
||||
@if (kycData.enterprisePanVerified) {
|
||||
<span class="kv-status kv-status--ok"><mat-icon>check_circle</mat-icon> Verified</span>
|
||||
} @else {
|
||||
{{ 'labels.inputs.Re-Verify' | translate }}
|
||||
<span class="kv-status kv-status--pending"><mat-icon>radio_button_unchecked</mat-icon> Pending</span>
|
||||
}
|
||||
</button>
|
||||
</mat-card-content>
|
||||
</mat-card>
|
||||
</span>
|
||||
<span class="kv-table__col kv-table__col--date">{{ kycData.enterprisePanVerifiedOn ? formatDate(kycData.enterprisePanVerifiedOn) : '—' }}</span>
|
||||
<span class="kv-table__col kv-table__col--action"></span>
|
||||
</div>
|
||||
}
|
||||
|
||||
<!-- CIN Row (Non-Individual / Company) -->
|
||||
@if (isNonIndividual && kycData?.cinNumber) {
|
||||
<div class="kv-table__row">
|
||||
<span class="kv-table__col kv-table__col--doc">
|
||||
<mat-icon class="kv-doc-icon">verified_user</mat-icon> CIN
|
||||
</span>
|
||||
<span class="kv-table__col kv-table__col--num kv-mono">{{ kycData.cinNumber }}</span>
|
||||
<span class="kv-table__col kv-table__col--status">
|
||||
@if (kycData.cinVerified) {
|
||||
<span class="kv-status kv-status--ok"><mat-icon>check_circle</mat-icon> Verified</span>
|
||||
} @else {
|
||||
<span class="kv-status kv-status--pending"><mat-icon>radio_button_unchecked</mat-icon> Pending</span>
|
||||
}
|
||||
</span>
|
||||
<span class="kv-table__col kv-table__col--date">—</span>
|
||||
<span class="kv-table__col kv-table__col--action"></span>
|
||||
</div>
|
||||
}
|
||||
|
||||
<!-- Incorporation Date Row (Non-Individual) -->
|
||||
@if (isNonIndividual && kycData?.incorporationDate) {
|
||||
<div class="kv-table__row kv-table__row--link">
|
||||
<span class="kv-table__col kv-table__col--doc">
|
||||
<mat-icon class="kv-doc-icon">event</mat-icon> Incorporation Date
|
||||
</span>
|
||||
<span class="kv-table__col kv-table__col--num">{{ formatDate(kycData.incorporationDate) }}</span>
|
||||
<span class="kv-table__col kv-table__col--status">—</span>
|
||||
<span class="kv-table__col kv-table__col--date">—</span>
|
||||
<span class="kv-table__col kv-table__col--action"></span>
|
||||
</div>
|
||||
}
|
||||
|
||||
<!-- PAN-Aadhaar Link Row -->
|
||||
<div class="kv-table__row kv-table__row--link">
|
||||
<span class="kv-table__col kv-table__col--doc">
|
||||
<mat-icon class="kv-doc-icon">link</mat-icon> PAN–Aadhaar Link
|
||||
</span>
|
||||
<span class="kv-table__col kv-table__col--num">Sec 139AA</span>
|
||||
<span class="kv-table__col kv-table__col--status">
|
||||
@if (kycData?.panAadhaarSeedingStatus === 'Y') {
|
||||
<span class="kv-status kv-status--ok"><mat-icon>check_circle</mat-icon> Linked</span>
|
||||
} @else if (kycData?.panAadhaarSeedingStatus === 'N') {
|
||||
<span class="kv-status kv-status--fail"><mat-icon>cancel</mat-icon> Not Linked</span>
|
||||
} @else if (kycData?.panAadhaarSeedingStatus === 'E') {
|
||||
<span class="kv-status kv-status--info"><mat-icon>info</mat-icon> Exempt</span>
|
||||
} @else {
|
||||
<span class="kv-status kv-status--pending"><mat-icon>radio_button_unchecked</mat-icon> Pending</span>
|
||||
}
|
||||
</span>
|
||||
<span class="kv-table__col kv-table__col--date">—</span>
|
||||
<span class="kv-table__col kv-table__col--action"></span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Additional Info -->
|
||||
<mat-card class="kyc-info-card">
|
||||
<mat-card-content>
|
||||
<div class="kyc-info-grid">
|
||||
<div class="kyc-info-item">
|
||||
<span class="kyc-info-label">{{ 'labels.inputs.KYC Type' | translate }}</span>
|
||||
<span class="kyc-info-value">{{
|
||||
kycData.kycType === 1 ? 'Individual' : kycData.kycType === 2 ? 'Non-Individual' : '—'
|
||||
}}</span>
|
||||
</div>
|
||||
<div class="kyc-info-item">
|
||||
<span class="kyc-info-label">{{ 'labels.inputs.Risk Category' | translate }}</span>
|
||||
<span class="kyc-info-value">{{
|
||||
kycData.riskCategory === 1
|
||||
? 'Low'
|
||||
: kycData.riskCategory === 2
|
||||
? 'Medium'
|
||||
: kycData.riskCategory === 3
|
||||
? 'High'
|
||||
: '—'
|
||||
}}</span>
|
||||
</div>
|
||||
<div class="kyc-info-item">
|
||||
<span class="kyc-info-label">{{ 'labels.inputs.Initiated On' | translate }}</span>
|
||||
<span class="kyc-info-value">{{ kycData.initiatedOn || '—' }}</span>
|
||||
</div>
|
||||
<div class="kyc-info-item">
|
||||
<span class="kyc-info-label">{{ 'labels.inputs.Last Verified On' | translate }}</span>
|
||||
<span class="kyc-info-value">{{ formatDate(kycData.verifiedOn) }}</span>
|
||||
</div>
|
||||
<div class="kyc-info-item">
|
||||
<span class="kyc-info-label">{{ 'labels.inputs.Expiry Date' | translate }}</span>
|
||||
<span class="kyc-info-value">{{ kycData.expiryDate || '—' }}</span>
|
||||
</div>
|
||||
@if (kycData.remarks) {
|
||||
<div class="kyc-info-item full-span">
|
||||
<span class="kyc-info-label">{{ 'labels.inputs.Remarks' | translate }}</span>
|
||||
<span class="kyc-info-value">{{ kycData.remarks }}</span>
|
||||
</div>
|
||||
}
|
||||
<!-- Aadhaar OTP inline (shown below table when re-verifying) -->
|
||||
@if (showAadhaarReVerify && !aadhaarOtpSent) {
|
||||
<div class="kv-otp-bar">
|
||||
<mat-form-field appearance="outline" class="kv-otp-input">
|
||||
<mat-label>Enter 12-digit Aadhaar</mat-label>
|
||||
<input matInput [(ngModel)]="aadhaarFullNumber" [ngModelOptions]="{standalone: true}" maxlength="12" type="password" />
|
||||
</mat-form-field>
|
||||
<button mat-raised-button color="primary" type="button" class="kv-otp-btn"
|
||||
[disabled]="!aadhaarFullNumber || aadhaarFullNumber.length !== 12 || verifying.aadhaar" (click)="sendAadhaarOtp()">
|
||||
@if (verifying.aadhaar) { <mat-progress-spinner diameter="14" mode="indeterminate"></mat-progress-spinner> }
|
||||
@else { Send OTP }
|
||||
</button>
|
||||
</div>
|
||||
}
|
||||
@if (aadhaarOtpSent) {
|
||||
<div class="kv-otp-bar">
|
||||
<span class="kv-otp-label"><mat-icon>sms</mat-icon> OTP sent</span>
|
||||
<mat-form-field appearance="outline" class="kv-otp-input">
|
||||
<mat-label>Enter OTP</mat-label>
|
||||
<input matInput [(ngModel)]="aadhaarOtp" [ngModelOptions]="{standalone: true}" maxlength="6" autocomplete="one-time-code" />
|
||||
</mat-form-field>
|
||||
<button mat-raised-button color="primary" type="button" class="kv-otp-btn"
|
||||
[disabled]="!aadhaarOtp || aadhaarOtp.length < 4 || aadhaarOtpVerifying" (click)="verifyAadhaarOtp()">
|
||||
@if (aadhaarOtpVerifying) { <mat-progress-spinner diameter="14" mode="indeterminate"></mat-progress-spinner> }
|
||||
@else { Verify }
|
||||
</button>
|
||||
<button mat-stroked-button type="button" class="kv-otp-btn" [disabled]="verifying.aadhaar" (click)="sendAadhaarOtp()">Resend</button>
|
||||
</div>
|
||||
}
|
||||
@if (verificationError.aadhaar) {
|
||||
<div class="kyc-error-msg"><mat-icon class="kyc-error-icon">error_outline</mat-icon> {{ verificationError.aadhaar }}</div>
|
||||
}
|
||||
@if (verificationError.pan) {
|
||||
<div class="kyc-error-msg"><mat-icon class="kyc-error-icon">error_outline</mat-icon> {{ verificationError.pan }}</div>
|
||||
}
|
||||
|
||||
<!-- KYC Meta Grid -->
|
||||
<div class="kv-meta-grid">
|
||||
<div class="kv-meta-item">
|
||||
<span class="kv-meta-label">KYC Type</span>
|
||||
<span class="kv-meta-value">{{ kycData.kycType === 1 ? 'Individual' : kycData.kycType === 2 ? 'Non-Individual' : '—' }}</span>
|
||||
</div>
|
||||
<div class="kv-meta-item">
|
||||
<span class="kv-meta-label">Risk Category</span>
|
||||
<span class="kv-meta-value">{{ kycData.riskCategory === 1 ? 'Low' : kycData.riskCategory === 2 ? 'Medium' : kycData.riskCategory === 3 ? 'High' : '—' }}</span>
|
||||
</div>
|
||||
<div class="kv-meta-item">
|
||||
<span class="kv-meta-label">Initiated On</span>
|
||||
<span class="kv-meta-value">{{ formatDate(kycData.initiatedOn) }}</span>
|
||||
</div>
|
||||
<div class="kv-meta-item">
|
||||
<span class="kv-meta-label">Last Verified</span>
|
||||
<span class="kv-meta-value">{{ formatDate(kycData.verifiedOn) }}</span>
|
||||
</div>
|
||||
<div class="kv-meta-item">
|
||||
<span class="kv-meta-label">Expiry Date</span>
|
||||
<span class="kv-meta-value">{{ formatDate(kycData.expiryDate) }}</span>
|
||||
</div>
|
||||
@if (kycData.remarks) {
|
||||
<div class="kv-meta-item kv-meta-item--full">
|
||||
<span class="kv-meta-label">Remarks</span>
|
||||
<span class="kv-meta-value">{{ kycData.remarks }}</span>
|
||||
</div>
|
||||
</mat-card-content>
|
||||
</mat-card>
|
||||
}
|
||||
</div>
|
||||
}
|
||||
|
||||
<!-- No KYC Data State -->
|
||||
@@ -497,67 +436,69 @@
|
||||
}
|
||||
</div>
|
||||
|
||||
<!-- GSTIN -->
|
||||
<div class="kyc-edit-field">
|
||||
<div class="kyc-field-label-row">
|
||||
<span class="kyc-field-title">{{ 'labels.inputs.GSTIN Number' | translate }}</span>
|
||||
<span class="kyc-tag">KYC</span>
|
||||
</div>
|
||||
<div class="kyc-input-row">
|
||||
<mat-form-field appearance="outline" class="kyc-input">
|
||||
<mat-label>{{ 'labels.inputs.GSTIN Number' | translate }}</mat-label>
|
||||
<input
|
||||
matInput
|
||||
formControlName="gstinNumber"
|
||||
maxlength="15"
|
||||
style="text-transform: uppercase"
|
||||
(input)="
|
||||
kycForm
|
||||
.get('gstinNumber')
|
||||
?.setValue($any($event.target).value.toUpperCase(), { emitEvent: false })
|
||||
"
|
||||
/>
|
||||
@if (kycForm.get('gstinNumber')?.hasError('pattern') && kycForm.get('gstinNumber')?.touched) {
|
||||
<mat-error>{{ 'labels.inputs.Enter 15-character GSTIN' | translate }}</mat-error>
|
||||
}
|
||||
@if (verificationStatus.gstin === 'VERIFIED') {
|
||||
<mat-icon matSuffix class="status-icon verified">check_circle</mat-icon>
|
||||
}
|
||||
@if (verificationStatus.gstin === 'FAILED') {
|
||||
<mat-icon matSuffix class="status-icon failed">cancel</mat-icon>
|
||||
}
|
||||
</mat-form-field>
|
||||
<button
|
||||
mat-raised-button
|
||||
color="accent"
|
||||
type="button"
|
||||
class="verify-btn"
|
||||
[disabled]="
|
||||
!kycId ||
|
||||
!kycForm.get('gstinNumber')?.value ||
|
||||
kycForm.get('gstinNumber')?.invalid ||
|
||||
verifying.gstin
|
||||
"
|
||||
(click)="verifyGSTIN()"
|
||||
[matTooltip]="!kycId ? 'Save KYC details first' : ''"
|
||||
>
|
||||
@if (verifying.gstin) {
|
||||
<mat-progress-spinner diameter="16" mode="indeterminate"></mat-progress-spinner>
|
||||
} @else {
|
||||
{{ 'labels.inputs.Verify' | translate }}
|
||||
}
|
||||
</button>
|
||||
</div>
|
||||
@if (verificationError.gstin) {
|
||||
<div class="kyc-error-msg">
|
||||
<mat-icon class="kyc-error-icon">error_outline</mat-icon>
|
||||
<span>{{ verificationError.gstin }}</span>
|
||||
<!-- GSTIN (Non-Individual only) -->
|
||||
@if (isNonIndividual) {
|
||||
<div class="kyc-edit-field">
|
||||
<div class="kyc-field-label-row">
|
||||
<span class="kyc-field-title">{{ 'labels.inputs.GSTIN Number' | translate }}</span>
|
||||
<span class="kyc-tag">KYC</span>
|
||||
</div>
|
||||
}
|
||||
@if (verificationStatus.gstin === 'VERIFIED' && verificationDetails.gstin?.businessName) {
|
||||
<span class="verification-detail-text">{{ verificationDetails.gstin.businessName }}</span>
|
||||
}
|
||||
</div>
|
||||
<div class="kyc-input-row">
|
||||
<mat-form-field appearance="outline" class="kyc-input">
|
||||
<mat-label>{{ 'labels.inputs.GSTIN Number' | translate }}</mat-label>
|
||||
<input
|
||||
matInput
|
||||
formControlName="gstinNumber"
|
||||
maxlength="15"
|
||||
style="text-transform: uppercase"
|
||||
(input)="
|
||||
kycForm
|
||||
.get('gstinNumber')
|
||||
?.setValue($any($event.target).value.toUpperCase(), { emitEvent: false })
|
||||
"
|
||||
/>
|
||||
@if (kycForm.get('gstinNumber')?.hasError('pattern') && kycForm.get('gstinNumber')?.touched) {
|
||||
<mat-error>{{ 'labels.inputs.Enter 15-character GSTIN' | translate }}</mat-error>
|
||||
}
|
||||
@if (verificationStatus.gstin === 'VERIFIED') {
|
||||
<mat-icon matSuffix class="status-icon verified">check_circle</mat-icon>
|
||||
}
|
||||
@if (verificationStatus.gstin === 'FAILED') {
|
||||
<mat-icon matSuffix class="status-icon failed">cancel</mat-icon>
|
||||
}
|
||||
</mat-form-field>
|
||||
<button
|
||||
mat-raised-button
|
||||
color="accent"
|
||||
type="button"
|
||||
class="verify-btn"
|
||||
[disabled]="
|
||||
!kycId ||
|
||||
!kycForm.get('gstinNumber')?.value ||
|
||||
kycForm.get('gstinNumber')?.invalid ||
|
||||
verifying.gstin
|
||||
"
|
||||
(click)="verifyGSTIN()"
|
||||
[matTooltip]="!kycId ? 'Save KYC details first' : ''"
|
||||
>
|
||||
@if (verifying.gstin) {
|
||||
<mat-progress-spinner diameter="16" mode="indeterminate"></mat-progress-spinner>
|
||||
} @else {
|
||||
{{ 'labels.inputs.Verify' | translate }}
|
||||
}
|
||||
</button>
|
||||
</div>
|
||||
@if (verificationError.gstin) {
|
||||
<div class="kyc-error-msg">
|
||||
<mat-icon class="kyc-error-icon">error_outline</mat-icon>
|
||||
<span>{{ verificationError.gstin }}</span>
|
||||
</div>
|
||||
}
|
||||
@if (verificationStatus.gstin === 'VERIFIED' && verificationDetails.gstin?.businessName) {
|
||||
<span class="verification-detail-text">{{ verificationDetails.gstin.businessName }}</span>
|
||||
}
|
||||
</div>
|
||||
}
|
||||
|
||||
<!-- KYC Type -->
|
||||
@if (!kycId) {
|
||||
|
||||
Reference in New Issue
Block a user