026fbcb81c
Porta la tienda de ítems/transfiguración del sistema antiguo: elegir personaje → árbol de categorías (3 niveles) → carrito → enviar por correo. Se paga con el saldo PD o PV de la cuenta (cada ítem lleva su precio y moneda). - BD: home_store_category (árbol por code "1-1-1") + home_store_item (mismos item_id, nombres, iconos, precios y moneda que el original; 2947 en PD, 121 en PV). Seed en sql/store_catalog.sql, extraído del HTML real. - lib/store.ts: getStoreCatalog (árbol anidado), getStoreBalances, priceStoreCart (precios REALES de BD), purchaseStoreCart (cobro atómico PD+PV con FOR UPDATE y reembolso si el envío SOAP falla; `.send items` troceado a 12/correo). - API: GET /api/store/catalog (tras elegir personaje) y POST /api/store/send. - components/StoreBrowser.tsx: selector de personaje, árbol colapsable (ítems montados solo al abrir), carrito con totales PD/PV, enviar, modal de resultado. - página /store con la info y el título "Tienda - REINO". Enlaces de ítems e iconos por wowhead/zamimg (con tooltip y locale). El enlace ya existía en AccountTools. i18n namespace Store (es/en). CSS del árbol/carrito/modal. Verificado: catálogo E2E (750 cats/3068 ítems), cobro atómico + reembolso y detección de saldo insuficiente (cuenta 15). SOAP real sin probar (worldserver caído en este entorno). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
61 lines
2.0 KiB
TypeScript
61 lines
2.0 KiB
TypeScript
import type { Metadata } from 'next'
|
|
import { getTranslations, setRequestLocale } from 'next-intl/server'
|
|
import { redirect } from '@/i18n/navigation'
|
|
import { getSession } from '@/lib/session'
|
|
import { getGameCharacters } from '@/lib/characters'
|
|
import { getStoreBalances } from '@/lib/store'
|
|
import { getRealmName } from '@/lib/realm'
|
|
import { wowheadWotlkHome } from '@/lib/wowhead'
|
|
import { PageShell } from '@/components/PageShell'
|
|
import { ServiceBox } from '@/components/ServiceBox'
|
|
import { StoreBrowser } from '@/components/StoreBrowser'
|
|
|
|
export const dynamic = 'force-dynamic'
|
|
|
|
export async function generateMetadata({ params }: { params: Promise<{ locale: string }> }): Promise<Metadata> {
|
|
const { locale } = await params
|
|
const t = await getTranslations({ locale, namespace: 'Store' })
|
|
return { title: t('title') }
|
|
}
|
|
|
|
export default async function StorePage({ params }: { params: Promise<{ locale: string }> }) {
|
|
const { locale } = await params
|
|
setRequestLocale(locale)
|
|
|
|
const session = await getSession()
|
|
if (!session.bnetId) redirect({ href: '/log-in', locale })
|
|
if (!session.username) redirect({ href: '/select-account', locale })
|
|
|
|
const [chars, balances, realm] = await Promise.all([
|
|
getGameCharacters(session.accountId!),
|
|
getStoreBalances(session.accountId!),
|
|
getRealmName(),
|
|
])
|
|
|
|
const t = await getTranslations('Store')
|
|
|
|
return (
|
|
<PageShell title={<>{t('title')} - <span className="blue-info">{realm.toUpperCase()}</span></>}>
|
|
<ServiceBox>
|
|
<br />
|
|
<p>{t('infoTooltip')}</p>
|
|
<p>
|
|
{t.rich('infoDb', {
|
|
link: (c) => (
|
|
<a href={wowheadWotlkHome(locale)} target="_blank" rel="noopener noreferrer">
|
|
{c}
|
|
</a>
|
|
),
|
|
})}
|
|
</p>
|
|
</ServiceBox>
|
|
|
|
<StoreBrowser
|
|
characters={chars.map((c) => ({ name: c.name, classCss: c.classCss }))}
|
|
dp={balances.dp}
|
|
vp={balances.vp}
|
|
/>
|
|
</PageShell>
|
|
)
|
|
}
|