Reclutamiento: página de usuario para reclamar recompensas (recruit-a-friend)

Portado de home/views/recruit.py:
- lib/recruit-claim.ts: getRecruitRewards (con marca de reclamadas),
  getRecruitedLevel80Count, y claimRecruitReward con las mismas validaciones que
  Django (recompensa existe, no reclamada, amigos reclutados a nivel 80 suficientes,
  anti-abuso por IP compartida), entrega por SOAP `.send items` (éxito si "Mail sent to")
  y registro en home_claimedreward. Extra de seguridad: valida que el personaje sea de la cuenta.
- API POST /api/recruit/claim (401 sin sesión).
- UI /recruit (pública): rejilla de recompensas con estado reclamada/elegible/bloqueada,
  selector de personaje y contador de amigos a nivel 80. Enlace en el footer.
- i18n es/en: namespace RecruitClaim + Nav.recruit.

Verificado: build OK, /recruit 200, claim 401 sin sesión.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-07-13 00:45:29 +00:00
parent c6c56c3d95
commit 7534b9cbbb
7 changed files with 355 additions and 2 deletions
+26 -1
View File
@@ -11,7 +11,8 @@
"logout": "Cerrar sesión",
"language": "Idioma",
"forum": "Foros",
"vote": "Votar"
"vote": "Votar",
"recruit": "Reclutar"
},
"Home": {
"brand": "Nova WoW",
@@ -374,5 +375,29 @@
"prev": "Anterior",
"next": "Siguiente",
"page": "Página"
},
"RecruitClaim": {
"title": "Recluta a un amigo",
"intro": "Invita a tus amigos: cuando alcancen el nivel 80, reclama recompensas.",
"loginToClaim": "Inicia sesión para reclamar recompensas",
"level80Friends": "Amigos reclutados a nivel 80",
"deliverTo": "Entregar a",
"noCharacters": "No tienes personajes.",
"noRewards": "No hay recompensas disponibles.",
"requires": "Requiere {n} amigo(s)",
"claimed": "Reclamada",
"claiming": "Reclamando…",
"claim": "Reclamar",
"locked": "Bloqueada",
"notEnoughFriends": "No tienes suficientes amigos a nivel 80.",
"notAuthenticated": "Debes iniciar sesión.",
"invalidRequest": "Solicitud no válida.",
"selectRewardAndCharacter": "Selecciona una recompensa y un personaje.",
"rewardNotFound": "Recompensa no encontrada.",
"invalidCharacter": "Ese personaje no es tuyo.",
"alreadyClaimed": "Ya has reclamado esta recompensa.",
"requirementsNotMet": "No cumples los requisitos (o los amigos comparten tu IP).",
"deliveryError": "Error al entregar la recompensa.",
"claimSuccess": "Recompensa «{reward}» entregada a {character}."
}
}