Files
MathApp/progress/views.py

110 lines
4.3 KiB
Python

from drf_spectacular.types import OpenApiTypes
from drf_spectacular.utils import OpenApiParameter, extend_schema
from rest_framework.permissions import IsAuthenticated
from rest_framework.response import Response
from rest_framework.views import APIView
from .models import LeaderboardEntry, StreakRecord, UserHearts, UserStats
from .serializers import (
LeaderboardResponseSerializer,
StreakCalendarResponseSerializer,
UserHeartsResponseSerializer,
UserSummaryResponseSerializer,
)
class UserSummaryView(APIView):
"""GET /api/user/summary — پروفایل + آمار + استریک (ادغام‌شده)"""
permission_classes = [IsAuthenticated]
@extend_schema(responses=UserSummaryResponseSerializer, tags=['Progress & Gamification (progress)'])
def get(self, request):
user = request.user # accounts.User، از طریق TadrisinoTokenAuthentication
stats = UserStats.objects.filter(user_id=user.id).first()
streak = StreakRecord.objects.filter(user_id=user.id).first()
data = {
'userId': str(user.id),
'name': user.name,
'avatar': user.avatar,
'gradeId': user.grade_id,
'xp': stats.xp if stats else 0,
'coins': stats.coins if stats else 0,
'streak': {
'current': streak.current_streak if streak else 0,
'longest': streak.longest_streak if streak else 0,
},
# اپ subscription هنوز در این فاز پیاده‌سازی نشده؛ فعلاً null.
'subscription': None,
}
return Response(UserSummaryResponseSerializer(data).data)
class StreakCalendarView(APIView):
"""GET /api/user/streak/calendar — تقویم کامل روزهای فعال"""
permission_classes = [IsAuthenticated]
@extend_schema(responses=StreakCalendarResponseSerializer, tags=['Progress & Gamification (progress)'])
def get(self, request):
user = request.user
streak = StreakRecord.objects.filter(user_id=user.id).first()
data = {
'currentStreak': streak.current_streak if streak else 0,
'longestStreak': streak.longest_streak if streak else 0,
'activeDays': list(streak.active_days.values_list('date', flat=True)) if streak else [],
}
return Response(StreakCalendarResponseSerializer(data).data)
class LeaderboardView(APIView):
"""GET /api/leaderboard?period= — رتبه‌بندی هفتگی/ماهانه"""
@extend_schema(
parameters=[OpenApiParameter('period', OpenApiTypes.STR, required=False,
enum=['weekly', 'all_time'])],
responses=LeaderboardResponseSerializer,
tags=['Progress & Gamification (progress)'],
)
def get(self, request):
period = request.query_params.get('period', 'weekly')
entries = LeaderboardEntry.objects.filter(period=period).order_by('rank')[:50]
# نام کاربر از accounts.User خونده می‌شه (فقط برای نمایش، بدون FK واقعی).
from accounts.models import User as AccountUser
user_ids = [e.user_id for e in entries]
names = {u.id: u.name for u in AccountUser.objects.filter(id__in=user_ids)}
data = {
'period': period,
'entries': [
{
'rank': e.rank,
'userId': str(e.user_id),
'name': names.get(e.user_id, ''),
'xpInPeriod': e.xp_in_period,
}
for e in entries
],
}
return Response(LeaderboardResponseSerializer(data).data)
class UserHeartsView(APIView):
"""GET /api/user/hearts — وضعیت فعلی جان‌ها (هارت)"""
permission_classes = [IsAuthenticated]
@extend_schema(responses=UserHeartsResponseSerializer, tags=['Progress & Gamification (progress)'])
def get(self, request):
user = request.user
hearts, _ = UserHearts.objects.get_or_create(user_id=user.id)
data = {
'currentHearts': hearts.current_hearts,
'maxHearts': hearts.max_hearts,
'nextRefillAt': hearts.next_refill_at,
}
return Response(UserHeartsResponseSerializer(data).data)