Skip to main content

Overview

The Dashboard API provides role-specific statistics and insights for administrators, organizers, and students. Two versions are available:
  • /api/dashboard/stats - Original dashboard with basic statistics
  • /api/dashboard/stats-v2 - Enhanced dashboard with additional insights and analytics

Get Dashboard Stats

curl -X GET https://api.example.com/api/dashboard/stats \
  -H "Authorization: Bearer YOUR_TOKEN"
GET /api/dashboard/stats
Authorization: Bearer YOUR_TOKEN
Retrieve dashboard statistics. The response varies based on the user’s role.

Authentication

Requires a valid JWT token. The response is customized based on the authenticated user’s role.

Response for ADMIN Role

data.totalStudents
integer
Total number of students in the system
data.totalOrganizers
integer
Total number of organizers (ORGANIZER + EVENT_ORGANIZER roles)
data.pendingProposalsCount
integer
Number of proposals pending review for admin’s department
data.pendingUpdatesCount
integer
Number of event update requests pending L1 review
data.activeEventsCount
integer
Number of upcoming events
data.activeEvents
array
Array of all active event objects (EventDTO[])
{
  "statusCode": 200,
  "message": "Stats fetched",
  "data": {
    "totalStudents": 1250,
    "totalOrganizers": 45,
    "pendingProposalsCount": 8,
    "pendingUpdatesCount": 3,
    "activeEventsCount": 12,
    "activeEvents": [
      {
        "eventID": 1,
        "title": "Spring Career Fair",
        "eventDate": "2024-04-15",
        "status": "UPCOMING",
        "currentRegistrations": 234,
        "capacity": 500
      }
    ]
  },
  "timestamp": "2024-03-07T10:30:00"
}

Response for ORGANIZER Role

data.myActiveEvents
integer
Number of active events organized by the user
data.totalRegistrationsForMyEvents
integer
Total registrations across all organizer’s events
data.myProposalStats
object
Object with proposal counts by status: {"APPROVED": 5, "PENDING": 2, "REJECTED": 1}
data.activeEvents
array
Array of events organized by the user
data.myProposals
array
Array of all proposals submitted by the organizer
{
  "statusCode": 200,
  "message": "Stats fetched",
  "data": {
    "myActiveEvents": 3,
    "totalRegistrationsForMyEvents": 145,
    "myProposalStats": {
      "APPROVED": 5,
      "PENDING": 2,
      "REJECTED": 1
    },
    "activeEvents": [
      {
        "eventID": 1,
        "title": "Tech Workshop",
        "eventDate": "2024-04-20",
        "currentRegistrations": 28,
        "capacity": 30,
        "isOwner": true
      }
    ],
    "myProposals": [
      {
        "proposalID": 1,
        "title": "Spring Conference",
        "status": "APPROVED",
        "submittedAt": "2024-03-01T10:00:00"
      }
    ]
  },
  "timestamp": "2024-03-07T10:30:00"
}

Response for STUDENT Role

data.myTotalRegistrations
integer
Total number of events the student is registered for
data.activeEvents
array
Array of events the student is registered for (deduplicated)
{
  "statusCode": 200,
  "message": "Stats fetched",
  "data": {
    "myTotalRegistrations": 5,
    "activeEvents": [
      {
        "eventID": 1,
        "title": "Career Fair",
        "eventDate": "2024-04-15",
        "venue": "Main Hall",
        "isRegistered": true
      },
      {
        "eventID": 3,
        "title": "Tech Workshop",
        "eventDate": "2024-04-20",
        "venue": "Lab 201",
        "isRegistered": true
      }
    ]
  },
  "timestamp": "2024-03-07T10:30:00"
}

Get Dashboard Stats V2

curl -X GET https://api.example.com/api/dashboard/stats-v2 \
  -H "Authorization: Bearer YOUR_TOKEN"
GET /api/dashboard/stats-v2
Authorization: Bearer YOUR_TOKEN
Retrieve enhanced dashboard statistics with additional insights and activity feeds.

Enhanced Fields for ADMIN (V2)

Includes all fields from V1 plus:
data.pendingReportsCount
integer
Number of post-event reports pending review for admin’s department
data.recentActivity
array
Array of recent activity/audit log entries (top 20)
data.recentActivity[].actorName
string
Email of the user who performed the action
data.recentActivity[].actorRole
string
Role of the actor: STUDENT, ORGANIZER, ADMIN
data.recentActivity[].action
string
Description of the action performed
data.recentActivity[].targetName
string
Name or identifier of the target entity
data.recentActivity[].timestamp
string
ISO 8601 timestamp of the activity
data.recentActivity[].navigationUrl
string
URL to navigate to the related resource
data.weeklyRegistrationCount
integer
Number of registrations in the past 7 days
{
  "statusCode": 200,
  "message": "Stats fetched",
  "data": {
    "totalStudents": 1250,
    "totalOrganizers": 45,
    "pendingProposalsCount": 8,
    "pendingUpdatesCount": 3,
    "pendingReportsCount": 2,
    "activeEventsCount": 12,
    "weeklyRegistrationCount": 87,
    "activeEvents": [...],
    "recentActivity": [
      {
        "actorName": "[email protected]",
        "actorRole": "STUDENT",
        "action": "registered for Spring Career Fair",
        "targetName": "Spring Career Fair",
        "timestamp": "2024-03-07T09:15:00",
        "navigationUrl": "/events/1"
      },
      {
        "actorName": "[email protected]",
        "actorRole": "ORGANIZER",
        "action": "submitted proposal Tech Conference 2024",
        "targetName": "Tech Conference 2024",
        "timestamp": "2024-03-07T08:30:00",
        "navigationUrl": "/proposals/5"
      },
      {
        "actorName": "[email protected]",
        "actorRole": "ADMIN",
        "action": "approved proposal Alumni Networking",
        "targetName": "Alumni Networking",
        "timestamp": "2024-03-06T16:45:00",
        "navigationUrl": "/proposals/3"
      }
    ]
  },
  "timestamp": "2024-03-07T10:30:00"
}

Enhanced Fields for ORGANIZER (V2)

Includes all fields from V1 plus:
data.eventsNeedingAttention
array
Events requiring organizer attention (low attendance or near capacity)
data.oldestPendingProposalDays
integer
Age in days of the oldest pending proposal
data.totalParticipantsAllTime
integer
Total number of participants across all organizer’s events (all time)
Events Needing Attention Logic:
  • Low attendance: less than 30% filled AND within 14 days
  • Near capacity: greater than 90% filled AND greater than 3 days out
{
  "statusCode": 200,
  "message": "Stats fetched",
  "data": {
    "myActiveEvents": 2,
    "totalRegistrationsForMyEvents": 145,
    "myProposalStats": {
      "APPROVED": 5,
      "PENDING": 2,
      "REJECTED": 1
    },
    "oldestPendingProposalDays": 7,
    "totalParticipantsAllTime": 523,
    "activeEvents": [...],
    "myProposals": [...],
    "eventsNeedingAttention": [
      {
        "eventID": 3,
        "title": "Workshop on AI",
        "eventDate": "2024-03-20",
        "currentRegistrations": 8,
        "capacity": 30,
        "venue": "Lab 201"
      }
    ]
  },
  "timestamp": "2024-03-07T10:30:00"
}

Enhanced Fields for STUDENT (V2)

Includes all fields from V1 plus:
data.nextEvent
object
Next upcoming event the student is registered for (EventDTO)
data.upcomingEventsCount
integer
Number of upcoming events student is registered for
data.pastEventsCount
integer
Number of past events student was registered for
data.thisMonthRegistrations
integer
Number of registrations created this month
{
  "statusCode": 200,
  "message": "Stats fetched",
  "data": {
    "myTotalRegistrations": 5,
    "upcomingEventsCount": 3,
    "pastEventsCount": 2,
    "thisMonthRegistrations": 2,
    "nextEvent": {
      "eventID": 1,
      "title": "Career Fair",
      "eventDate": "2024-04-15",
      "startTime": "09:00:00",
      "venue": "Main Hall",
      "isRegistered": true
    },
    "activeEvents": [...]
  },
  "timestamp": "2024-03-07T10:30:00"
}

Implementation Details

Admin Proposal Counting Logic

From DashboardController.java:416-427:
private long countPendingProposalsForAdmin(User user) {
    if (!(user instanceof Administrator admin) || admin.getDepartment() == null) {
        return proposalRepository.countByStatus(ProposalStatus.PENDING_L1);
    }
    return switch (admin.getDepartment()) {
        case YOUTH_UNION -> proposalRepository.countByStatusAndOrganizationType(
                ProposalStatus.PENDING_L1, OrganizationType.YOUTH_UNION);
        case STUDENT_ASSOCIATION -> proposalRepository.countByStatusAndOrganizationType(
                ProposalStatus.PENDING_L1, OrganizationType.STUDENT_ASSOCIATION);
        case FACULTY -> proposalRepository.countByStatus(ProposalStatus.PENDING_L2);
        case RECTOR -> proposalRepository.countByStatus(ProposalStatus.PENDING_L3);
    };
}
Admins only see proposal counts relevant to their department and approval level.

Next Event Calculation (Student)

From DashboardController.java:242-249:
Event nextEvent = registrations.stream()
    .map(Registration::getEvent)
    .filter(e -> e.getEventDate().isAfter(today) ||
                (e.getEventDate().isEqual(today) &&
                 e.getStartTime().isAfter(now)))
    .min(Comparator.comparing(Event::getEventDate)
            .thenComparing(Event::getStartTime))
    .orElse(null);
Finds the soonest future event based on both date and time.

Response Wrapper

All dashboard endpoints use the standard Response<T> wrapper:
{
  statusCode: number;      // HTTP status code
  message: string;         // Success message
  data: T;                 // Dashboard data (varies by role)
  timestamp: string;       // ISO 8601 timestamp
  errors?: string[];       // Error messages (if any)
}

Build docs developers (and LLMs) love