Skip to content

Commit 3cff87f

Browse files
author
Diogo Ferraz
committed
feat(activity): add My Activity page with personal timeline, live updates, and filters
1 parent a4fa273 commit 3cff87f

5 files changed

Lines changed: 694 additions & 0 deletions

File tree

src/app/app.routes.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ import { ProjectDocsComponent } from './features/docs/components/project-docs/pr
1717
import { TaskCalendarComponent } from './features/calendar/components/task-calendar/task-calendar.component';
1818
import { AdminDashboardComponent } from './features/admin/components/admin-dashboard/admin-dashboard.component';
1919
import { adminRoleGuard } from './core/auth/guards/admin-role.guard';
20+
import { MyActivityComponent } from './features/activity/components/my-activity/my-activity.component';
2021

2122
export const routes: Routes = [
2223
{ path: '', component: LandingPageComponent },
@@ -29,6 +30,7 @@ export const routes: Routes = [
2930
{ path: 'search', component: SearchFiltersComponent, canActivate: [authGuard] },
3031
{ path: 'docs', component: ProjectDocsComponent, canActivate: [authGuard] },
3132
{ path: 'calendar', component: TaskCalendarComponent, canActivate: [authGuard] },
33+
{ path: 'activity/my', component: MyActivityComponent, canActivate: [authGuard] },
3234
{ path: 'admin', component: AdminDashboardComponent, canActivate: [authGuard, adminRoleGuard] },
3335
{ path: 'tasks/create', component: TaskItemCreateComponent, canActivate: [authGuard] },
3436
{ 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
@@ -41,6 +41,7 @@ export class AppMenuComponent {
4141
{
4242
label: 'Insights',
4343
items: [
44+
{ label: 'My Activity', icon: 'pi pi-fw pi-history', routerLink: ['/activity/my'] },
4445
{ label: 'Search & Filters', icon: 'pi pi-fw pi-search', routerLink: ['/search'] },
4546
{ label: 'Calendar', icon: 'pi pi-fw pi-calendar', routerLink: ['/calendar'] },
4647
{ label: 'Project Docs', icon: 'pi pi-fw pi-book', routerLink: ['/docs'] }
Lines changed: 118 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,118 @@
1+
<div class="my-activity-page">
2+
<p-card class="my-activity-header-card">
3+
<div class="my-activity-header">
4+
<div class="my-activity-header__title">
5+
<h2>My Activity</h2>
6+
<p>Your recent actions across projects and tasks, with live updates from the activity hub.</p>
7+
</div>
8+
9+
<div class="my-activity-header__meta">
10+
<span class="meta-pill">
11+
<i class="pi pi-bolt"></i>
12+
{{ isLiveConnected ? 'Live connected' : 'Live disconnected' }}
13+
</span>
14+
<span class="meta-pill" *ngIf="isPreviewMode">
15+
<i class="pi pi-eye"></i>
16+
Preview mode
17+
</span>
18+
<span class="meta-pill" *ngIf="previewDetail">{{ previewDetail }}</span>
19+
</div>
20+
</div>
21+
</p-card>
22+
23+
<div class="activity-kpis">
24+
<p-card class="kpi-card"><span class="kpi-card__label">Total Events</span><span class="kpi-card__value">{{ totalEvents }}</span></p-card>
25+
<p-card class="kpi-card"><span class="kpi-card__label">Today</span><span class="kpi-card__value">{{ todayEvents }}</span></p-card>
26+
<p-card class="kpi-card"><span class="kpi-card__label">Task Events</span><span class="kpi-card__value">{{ taskEvents }}</span></p-card>
27+
<p-card class="kpi-card"><span class="kpi-card__label">Project Events</span><span class="kpi-card__value">{{ projectEvents }}</span></p-card>
28+
</div>
29+
30+
<div class="activity-content-grid">
31+
<p-card class="activity-feed-card">
32+
<div class="activity-feed-card__header">
33+
<div>
34+
<h3>Activity Timeline</h3>
35+
<p>Track your changes and jump back to related project context.</p>
36+
</div>
37+
</div>
38+
39+
<div class="activity-error" *ngIf="errorMessage">
40+
<i class="pi pi-exclamation-triangle"></i>
41+
{{ errorMessage }}
42+
</div>
43+
44+
<div class="activity-list" *ngIf="!isLoading; else loadingState">
45+
<div class="activity-row" *ngFor="let activity of filteredActivities; let isLast = last" [class.activity-row--last]="isLast">
46+
<div class="activity-row__icon" [ngClass]="activity.bgColor">
47+
<i class="{{ activity.icon }}" [ngClass]="activity.iconColor"></i>
48+
</div>
49+
50+
<div class="activity-row__content">
51+
<div class="activity-row__summary" [innerHTML]="activity.summary"></div>
52+
<div class="activity-row__meta">
53+
<span>{{ activity.time }}</span>
54+
<p-tag [value]="getTypeLabel(activity.rawEvent.type)" severity="contrast"></p-tag>
55+
<button
56+
*ngIf="activity.rawEvent.projectId"
57+
pButton
58+
type="button"
59+
class="p-button-text p-button-sm"
60+
icon="pi pi-external-link"
61+
label="Open Project"
62+
(click)="openRelatedProject(activity)">
63+
</button>
64+
</div>
65+
</div>
66+
</div>
67+
68+
<div class="empty-state" *ngIf="filteredActivities.length === 0">
69+
<i class="pi pi-inbox"></i>
70+
<p>No activity matches your filters.</p>
71+
</div>
72+
</div>
73+
</p-card>
74+
75+
<p-card class="activity-filters-card">
76+
<div class="activity-filters-card__header">
77+
<h3>Filters</h3>
78+
<button pButton type="button" class="p-button-text p-button-sm" icon="pi pi-filter-slash" label="Clear" (click)="clearFilters()"></button>
79+
</div>
80+
81+
<div class="filters-form">
82+
<div class="field">
83+
<label for="typeFilter">Event Type</label>
84+
<p-dropdown
85+
inputId="typeFilter"
86+
[options]="typeOptions"
87+
optionLabel="label"
88+
optionValue="value"
89+
[(ngModel)]="selectedType"
90+
[appendTo]="'body'">
91+
</p-dropdown>
92+
</div>
93+
94+
<div class="field">
95+
<label for="searchFilter">Search</label>
96+
<span class="filter-search">
97+
<i class="pi pi-search"></i>
98+
<input id="searchFilter" pInputText type="text" [(ngModel)]="search" placeholder="Project, task, or action" />
99+
</span>
100+
</div>
101+
102+
<button pButton type="button" icon="pi pi-refresh" label="Refresh" class="p-button-outlined" [loading]="isLoading" (click)="refresh()"></button>
103+
</div>
104+
</p-card>
105+
</div>
106+
</div>
107+
108+
<ng-template #loadingState>
109+
<div class="activity-list activity-list--loading">
110+
<div class="activity-row" *ngFor="let item of [1, 2, 3, 4, 5]">
111+
<p-skeleton shape="circle" size="2.5rem"></p-skeleton>
112+
<div class="activity-row__skeleton">
113+
<p-skeleton width="85%" height="0.95rem"></p-skeleton>
114+
<p-skeleton width="55%" height="0.85rem"></p-skeleton>
115+
</div>
116+
</div>
117+
</div>
118+
</ng-template>

0 commit comments

Comments
 (0)