Files
cbsnexora/src/app/home/home.component.html
T
AdityaandClaude Opus 4.7 6714897688 feat(client+home): single-instance family relations + DSC verified badge
- Family member dialog: disable Father / Mother / Spouse in the Relationship
  dropdown when one is already added to the client. Son, daughter, brother
  etc. stay unrestricted. Editing a member keeps its own current relation
  selectable. Hint added below the field.
- Home welcome banner: render a small green "DSC Verified" pill next to the
  username when GET /v1/dsc/me returns at least one ACTIVE certificate.
  Tooltip surfaces the masked serial. Silent when no DSC is mapped.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-12 18:16:20 +05:30

206 lines
7.6 KiB
HTML

<!--
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/.
-->
<div class="home-container">
<!-- Welcome Banner -->
<div class="welcome-banner">
<div class="welcome-left">
<div class="welcome-greeting">
<h2>
{{ 'labels.text.Welcome' | translate }}, <strong>{{ username }}</strong>
@if (dscMapped) {
<span class="dsc-badge" [matTooltip]="'DSC verified · serial ' + dscSerial" matTooltipPosition="right">
<span class="dsc-badge__shield">
<fa-icon icon="shield-alt"></fa-icon>
<span class="dsc-badge__check"><fa-icon icon="check"></fa-icon></span>
</span>
<span class="dsc-badge__label">DSC Verified</span>
</span>
}
</h2>
<p class="welcome-sub">{{ tenant | titlecase }} &middot; CBSNexora Core Banking Platform</p>
</div>
</div>
<div class="welcome-right">
<div #searchActivity class="search-box">
<fa-icon icon="search" class="search-icon"></fa-icon>
<input
matInput
placeholder="{{ 'labels.placeholders.Search Activity' | translate }}"
[matAutocomplete]="activitySearch"
[formControl]="searchText"
class="search-input"
/>
<mat-autocomplete #activitySearch="matAutocomplete">
@for (activity of filteredActivities | async; track activity) {
<mat-option [routerLink]="activity.path">
<span>{{ activity.activity }}</span>
</mat-option>
}
</mat-autocomplete>
</div>
</div>
</div>
<!-- Quick Action Cards -->
<div class="quick-actions">
<a class="qa-card" [routerLink]="['/dashboard']" #buttonDashboard>
<div class="qa-icon blue"><fa-icon icon="tachometer-alt"></fa-icon></div>
<div class="qa-info">
<span class="qa-title">{{ 'labels.buttons.Dashboard' | translate }}</span>
<span class="qa-desc">Analytics & Reports</span>
</div>
</a>
<a class="qa-card" [routerLink]="['/clients/create']">
<div class="qa-icon green"><fa-icon icon="user-plus"></fa-icon></div>
<div class="qa-info">
<span class="qa-title">New Client</span>
<span class="qa-desc">Onboard Customer</span>
</div>
</a>
<a class="qa-card" [routerLink]="['/loans']">
<div class="qa-icon purple"><fa-icon icon="hand-holding-usd"></fa-icon></div>
<div class="qa-info">
<span class="qa-title">Loans</span>
<span class="qa-desc">Manage Advances</span>
</div>
</a>
<a class="qa-card" [routerLink]="['/savings']">
<div class="qa-icon amber"><fa-icon icon="piggy-bank"></fa-icon></div>
<div class="qa-info">
<span class="qa-title">Savings</span>
<span class="qa-desc">Deposit Accounts</span>
</div>
</a>
<a class="qa-card" [routerLink]="['/accounting']">
<div class="qa-icon teal"><fa-icon icon="calculator"></fa-icon></div>
<div class="qa-info">
<span class="qa-title">Accounting</span>
<span class="qa-desc">GL & Journals</span>
</div>
</a>
<a class="qa-card" [routerLink]="['/reports']">
<div class="qa-icon red"><fa-icon icon="chart-bar"></fa-icon></div>
<div class="qa-info">
<span class="qa-title">Reports</span>
<span class="qa-desc">MIS & Statements</span>
</div>
</a>
</div>
<!-- Info Row -->
<div class="info-row">
<div class="info-card">
<div class="info-card-header">
<fa-icon icon="clock" class="info-icon"></fa-icon>
<span>Today's Summary</span>
</div>
<div class="info-grid">
<div class="info-item">
<span class="info-label">Date</span>
<span class="info-value">{{ today | date: 'dd MMM yyyy' }}</span>
</div>
<div class="info-item">
<span class="info-label">Branch</span>
<span class="info-value">Head Office</span>
</div>
<div class="info-item">
<span class="info-label">User</span>
<span class="info-value">{{ username }}</span>
</div>
<div class="info-item">
<span class="info-label">Tenant</span>
<span class="info-value">{{ tenant | titlecase }}</span>
</div>
</div>
</div>
<div class="info-card">
<div class="info-card-header">
<fa-icon icon="bolt" class="info-icon"></fa-icon>
<span>Quick Links</span>
</div>
<div class="quick-links">
<a [routerLink]="['/tasks']">Checker Inbox & Tasks</a>
<a [routerLink]="['/organization']">Organization Setup</a>
<a [routerLink]="['/products']">Product Configuration</a>
<a [routerLink]="['/system']">System Administration</a>
<a [routerLink]="['/users']">User Management</a>
<a [routerLink]="['/settings']">Settings</a>
</div>
</div>
</div>
</div>
<!-- Configuration Wizard Popovers (kept for backward compat) -->
<ng-template #popoverButtons let-popover="popover" let-prev="prev" let-next="next">
<div class="layout-row align-end gap-2px responsive-column">
<button mat-raised-button color="warn" (click)="popover.close(); configurationWizardService.closeConfigWizard()">
{{ 'labels.buttons.Close' | translate }}
</button>
@if (prev) {
<button
mat-raised-button
color="primary"
(click)="popover.close(); showPopover(prev.template, prev.target, 'bottom', true)"
>
{{ 'labels.buttons.Back' | translate }}
</button>
}
@if (next) {
<button
mat-raised-button
color="primary"
(click)="popover.close(); showPopover(next.template, next.target, 'bottom', true)"
>
{{ 'labels.buttons.Next' | translate }}
</button>
}
</div>
</ng-template>
<ng-template #templateButtonDashboard let-popover="popover">
<h2>{{ 'labels.heading.Dashboard' | translate }}</h2>
<p class="mw300">{{ 'labels.text.This will navigate the user to the dashboard component.' | translate }}</p>
<div class="layout-row align-end gap-2px responsive-column">
<button mat-raised-button color="warn" (click)="popover.close(); configurationWizardService.closeConfigWizard()">
{{ 'labels.buttons.Close' | translate }}
</button>
<button mat-raised-button color="primary" (click)="popover.close(); previousStep()">
{{ 'labels.buttons.Back' | translate }}
</button>
<button
mat-raised-button
color="primary"
(click)="popover.close(); showPopover(templateSearchActivity, searchActivity, 'top', true)"
>
{{ 'labels.buttons.Next' | translate }}
</button>
</div>
</ng-template>
<ng-template #templateSearchActivity let-popover="popover">
<h2>{{ 'labels.heading.Search Activity' | translate }}</h2>
<p class="mw300">{{ 'labels.text.This will navigate the user to the searched activity.' | translate }}</p>
<div class="layout-row align-end gap-2px responsive-column">
<button mat-raised-button color="warn" (click)="popover.close(); configurationWizardService.closeConfigWizard()">
{{ 'labels.buttons.Close' | translate }}
</button>
<button
mat-raised-button
color="primary"
(click)="popover.close(); showPopover(templateButtonDashboard, buttonDashboard, 'bottom', true)"
>
{{ 'labels.buttons.Back' | translate }}
</button>
<button mat-raised-button color="primary" (click)="popover.close(); nextStep()">
{{ 'labels.buttons.Next' | translate }}
</button>
</div>
</ng-template>