feat(election,family): family member KYC display, collapsible cards, linked/manual badges, create-as-client flow
- nomination-apply: show full KYC for linked family members via nested forkJoin, accordion expand/collapse cards, owner chips on KYC headers, 'Create as Client' button for manual entries - family-members-tab: show Linked Client / Manual Entry badges, entry type in detail grid, 'Create as Client' button navigating with prefill state - create-client + client-general-step: accept prefillData @Input from navigation state, patch form fields from family member data - Add MPL-2.0 headers to all election module files Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Sonnet 4.6
parent
822fa4c68d
commit
10b301c30c
@@ -33,11 +33,22 @@
|
||||
<mat-expansion-panel class="nom-panel">
|
||||
<mat-expansion-panel-header class="nom-panel__header">
|
||||
<mat-panel-title class="nom-panel__title">
|
||||
<mat-icon class="nom-panel__mat-icon">person</mat-icon>
|
||||
<mat-icon class="nom-panel__mat-icon" [class.nom-panel__mat-icon--linked]="isLinkedClient(member)">
|
||||
{{ isLinkedClient(member) ? 'person_pin' : 'person' }}
|
||||
</mat-icon>
|
||||
<span class="nom-panel__name">{{ displayName(member) }}</span>
|
||||
@if (getRelationship(member)) {
|
||||
<span class="nom-panel__badge nom-panel__badge--relation">{{ getRelationship(member) }}</span>
|
||||
}
|
||||
@if (isLinkedClient(member)) {
|
||||
<span class="nom-panel__badge nom-panel__badge--linked">
|
||||
<mat-icon>person_pin</mat-icon> Linked Client
|
||||
</span>
|
||||
} @else {
|
||||
<span class="nom-panel__badge nom-panel__badge--manual">
|
||||
<mat-icon>edit_note</mat-icon> Manual Entry
|
||||
</span>
|
||||
}
|
||||
</mat-panel-title>
|
||||
<mat-panel-description class="nom-panel__desc">
|
||||
@if (member.dateOfBirth) {
|
||||
@@ -66,14 +77,42 @@
|
||||
<fa-icon icon="trash" class="m-r-10"></fa-icon> Delete
|
||||
</button>
|
||||
</div>
|
||||
@if (!isLinkedClient(member)) {
|
||||
<button mat-flat-button class="nom-actions__create-client" (click)="createClientFromMember(member)">
|
||||
<mat-icon>person_add</mat-icon> Create as Client
|
||||
</button>
|
||||
}
|
||||
</div>
|
||||
}
|
||||
|
||||
<div class="nom-grid">
|
||||
<!-- Entry type row (always shown) -->
|
||||
<div class="nom-field">
|
||||
<div class="nom-field__label">Entry Type</div>
|
||||
<div class="nom-field__value">
|
||||
@if (isLinkedClient(member)) {
|
||||
<span class="nom-type-badge nom-type-badge--linked">
|
||||
<mat-icon>person_pin</mat-icon> Linked Existing Client
|
||||
</span>
|
||||
} @else {
|
||||
<span class="nom-type-badge nom-type-badge--manual">
|
||||
<mat-icon>edit_note</mat-icon> Manually Entered
|
||||
</span>
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
@if (isLinkedClient(member)) {
|
||||
<div class="nom-field">
|
||||
<div class="nom-field__label">CBS Client ID</div>
|
||||
<div class="nom-field__value nom-field__value--mono">
|
||||
{{ member.linkedClientCif || member.linkedClientId }}
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
@if (member.firstName) {
|
||||
<div class="nom-field">
|
||||
<div class="nom-field__label">Name</div>
|
||||
<div class="nom-field__value">{{ member.firstName }}</div>
|
||||
<div class="nom-field__value">{{ displayName(member) }}</div>
|
||||
</div>
|
||||
}
|
||||
@if (getRelationship(member)) {
|
||||
|
||||
@@ -182,6 +182,41 @@ $orange-light: #fff3e0;
|
||||
background: $orange-light;
|
||||
color: $orange;
|
||||
}
|
||||
|
||||
&--linked {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: 3px;
|
||||
background: $green-light;
|
||||
color: $green;
|
||||
border: 1px solid color.adjust($green-light, $lightness: -8%);
|
||||
|
||||
mat-icon {
|
||||
font-size: 12px;
|
||||
height: 12px;
|
||||
width: 12px;
|
||||
}
|
||||
}
|
||||
|
||||
&--manual {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: 3px;
|
||||
background: $gray-100;
|
||||
color: $gray-700;
|
||||
border: 1px solid $gray-200;
|
||||
|
||||
mat-icon {
|
||||
font-size: 12px;
|
||||
height: 12px;
|
||||
width: 12px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&__mat-icon--linked {
|
||||
background: $green-light;
|
||||
color: $green;
|
||||
}
|
||||
|
||||
&__desc {
|
||||
@@ -213,6 +248,29 @@ $orange-light: #fff3e0;
|
||||
font-weight: 600 !important;
|
||||
height: 32px !important;
|
||||
}
|
||||
|
||||
&__create-client {
|
||||
display: inline-flex !important;
|
||||
align-items: center !important;
|
||||
gap: 5px !important;
|
||||
border-radius: 6px !important;
|
||||
font-size: 12px !important;
|
||||
font-weight: 700 !important;
|
||||
height: 32px !important;
|
||||
background: $green !important;
|
||||
color: $white !important;
|
||||
margin-left: auto;
|
||||
|
||||
mat-icon {
|
||||
font-size: 15px;
|
||||
height: 15px;
|
||||
width: 15px;
|
||||
}
|
||||
|
||||
&:hover {
|
||||
background: color.adjust($green, $lightness: -8%) !important;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Details grid
|
||||
@@ -269,3 +327,32 @@ $orange-light: #fff3e0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Entry-type pill inside expanded grid
|
||||
.nom-type-badge {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: 4px;
|
||||
border-radius: 20px;
|
||||
font-size: 11px;
|
||||
font-weight: 700;
|
||||
padding: 3px 10px;
|
||||
|
||||
mat-icon {
|
||||
font-size: 13px;
|
||||
height: 13px;
|
||||
width: 13px;
|
||||
}
|
||||
|
||||
&--linked {
|
||||
background: $green-light;
|
||||
color: $green;
|
||||
border: 1px solid color.adjust($green-light, $lightness: -8%);
|
||||
}
|
||||
|
||||
&--manual {
|
||||
background: $gray-100;
|
||||
color: $gray-700;
|
||||
border: 1px solid $gray-200;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
|
||||
/** Angular Imports */
|
||||
import { Component, inject } from '@angular/core';
|
||||
import { ActivatedRoute } from '@angular/router';
|
||||
import { ActivatedRoute, Router } from '@angular/router';
|
||||
import { MatDialog } from '@angular/material/dialog';
|
||||
|
||||
/** Custom Components */
|
||||
@@ -60,6 +60,7 @@ import { STANDALONE_SHARED_IMPORTS } from 'app/standalone-shared.module';
|
||||
})
|
||||
export class FamilyMembersTabComponent {
|
||||
private route = inject(ActivatedRoute);
|
||||
private router = inject(Router);
|
||||
private clientsService = inject(ClientsService);
|
||||
private dialog = inject(MatDialog);
|
||||
private translateService = inject(TranslateService);
|
||||
@@ -117,7 +118,31 @@ export class FamilyMembersTabComponent {
|
||||
return '';
|
||||
}
|
||||
|
||||
isLinkedClient(member: any): boolean {
|
||||
return !!member.linkedClientId;
|
||||
}
|
||||
|
||||
createClientFromMember(member: any): void {
|
||||
const prefill = {
|
||||
firstname: (member.firstName || '').toString().trim(),
|
||||
mobileNo: member.mobileNumber || '',
|
||||
dateOfBirth: member.dateOfBirth || null,
|
||||
panNumber: member.panNumber || '',
|
||||
aadhaarNumber: member.aadhaarNumber || '',
|
||||
familyMemberId: member.id,
|
||||
parentClientId: this.clientId
|
||||
};
|
||||
this.router.navigate(
|
||||
[
|
||||
'/clients',
|
||||
'create'
|
||||
],
|
||||
{ state: { prefill } }
|
||||
);
|
||||
}
|
||||
|
||||
displayName(member: any): string {
|
||||
if (member.linkedClientName) return member.linkedClientName;
|
||||
return member.firstName || '';
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user