feat: redesign all dialogs, file upload, address/nominee/identifier tabs

- File upload: compact dashed zone (54px height), inline icon+filename+change
- Dialogs: no scroll, rounded close button (red on hover), 700px width
- Identifier dialog: 2-column grid, section divider, outline fields
- Nominee: new NomineeDialogComponent popup (replaces page navigation)
- Address tab: card panels, status badges, 3-column grid
- Nominee tab: accordion with badges, 3-column grid
- Shared form dialog: outline fields, fixed close button

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
Aditya
2026-03-21 00:09:59 +05:30
co-authored by Claude Opus 4.6
parent b7f612c2f6
commit 97f30ac3c1
17 changed files with 1589 additions and 281 deletions
@@ -6,83 +6,124 @@
file, You can obtain one at http://mozilla.org/MPL/2.0/.
-->
<div class="tab-container mat-typography">
<router-outlet>
<div class="layout-row align-start">
<div class="m-b-10">
<h3>{{ 'labels.heading.Family Members' | translate }}</h3>
</div>
<div class="action-button m-b-10 gap-25px">
<button mat-raised-button color="primary" [routerLink]="['./add']">
<fa-icon icon="plus" class="m-r-10" aria-hidden="true"></fa-icon>{{ 'labels.buttons.Add' | translate }}
</button>
</div>
<div class="nom-container mat-typography">
<!-- Header -->
<div class="nom-header">
<div class="nom-header__left">
<i class="fa fa-users nom-header__icon"></i>
<h3 class="nom-header__title">{{ 'labels.heading.Family Members' | translate }}</h3>
<span class="nom-header__badge">{{ clientFamilyMembers?.length || 0 }}</span>
</div>
<button mat-flat-button color="primary" class="nom-header__btn" (click)="addNominee()">
<fa-icon icon="plus" class="m-r-10"></fa-icon>{{ 'labels.buttons.Add' | translate }}
</button>
</div>
<mat-accordion>
@for (member of clientFamilyMembers; track member.id; let i = $index) {
<mat-expansion-panel class="family-member">
<mat-expansion-panel-header>
<mat-panel-title>
{{ displayName(member) }}
</mat-panel-title>
<mat-panel-description>
{{ member.relationship }}
</mat-panel-description>
</mat-expansion-panel-header>
<mat-divider [inset]="true"></mat-divider>
<div class="family-member-actions layout-row align-end">
<button
mat-raised-button
color="primary"
[routerLink]="[member.id, 'edit']"
[title]="'labels.buttons.Edit' | translate"
>
<fa-icon icon="edit" class="m-r-10" aria-hidden="true"></fa-icon>{{ 'labels.buttons.Edit' | translate }}
<!-- Empty State -->
@if (!clientFamilyMembers || clientFamilyMembers.length === 0) {
<div class="nom-empty">
<i class="fa fa-user-o nom-empty__icon"></i>
<p class="nom-empty__text">{{ 'labels.text.No nominees added yet' | translate }}</p>
</div>
}
<!-- Nominee Cards -->
<mat-accordion multi>
@for (member of clientFamilyMembers; track member.id; let i = $index) {
<mat-expansion-panel class="nom-panel">
<mat-expansion-panel-header class="nom-panel__header">
<mat-panel-title class="nom-panel__title">
<i class="fa fa-user nom-panel__type-icon"></i>
<span class="nom-panel__name">{{ displayName(member) }}</span>
@if (member.relationship) {
<span class="nom-panel__badge nom-panel__badge--relation">{{ member.relationship }}</span>
}
@if (member.nominationType) {
<span class="nom-panel__badge nom-panel__badge--type">{{ member.nominationType }}</span>
}
</mat-panel-title>
<mat-panel-description class="nom-panel__desc">
@if (member.percentageShare != null) {
{{ member.percentageShare }}%
}
</mat-panel-description>
</mat-expansion-panel-header>
<!-- Actions Bar -->
<div class="nom-actions">
<div class="nom-actions__buttons">
<button mat-stroked-button color="primary" class="nom-actions__edit" (click)="editNominee(member, i)">
<fa-icon icon="edit" class="m-r-10"></fa-icon>{{ 'labels.buttons.Edit' | translate }}
</button>
<button
mat-raised-button
mat-stroked-button
color="warn"
class="nom-actions__delete"
(click)="deleteFamilyMember(member.clientId, member.id, member.firstName, i)"
[title]="'labels.buttons.Delete' | translate"
>
<fa-icon icon="trash" class="m-r-10" aria-hidden="true"></fa-icon
>{{ 'labels.buttons.Delete' | translate }}
<fa-icon icon="trash" class="m-r-10"></fa-icon>{{ 'labels.buttons.Delete' | translate }}
</button>
</div>
<p>
@if (member.nominationType) {
<span>{{ 'labels.inputs.Nomination Type' | translate }} : {{ member.nominationType }}<br /></span>
}
@if (member.firstName) {
<span>{{ 'labels.inputs.Nominee Name' | translate }} : {{ member.firstName }}<br /></span>
}
@if (member.relationship) {
<span>{{ 'labels.inputs.Relationship' | translate }} : {{ member.relationship }}<br /></span>
}
@if (member.dateOfBirth) {
<span>{{ 'labels.inputs.Date Of Birth' | translate }} : {{ member.dateOfBirth | dateFormat }}<br /></span>
}
@if (member.percentageShare != null) {
<span>{{ 'labels.inputs.Percentage Share' | translate }} : {{ member.percentageShare }}%<br /></span>
}
@if (member.isDependent) {
<span>{{ 'labels.inputs.Nominee is Minor' | translate }} : {{ member.isDependent | yesNo }}<br /></span>
}
@if (member.guardianName) {
<span>{{ 'labels.inputs.Guardian Name' | translate }} : {{ member.guardianName }}<br /></span>
}
@if (member.guardianRelationship) {
<span
>{{ 'labels.inputs.Relationship with Minor' | translate }} : {{ member.guardianRelationship }}<br
/></span>
}
@if (member.remarks) {
<span>{{ 'labels.inputs.Remarks' | translate }} : {{ member.remarks }}<br /></span>
}
</p>
</mat-expansion-panel>
}
</mat-accordion>
</router-outlet>
</div>
<!-- Details Grid -->
<div class="nom-grid">
@if (member.nominationType) {
<div class="nom-field">
<div class="nom-field__label">{{ 'labels.inputs.Nomination Type' | translate }}</div>
<div class="nom-field__value">{{ member.nominationType }}</div>
</div>
}
@if (member.firstName) {
<div class="nom-field">
<div class="nom-field__label">{{ 'labels.inputs.Nominee Name' | translate }}</div>
<div class="nom-field__value">{{ member.firstName }}</div>
</div>
}
@if (member.relationship) {
<div class="nom-field">
<div class="nom-field__label">{{ 'labels.inputs.Relationship' | translate }}</div>
<div class="nom-field__value">{{ member.relationship }}</div>
</div>
}
@if (member.dateOfBirth) {
<div class="nom-field">
<div class="nom-field__label">{{ 'labels.inputs.Date Of Birth' | translate }}</div>
<div class="nom-field__value">{{ member.dateOfBirth | dateFormat }}</div>
</div>
}
@if (member.percentageShare != null) {
<div class="nom-field">
<div class="nom-field__label">{{ 'labels.inputs.Percentage Share' | translate }}</div>
<div class="nom-field__value nom-field__value--mono">{{ member.percentageShare }}%</div>
</div>
}
@if (member.isDependent != null) {
<div class="nom-field">
<div class="nom-field__label">{{ 'labels.inputs.Nominee is Minor' | translate }}</div>
<div class="nom-field__value">{{ member.isDependent | yesNo }}</div>
</div>
}
@if (member.guardianName) {
<div class="nom-field">
<div class="nom-field__label">{{ 'labels.inputs.Guardian Name' | translate }}</div>
<div class="nom-field__value">{{ member.guardianName }}</div>
</div>
}
@if (member.guardianRelationship) {
<div class="nom-field">
<div class="nom-field__label">{{ 'labels.inputs.Relationship with Minor' | translate }}</div>
<div class="nom-field__value">{{ member.guardianRelationship }}</div>
</div>
}
@if (member.remarks) {
<div class="nom-field">
<div class="nom-field__label">{{ 'labels.inputs.Remarks' | translate }}</div>
<div class="nom-field__value">{{ member.remarks }}</div>
</div>
}
</div>
</mat-expansion-panel>
}
</mat-accordion>
</div>