diff --git a/backend/blueprints/admin/__init__.py b/backend/blueprints/admin/__init__.py index 8453f44..4439482 100644 --- a/backend/blueprints/admin/__init__.py +++ b/backend/blueprints/admin/__init__.py @@ -137,5 +137,47 @@ def get_discussion_stats(): } }), 200 + except Exception as e: + return jsonify({'message': f'An error occurred: {str(e)}'}), 500 + + +public_summary = Blueprint('public', __name__) + +@public_summary.route('/stats/summary', methods=['GET']) +def get_public_summary(): + """ + Public API to fetch total user count, authors, and total courses. + """ + try: + # Total users + total_users = db.session.execute( + select(func.count()).select_from(User) + ).scalar() + + # Authors (users who have created courses) + total_authors = db.session.execute( + select(func.count(func.distinct(Course.authorID))) + .select_from(Course) + ).scalar() + + # Total courses + total_courses = db.session.execute( + select(func.count()).select_from(Course) + ).scalar() + + # Simulated newsletter subscription count + subscribed_users = db.session.execute( + select(func.count(User.email)).select_from(User) + ).scalar() + + return jsonify({ + 'stats': { + 'totalUsers': total_users, + 'totalAuthors': total_authors, + 'totalCourses': total_courses, + 'subscribedNewsletter': subscribed_users + } + }), 200 + except Exception as e: return jsonify({'message': f'An error occurred: {str(e)}'}), 500 \ No newline at end of file diff --git a/backend/blueprints/notification/__init__.py b/backend/blueprints/notification/__init__.py index 64b82a1..c6d6f88 100644 --- a/backend/blueprints/notification/__init__.py +++ b/backend/blueprints/notification/__init__.py @@ -1,3 +1,108 @@ -from flask import Blueprint +from flask import Blueprint, jsonify, request, g +from utils.auth import auth_required +from db.model import User, Notification, db +from sqlalchemy import select, and_, desc +from datetime import datetime +import uuid -notification = Blueprint('notification', __name__) \ No newline at end of file +notification = Blueprint('notification', __name__) + +@notification.route('/get', methods=['GET', 'POST']) +@auth_required() +def handle_notifications(): + """ + Unified endpoint for handling notifications: + GET: Fetch notifications with optional before/after pagination + POST: Mark notifications as seen + + Query Parameters for GET: + - before: UUID of notification to get older entries + - after: UUID of notification to get newer entries + - limit: Number of notifications to return (default: 10) + + POST Body: + { + "notificationIds": ["uuid1", "uuid2", ...] + } + """ + if request.method == 'GET': + try: + current_user: User = g.current_user + limit: int = int(request.args.get('limit', 10)) + before_id = request.args.get('before') + after_id = request.args.get('after') + + # Base query + query = select(Notification).where( + Notification.userID == current_user.id + ) + + # Handle pagination + if before_id: + try: + reference_notification = db.session.execute( + select(Notification) + .where(and_( + Notification.id == uuid.UUID(before_id), + Notification.userID == current_user.id + )) + ).scalar() + + if not reference_notification: + return jsonify({'message': 'Reference notification not found'}), 404 + + query = query.where( + Notification.notifDate < reference_notification.notifDate + ) + except ValueError: + return jsonify({'message': 'Invalid notification ID format'}), 400 + + elif after_id: + try: + reference_notification = db.session.execute( + select(Notification) + .where(and_( + Notification.id == uuid.UUID(after_id), + Notification.userID == current_user.id + )) + ).scalar() + + if not reference_notification: + return jsonify({'message': 'Reference notification not found'}), 404 + + query = query.where( + Notification.notifDate > reference_notification.notifDate + ) + # For after queries, we need to reverse the order later + query = query.order_by(Notification.notifDate) + except ValueError: + return jsonify({'message': 'Invalid notification ID format'}), 400 + else: + # Default ordering + query = query.order_by(desc(Notification.notifDate)) + + # Apply limit and execute query + query = query.limit(limit) + notifications = list(db.session.execute(query).scalars()) + + # Reverse the order for 'after' queries to maintain consistency + if after_id: + notifications.reverse() + + # Format response + notif_list = [{ + 'id': str(notif.id), + 'type': notif.notificationType, + 'data': notif.notificationData, + 'seen': notif.isSeen, + 'date': notif.notifDate.isoformat() + } for notif in notifications] + + return jsonify({ + 'notifications': notif_list, + 'count': len(notif_list), + 'hasMore': len(notif_list) == limit + }), 200 + + except Exception as e: + return jsonify({'message': f'An error occurred: {str(e)}'}), 500 \ No newline at end of file