feat: add CFCFRMS module, bank menus, mock backend, and dashboard redesign

- CFCFRMS cyber fraud complaint management with dashboard, complaints,
  escalation, report suspect/mule/fraud txn, FMR submission, CFR lookup
- Mock HTTP interceptor with 20 dummy complaints and all endpoints
- Simulator service for I4C/MHA integration testing
- 3-row menu bar with 22 items (7+8+8 layout)
- Mega menus for General Ledger, Sub Ledger, Deposits, Share, Others,
  HRM, RBI with search and grouped columns
- Dropdowns for Cashier, Clearing, NPA, CKYC, Advances, Letter Mgmt,
  Insurance, Digital
- Dashboard redesign with regulatory, financial health, deposits,
  risk/NPA sections using static banking data
- All translations added to en-US.json
- FontAwesome icons registered for all new menu items

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
Aditya
2026-03-18 18:05:43 +05:30
co-authored by Claude Opus 4.6
parent 0a32d7135e
commit b3a4cce0cf
55 changed files with 9667 additions and 298 deletions
@@ -18,8 +18,8 @@
.breadcrumb {
list-style: none;
padding: 0;
margin: 1.5rem 0;
line-height: 40px;
margin: 0.5rem 0;
line-height: 32px;
.breadcrumb-title {
font-size: 1.25rem;
File diff suppressed because it is too large Load Diff
+150 -6
View File
@@ -34,30 +34,31 @@ $color: #e2e4ec;
.sidenav {
overflow-x: hidden;
position: relative;
}
.sub-menu-bar {
display: flex;
flex-wrap: nowrap;
align-items: center;
background-color: #1074b9;
padding: 2px 0.5rem 2px calc(48px + 2rem);
padding: 0 100px 0 48px;
width: 100%;
z-index: 1;
z-index: 2;
position: relative;
font-family: Roboto, 'Helvetica Neue', sans-serif;
font-size: 14px;
font-size: 13px;
font-weight: 500;
letter-spacing: normal;
line-height: 1;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
box-sizing: border-box;
}
.sub-menu-link {
display: inline-flex;
align-items: center;
padding: 6px 0.5rem;
flex: 1;
padding: 11px 2px;
text-decoration: none;
font-weight: 500;
font-size: 14px;
@@ -81,6 +82,149 @@ $color: #e2e4ec;
font-size: 12px;
}
.sub-menu-spacer {
visibility: hidden;
pointer-events: none;
}
.menu-item-icon {
margin-right: 10px;
width: 16px;
color: #667085;
font-size: 14px;
}
/* Deposits Mega Panel (inside mat-menu overlay) */
.deposit-menu-grid {
display: grid;
grid-template-columns: repeat(3, 1fr);
gap: 8px 24px;
padding: 8px 12px;
min-width: 600px;
}
.deposit-menu-group {
.deposit-group-title {
font-weight: 700;
font-size: 11px;
text-transform: uppercase;
letter-spacing: 0.6px;
color: #1074b9;
padding: 4px 16px 6px;
margin-bottom: 2px;
border-bottom: 2px solid #1074b9;
}
}
/* General Ledger Mega Menu */
.gl-backdrop {
position: fixed;
top: 0;
left: 0;
width: 100vw;
height: 100vh;
z-index: 999;
}
.gl-mega-menu {
position: absolute;
top: 100px;
left: 50%;
transform: translateX(-50%);
background: #fff;
width: 860px;
max-width: 95vw;
padding: 20px 24px;
box-shadow: 0 6px 24px rgba(0, 0, 0, 0.22);
border-radius: 0 0 10px 10px;
z-index: 1000;
border-top: 3px solid #0d47a1;
}
.gl-search {
width: 100%;
padding: 10px 14px;
margin-bottom: 16px;
border: 1px solid #d0d5dd;
border-radius: 6px;
font-size: 14px;
box-sizing: border-box;
background: #f9fafb;
&:focus {
outline: none;
border-color: #0d47a1;
background: #fff;
box-shadow: 0 0 0 3px rgba(13, 71, 161, 0.1);
}
}
.gl-columns {
display: grid;
grid-template-columns: repeat(4, 1fr);
gap: 24px;
}
.gl-group-title {
font-weight: 700;
font-size: 11px;
text-transform: uppercase;
letter-spacing: 0.8px;
color: #0d47a1;
margin-bottom: 10px;
padding-bottom: 6px;
border-bottom: 2px solid #0d47a1;
}
.gl-link {
display: flex;
align-items: center;
padding: 7px 6px;
text-decoration: none;
color: #344054;
font-size: 13px;
cursor: pointer;
border-radius: 5px;
transition:
background 0.15s,
color 0.15s;
&:hover {
background: #e3f2fd;
color: #0d47a1;
}
&.hidden {
display: none;
}
}
.gl-icon {
width: 18px;
margin-right: 8px;
color: #667085;
font-size: 13px;
.gl-link:hover & {
color: #0d47a1;
}
}
/* RBI Mega Menu */
.rbi-mega-menu {
width: 1100px;
max-width: 97vw;
max-height: 80vh;
overflow-y: auto;
border-top-color: #b71c1c;
}
.rbi-columns {
display: grid;
grid-template-columns: repeat(4, 1fr);
gap: 20px;
}
@keyframes move {
0% {
left: 0;
+31
View File
@@ -66,6 +66,33 @@ export class ShellComponent implements OnInit, OnDestroy {
/** Subscription to progress bar. */
progressBar$: Subscription;
/** Sub Ledger mega menu state */
subLedgerOpen = false;
subLedgerSearch = '';
/** General Ledger mega menu state */
glMenuOpen = false;
glSearch = '';
/** RBI mega menu state */
rbiMenuOpen = false;
rbiSearch = '';
matchesSubLedgerSearch(label: string): boolean {
if (!this.subLedgerSearch) return true;
return label.toLowerCase().includes(this.subLedgerSearch.toLowerCase());
}
matchesGlSearch(label: string): boolean {
if (!this.glSearch) return true;
return label.toLowerCase().includes(this.glSearch.toLowerCase());
}
matchesRbiSearch(label: string): boolean {
if (!this.rbiSearch) return true;
return label.toLowerCase().includes(this.rbiSearch.toLowerCase());
}
/**
* Subscribes to progress bar to update its mode.
*/
@@ -85,6 +112,10 @@ export class ShellComponent implements OnInit, OnDestroy {
this.cdr.detectChanges();
}
openConfigWizard(): void {
// Placeholder — config wizard is handled by toolbar component
}
/**
* Unsubscribes from progress bar.
*/
@@ -171,6 +171,119 @@
</mat-icon>
<a matLine>{{ 'labels.menus.Analytics' | translate }}</a>
</mat-list-item>
<!-- CFCFRMS Section -->
<div class="nav-item-sep mt-1">
<mat-divider></mat-divider>
<span class="text-muted">{{ 'labels.menus.CFCFRMS' | translate }}</span>
</div>
<mat-list-item
[routerLink]="['/cfcfrms/dashboard']"
[matTooltipPosition]="tooltipPosition"
matTooltip="{{ 'tooltips.CFCFRMS Dashboard' | translate }}"
routerLinkActive="active-menu"
[routerLinkActiveOptions]="{ exact: true }"
>
<mat-icon matListIcon>
<fa-icon icon="shield-alt" size="sm"></fa-icon>
</mat-icon>
<a matLine>{{ 'labels.menus.CFCFRMS Dashboard' | translate }}</a>
</mat-list-item>
<mat-list-item
[routerLink]="['/cfcfrms/complaints']"
[matTooltipPosition]="tooltipPosition"
matTooltip="{{ 'tooltips.Complaints' | translate }}"
routerLinkActive="active-menu"
[routerLinkActiveOptions]="{ exact: false }"
>
<mat-icon matListIcon>
<fa-icon icon="list-alt" size="sm"></fa-icon>
</mat-icon>
<a matLine>{{ 'labels.menus.Complaints' | translate }}</a>
</mat-list-item>
<mat-list-item
[routerLink]="['/cfcfrms/escalate']"
[matTooltipPosition]="tooltipPosition"
matTooltip="{{ 'tooltips.Escalate Complaint' | translate }}"
routerLinkActive="active-menu"
[routerLinkActiveOptions]="{ exact: false }"
>
<mat-icon matListIcon>
<fa-icon icon="arrow-up" size="sm"></fa-icon>
</mat-icon>
<a matLine>{{ 'labels.menus.Escalate' | translate }}</a>
</mat-list-item>
<mat-list-item
[routerLink]="['/cfcfrms/report-suspect']"
[matTooltipPosition]="tooltipPosition"
matTooltip="{{ 'tooltips.Report Suspect' | translate }}"
routerLinkActive="active-menu"
[routerLinkActiveOptions]="{ exact: false }"
>
<mat-icon matListIcon>
<fa-icon icon="user-shield" size="sm"></fa-icon>
</mat-icon>
<a matLine>{{ 'labels.menus.Report Suspect' | translate }}</a>
</mat-list-item>
<mat-list-item
[routerLink]="['/cfcfrms/report-mule']"
[matTooltipPosition]="tooltipPosition"
matTooltip="{{ 'tooltips.Report Mule Account' | translate }}"
routerLinkActive="active-menu"
[routerLinkActiveOptions]="{ exact: false }"
>
<mat-icon matListIcon>
<fa-icon icon="user-slash" size="sm"></fa-icon>
</mat-icon>
<a matLine>{{ 'labels.menus.Report Mule' | translate }}</a>
</mat-list-item>
<mat-list-item
[routerLink]="['/cfcfrms/report-fraud-txn']"
[matTooltipPosition]="tooltipPosition"
matTooltip="{{ 'tooltips.Report Fraud Transaction' | translate }}"
routerLinkActive="active-menu"
[routerLinkActiveOptions]="{ exact: false }"
>
<mat-icon matListIcon>
<fa-icon icon="exclamation-triangle" size="sm"></fa-icon>
</mat-icon>
<a matLine>{{ 'labels.menus.Report Fraud Txn' | translate }}</a>
</mat-list-item>
<!-- RBI Integration Section -->
<div class="nav-item-sep mt-1">
<mat-divider></mat-divider>
<span class="text-muted">{{ 'labels.menus.RBI Integration' | translate }}</span>
</div>
<mat-list-item
[routerLink]="['/cfcfrms/fmr-submission']"
[matTooltipPosition]="tooltipPosition"
matTooltip="{{ 'tooltips.FMR Submission' | translate }}"
routerLinkActive="active-menu"
[routerLinkActiveOptions]="{ exact: false }"
>
<mat-icon matListIcon>
<fa-icon icon="university" size="sm"></fa-icon>
</mat-icon>
<a matLine>{{ 'labels.menus.FMR Submission' | translate }}</a>
</mat-list-item>
<mat-list-item
[routerLink]="['/cfcfrms/cfr-lookup']"
[matTooltipPosition]="tooltipPosition"
matTooltip="{{ 'tooltips.CFR Lookup' | translate }}"
routerLinkActive="active-menu"
[routerLinkActiveOptions]="{ exact: false }"
>
<mat-icon matListIcon>
<fa-icon icon="search" size="sm"></fa-icon>
</mat-icon>
<a matLine>{{ 'labels.menus.CFR Lookup' | translate }}</a>
</mat-list-item>
<div class="nav-item-sep mt-1">
<mat-divider></mat-divider>
<span class="text-muted">{{ 'labels.menus.Main Items' | translate }}</span>
</div>
<mat-list-item
[routerLink]="['/rbi-circulars']"
[matTooltipPosition]="tooltipPosition"
+214 -78
View File
@@ -35,87 +35,14 @@
</button>
}
<div class="tab-nav-bar">
<a
#institution
class="tab-link"
[matMenuTriggerFor]="institutionMenu"
#institutionMenuTrigger="matMenuTrigger"
tabindex="0"
*mifosxHasPermission="'READ_INSTITUTION'"
>
<fa-icon class="mr-05" icon="university" size="lg"></fa-icon>
{{ 'labels.menus.Institution' | translate }}
<fa-icon icon="caret-down" class="ml-05"></fa-icon>
</a>
<span class="hide-lt-md">
<a
#tasks
class="tab-link tasks-link"
[routerLink]="['/checker-inbox-and-tasks/checker-inbox']"
tabindex="0"
*mifosxHasPermission="'ALL_FUNCTIONS_READ'"
>
<fa-icon class="mr-05" icon="check" size="lg"></fa-icon>
{{ 'labels.menus.Tasks' | translate }}
</a>
<a
#accounting
class="tab-link accounting-link"
[routerLink]="['/accounting']"
tabindex="0"
*mifosxHasPermission="'READ_ACCOUNTING'"
>
<fa-icon class="mr-05" icon="money-bill-alt" size="lg"></fa-icon>
{{ 'labels.menus.Accounting' | translate }}
</a>
<a
#reports
class="tab-link"
[matMenuTriggerFor]="reportsMenu"
#reportsMenuTrigger="matMenuTrigger"
tabindex="0"
*mifosxHasPermission="'READ_REPORTS'"
>
<fa-icon class="mr-05" icon="chart-bar" size="lg"></fa-icon>
{{ 'labels.menus.Reports' | translate }}
<fa-icon icon="caret-down" class="ml-05"></fa-icon>
</a>
<a
#admin
class="tab-link"
[matMenuTriggerFor]="adminMenu"
#adminMenuTrigger="matMenuTrigger"
tabindex="0"
*mifosxHasPermission="'READ_ADMIN'"
>
<fa-icon class="mr-05" icon="shield-alt" size="lg"></fa-icon>
{{ 'labels.menus.Admin' | translate }}
<fa-icon icon="caret-down" class="ml-05"></fa-icon>
</a>
<a #configWizard class="tab-link" (click)="openDialog()" tabindex="0" *mifosxHasPermission="'READ_CONFIG_WIZARD'">
<fa-icon class="mr-05" icon="info" size="lg"></fa-icon>
{{ 'labels.menus.Configuration Wizard' | translate }}
</a>
<a class="tab-link" [matMenuTriggerFor]="ledgerMenu" tabindex="0">
<fa-icon class="mr-05" icon="book" size="lg"></fa-icon>
Ledger
<fa-icon icon="caret-down" class="ml-05"></fa-icon>
</a>
</span>
</div>
<span class="toolbar-spacer"></span>
<div #notifications>
<mifosx-notifications-tray #notificationsTray class="hide-lt-md" tabindex="0"></mifosx-notifications-tray>
</div>
<div #themeToggle>
<mifosx-theme-toggle tabindex="0"></mifosx-theme-toggle>
</div>
<div #appMenu>
<button mat-icon-button class="ml-1 img-button" [matMenuTriggerFor]="applicationMenu" tabindex="0">
<img src="assets/images/user_placeholder.png" [alt]="'labels.headings.User Profile' | translate" />
@@ -144,11 +71,220 @@
</span>
</mat-menu>
<!-- Ledger Menu -->
<mat-menu #ledgerMenu="matMenu" [overlapTrigger]="false">
<button mat-menu-item tabindex="0">Sub Ledger</button>
<button mat-menu-item tabindex="0">General Ledger</button>
</mat-menu>
<!-- Sub Ledger Mega Menu -->
@if (subLedgerOpen) {
<div class="subledger-backdrop" (click)="subLedgerOpen = false"></div>
<div class="subledger-mega-menu">
<input
type="text"
class="subledger-search"
placeholder="Search menu..."
(input)="subLedgerSearch = $event.target.value"
/>
<div class="subledger-columns">
<!-- Transactions -->
<div class="subledger-group">
<div class="subledger-group-title">Transactions</div>
<a
class="subledger-link"
[class.hidden]="!matchesSearch('Cash / Clearing / Transfer')"
(click)="subLedgerOpen = false"
>
<fa-icon icon="money-bill" class="subledger-icon"></fa-icon> Cash / Clearing / Transfer
</a>
<a class="subledger-link" [class.hidden]="!matchesSearch('Batch Transaction')" (click)="subLedgerOpen = false">
<fa-icon icon="layer-group" class="subledger-icon"></fa-icon> Batch Transaction
</a>
<a class="subledger-link" [class.hidden]="!matchesSearch('Draft Reconcile')" (click)="subLedgerOpen = false">
<fa-icon icon="file-invoice" class="subledger-icon"></fa-icon> Draft Reconcile
</a>
<a class="subledger-link" [class.hidden]="!matchesSearch('Insurance Entry')" (click)="subLedgerOpen = false">
<fa-icon icon="shield-alt" class="subledger-icon"></fa-icon> Insurance Entry
</a>
<a class="subledger-link" [class.hidden]="!matchesSearch('Share Entry')" (click)="subLedgerOpen = false">
<fa-icon icon="chart-line" class="subledger-icon"></fa-icon> Share Entry
</a>
</div>
<!-- Instruments -->
<div class="subledger-group">
<div class="subledger-group-title">Instruments</div>
<a class="subledger-link" [class.hidden]="!matchesSearch('Draft / Payorder')" (click)="subLedgerOpen = false">
<fa-icon icon="file-signature" class="subledger-icon"></fa-icon> Draft / Payorder
</a>
<a class="subledger-link" [class.hidden]="!matchesSearch('Passbook Issue')" (click)="subLedgerOpen = false">
<fa-icon icon="book" class="subledger-icon"></fa-icon> Passbook Issue
</a>
<a class="subledger-link" [class.hidden]="!matchesSearch('Cheque Book')" (click)="subLedgerOpen = false">
<fa-icon icon="credit-card" class="subledger-icon"></fa-icon> Cheque Book
</a>
<a class="subledger-link" [class.hidden]="!matchesSearch('DD Entry')" (click)="subLedgerOpen = false">
<fa-icon icon="money-check-alt" class="subledger-icon"></fa-icon> DD Entry
</a>
</div>
<!-- Deposits -->
<div class="subledger-group">
<div class="subledger-group-title">Deposits</div>
<a class="subledger-link" [class.hidden]="!matchesSearch('FD / RD Entry')" (click)="subLedgerOpen = false">
<fa-icon icon="piggy-bank" class="subledger-icon"></fa-icon> FD / RD Entry
</a>
<a class="subledger-link" [class.hidden]="!matchesSearch('DDS Entry')" (click)="subLedgerOpen = false">
<fa-icon icon="coins" class="subledger-icon"></fa-icon> DDS Entry
</a>
</div>
<!-- Customer -->
<div class="subledger-group">
<div class="subledger-group-title">Customer</div>
<a
class="subledger-link"
[class.hidden]="!matchesSearch('Client Master')"
routerLink="/clients"
(click)="subLedgerOpen = false"
>
<fa-icon icon="user" class="subledger-icon"></fa-icon> Client Master
</a>
<a class="subledger-link" [class.hidden]="!matchesSearch('Account Master')" (click)="subLedgerOpen = false">
<fa-icon icon="id-card" class="subledger-icon"></fa-icon> Account Master
</a>
<a class="subledger-link" [class.hidden]="!matchesSearch('Aadhaar Entry')" (click)="subLedgerOpen = false">
<fa-icon icon="address-card" class="subledger-icon"></fa-icon> Aadhaar Entry
</a>
<a class="subledger-link" [class.hidden]="!matchesSearch('Minor to Major')" (click)="subLedgerOpen = false">
<fa-icon icon="child" class="subledger-icon"></fa-icon> Minor to Major
</a>
</div>
<!-- Account Status -->
<div class="subledger-group">
<div class="subledger-group-title">Account Status</div>
<a
class="subledger-link"
[class.hidden]="!matchesSearch('Inoperative to Operative')"
(click)="subLedgerOpen = false"
>
<fa-icon icon="lock-open" class="subledger-icon"></fa-icon> Inoperative &rarr; Operative
</a>
<a
class="subledger-link"
[class.hidden]="!matchesSearch('Account Status Master')"
(click)="subLedgerOpen = false"
>
<fa-icon icon="cog" class="subledger-icon"></fa-icon> Account Status Master
</a>
<a class="subledger-link" [class.hidden]="!matchesSearch('Restrict Account')" (click)="subLedgerOpen = false">
<fa-icon icon="ban" class="subledger-icon"></fa-icon> Restrict Account
</a>
<a class="subledger-link" [class.hidden]="!matchesSearch('Account Death')" (click)="subLedgerOpen = false">
<fa-icon icon="user-slash" class="subledger-icon"></fa-icon> Account Death
</a>
<a class="subledger-link" [class.hidden]="!matchesSearch('Closed Account')" (click)="subLedgerOpen = false">
<fa-icon icon="times" class="subledger-icon"></fa-icon> Closed Account
</a>
</div>
<!-- Others -->
<div class="subledger-group">
<div class="subledger-group-title">Others</div>
<a class="subledger-link" [class.hidden]="!matchesSearch('Suit File Entry')" (click)="subLedgerOpen = false">
<fa-icon icon="balance-scale" class="subledger-icon"></fa-icon> Suit File Entry
</a>
<a class="subledger-link" [class.hidden]="!matchesSearch('Locker Entry')" (click)="subLedgerOpen = false">
<fa-icon icon="lock" class="subledger-icon"></fa-icon> Locker Entry
</a>
<a class="subledger-link" [class.hidden]="!matchesSearch('Holiday Marking')" (click)="subLedgerOpen = false">
<fa-icon icon="calendar" class="subledger-icon"></fa-icon> Holiday Marking
</a>
<a
class="subledger-link"
[class.hidden]="!matchesSearch('Open Closed Register')"
(click)="subLedgerOpen = false"
>
<fa-icon icon="book-open" class="subledger-icon"></fa-icon> Open Closed Register
</a>
</div>
</div>
</div>
}
<!-- General Ledger Mega Menu -->
@if (glMenuOpen) {
<div class="subledger-backdrop" (click)="glMenuOpen = false"></div>
<div class="subledger-mega-menu">
<input
type="text"
class="subledger-search"
placeholder="Search GL reports..."
(input)="glSearch = $event.target.value"
/>
<div class="subledger-columns">
<div class="subledger-group">
<div class="subledger-group-title">Financial Statements</div>
<a class="subledger-link" [class.hidden]="!matchesGlSearch('Trial Balance')" (click)="glMenuOpen = false"
><fa-icon icon="balance-scale" class="subledger-icon"></fa-icon> Trial Balance</a
>
<a class="subledger-link" [class.hidden]="!matchesGlSearch('Profit and Loss')" (click)="glMenuOpen = false"
><fa-icon icon="chart-line" class="subledger-icon"></fa-icon> Profit and Loss</a
>
<a
class="subledger-link"
[class.hidden]="!matchesGlSearch('Consolidate Balance Sheet')"
(click)="glMenuOpen = false"
><fa-icon icon="file-alt" class="subledger-icon"></fa-icon> Consolidate Balance Sheet</a
>
</div>
<div class="subledger-group">
<div class="subledger-group-title">GL Reports</div>
<a class="subledger-link" [class.hidden]="!matchesGlSearch('GL Average Balance')" (click)="glMenuOpen = false"
><fa-icon icon="calculator" class="subledger-icon"></fa-icon> GL Average Balance</a
>
<a
class="subledger-link"
[class.hidden]="!matchesGlSearch('GL Mapping for Report')"
(click)="glMenuOpen = false"
><fa-icon icon="project-diagram" class="subledger-icon"></fa-icon> GL Mapping for Report</a
>
<a
class="subledger-link"
[class.hidden]="!matchesGlSearch('Account wise Balance List')"
(click)="glMenuOpen = false"
><fa-icon icon="list" class="subledger-icon"></fa-icon> Account wise Balance List</a
>
<a
class="subledger-link"
[class.hidden]="!matchesGlSearch('Distribution of Balance')"
(click)="glMenuOpen = false"
><fa-icon icon="chart-pie" class="subledger-icon"></fa-icon> Distribution of Balance</a
>
</div>
<div class="subledger-group">
<div class="subledger-group-title">Account Reports</div>
<a
class="subledger-link"
[class.hidden]="!matchesGlSearch('Client wise Balance Report')"
(click)="glMenuOpen = false"
><fa-icon icon="users" class="subledger-icon"></fa-icon> Client wise Balance Report</a
>
<a class="subledger-link" [class.hidden]="!matchesGlSearch('Contingent Expense')" (click)="glMenuOpen = false"
><fa-icon icon="exclamation-circle" class="subledger-icon"></fa-icon> Contingent Expense</a
>
<a class="subledger-link" [class.hidden]="!matchesGlSearch('Banker Head Report')" (click)="glMenuOpen = false"
><fa-icon icon="university" class="subledger-icon"></fa-icon> Banker Head Report</a
>
</div>
<div class="subledger-group">
<div class="subledger-group-title">Registers</div>
<a class="subledger-link" [class.hidden]="!matchesGlSearch('Sundry Register')" (click)="glMenuOpen = false"
><fa-icon icon="clipboard-list" class="subledger-icon"></fa-icon> Sundry Register</a
>
<a class="subledger-link" [class.hidden]="!matchesGlSearch('Voucher Register')" (click)="glMenuOpen = false"
><fa-icon icon="receipt" class="subledger-icon"></fa-icon> Voucher Register</a
>
</div>
</div>
</div>
}
<!-- Toolbar Menus -->
<mat-menu #reportsMenu="matMenu" [overlapTrigger]="false">
+125 -27
View File
@@ -7,28 +7,25 @@
*/
#mifosx-toolbar {
position: relative;
position: absolute;
top: 0;
left: 0;
right: 0;
z-index: 10;
box-shadow: none;
background: transparent;
color: #fff;
pointer-events: none;
min-height: 0;
height: 44px;
padding: 0 4px;
.tab-nav-bar {
display: flex;
align-items: center;
padding: 0 1rem;
* {
pointer-events: auto;
}
.tab-link {
min-width: auto;
padding: 15px 0.5rem;
text-decoration: none;
font-weight: 500;
font-size: 14px;
color: rgb(255 255 255 / 70%);
&:hover {
color: #fff;
}
cursor: pointer;
.mat-mdc-icon-button {
color: #fff;
}
.img-button {
@@ -39,20 +36,121 @@
}
}
.ml-05 {
margin-left: 0.35rem;
font-size: 12px;
}
.ml-1 {
margin-left: 1rem;
margin-left: 0.5rem;
}
}
.mr-1 {
margin-right: 1rem;
}
::host-context(.dark-theme) #mifosx-toolbar {
// transparent, inherits from sub-menu-bar background
}
.toolbar-spacer {
flex: 1 1 auto;
}
/* Toolbar Deposit Mega Grid */
.toolbar-deposit-grid {
display: grid;
grid-template-columns: repeat(3, 1fr);
gap: 8px 24px;
padding: 8px 12px;
min-width: 600px;
}
.toolbar-deposit-group {
.toolbar-deposit-title {
font-weight: 700;
font-size: 11px;
text-transform: uppercase;
letter-spacing: 0.6px;
color: #1074b9;
padding: 4px 16px 6px;
margin-bottom: 2px;
border-bottom: 2px solid #1074b9;
}
}
/* Sub Ledger Mega Menu */
.subledger-backdrop {
position: fixed;
top: 0;
left: 0;
width: 100vw;
height: 100vh;
z-index: 999;
}
.subledger-mega-menu {
position: absolute;
top: 64px;
left: 50%;
transform: translateX(-50%);
background: #fff;
width: 800px;
max-width: 95vw;
padding: 16px 20px;
box-shadow: 0 4px 20px rgba(0, 0, 0, 0.25);
border-radius: 0 0 8px 8px;
z-index: 1000;
}
.subledger-search {
width: 100%;
padding: 8px 12px;
margin-bottom: 14px;
border: 1px solid #ccc;
border-radius: 4px;
font-size: 14px;
box-sizing: border-box;
&:focus {
outline: none;
border-color: #1074b9;
}
}
.subledger-columns {
display: grid;
grid-template-columns: repeat(3, 1fr);
gap: 20px;
}
.subledger-group-title {
font-weight: 600;
font-size: 13px;
text-transform: uppercase;
letter-spacing: 0.5px;
color: #2c3e50;
margin-bottom: 8px;
padding-bottom: 4px;
border-bottom: 2px solid #1074b9;
}
.subledger-link {
display: flex;
align-items: center;
padding: 5px 4px;
text-decoration: none;
color: #333;
font-size: 13px;
cursor: pointer;
border-radius: 4px;
transition: background 0.15s;
&:hover {
background: #e3f2fd;
color: #1074b9;
}
&.hidden {
display: none;
}
}
.subledger-icon {
width: 18px;
margin-right: 8px;
color: #666;
font-size: 13px;
}
@@ -102,6 +102,19 @@ export class ToolbarComponent implements OnInit, AfterViewInit, AfterContentChec
/** Sets the initial state of sidenav as collapsed. Not collapsed if false. */
sidenavCollapsed = true;
/** Sub Ledger mega menu state */
subLedgerOpen = false;
subLedgerSearch = '';
/** General Ledger mega menu state */
glMenuOpen = false;
glSearch = '';
matchesGlSearch(label: string): boolean {
if (!this.glSearch) return true;
return label.toLowerCase().includes(this.glSearch.toLowerCase());
}
/** Instance of sidenav. */
@Input() sidenav: MatSidenav;
/** Sidenav collapse event. */
@@ -251,6 +264,11 @@ export class ToolbarComponent implements OnInit, AfterViewInit, AfterContentChec
}
}
matchesSearch(label: string): boolean {
if (!this.subLedgerSearch) return true;
return label.toLowerCase().includes(this.subLedgerSearch.toLowerCase());
}
navigateMenu(routePath: string): void {
this.router.navigate([routePath]);
}