mirror of
https://github.com/th30d4y/OpenLearnX.git
synced 2026-05-26 19:26:33 +00:00
backend
This commit is contained in:
@@ -0,0 +1,211 @@
|
||||
from flask import Blueprint, request, jsonify, current_app
|
||||
import jwt
|
||||
from datetime import datetime, timedelta
|
||||
|
||||
bp = Blueprint('dashboard', __name__)
|
||||
|
||||
def get_user_from_token(token):
|
||||
"""Extract user from JWT token"""
|
||||
try:
|
||||
payload = jwt.decode(
|
||||
token,
|
||||
current_app.config['SECRET_KEY'],
|
||||
algorithms=['HS256']
|
||||
)
|
||||
return payload['user_id']
|
||||
except:
|
||||
return None
|
||||
|
||||
@bp.route('/student/<user_id>', methods=['GET'])
|
||||
async def get_student_dashboard(user_id):
|
||||
"""Get comprehensive student dashboard"""
|
||||
token = request.headers.get('Authorization', '').replace('Bearer ', '')
|
||||
token_user_id = get_user_from_token(token)
|
||||
|
||||
if not token_user_id or token_user_id != user_id:
|
||||
return jsonify({"error": "Unauthorized"}), 403
|
||||
|
||||
mongo_service = current_app.config['MONGO_SERVICE']
|
||||
analytics = await mongo_service.get_user_analytics(user_id)
|
||||
|
||||
if not analytics:
|
||||
return jsonify({"error": "User not found"}), 404
|
||||
|
||||
# Get recent activity
|
||||
recent_sessions = await mongo_service.test_sessions.find({
|
||||
"user_id": user_id
|
||||
}).sort("created_at", -1).limit(5).to_list(length=5)
|
||||
|
||||
# Get certificates
|
||||
certificates = await mongo_service.get_user_certificates(user_id)
|
||||
|
||||
# Calculate streaks and progress
|
||||
today = datetime.utcnow().date()
|
||||
week_ago = today - timedelta(days=7)
|
||||
month_ago = today - timedelta(days=30)
|
||||
|
||||
week_sessions = [s for s in recent_sessions
|
||||
if s['created_at'].date() >= week_ago]
|
||||
month_sessions = [s for s in recent_sessions
|
||||
if s['created_at'].date() >= month_ago]
|
||||
|
||||
dashboard_data = {
|
||||
"user_info": {
|
||||
"id": str(analytics['user']['_id']),
|
||||
"wallet_address": analytics['user']['wallet_address'],
|
||||
"member_since": analytics['user']['created_at'].isoformat(),
|
||||
"last_login": analytics['user']['last_login'].isoformat()
|
||||
},
|
||||
"overview": {
|
||||
"total_tests": analytics['total_tests'],
|
||||
"completed_tests": analytics['completed_tests'],
|
||||
"average_score": round(analytics['average_score'] * 100, 1),
|
||||
"certificates_earned": analytics['certificates_earned'],
|
||||
"this_week_tests": len(week_sessions),
|
||||
"this_month_tests": len(month_sessions)
|
||||
},
|
||||
"subject_breakdown": {
|
||||
subject: {
|
||||
"tests_taken": data['tests'],
|
||||
"average_score": round(data['avg_score'] * 100, 1),
|
||||
"mastery_level": get_mastery_level(data['avg_score'])
|
||||
}
|
||||
for subject, data in analytics['subject_breakdown'].items()
|
||||
},
|
||||
"recent_activity": [
|
||||
{
|
||||
"id": str(session['_id']),
|
||||
"subject": session['subject'],
|
||||
"score": round(session.get('score', 0) * 100, 1),
|
||||
"completed": session.get('completed', False),
|
||||
"date": session['created_at'].isoformat(),
|
||||
"questions_answered": len(session.get('answers', []))
|
||||
}
|
||||
for session in recent_sessions
|
||||
],
|
||||
"certificates": [
|
||||
{
|
||||
"id": str(cert['_id']),
|
||||
"token_id": cert['token_id'],
|
||||
"subject": cert['subject'],
|
||||
"score": round(cert['score'] * 100, 1),
|
||||
"earned_date": cert['created_at'].isoformat(),
|
||||
"blockchain_verified": cert.get('verified', True)
|
||||
}
|
||||
for cert in certificates
|
||||
],
|
||||
"progress_chart": await get_progress_chart_data(mongo_service, user_id),
|
||||
"competency_radar": get_competency_radar_data(analytics['subject_breakdown'])
|
||||
}
|
||||
|
||||
return jsonify(dashboard_data)
|
||||
|
||||
@bp.route('/instructor/overview', methods=['GET'])
|
||||
async def get_instructor_dashboard():
|
||||
"""Get instructor dashboard with class overview"""
|
||||
token = request.headers.get('Authorization', '').replace('Bearer ', '')
|
||||
user_id = get_user_from_token(token)
|
||||
|
||||
if not user_id:
|
||||
return jsonify({"error": "Unauthorized"}), 403
|
||||
|
||||
mongo_service = current_app.config['MONGO_SERVICE']
|
||||
|
||||
# Get overall platform statistics
|
||||
total_users = await mongo_service.users.count_documents({})
|
||||
total_tests = await mongo_service.test_sessions.count_documents({})
|
||||
total_certificates = await mongo_service.certificates.count_documents({})
|
||||
|
||||
# Get recent activity across all users
|
||||
recent_sessions = await mongo_service.test_sessions.find({}).sort(
|
||||
"created_at", -1
|
||||
).limit(20).to_list(length=20)
|
||||
|
||||
# Calculate subject popularity
|
||||
subject_stats = {}
|
||||
for session in recent_sessions:
|
||||
subject = session.get('subject', 'Unknown')
|
||||
if subject not in subject_stats:
|
||||
subject_stats[subject] = {'count': 0, 'total_score': 0}
|
||||
subject_stats[subject]['count'] += 1
|
||||
subject_stats[subject]['total_score'] += session.get('score', 0)
|
||||
|
||||
for subject in subject_stats:
|
||||
subject_stats[subject]['avg_score'] = (
|
||||
subject_stats[subject]['total_score'] / subject_stats[subject]['count']
|
||||
)
|
||||
|
||||
dashboard_data = {
|
||||
"platform_overview": {
|
||||
"total_users": total_users,
|
||||
"total_tests": total_tests,
|
||||
"total_certificates": total_certificates,
|
||||
"active_users_today": len([s for s in recent_sessions
|
||||
if s['created_at'].date() == datetime.utcnow().date()])
|
||||
},
|
||||
"subject_performance": {
|
||||
subject: {
|
||||
"total_attempts": data['count'],
|
||||
"average_score": round(data['avg_score'] * 100, 1),
|
||||
"difficulty_trend": "increasing" if data['avg_score'] > 0.7 else "stable"
|
||||
}
|
||||
for subject, data in subject_stats.items()
|
||||
},
|
||||
"recent_activity": [
|
||||
{
|
||||
"user_id": session['user_id'],
|
||||
"subject": session['subject'],
|
||||
"score": round(session.get('score', 0) * 100, 1),
|
||||
"completed": session.get('completed', False),
|
||||
"timestamp": session['created_at'].isoformat()
|
||||
}
|
||||
for session in recent_sessions[:10]
|
||||
]
|
||||
}
|
||||
|
||||
return jsonify(dashboard_data)
|
||||
|
||||
def get_mastery_level(score):
|
||||
"""Determine mastery level based on score"""
|
||||
if score >= 0.9:
|
||||
return "Expert"
|
||||
elif score >= 0.8:
|
||||
return "Advanced"
|
||||
elif score >= 0.7:
|
||||
return "Proficient"
|
||||
elif score >= 0.6:
|
||||
return "Developing"
|
||||
else:
|
||||
return "Beginner"
|
||||
|
||||
async def get_progress_chart_data(mongo_service, user_id):
|
||||
"""Get progress chart data for the last 30 days"""
|
||||
thirty_days_ago = datetime.utcnow() - timedelta(days=30)
|
||||
|
||||
sessions = await mongo_service.test_sessions.find({
|
||||
"user_id": user_id,
|
||||
"created_at": {"$gte": thirty_days_ago},
|
||||
"completed": True
|
||||
}).sort("created_at", 1).to_list(length=None)
|
||||
|
||||
progress_data = []
|
||||
for session in sessions:
|
||||
progress_data.append({
|
||||
"date": session['created_at'].strftime("%Y-%m-%d"),
|
||||
"score": round(session.get('score', 0) * 100, 1),
|
||||
"subject": session['subject']
|
||||
})
|
||||
|
||||
return progress_data
|
||||
|
||||
def get_competency_radar_data(subject_breakdown):
|
||||
"""Generate radar chart data for competencies"""
|
||||
radar_data = []
|
||||
for subject, data in subject_breakdown.items():
|
||||
radar_data.append({
|
||||
"subject": subject,
|
||||
"score": round(data['avg_score'] * 100, 1),
|
||||
"tests": data['tests']
|
||||
})
|
||||
|
||||
return radar_data
|
||||
Reference in New Issue
Block a user