217 lines
6.3 KiB
TypeScript
217 lines
6.3 KiB
TypeScript
import { Component, OnInit, OnDestroy, HostListener } from '@angular/core';
|
|
import { CommonModule } from '@angular/common';
|
|
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,
|
|
RouterOutlet,
|
|
IconsModule,
|
|
],
|
|
templateUrl: './user-portal.component.html',
|
|
styleUrls: ['./user-portal.component.scss']
|
|
})
|
|
export class UserPortalComponent implements OnInit, OnDestroy {
|
|
sidebarCollapsed = false;
|
|
isMobile = false;
|
|
currentUser: UserInfo | null = null;
|
|
currentPageTitle = 'Dashboard';
|
|
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(
|
|
private authService: AuthService,
|
|
private router: Router
|
|
) { }
|
|
|
|
ngOnInit(): void {
|
|
this.checkScreenSize();
|
|
this.setupUserSubscription();
|
|
this.setupRouteSubscription();
|
|
}
|
|
|
|
ngOnDestroy(): void {
|
|
this.destroy$.next();
|
|
this.destroy$.complete();
|
|
}
|
|
|
|
@HostListener('window:resize', ['$event'])
|
|
onResize(event: any): void {
|
|
this.checkScreenSize();
|
|
}
|
|
|
|
private checkScreenSize(): void {
|
|
this.isMobile = window.innerWidth <= 768;
|
|
if (this.isMobile) {
|
|
this.sidebarCollapsed = true;
|
|
} else {
|
|
// On desktop, start with sidebar expanded
|
|
this.sidebarCollapsed = false;
|
|
}
|
|
}
|
|
|
|
private setupUserSubscription(): void {
|
|
this.authService.currentUser$
|
|
.pipe(takeUntil(this.destroy$))
|
|
.subscribe(user => {
|
|
this.currentUser = user;
|
|
const roles = user?.roles ?? [];
|
|
this.showMemberAdminSection = roles.some(r => r === 'super_admin' || r === 'secretary');
|
|
this.showUserAdminSection = roles.includes('super_admin');
|
|
});
|
|
}
|
|
|
|
private setupRouteSubscription(): void {
|
|
this.router.events
|
|
.pipe(
|
|
filter(event => event instanceof NavigationEnd),
|
|
takeUntil(this.destroy$)
|
|
)
|
|
.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 segments = url.split('/').filter(s => s);
|
|
const key = segments.length >= 3
|
|
? `${segments[1]}/${segments[2]}` // e.g. 'admin/members'
|
|
: segments[1] ?? '';
|
|
this.currentPageTitle = this.getPageTitle(key);
|
|
}
|
|
|
|
private getPageTitle(page: string): string {
|
|
const titles: { [key: string]: string } = {
|
|
'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';
|
|
}
|
|
|
|
toggleSidebar(): void {
|
|
this.sidebarCollapsed = !this.sidebarCollapsed;
|
|
}
|
|
|
|
get mainContentClass(): string {
|
|
return this.sidebarCollapsed ? 'main-content sidebar-collapsed' : 'main-content';
|
|
}
|
|
|
|
onSidebarOverlayClick(): void {
|
|
if (this.isMobile && !this.sidebarCollapsed) {
|
|
this.sidebarCollapsed = true;
|
|
}
|
|
}
|
|
|
|
onNavigationClick(): void {
|
|
if (this.isMobile) {
|
|
this.sidebarCollapsed = true;
|
|
}
|
|
}
|
|
|
|
logout(): void {
|
|
this.authService.logout();
|
|
this.router.navigate(['/login']);
|
|
}
|
|
|
|
getDisplayName(): string {
|
|
return this.currentUser?.email || '';
|
|
}
|
|
} |