diff --git a/web-next/.bak-armory/page.tsx.pretabs b/web-next/.bak-armory/page.tsx.pretabs
new file mode 100644
index 0000000..3c0f7c7
--- /dev/null
+++ b/web-next/.bak-armory/page.tsx.pretabs
@@ -0,0 +1,278 @@
+import { notFound } from 'next/navigation'
+import { getTranslations, setRequestLocale } from 'next-intl/server'
+import { Link } from '@/i18n/navigation'
+import {
+ getCharacter,
+ getCharacterEquipment,
+ getCharacterCustomizations,
+ getCharacterStats,
+ getCharacterProfessions,
+ getItemIcons,
+ getAchievementPoints,
+ getCharacterTalents,
+ getCharacterSpecs,
+ getSpellIcons,
+ getActivityPage,
+} from '@/lib/armory'
+import { raceName, className, classColor, factionOf, classPower } from '@/lib/wow-data'
+import { PageShell } from '@/components/PageShell'
+import { ArmoryPaperdoll, type SheetItem } from '@/components/ArmoryPaperdoll'
+import { wowheadIcon } from '@/lib/wowhead'
+import { ArmoryTalents } from '@/components/ArmoryTalents'
+import { ArmoryActivity } from '@/components/ArmoryActivity'
+import { WowheadRefresh } from '@/components/WowheadRefresh'
+
+export const dynamic = 'force-dynamic'
+
+export default async function CharacterPage({
+ params,
+}: {
+ params: Promise<{ locale: string; guid: string }>
+}) {
+ const { locale, guid } = await params
+ setRequestLocale(locale)
+ const t = await getTranslations('Armory')
+
+ const id = Number(guid)
+ const character = await getCharacter(id)
+ if (!character) notFound()
+
+ const [equipment, customizations, stats, professions, achievementPoints, talents, specs, activityData] = await Promise.all([
+ getCharacterEquipment(id, locale),
+ getCharacterCustomizations(id),
+ getCharacterStats(id),
+ getCharacterProfessions(id, locale),
+ getAchievementPoints(id),
+ getCharacterTalents(id, character.class, locale),
+ getCharacterSpecs(id, character.class, locale),
+ getActivityPage(id, locale, 1, 10, ''),
+ ])
+ const icons = await getItemIcons(equipment.map((e) => e.entry))
+ const spellIcons = talents ? await getSpellIcons(talents.trees.flatMap((tr) => tr.talents.map((c) => c.spell))) : {}
+
+ const items: SheetItem[] = equipment.map((e) => ({
+ slot: e.slot,
+ entry: e.entry,
+ name: e.name,
+ quality: e.quality,
+ itemLevel: e.itemLevel,
+ inventoryType: e.inventoryType,
+ displayId: e.displayId,
+ transmogDisplayId: e.transmogDisplayId,
+ ench: e.ench,
+ gems: e.gems,
+ icon: icons[e.entry] ?? null,
+ }))
+
+ const gear = equipment.filter((e) => e.slot !== 3 && e.slot !== 18 && e.itemLevel > 0)
+ const avgItemLevel = gear.length ? Math.round(gear.reduce((s, e) => s + e.itemLevel, 0) / gear.length) : 0
+ const faction = factionOf(character.race)
+ const factionLabel = faction === 'alliance' ? t('alliance') : faction === 'horde' ? t('horde') : ''
+ const power = classPower(character.class, locale)
+
+ const statRows = stats
+ ? [
+ { label: t('strength'), value: `${stats.strength}` },
+ { label: t('agility'), value: `${stats.agility}` },
+ { label: t('stamina'), value: `${stats.stamina}` },
+ { label: t('intellect'), value: `${stats.intellect}` },
+ { label: t('armor'), value: `${stats.armor}` },
+ { label: t('attackPower'), value: `${stats.attackPower}` },
+ { label: t('rangedAttackPower'), value: `${stats.rangedAttackPower}` },
+ { label: t('spellPower'), value: `${stats.spellPower}` },
+ { label: t('critChance'), value: `${stats.critPct.toFixed(2)}%` },
+ { label: t('spellCrit'), value: `${stats.spellCritPct.toFixed(2)}%` },
+ { label: t('dodge'), value: `${stats.dodgePct.toFixed(2)}%` },
+ { label: t('parry'), value: `${stats.parryPct.toFixed(2)}%` },
+ { label: t('block'), value: `${stats.blockPct.toFixed(2)}%` },
+ { label: t('resilience'), value: `${stats.resilience}` },
+ ]
+ : []
+
+ return (
+
+ ← {t('backToArmory')}
+ {t('statsPending')} {t('noProfessions')}
+ {character.name}
+ {avgItemLevel > 0 ? (
+
+ {' '}
+ ({t('itemLevel')} {avgItemLevel})
+
+ ) : null}
+
+ {t('specialization')}
+ {t('talents')}
+ {t('recentActivity')}
+ {t('stats')}
+ {stats ? (
+ {t('professions')}
+ {professions.length ? (
+
+ {kind === 'primary' ? t('primaryProfs') : t('secondaryProfs')}
+
+ {list.map((p) => (
+
{t('statsPending')}
+ )} +{t('noProfessions')}
+ )} +{t('noTalents')}
+{t('statsPending')}
- )} -{t('noProfessions')}
- )} +← {t('backToArmory')}
-{labels.empty}
+ ) : ( +{a.description}
: null} + {a.reward ? ( ++ {labels.reward}: {a.reward} +
+ ) : null} +{summary}
+{labels.empty}
- ) : ( - entries.map((a, i) => ( -{countLine}
+ +{labels.empty}
+ ) : ( +| {labels.logro} | +{labels.date} | +
|---|---|
| + + {a.name} + + ({a.id}) + | +{fmt(a.date)} | +