Fase 3 (isla): dashboard de «Mi cuenta» en React/TSX
De las ~508 líneas de partials/my-account.html, solo la parte superior es dinámica (datos de cuenta, estado, puntos, token, personajes); el resto son paneles de navegación estáticos (enlaces), que se quedan en Django. - API: account_me_api -> /api/account/me/ (protegido por sesión, 401 si no hay): user_info, account_status, dp/vp, créditos Battlepay, token de seguridad y personajes. Reutiliza get_account_characters/get_account_status/formatear_fecha. Resiliente si acore no está disponible. - React: AccountDashboard.tsx (fieldsets de datos + estado con contador de baneo en vivo + rejilla de personajes). Entry my_account. - partials/my-account.html: los 2 fieldsets + la rejilla de personajes + el script del contador se sustituyen por #account-dashboard-app; los paneles de utilidades e historiales siguen en Django. Verificado: check OK, /api/account/me/ 401 sin sesión, my-account redirige a login. (El render con datos reales requiere sesión + BD AzerothCore.) Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -1,6 +1,7 @@
|
||||
from ._base import *
|
||||
from .pages import check_server_status, get_online_characters_count
|
||||
from .auth import _set_game_account_session
|
||||
from .account import get_account_characters, get_account_status, formatear_fecha
|
||||
|
||||
# Endpoints JSON que alimentan las islas React/TSX del frontend (Vite).
|
||||
# Se montan bajo /api/ (fuera de i18n_patterns). De momento con JsonResponse;
|
||||
@@ -60,3 +61,49 @@ def account_select_api(request):
|
||||
return JsonResponse({"success": False, "error": "Cuenta de juego no válida."})
|
||||
_set_game_account_session(request, chosen)
|
||||
return JsonResponse({"success": True, "redirect": reverse("my-account")})
|
||||
|
||||
|
||||
def account_me_api(request):
|
||||
"""Datos del panel «Mi cuenta» (isla): info de cuenta, estado, puntos,
|
||||
créditos Battlepay, token de seguridad y personajes. Requiere sesión."""
|
||||
username = request.session.get('username')
|
||||
if not username:
|
||||
return JsonResponse({"authenticated": False}, status=401)
|
||||
try:
|
||||
with connections['acore_auth'].cursor() as cursor:
|
||||
cursor.execute(
|
||||
"SELECT id, username, reg_mail, email, last_ip, last_attempt_ip, joindate "
|
||||
"FROM account WHERE username = %s", [username])
|
||||
row = cursor.fetchone()
|
||||
if not row:
|
||||
return JsonResponse({"authenticated": False}, status=404)
|
||||
account_id = row[0]
|
||||
characters = get_account_characters(account_id)
|
||||
status = get_account_status(account_id)
|
||||
points = HomeApiPoints.objects.filter(accountID=account_id).first()
|
||||
sectoken = SecurityToken.objects.filter(user_id=account_id).first()
|
||||
with connections['acore_auth'].cursor() as cursor:
|
||||
credits = bnet.get_battlepay_credits(cursor, request.session.get('bnet_id'))
|
||||
except Exception as e:
|
||||
logger.error("account_me_api: %s", e)
|
||||
return JsonResponse({"authenticated": True, "error": "No se pudieron cargar los datos de la cuenta."}, status=200)
|
||||
|
||||
return JsonResponse({
|
||||
"authenticated": True,
|
||||
"user_info": {
|
||||
"bnet_email": request.session.get('bnet_email') or row[3],
|
||||
"username": row[1],
|
||||
"reg_mail": row[2],
|
||||
"email": row[3],
|
||||
"last_ip": row[4],
|
||||
"last_attempt_ip": row[5],
|
||||
"joindate": formatear_fecha(row[6]),
|
||||
},
|
||||
"account_status": status,
|
||||
"dp": points.dp if points else 0,
|
||||
"vp": points.vp if points else 0,
|
||||
"battlepay_credits": credits,
|
||||
"token_status": "Solicitado" if sectoken else "Sin solicitar",
|
||||
"token_date": sectoken.created_at.strftime('%H:%M:%S %d-%m-%Y') if sectoken else None,
|
||||
"characters": characters,
|
||||
})
|
||||
|
||||
Reference in New Issue
Block a user