This commit is contained in:
Chris Chen
2026-05-28 15:25:31 -07:00
parent d79b1faa8f
commit a525c71baa
21 changed files with 484 additions and 126 deletions
@@ -1,19 +1,26 @@
import { Component, OnInit, OnDestroy, HostListener } from '@angular/core';
import { CommonModule } from '@angular/common';
import { Router, NavigationEnd, RouterModule, RouterLink, RouterLinkActive } from '@angular/router';
import { RouterOutlet } from '@angular/router';
import { Router, NavigationEnd, RouterModule, RouterOutlet } from '@angular/router';
import { IconsModule } from '@progress/kendo-angular-icons';
import { SVGIcon, homeIcon, calendarIcon, userIcon, groupIcon } from '@progress/kendo-svg-icons';
import { AuthService, UserInfo } from '../../shared/services/auth.service';
import { Subject, takeUntil, filter } from 'rxjs';
interface NavItem {
text: string;
icon: SVGIcon;
path: string;
active?: boolean;
}
@Component({
selector: 'app-user-portal',
standalone: true,
imports: [
CommonModule,
RouterModule,
RouterLink,
RouterLinkActive,
RouterOutlet
RouterOutlet,
IconsModule,
],
templateUrl: './user-portal.component.html',
styleUrls: ['./user-portal.component.scss']
@@ -23,10 +30,49 @@ export class UserPortalComponent implements OnInit, OnDestroy {
isMobile = false;
currentUser: UserInfo | null = null;
currentPageTitle = 'Dashboard';
showAdminSection = false;
unreadMessages = 3;
unreadNotifications = 2;
public homeIcon: SVGIcon = homeIcon;
public calendarIcon: SVGIcon = calendarIcon;
public peopleIcon: SVGIcon = userIcon;
public bedIcon: SVGIcon = userIcon;
public userIcon: SVGIcon = userIcon;
public pillIcon: SVGIcon = userIcon;
public chartIcon: SVGIcon = userIcon;
public buildingIcon: SVGIcon = userIcon;
public creditCardIcon: SVGIcon = userIcon;
public supportIcon: SVGIcon = userIcon;
public mainNavItems: NavItem[] = [
{ text: 'Dashboard', icon: this.homeIcon, path: '/user-portal/dashboard' },
// { text: 'Schedule', icon: this.calendarIcon, path: '/user-portal/schedule' },
// { text: 'Patients', icon: this.peopleIcon, path: '/user-portal/patients' },
];
public managementNavItems: NavItem[] = [
// { text: 'Staff', icon: this.userIcon, path: '/user-portal/staff' },
// { text: 'Pharmacy', icon: this.pillIcon, path: '/user-portal/pharmacy' },
// { text: 'Reports', icon: this.chartIcon, path: '/user-portal/reports' },1124
// { text: 'Departments', icon: this.buildingIcon, path: '/user-portal/departments' },
// { text: 'Payments', icon: this.creditCardIcon, path: '/user-portal/payments' },
];
public supportNavItems: NavItem[] = [
{ text: 'Support', icon: this.supportIcon, path: '/user-portal/support' },
];
public memberAdminNavItems: NavItem[] = [
{ text: 'Members', icon: groupIcon, path: '/user-portal/admin/members' },
];
public userAdminNavItems: NavItem[] = [
{ text: 'User Management', icon: userIcon, path: '/user-portal/admin/users' },
];
public showMemberAdminSection = false;
public showUserAdminSection = false;
private destroy$ = new Subject<void>();
constructor(
@@ -65,7 +111,9 @@ export class UserPortalComponent implements OnInit, OnDestroy {
.pipe(takeUntil(this.destroy$))
.subscribe(user => {
this.currentUser = user;
this.showAdminSection = !!user?.roles?.includes('super_admin');
const roles = user?.roles ?? [];
this.showMemberAdminSection = roles.some(r => r === 'super_admin' || r === 'secretary');
this.showUserAdminSection = roles.includes('super_admin');
});
}
@@ -75,17 +123,40 @@ export class UserPortalComponent implements OnInit, OnDestroy {
filter(event => event instanceof NavigationEnd),
takeUntil(this.destroy$)
)
.subscribe(() => {
.subscribe((event: NavigationEnd) => {
this.updateActiveStates(event.url);
this.updatePageTitle();
});
this.updateActiveStates(this.router.url);
this.updatePageTitle();
}
public navigateTo(path: string): void {
this.router.navigate([path]);
this.onNavigationClick();
}
private updateActiveStates(currentUrl: string): void {
const allItems = [
...this.mainNavItems,
...this.managementNavItems,
...this.supportNavItems,
...this.memberAdminNavItems,
...this.userAdminNavItems,
];
allItems.forEach(item => (item.active = false));
const activeItem = allItems.find(item => currentUrl.startsWith(item.path));
if (activeItem) {
activeItem.active = true;
}
}
private updatePageTitle(): void {
const url = this.router.url;
const url = this.router.url;
const segments = url.split('/').filter(s => s);
const key = segments.length >= 3
const key = segments.length >= 3
? `${segments[1]}/${segments[2]}` // e.g. 'admin/members'
: segments[1] ?? '';
this.currentPageTitle = this.getPageTitle(key);
@@ -93,15 +164,24 @@ export class UserPortalComponent implements OnInit, OnDestroy {
private getPageTitle(page: string): string {
const titles: { [key: string]: string } = {
'dashboard': 'Dashboard',
'transactions': 'Escrow Transactions',
'tasks': 'Tasks & Todos',
'contacts': 'Contacts',
'documents': 'Documents',
'messages': 'Messages',
'settings': 'Settings',
'admin/members': 'Member Management',
'admin/users': 'User Management',
'dashboard': 'Dashboard',
'schedule': 'Schedule',
'patients': 'Patients',
'bed-management': 'Bed Management',
'staff': 'Staff',
'pharmacy': 'Pharmacy',
'reports': 'Reports',
'departments': 'Departments',
'payments': 'Payments',
'support': 'Support',
'transactions': 'Escrow Transactions',
'tasks': 'Tasks & Todos',
'contacts': 'Contacts',
'documents': 'Documents',
'messages': 'Messages',
'settings': 'Settings',
'admin/members': 'Member Management',
'admin/users': 'User Management',
};
return titles[page] ?? 'Dashboard';
}