fix(giving): render Finance nav section in UserPortal sidebar

Task 11 added the finance nav to user-navbar.component, but the active
sidebar is rendered inline by UserPortalComponent (app-user-navbar is
not mounted). Added the role-gated Finance section (Offering Entry /
Givings / Giving Types) to UserPortalComponent, matching its
Administration pattern. Verified at runtime: section renders for
super_admin and links load the giving pages.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
Chris Chen
2026-05-28 18:22:50 -07:00
parent 5f8676f962
commit a2d394029a
2 changed files with 23 additions and 0 deletions
@@ -73,6 +73,17 @@
</a> </a>
</ng-container> </ng-container>
</div> </div>
<div class="nav-section" *ngIf="showFinanceSection">
<h4 *ngIf="!sidebarCollapsed">Finance</h4>
<a *ngFor="let item of financeNavItems" class="nav-item" [class.active]="item.active"
[title]="item.text" (click)="navigateTo(item.path)">
<div class="nav-icon">
<kendo-svgicon [icon]="item.icon"></kendo-svgicon>
</div>
<span *ngIf="!sidebarCollapsed">{{ item.text }}</span>
</a>
</div>
</nav> </nav>
<div class="sidebar-footer" *ngIf="!sidebarCollapsed"> <div class="sidebar-footer" *ngIf="!sidebarCollapsed">
@@ -70,8 +70,15 @@ export class UserPortalComponent implements OnInit, OnDestroy {
{ text: 'User Management', icon: userIcon, path: '/user-portal/admin/users' }, { text: 'User Management', icon: userIcon, path: '/user-portal/admin/users' },
]; ];
public financeNavItems: NavItem[] = [
{ text: 'Offering Entry', icon: this.creditCardIcon, path: '/user-portal/finance/offering-session' },
{ text: 'Givings', icon: this.creditCardIcon, path: '/user-portal/finance/givings' },
{ text: 'Giving Types', icon: this.creditCardIcon, path: '/user-portal/finance/giving-categories' },
];
public showMemberAdminSection = false; public showMemberAdminSection = false;
public showUserAdminSection = false; public showUserAdminSection = false;
public showFinanceSection = false;
private destroy$ = new Subject<void>(); private destroy$ = new Subject<void>();
@@ -114,6 +121,7 @@ export class UserPortalComponent implements OnInit, OnDestroy {
const roles = user?.roles ?? []; const roles = user?.roles ?? [];
this.showMemberAdminSection = roles.some(r => r === 'super_admin' || r === 'secretary'); this.showMemberAdminSection = roles.some(r => r === 'super_admin' || r === 'secretary');
this.showUserAdminSection = roles.includes('super_admin'); this.showUserAdminSection = roles.includes('super_admin');
this.showFinanceSection = roles.some(r => r === 'finance' || r === 'super_admin');
}); });
} }
@@ -144,6 +152,7 @@ export class UserPortalComponent implements OnInit, OnDestroy {
...this.supportNavItems, ...this.supportNavItems,
...this.memberAdminNavItems, ...this.memberAdminNavItems,
...this.userAdminNavItems, ...this.userAdminNavItems,
...this.financeNavItems,
]; ];
allItems.forEach(item => (item.active = false)); allItems.forEach(item => (item.active = false));
@@ -182,6 +191,9 @@ export class UserPortalComponent implements OnInit, OnDestroy {
'settings': 'Settings', 'settings': 'Settings',
'admin/members': 'Member Management', 'admin/members': 'Member Management',
'admin/users': 'User Management', 'admin/users': 'User Management',
'finance/offering-session': 'Sunday Offering Entry',
'finance/givings': 'Givings',
'finance/giving-categories': 'Giving Types',
}; };
return titles[page] ?? 'Dashboard'; return titles[page] ?? 'Dashboard';
} }