add changes
This commit is contained in:
321
ADMIN_QUESTIONS_API.md
Normal file
321
ADMIN_QUESTIONS_API.md
Normal file
@@ -0,0 +1,321 @@
|
||||
# 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
|
||||
Reference in New Issue
Block a user