Skip to content

Commit 27f7859

Browse files
author
Diogo Ferraz
committed
feat(profile): add User Profile & Security page with session insights and consistent card layout
1 parent 3cff87f commit 27f7859

5 files changed

Lines changed: 528 additions & 0 deletions

File tree

src/app/app.routes.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ import { TaskCalendarComponent } from './features/calendar/components/task-calen
1818
import { AdminDashboardComponent } from './features/admin/components/admin-dashboard/admin-dashboard.component';
1919
import { adminRoleGuard } from './core/auth/guards/admin-role.guard';
2020
import { MyActivityComponent } from './features/activity/components/my-activity/my-activity.component';
21+
import { UserProfileSecurityComponent } from './features/profile/components/user-profile-security/user-profile-security.component';
2122

2223
export const routes: Routes = [
2324
{ path: '', component: LandingPageComponent },
@@ -31,6 +32,7 @@ export const routes: Routes = [
3132
{ path: 'docs', component: ProjectDocsComponent, canActivate: [authGuard] },
3233
{ path: 'calendar', component: TaskCalendarComponent, canActivate: [authGuard] },
3334
{ path: 'activity/my', component: MyActivityComponent, canActivate: [authGuard] },
35+
{ path: 'profile', component: UserProfileSecurityComponent, canActivate: [authGuard] },
3436
{ path: 'admin', component: AdminDashboardComponent, canActivate: [authGuard, adminRoleGuard] },
3537
{ path: 'tasks/create', component: TaskItemCreateComponent, canActivate: [authGuard] },
3638
{ path: 'tasks/my-tasks', component: UserTaskItemsComponent, canActivate: [authGuard] },

src/app/core/layout/component/app-menu/app-menu.component.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ export class AppMenuComponent {
4242
label: 'Insights',
4343
items: [
4444
{ label: 'My Activity', icon: 'pi pi-fw pi-history', routerLink: ['/activity/my'] },
45+
{ label: 'Profile & Security', icon: 'pi pi-fw pi-user-edit', routerLink: ['/profile'] },
4546
{ label: 'Search & Filters', icon: 'pi pi-fw pi-search', routerLink: ['/search'] },
4647
{ label: 'Calendar', icon: 'pi pi-fw pi-calendar', routerLink: ['/calendar'] },
4748
{ label: 'Project Docs', icon: 'pi pi-fw pi-book', routerLink: ['/docs'] }
Lines changed: 115 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,115 @@
1+
<div class="profile-page">
2+
<p-card class="profile-header-card">
3+
<div class="profile-header">
4+
<div class="profile-header__title">
5+
<h2>User Profile & Security</h2>
6+
<p>Identity claims, roles, active session health, and security posture for this account.</p>
7+
<div class="profile-header__meta">
8+
<span class="meta-pill">
9+
<i class="pi pi-user"></i>
10+
{{ userDisplayName() }}
11+
</span>
12+
<span class="meta-pill">
13+
<i class="pi pi-envelope"></i>
14+
{{ userEmail() }}
15+
</span>
16+
<span class="meta-pill" *ngIf="isDebugSession">
17+
<i class="pi pi-eye"></i>
18+
Debug session
19+
</span>
20+
</div>
21+
</div>
22+
23+
<div class="profile-header__actions">
24+
<button pButton type="button" label="Create Account" icon="pi pi-user-plus" class="p-button-outlined" (click)="register()"></button>
25+
<button pButton type="button" label="Logout" icon="pi pi-sign-out" class="p-button-outlined" (click)="logout()"></button>
26+
</div>
27+
</div>
28+
</p-card>
29+
30+
<div class="profile-kpis">
31+
<div class="profile-kpis__item">
32+
<p-card class="kpi-card"><span class="kpi-card__label">User Id</span><span class="kpi-card__value kpi-card__value--small">{{ currentUserId() || '-' }}</span></p-card>
33+
</div>
34+
<div class="profile-kpis__item">
35+
<p-card class="kpi-card"><span class="kpi-card__label">Roles</span><span class="kpi-card__value">{{ roles().length }}</span></p-card>
36+
</div>
37+
<div class="profile-kpis__item">
38+
<p-card class="kpi-card"><span class="kpi-card__label">Scopes</span><span class="kpi-card__value">{{ scopes().length }}</span></p-card>
39+
</div>
40+
<div class="profile-kpis__item">
41+
<p-card class="kpi-card"><span class="kpi-card__label">Expires In</span><span class="kpi-card__value">{{ expiresInMinutes() }}m</span></p-card>
42+
</div>
43+
</div>
44+
45+
<div class="profile-grid">
46+
<div class="profile-grid__col profile-grid__col--roles">
47+
<p-card header="Role Membership" styleClass="profile-panel-card">
48+
<div class="roles-list" *ngIf="roles().length > 0; else noRolesState">
49+
<div class="role-item" *ngFor="let role of roles()">
50+
<div class="role-item__head">
51+
<span class="role-item__name">{{ role }}</span>
52+
</div>
53+
<p class="role-item__description">{{ getRoleDescription(role) }}</p>
54+
</div>
55+
</div>
56+
</p-card>
57+
</div>
58+
59+
<div class="profile-grid__col profile-grid__col--session">
60+
<p-card header="Session Details" styleClass="profile-panel-card">
61+
<div class="session-details">
62+
<div class="session-item"><span>Token Type</span><strong>{{ tokenType }}</strong></div>
63+
<div class="session-item"><span>Expires At</span><strong>{{ expiresAt() ? (expiresAt() | date:'medium') : '-' }}</strong></div>
64+
<div class="session-item"><span>Debug Session</span><strong>{{ isDebugSession ? 'Yes' : 'No' }}</strong></div>
65+
</div>
66+
</p-card>
67+
</div>
68+
69+
<div class="profile-grid__col profile-grid__col--security">
70+
<p-card header="Security Notes" styleClass="profile-panel-card">
71+
<ul class="security-list">
72+
<li *ngFor="let item of securityChecklist">{{ item }}</li>
73+
</ul>
74+
</p-card>
75+
</div>
76+
77+
<div class="profile-grid__col profile-grid__col--claims">
78+
<p-card header="Identity Claims" styleClass="profile-panel-card">
79+
<p-table [value]="claimRows()" [rows]="8" [paginator]="claimRows().length > 8" [rowsPerPageOptions]="[8, 16, 30]" [scrollable]="true" scrollHeight="22rem">
80+
<ng-template pTemplate="header">
81+
<tr>
82+
<th style="width: 30%;">Claim</th>
83+
<th>Value</th>
84+
</tr>
85+
</ng-template>
86+
87+
<ng-template pTemplate="body" let-claim>
88+
<tr>
89+
<td><code>{{ claim.key }}</code></td>
90+
<td class="claim-value">{{ claim.value }}</td>
91+
</tr>
92+
</ng-template>
93+
94+
<ng-template pTemplate="emptymessage">
95+
<tr>
96+
<td colspan="2" class="empty-cell">
97+
<div class="empty-state">
98+
<i class="pi pi-id-card"></i>
99+
<p>No claims available for this session.</p>
100+
</div>
101+
</td>
102+
</tr>
103+
</ng-template>
104+
</p-table>
105+
</p-card>
106+
</div>
107+
</div>
108+
</div>
109+
110+
<ng-template #noRolesState>
111+
<div class="empty-state">
112+
<i class="pi pi-users"></i>
113+
<p>No role claims present in the current token.</p>
114+
</div>
115+
</ng-template>

0 commit comments

Comments
 (0)