7534b9cbbb
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>
39 lines
1.3 KiB
TypeScript
39 lines
1.3 KiB
TypeScript
import { getTranslations, setRequestLocale } from 'next-intl/server'
|
|
import { Link } from '@/i18n/navigation'
|
|
import { getSession } from '@/lib/session'
|
|
import { getGameCharacters } from '@/lib/characters'
|
|
import { getRecruitRewards, getRecruitedLevel80Count } from '@/lib/recruit-claim'
|
|
import { RecruitClaim } from '@/components/RecruitClaim'
|
|
|
|
export const dynamic = 'force-dynamic'
|
|
|
|
export default async function RecruitPage({ params }: { params: Promise<{ locale: string }> }) {
|
|
const { locale } = await params
|
|
setRequestLocale(locale)
|
|
const t = await getTranslations('RecruitClaim')
|
|
const session = await getSession()
|
|
|
|
const rewards = await getRecruitRewards(session.accountId ?? null)
|
|
|
|
return (
|
|
<main className="mx-auto max-w-4xl px-4 py-8">
|
|
<h1 className="mb-2 text-2xl font-bold text-amber-500">{t('title')}</h1>
|
|
<p className="mb-6 text-nw-muted">{t('intro')}</p>
|
|
|
|
{session.accountId ? (
|
|
<RecruitClaim
|
|
rewards={rewards}
|
|
characters={(await getGameCharacters(session.accountId)).map((c) => c.name)}
|
|
level80Count={await getRecruitedLevel80Count(session.accountId)}
|
|
/>
|
|
) : (
|
|
<p className="text-amber-200/70">
|
|
<Link href="/login" className="text-sky-400 hover:underline">
|
|
{t('loginToClaim')}
|
|
</Link>
|
|
</p>
|
|
)}
|
|
</main>
|
|
)
|
|
}
|