Major Features Added: - Complete Plugin Architecture System with financial plugin - Multi-currency support with exchange rates - Course type system (online, classroom, hybrid) - Attendance tracking and QR code scanning - Classroom sessions management - Course sections and content management - Professional video player with authentication - Secure media serving system - Shopping cart and checkout system - Financial dashboard and earnings tracking - Trainee progress tracking - User notes and assignments system Backend Infrastructure: - Plugin loader and registry system - Multi-currency database models - Secure media middleware - Course access middleware - Financial plugin with payment processing - Database migrations for new features - API endpoints for all new functionality Frontend Components: - Course management interface - Content creation and editing - Section management with drag-and-drop - Professional video player - QR scanner for attendance - Shopping cart and checkout flow - Financial dashboard - Plugin management interface - Trainee details and progress views This represents a major evolution of CourseWorx from a basic LMS to a comprehensive educational platform with plugin architecture.
115 lines
3.5 KiB
JavaScript
115 lines
3.5 KiB
JavaScript
const express = require('express');
|
|
const router = express.Router();
|
|
const { CourseStats, Course, Enrollment, CourseContent } = require('../models');
|
|
const { auth, requireTrainer } = require('../middleware/auth');
|
|
|
|
// Get course statistics by course ID
|
|
router.get('/:courseId', auth, async (req, res) => {
|
|
try {
|
|
const { courseId } = req.params;
|
|
|
|
// Check if course exists
|
|
const course = await Course.findByPk(courseId);
|
|
if (!course) {
|
|
return res.status(404).json({ error: 'Course not found' });
|
|
}
|
|
|
|
// Get or create course stats
|
|
let courseStats = await CourseStats.findOne({ where: { courseId } });
|
|
|
|
if (!courseStats) {
|
|
// Create default stats if none exist
|
|
const enrollmentCount = await Enrollment.count({ where: { courseId } });
|
|
const totalLessons = await CourseContent.count({ where: { courseId } });
|
|
|
|
courseStats = await CourseStats.create({
|
|
courseId,
|
|
enrollmentCount,
|
|
totalLessons,
|
|
skillLevel: 'beginner',
|
|
language: 'English',
|
|
publishedDate: course.createdAt,
|
|
certificateAvailable: true
|
|
});
|
|
}
|
|
|
|
res.json(courseStats);
|
|
} catch (error) {
|
|
console.error('Error fetching course stats:', error);
|
|
res.status(500).json({ error: 'Internal server error' });
|
|
}
|
|
});
|
|
|
|
// Update course statistics (trainer only)
|
|
router.put('/:courseId', auth, requireTrainer, async (req, res) => {
|
|
try {
|
|
const { courseId } = req.params;
|
|
const updateData = req.body;
|
|
|
|
// Check if course exists and user is the trainer
|
|
const course = await Course.findByPk(courseId);
|
|
if (!course) {
|
|
return res.status(404).json({ error: 'Course not found' });
|
|
}
|
|
|
|
if (course.trainerId !== req.user.id) {
|
|
return res.status(403).json({ error: 'Not authorized to update this course' });
|
|
}
|
|
|
|
// Update or create stats
|
|
const [courseStats, created] = await CourseStats.findOrCreate({
|
|
where: { courseId },
|
|
defaults: {
|
|
courseId,
|
|
skillLevel: 'beginner',
|
|
language: 'English',
|
|
publishedDate: course.createdAt,
|
|
certificateAvailable: true
|
|
}
|
|
});
|
|
|
|
await courseStats.update(updateData);
|
|
res.json(courseStats);
|
|
} catch (error) {
|
|
console.error('Error updating course stats:', error);
|
|
res.status(500).json({ error: 'Internal server error' });
|
|
}
|
|
});
|
|
|
|
// Create course statistics (trainer only)
|
|
router.post('/:courseId', auth, requireTrainer, async (req, res) => {
|
|
try {
|
|
const { courseId } = req.params;
|
|
const statsData = req.body;
|
|
|
|
// Check if course exists and user is the trainer
|
|
const course = await Course.findByPk(courseId);
|
|
if (!course) {
|
|
return res.status(404).json({ error: 'Course not found' });
|
|
}
|
|
|
|
if (course.trainerId !== req.user.id) {
|
|
return res.status(403).json({ error: 'Not authorized to create stats for this course' });
|
|
}
|
|
|
|
// Check if stats already exist
|
|
const existingStats = await CourseStats.findOne({ where: { courseId } });
|
|
if (existingStats) {
|
|
return res.status(400).json({ error: 'Course statistics already exist' });
|
|
}
|
|
|
|
// Create new stats
|
|
const courseStats = await CourseStats.create({
|
|
courseId,
|
|
...statsData,
|
|
publishedDate: statsData.publishedDate || course.createdAt
|
|
});
|
|
|
|
res.status(201).json(courseStats);
|
|
} catch (error) {
|
|
console.error('Error creating course stats:', error);
|
|
res.status(500).json({ error: 'Internal server error' });
|
|
}
|
|
});
|
|
|
|
module.exports = router;
|