generated from nhcarrigan/template
b1aab70b44
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
43 lines
1.2 KiB
TypeScript
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()}`);
|
|
}
|
|
}
|