diff --git a/web-next/app/[locale]/account/page.tsx b/web-next/app/[locale]/account/page.tsx index a4a0a23..b9585ce 100644 --- a/web-next/app/[locale]/account/page.tsx +++ b/web-next/app/[locale]/account/page.tsx @@ -1,6 +1,7 @@ import { getTranslations, setRequestLocale } from 'next-intl/server' import { redirect } from '@/i18n/navigation' import { getSession } from '@/lib/session' +import { getAccountDashboard } from '@/lib/account' import { LogoutButton } from '@/components/LogoutButton' export const dynamic = 'force-dynamic' @@ -14,20 +15,61 @@ export default async function AccountPage({ params }: { params: Promise<{ locale if (!session.bnetId) redirect({ href: '/login', locale }) if (!session.username) redirect({ href: '/select-account', locale }) + const data = await getAccountDashboard(session) + + const card = 'rounded-lg border border-amber-900/60 bg-[#241812] p-4' + return ( -
-

{t('title')}

-
-

- {t('bnetAccount')}: {session.bnetEmail} -

-

- {t('gameAccount')}: {session.username} -

+
+
+

{t('title')}

+
-
- + +
+
+
+

{t('bnetAccount')}: {data.bnetEmail}

+

{t('gameAccount')}: {data.gameAccount}

+

+ {t('securityToken')}:{' '} + + {data.securityTokenDate + ? `${t('requested')} — ${new Date(data.securityTokenDate).toLocaleString(locale)}` + : t('notRequested')} + +

+
+
+ +
+

{t('points')}

+
+

{t('dp')}: {data.dp}

+

{t('vp')}: {data.vp}

+

{t('battlepayCredits')}: {data.battlepayCredits}

+
+
+ +
+

{t('characters')}

+ {data.characters.length === 0 ? ( +

{t('noCharacters')}

+ ) : ( +
+ {data.characters.map((c) => ( +
+

{c.name}

+

{t('level')} {c.level}

+

+ {c.gold}g {c.silver}s {c.copper}c +

+
+ ))} +
+ )} +
) } diff --git a/web-next/lib/account.ts b/web-next/lib/account.ts new file mode 100644 index 0000000..48ada6e --- /dev/null +++ b/web-next/lib/account.ts @@ -0,0 +1,90 @@ +import type { RowDataPacket } from 'mysql2' +import { db, DB } from './db' +import type { SessionData } from './session' + +export interface Character { + name: string + level: number + gold: number + silver: number + copper: number +} + +export interface AccountDashboard { + bnetEmail: string + gameAccount: string + dp: number + vp: number + battlepayCredits: number + securityTokenDate: string | null + characters: Character[] +} + +/** Datos del panel de cuenta. Resiliente si las BD de AzerothCore no están pobladas. */ +export async function getAccountDashboard(session: SessionData): Promise { + const accountId = session.accountId ?? 0 + + let dp = 0 + let vp = 0 + try { + const [p] = await db(DB.default).query( + 'SELECT dp, vp FROM home_api_points WHERE accountID = ?', + [accountId], + ) + if (p[0]) { + dp = p[0].dp + vp = p[0].vp + } + } catch { + /* ignore */ + } + + let battlepayCredits = 0 + try { + const [c] = await db(DB.auth).query( + 'SELECT battlePayCredits FROM battlenet_accounts WHERE id = ?', + [session.bnetId ?? 0], + ) + if (c[0]?.battlePayCredits != null) battlepayCredits = c[0].battlePayCredits + } catch { + /* ignore */ + } + + let securityTokenDate: string | null = null + try { + const [s] = await db(DB.default).query( + 'SELECT created_at FROM home_securitytoken WHERE user_id = ? ORDER BY created_at DESC LIMIT 1', + [accountId], + ) + if (s[0]) securityTokenDate = new Date(s[0].created_at).toISOString() + } catch { + /* ignore */ + } + + let characters: Character[] = [] + try { + const [ch] = await db(DB.characters).query( + 'SELECT name, level, money FROM characters WHERE account = ?', + [accountId], + ) + characters = ch.map((r) => ({ + name: r.name, + level: r.level, + gold: Math.floor(r.money / 10000), + silver: Math.floor((r.money % 10000) / 100), + copper: r.money % 100, + })) + } catch { + /* la BD de personajes puede no estar poblada */ + } + + return { + bnetEmail: session.bnetEmail ?? '', + gameAccount: session.username ?? '', + dp, + vp, + battlepayCredits, + securityTokenDate, + characters, + } +} diff --git a/web-next/messages/en.json b/web-next/messages/en.json index 9c21eda..1614905 100644 --- a/web-next/messages/en.json +++ b/web-next/messages/en.json @@ -44,7 +44,17 @@ "title": "My account", "bnetAccount": "Account (Battle.net)", "gameAccount": "Game account", - "logout": "Log out" + "logout": "Log out", + "points": "Points", + "dp": "DP", + "vp": "VP", + "battlepayCredits": "Battlepay credits", + "securityToken": "Security token", + "requested": "Requested", + "notRequested": "Not requested", + "characters": "My characters", + "level": "Level", + "noCharacters": "You have no characters yet." }, "SelectAccount": { "title": "Select your game account", diff --git a/web-next/messages/es.json b/web-next/messages/es.json index ebefa1a..de6b9ab 100644 --- a/web-next/messages/es.json +++ b/web-next/messages/es.json @@ -44,7 +44,17 @@ "title": "Mi cuenta", "bnetAccount": "Cuenta (Battle.net)", "gameAccount": "Cuenta de juego", - "logout": "Cerrar sesión" + "logout": "Cerrar sesión", + "points": "Puntos", + "dp": "PD", + "vp": "PV", + "battlepayCredits": "Créditos Battlepay", + "securityToken": "Token de seguridad", + "requested": "Solicitado", + "notRequested": "Sin solicitar", + "characters": "Mis personajes", + "level": "Nivel", + "noCharacters": "No tienes personajes todavía." }, "SelectAccount": { "title": "Selecciona tu cuenta de juego",