Files
Tasks/backend/ADMIN_QUESTIONS_API.md
2025-11-20 00:39:00 +02:00

322 lines
7.9 KiB
Markdown

# Admin Questions API - Pagination & Search Documentation
## Endpoint
```
GET /api/admin/questions
```
**Authentication Required:** Admin only (Bearer token)
## Description
Retrieves all questions with comprehensive pagination, filtering, and search capabilities. This endpoint is designed for admin dashboards to manage questions efficiently.
## Query Parameters
| Parameter | Type | Default | Description | Validation |
|-----------|------|---------|-------------|------------|
| `page` | number | 1 | Page number for pagination | Min: 1 |
| `limit` | number | 10 | Number of results per page | Min: 1, Max: 100 |
| `search` | string | '' | Search term for question text, explanation, or tags | - |
| `category` | UUID | '' | Filter by category UUID | Must be valid UUID |
| `difficulty` | string | '' | Filter by difficulty level | `easy`, `medium`, `hard` |
| `sortBy` | string | 'createdAt' | Field to sort by | See valid fields below |
| `order` | string | 'DESC' | Sort order | `ASC` or `DESC` |
### Valid Sort Fields
- `createdAt` (default)
- `updatedAt`
- `questionText`
- `difficulty`
- `points`
- `timesAttempted`
## Response Structure
```json
{
"success": true,
"count": 10,
"total": 45,
"page": 1,
"totalPages": 5,
"limit": 10,
"filters": {
"search": "javascript",
"category": "68b4c87f-db0b-48ea-b8a4-b2f4fce785a2",
"difficulty": "easy",
"sortBy": "createdAt",
"order": "DESC"
},
"data": [
{
"id": "uuid",
"questionText": "What is a closure in JavaScript?",
"questionType": "multiple",
"options": [
{
"id": "a",
"text": "Option A"
}
],
"correctAnswer": "a",
"difficulty": "medium",
"points": 10,
"explanation": "Detailed explanation...",
"tags": ["closures", "functions"],
"keywords": ["closure", "scope"],
"timesAttempted": 150,
"timesCorrect": 120,
"accuracy": 80,
"isActive": true,
"category": {
"id": "uuid",
"name": "JavaScript",
"slug": "javascript",
"icon": "code",
"color": "#F7DF1E",
"guestAccessible": true
},
"createdAt": "2025-11-19T10:00:00.000Z",
"updatedAt": "2025-11-19T10:00:00.000Z"
}
],
"message": "Retrieved 10 of 45 questions"
}
```
## Usage Examples
### Basic Request
```bash
curl -X GET "http://localhost:3000/api/admin/questions" \
-H "Authorization: Bearer YOUR_ADMIN_TOKEN"
```
### With Pagination
```bash
curl -X GET "http://localhost:3000/api/admin/questions?page=2&limit=20" \
-H "Authorization: Bearer YOUR_ADMIN_TOKEN"
```
### Search Questions
```bash
curl -X GET "http://localhost:3000/api/admin/questions?search=async" \
-H "Authorization: Bearer YOUR_ADMIN_TOKEN"
```
### Filter by Category
```bash
curl -X GET "http://localhost:3000/api/admin/questions?category=68b4c87f-db0b-48ea-b8a4-b2f4fce785a2" \
-H "Authorization: Bearer YOUR_ADMIN_TOKEN"
```
### Filter by Difficulty
```bash
curl -X GET "http://localhost:3000/api/admin/questions?difficulty=easy" \
-H "Authorization: Bearer YOUR_ADMIN_TOKEN"
```
### Combined Filters
```bash
curl -X GET "http://localhost:3000/api/admin/questions?search=javascript&difficulty=medium&category=68b4c87f-db0b-48ea-b8a4-b2f4fce785a2&page=1&limit=15" \
-H "Authorization: Bearer YOUR_ADMIN_TOKEN"
```
### Custom Sorting
```bash
# Sort by points ascending
curl -X GET "http://localhost:3000/api/admin/questions?sortBy=points&order=ASC" \
-H "Authorization: Bearer YOUR_ADMIN_TOKEN"
# Sort by difficulty descending
curl -X GET "http://localhost:3000/api/admin/questions?sortBy=difficulty&order=DESC" \
-H "Authorization: Bearer YOUR_ADMIN_TOKEN"
```
## JavaScript/Axios Examples
### Basic Request
```javascript
const axios = require('axios');
const response = await axios.get('http://localhost:3000/api/admin/questions', {
headers: { Authorization: `Bearer ${adminToken}` }
});
console.log(`Total questions: ${response.data.total}`);
console.log(`Current page: ${response.data.page}`);
console.log(`Questions:`, response.data.data);
```
### With All Filters
```javascript
const params = {
page: 1,
limit: 20,
search: 'async',
category: '68b4c87f-db0b-48ea-b8a4-b2f4fce785a2',
difficulty: 'medium',
sortBy: 'points',
order: 'DESC'
};
const response = await axios.get('http://localhost:3000/api/admin/questions', {
params,
headers: { Authorization: `Bearer ${adminToken}` }
});
```
### Paginate Through All Questions
```javascript
async function getAllQuestions(adminToken) {
const allQuestions = [];
let currentPage = 1;
let totalPages = 1;
do {
const response = await axios.get('http://localhost:3000/api/admin/questions', {
params: { page: currentPage, limit: 50 },
headers: { Authorization: `Bearer ${adminToken}` }
});
allQuestions.push(...response.data.data);
totalPages = response.data.totalPages;
currentPage++;
} while (currentPage <= totalPages);
return allQuestions;
}
```
## Error Responses
### 401 Unauthorized
```json
{
"success": false,
"message": "Authentication required"
}
```
### 403 Forbidden
```json
{
"success": false,
"message": "Admin access required"
}
```
### 500 Internal Server Error
```json
{
"success": false,
"message": "An error occurred while retrieving questions",
"error": "Error details (in development mode)"
}
```
## Features
### ✅ Pagination
- Efficient offset-based pagination
- Configurable page size (1-100)
- Total count and pages metadata
- Handles out-of-range pages gracefully
### ✅ Search
- Full-text search across question text
- Search in explanations
- Search in tags
- Case-insensitive matching
- Handles special characters
### ✅ Filtering
- Filter by category (UUID)
- Filter by difficulty (easy/medium/hard)
- Combine multiple filters
- Invalid UUIDs handled gracefully
### ✅ Sorting
- Sort by multiple fields
- Ascending or descending order
- Invalid sort fields default to createdAt
- Consistent ordering
### ✅ Response Data
- Calculated accuracy percentage
- Complete question details including correctAnswer (admin only)
- Category information
- Active/inactive status
- Timestamps
## Performance Considerations
1. **Limit:** Maximum 100 questions per page to prevent performance issues
2. **Indexing:** Database indexes on frequently queried fields (categoryId, difficulty, isActive)
3. **Pagination:** Offset-based pagination is efficient for moderate dataset sizes
4. **Search:** Uses SQL LIKE for search - consider full-text indexes for large datasets
## Testing
Run the comprehensive test suite:
```bash
node test-admin-questions-pagination.js
```
The test suite covers:
- ✅ Authorization (35 tests)
- ✅ Pagination (8 tests)
- ✅ Search functionality (4 tests)
- ✅ Filtering (9 tests)
- ✅ Combined filters (4 tests)
- ✅ Sorting (5 tests)
- ✅ Response structure (5 tests)
- ✅ Edge cases and performance
Total: 35 comprehensive test cases
## Related Endpoints
- `POST /api/admin/questions` - Create a new question
- `PUT /api/admin/questions/:id` - Update a question
- `DELETE /api/admin/questions/:id` - Delete a question (soft delete)
- `GET /api/questions/category/:categoryId` - Public endpoint for questions by category
- `GET /api/questions/search` - Public search endpoint with guest filtering
- `GET /api/questions/:id` - Get single question by ID
## Notes
- **Admin Only:** This endpoint requires admin authentication
- **correctAnswer:** Admin responses include the correct answer (unlike public endpoints)
- **isActive:** Includes both active and inactive questions for admin management
- **Accuracy:** Calculated as (timesCorrect / timesAttempted) * 100
- **Category Filtering:** Invalid UUIDs are silently ignored (returns all categories)
- **Search:** Empty search string returns all questions
## Changelog
### Version 1.0.0 (2025-11-19)
- Initial implementation
- Pagination support (page, limit)
- Search functionality (question text, explanation, tags)
- Filtering by category and difficulty
- Sorting by multiple fields
- Comprehensive test suite