This commit is contained in:
Chris Chen
2026-05-25 17:32:18 -07:00
parent 9b28fbcfb6
commit d5648315a0
262 changed files with 32074 additions and 0 deletions
@@ -0,0 +1,40 @@
<header>
<kendo-appbar positionMode='sticky' themeColor="inherit" class='k-bg-surface-alt' [style.z-index]="10000">
<kendo-appbar-section class="k-flex-basis-0 k-flex-grow k-gap-2">
<button kendoButton [svgIcon]="menuIcon" fillMode="clear" title="Menu" (click)="onMenuClick()"></button>
<a href="#" class="k-d-none k-d-sm-flex logo-link">
<img src="assets/rbj-logo.svg" class="k-h-8" alt="RBJ RBJ Identity logo" />
<span class="logo-text">RBJ Identity Portal</span>
</a>
<a href="#" class="k-d-flex k-d-sm-none">
<img src="assets/rbj-logo.svg" class="k-h-8" alt="RBJ RBJ Identity compact logo" />
</a>
</kendo-appbar-section>
<kendo-appbar-section class="k-flex-basis-0 k-flex-grow k-justify-content-center">
<div class="k-d-flex k-d-md-none">
<button kendoButton [svgIcon]="searchIcon" fillMode="clear" title="Search"></button>
</div>
<div class="k-d-none k-d-md-flex search-box-wrapper">
<kendo-textbox class="search-box" placeholder="Search..." fillMode="flat">
<ng-template kendoTextBoxPrefixTemplate>
<kendo-svgicon [icon]="searchIcon"></kendo-svgicon>
<kendo-textbox-separator></kendo-textbox-separator>
</ng-template>
</kendo-textbox>
</div>
</kendo-appbar-section>
<kendo-appbar-section class="k-flex-basis-0 k-flex-grow k-justify-content-end k-gap-1.5">
<kendo-badge-container>
<button kendoButton [svgIcon]="bellIcon" fillMode="clear" title="Notifications"></button>
<kendo-badge rounded="medium" position="inside" [align]="badgeAlign" themeColor="error"></kendo-badge>
</kendo-badge-container>
<span class="k-appbar-separator k-color-border k-d-none k-d-sm-inline"></span>
<kendo-dropdownbutton [data]="userMenuItems" fillMode="clear" [svgIcon]="userIcon" [arrowIcon]="true"
(itemClick)="onUserMenuClick($event)">
<span class="k-d-none k-d-sm-inline">
{{ getDisplayName() || currentUser?.email || 'User' }}
</span>
</kendo-dropdownbutton>
</kendo-appbar-section>
</kendo-appbar>
</header>
@@ -0,0 +1,21 @@
.logo-link {
display: flex;
align-items: center;
text-decoration: none;
color: inherit;
.logo-text {
margin-left: 0.5rem;
font-weight: 600;
font-size: 1.1rem;
}
}
.search-box-wrapper {
width: 100%;
max-width: 400px;
.search-box {
width: 100%;
}
}
@@ -0,0 +1,118 @@
import { Component, OnInit, OnDestroy } from '@angular/core';
import { CommonModule } from '@angular/common';
import { Router } from '@angular/router';
import { AppBarModule } from '@progress/kendo-angular-navigation';
import { ButtonsModule } from '@progress/kendo-angular-buttons';
import { IndicatorsModule } from '@progress/kendo-angular-indicators';
import { InputsModule } from '@progress/kendo-angular-inputs';
import { DropDownsModule } from '@progress/kendo-angular-dropdowns';
import { IconsModule } from '@progress/kendo-angular-icons';
import { SVGIcon, bellIcon, menuIcon, searchIcon, userIcon, logoutIcon } from '@progress/kendo-svg-icons';
import { AuthService, User } from '../../../../shared/services/auth.service';
import { LayoutService } from '../../../../layout/services/layout.service';
import { Subject, takeUntil } from 'rxjs';
@Component({
selector: 'app-user-header',
standalone: true,
imports: [
CommonModule,
AppBarModule,
ButtonsModule,
IndicatorsModule,
InputsModule,
IconsModule,
DropDownsModule
],
templateUrl: './user-header.component.html',
styleUrls: ['./user-header.component.scss']
})
export class UserHeaderComponent implements OnInit, OnDestroy {
public menuIcon: SVGIcon = menuIcon;
public searchIcon: SVGIcon = searchIcon;
public bellIcon: SVGIcon = bellIcon;
public userIcon: SVGIcon = userIcon;
public logoutIcon: SVGIcon = logoutIcon;
public userMenuItems: any[] = [];
public currentUser: User | null = null;
public badgeAlign = {
vertical: 'top' as const,
horizontal: 'end' as const
};
private destroy$ = new Subject<void>();
constructor(
private authService: AuthService,
private layoutService: LayoutService,
private router: Router
) { }
ngOnInit(): void {
// Subscribe to authentication state changes
this.authService.currentUser$
.pipe(takeUntil(this.destroy$))
.subscribe(user => {
this.currentUser = user;
this.updateUserMenu();
});
}
ngOnDestroy(): void {
this.destroy$.next();
this.destroy$.complete();
}
public onMenuClick(): void {
this.layoutService.toggleDrawer();
}
public onLogout(): void {
this.authService.logout();
this.router.navigate(['/login']);
}
public onUserMenuClick(item: any): void {
if (item.click) {
item.click();
}
}
public getDisplayName(): string {
if (this.currentUser) {
const fullName = `${this.currentUser.firstName} ${this.currentUser.lastName}`.trim();
return fullName || this.currentUser.email;
}
return '';
}
private updateUserMenu(): void {
if (this.currentUser) {
this.userMenuItems = [
{
text: `Welcome, ${this.getDisplayName() || this.currentUser.email}`,
disabled: true
},
{ separator: true },
{
text: 'Profile',
icon: 'user',
disabled: true
},
{
text: 'Settings',
icon: 'settings',
disabled: true
},
{ separator: true },
{
text: 'Logout',
icon: 'logout',
click: () => this.onLogout()
}
];
}
}
}