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:
Jaanu423
2026-06-19 17:30:29 +05:30
co-authored by Claude Sonnet 4.6
parent 822fa4c68d
commit 10b301c30c
38 changed files with 7846 additions and 131 deletions
@@ -0,0 +1,86 @@
/**
* Copyright since 2025 Mifos Initiative
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
import { NgModule } from '@angular/core';
import { RouterModule, Routes } from '@angular/router';
import { Route } from '../core/route/route.service';
const routes: Routes = [
Route.withShell([
{
path: 'election',
data: { title: 'Election Management' },
children: [
{
path: '',
loadComponent: () =>
import('./components/election-dashboard/election-dashboard.component').then(
(m) => m.ElectionDashboardComponent
),
data: { title: 'Elections Dashboard' }
},
{
path: 'config/new',
loadComponent: () =>
import('./components/election-config/election-config.component').then((m) => m.ElectionConfigComponent),
data: { title: 'Create Election' }
},
{
path: 'config/:electionId/edit',
loadComponent: () =>
import('./components/election-config/election-config.component').then((m) => m.ElectionConfigComponent),
data: { title: 'Edit Election' }
},
{
path: ':electionId/nominations',
loadComponent: () =>
import('./components/nomination-list/nomination-list.component').then((m) => m.NominationListComponent),
data: { title: 'Nominations' }
},
{
path: ':electionId/nomination/apply',
loadComponent: () =>
import('./components/nomination-apply/nomination-apply.component').then((m) => m.NominationApplyComponent),
data: { title: 'Apply for Nomination' }
},
{
path: ':electionId/nomination/:nominationId',
loadComponent: () =>
import('./components/nomination-detail/nomination-detail.component').then(
(m) => m.NominationDetailComponent
),
data: { title: 'Nomination Detail' }
},
{
path: ':electionId/candidates',
loadComponent: () =>
import('./components/candidate-board/candidate-board.component').then((m) => m.CandidateBoardComponent),
data: { title: 'Candidate Board' }
},
{
path: ':electionId/vote',
loadComponent: () =>
import('./components/voting-interface/voting-interface.component').then((m) => m.VotingInterfaceComponent),
data: { title: 'Cast Your Vote' }
},
{
path: ':electionId/results',
loadComponent: () =>
import('./components/election-results/election-results.component').then((m) => m.ElectionResultsComponent),
data: { title: 'Election Results' }
}
]
}
])
];
@NgModule({
imports: [RouterModule.forChild(routes)],
exports: [RouterModule]
})
export class ElectionRoutingModule {}