Files
library/apps/frontend/src/app/services/activity.service.ts
T
hikari b1aab70b44 feat: implement comprehensive activity feed feature
Implements issue #56 with a timeline-style activity feed showing recent
user activity across the library.

Activity Types Displayed:
- Suggestions: Shows suggested items with status badges
- Likes: Shows liked content with links to items
- Comments: Shows comments with preview text
- Achievements: Shows earned achievements with icons and points

Database & Backend:
- Created ActivityService to aggregate from existing data sources
- No new database table needed (uses existing suggestions, likes, comments, achievements)
- Efficient querying with parallel data fetching
- Privacy-aware: Only shows activity from users with profilePublic: true
- Filters out banned users automatically

API Endpoints:
- GET /api/activity - Get general activity feed with pagination
- GET /api/activity/:userId - Get specific user's activity
- Query parameters: limit (max 100, default 50), offset (default 0)
- Returns: activities array, total count, hasMore flag

Frontend Activity Feed:
- Beautiful timeline layout with user avatars and badges
- Relative timestamps ("5m ago", "2h ago", "3d ago")
- Activity type icons (💡 💬 ❤️ 🏆)
- Colour-coded status badges for suggestions
- Comment previews with styled quote blocks
- Achievement displays with icons and points
- Infinite scroll with "Load More" button
- Links to user profiles and content items

UI Components:
- Responsive card-based design
- User avatars with placeholder fallback
- Badge display (STAFF, MOD, VIP, primary badges)
- Entity links that route to appropriate media pages
- Clean typography and spacing
- Loading and empty states

Privacy & Performance:
- Respects profilePublic setting (existing privacy control)
- Only displays activity from non-banned users
- Pagination to prevent loading too much data
- Efficient aggregation with limit multipliers
- Clean separation of concerns (service/routes/component)

Navigation:
- Added /activity route
- Added "📰 Activity Feed" link to user dropdown menu
- Positioned between Leaderboard and About

Implementation Notes:
- Built entirely from existing data (no activity table needed)
- Retroactive: Shows all historical activity automatically
- Type-safe with full TypeScript interfaces
- Activity union type for type discrimination
- Standalone Angular component
- Clean, maintainable code structure
2026-02-20 00:00:26 -08:00

43 lines
1.2 KiB
TypeScript

/**
* @copyright 2026 NHCarrigan
* @license Naomi's Public License
* @author Naomi Carrigan
*/
import { Injectable, inject } from '@angular/core';
import { Observable } from 'rxjs';
import type { ActivityFeedResponse } from '@library/shared-types';
import { ApiService } from './api.service';
@Injectable({
providedIn: 'root'
})
export class ActivityService {
private apiService = inject(ApiService);
/**
* Get activity feed with pagination.
*/
getActivityFeed(limit = 50, offset = 0, userId?: string): Observable<ActivityFeedResponse> {
const params = new URLSearchParams();
params.append('limit', limit.toString());
params.append('offset', offset.toString());
if (userId) {
params.append('userId', userId);
}
return this.apiService.get<ActivityFeedResponse>(`/activity?${params.toString()}`);
}
/**
* Get activity feed for a specific user.
*/
getUserActivityFeed(userId: string, limit = 50, offset = 0): Observable<ActivityFeedResponse> {
const params = new URLSearchParams();
params.append('limit', limit.toString());
params.append('offset', offset.toString());
return this.apiService.get<ActivityFeedResponse>(`/activity/${userId}?${params.toString()}`);
}
}