# Dashboard Aggregation Endpoint Contract

**Date**: 2025-01-27  
**Action**: 2.1.1.1 - Design dashboard endpoint contract  
**Status**: ✅ Complete

## Overview

This document defines the contract for a new aggregated dashboard endpoint that consolidates multiple API calls into a single request, reducing over-fetching and improving performance.

## Current Implementation

The dashboard currently makes **4+ separate API calls**:

1. **GET /audit/stats** - Dashboard statistics
2. **GET /audit/activity** - Recent activity logs
3. **Social feed API** - Recent posts/feed items
4. **GET /tracks** (with limit: 5) - Library preview

**Problems**:
- Multiple round trips increase latency
- Over-fetching of data
- Race conditions possible
- No atomic data consistency

## Proposed Endpoint

### Endpoint Specification

**Method**: `GET`  
**Path**: `/api/v1/dashboard`  
**Authentication**: Required (Bearer token)  
**Response Format**: Wrapped format `{ success: true, data: DashboardResponse }`

### Request Parameters

**Query Parameters** (all optional):
- `activity_limit` (integer, default: 10) - Number of recent activity items to return
- `library_limit` (integer, default: 5) - Number of library items to return in preview
- `stats_period` (string, default: "30d") - Time period for statistics ("7d", "30d", "90d", "all")

### Response Structure

```typescript
interface DashboardResponse {
  stats: DashboardStats;
  recent_activity: RecentActivity[];
  library_preview: LibraryPreview;
}

interface DashboardStats {
  tracks_played: number;
  messages_sent: number;
  favorites: number;
  active_friends: number;
  tracks_played_change?: string;      // Percentage change (e.g., "+12%", "-5%")
  messages_sent_change?: string;
  favorites_change?: string;
  active_friends_change?: string;
  period: string;                      // "7d", "30d", "90d", "all"
}

interface RecentActivity {
  id: string;                         // UUID
  type: 'track_upload' | 'message_received' | 'favorite_added' | 
        'playlist_created' | 'comment_added' | 'post';
  title: string;                      // Human-readable title
  description?: string;                // Optional description/details
  timestamp: string;                  // ISO8601 timestamp
  icon?: string;                      // Optional icon URL or identifier
  metadata?: Record<string, any>;      // Additional context (track_id, user_id, etc.)
}

interface LibraryPreview {
  items: TrackPreview[];
  total_count: number;                // Total tracks in user's library
  has_more: boolean;                  // Whether there are more items beyond limit
}

interface TrackPreview {
  id: string;                         // UUID
  title: string;
  artist: string;
  duration: number;                   // Seconds
  cover_art_path?: string;
  play_count: number;
  like_count: number;
  created_at: string;                 // ISO8601 timestamp
}
```

### Response Example

```json
{
  "success": true,
  "data": {
    "stats": {
      "tracks_played": 1234,
      "messages_sent": 567,
      "favorites": 89,
      "active_friends": 45,
      "tracks_played_change": "+12%",
      "messages_sent_change": "+8%",
      "favorites_change": "+23%",
      "active_friends_change": "+5%",
      "period": "30d"
    },
    "recent_activity": [
      {
        "id": "550e8400-e29b-41d4-a716-446655440000",
        "type": "track_upload",
        "title": "Nouvelle piste ajoutée",
        "description": "My New Track.mp3",
        "timestamp": "2025-01-27T10:30:00Z",
        "metadata": {
          "track_id": "660e8400-e29b-41d4-a716-446655440001",
          "file_name": "My New Track.mp3"
        }
      },
      {
        "id": "550e8400-e29b-41d4-a716-446655440002",
        "type": "message_received",
        "title": "Message reçu de @username",
        "timestamp": "2025-01-27T09:15:00Z",
        "metadata": {
          "conversation_id": "770e8400-e29b-41d4-a716-446655440003",
          "from_user_id": "880e8400-e29b-41d4-a716-446655440004"
        }
      }
    ],
    "library_preview": {
      "items": [
        {
          "id": "990e8400-e29b-41d4-a716-446655440005",
          "title": "My Favorite Track",
          "artist": "Artist Name",
          "duration": 240,
          "cover_art_path": "/covers/track-123.jpg",
          "play_count": 42,
          "like_count": 7,
          "created_at": "2025-01-20T14:30:00Z"
        }
      ],
      "total_count": 156,
      "has_more": true
    }
  }
}
```

## Data Sources

### Stats Calculation

**tracks_played**: Sum of play actions from audit logs + track play counts  
**messages_sent**: Count of message actions from audit logs  
**favorites**: Count of favorite/like actions from audit logs  
**active_friends**: Count of unique users interacted with in period

**Change percentages**: Compare current period to previous period (e.g., last 30d vs previous 30d)

### Recent Activity

Combines:
1. **Audit logs** (`/audit/activity`) - User actions (uploads, plays, favorites, etc.)
2. **Social feed** - Recent posts from followed users
3. **Chat messages** - Recent messages received
4. **Comments** - Comments on user's tracks/playlists

Sorted by `timestamp` descending, limited by `activity_limit`.

### Library Preview

Returns user's most recently added or most played tracks, limited by `library_limit`.

## Error Handling

**401 Unauthorized**: User not authenticated  
**500 Internal Server Error**: Backend error during aggregation

Error responses follow standard format:
```json
{
  "success": false,
  "error": {
    "code": 500,
    "message": "Failed to fetch dashboard data",
    "timestamp": "2025-01-27T10:30:00Z"
  }
}
```

## Performance Considerations

- **Caching**: Response can be cached for 30-60 seconds (user-specific)
- **Database queries**: Use efficient joins and indexes
- **Parallel fetching**: Fetch stats, activity, and library in parallel
- **Timeouts**: Aggregate endpoint should complete within 2 seconds

## Migration Strategy

1. **Phase 1**: Implement backend endpoint (Action 2.1.1.2)
2. **Phase 2**: Update frontend to use new endpoint (Action 2.1.1.3)
3. **Phase 3**: Remove old API calls (Actions 2.1.1.4-2.1.1.6)
4. **Phase 4**: Add caching (Action 2.1.1.7)

## Validation

✅ Contract documented  
✅ Response structure defined  
✅ Data sources identified  
✅ Error handling specified  
✅ Performance considerations noted  
⏭️ Next: Action 2.1.1.2 - Implement backend dashboard handler
