refactor(personajes): consolidate capacity table into single cross-character grid with totals
CI / Build Native (push) Successful in 6m53s

This commit is contained in:
2026-08-24 09:42:39 -04:00
parent c9622200a7
commit 38902f972e
@@ -160,53 +160,63 @@
<article x-show="characters.length > 0"> <article x-show="characters.length > 0">
<header> <header>
<h2>💼 Capacidad de inventario de shots (por peso)</h2> <h2>💼 Capacidad de inventario de shots (por peso)</h2>
<p class="text-sm text-muted">Cada card muestra cuántos shots de cada tipo×grado caben en el inventario según el pasivo del personaje. Peso máx = baseWeight × (1 + skillLevel).</p> <p class="text-sm text-muted">Cuántos shots de cada tipo×grado caben en el inventario según el pasivo de cada personaje. Peso máx = baseWeight × (1 + skillLevel).</p>
</header> </header>
<div class="flex-row gap-2" style="flex-wrap:wrap"> <div class="table-wrapper" style="overflow-x: auto;">
<template x-for="c in characters" :key="c.id"> <table style="font-size: 0.75rem;">
<article style="flex:1; min-width:320px; max-width:560px"> <thead>
<header style="flex-wrap:wrap;gap:0.5rem;align-items:center"> <tr>
<div> <th class="cell-label text-left" rowspan="2">Personaje</th>
<p class="text-sm text-bold" x-text="c.name" style="margin:0"></p> <th class="cell-label text-center" rowspan="2">Clase / Lv</th>
<p class="text-xs text-muted" style="margin:0" <th class="cell-label text-right" rowspan="2">Peso máx</th>
x-text="c.characterClass + ' · Lv ' + c.level + ' · base ' + fmtAdena(c.baseWeight) + ' · ×' + (c.skillLevel + 1)"></p> <template x-for="t in shots.TIPOS" :key="t">
</div> <th class="cell-label text-center" colspan="5" x-text="shots.tipoShort(t)"></th>
<span style="margin-left:auto" </template>
:class="c.skillLevel > 0 ? 'badge-success' : 'badge-muted'" <th class="cell-label text-right" rowspan="2">Total shots</th>
x-text="c.skillLevel === 0 ? 'Sin pasivo' : 'Skill +' + (c.skillLevel * 100) + '%'"></span> </tr>
</header> <tr>
<template x-for="t in shots.TIPOS" :key="'h-' + t">
<p class="text-xs text-muted mt-2">Peso máx: <span class="text-bold text-mono" x-text="fmtAdena(maxWeightOf(c))"></span></p> <template x-for="g in shots.GRADOS" :key="t + '-' + g">
<th class="cell-label text-center" x-text="g"></th>
<div class="table-wrapper" style="margin-top:0.5rem"> </template>
<table style="font-size:0.7rem; margin:0"> </template>
<thead> </tr>
<tr> </thead>
<th class="cell-label text-left"></th> <tbody>
<template x-for="g in GRADOS" :key="g"> <template x-for="c in characters" :key="c.id">
<th class="cell-label text-right" x-text="g"></th> <tr>
</template> <td class="text-bold" x-text="c.name"></td>
</tr> <td class="text-muted" style="white-space: nowrap;"
</thead> x-text="c.characterClass + ' · Lv ' + c.level"></td>
<tbody> <td class="text-right text-mono">
<template x-for="t in TIPOS" :key="t"> <span x-text="fmtAdena(shots.maxWeight(c))"></span>
<tr> <span class="text-xs"
<td class="text-bold text-mono" x-text="tipoShort(t)"></td> :class="c.skillLevel > 0 ? 'badge-success' : 'badge-muted'"
<template x-for="g in GRADOS" :key="t + '-' + g"> style="margin-left: 0.25rem;"
<td class="text-right text-mono" x-text="fmtAdena(capacityOf(c, t, g))"></td> x-text="c.skillLevel === 0 ? 'sin pasivo' : '+' + (c.skillLevel * 100) + '%'"></span>
</template> </td>
</tr> <template x-for="t in shots.TIPOS" :key="'r-' + t">
<template x-for="g in shots.GRADOS" :key="c.id + '-' + t + '-' + g">
<td class="text-right text-mono" x-text="fmtAdena(shots.capacityOf(c, t, g))"></td>
</template> </template>
</tbody> </template>
</table> <td class="text-right text-mono text-bold" x-text="fmtAdena(shots.totalCapacityOf(c))"></td>
</div> </tr>
</template>
<p class="text-xs text-muted mt-2"> </tbody>
Total 15 tipos: <span class="text-mono text-bold" x-text="fmtAdena(totalCapacityOf(c))"></span> shots <tfoot>
</p> <tr>
</article> <td class="cell-label" colspan="3">Totales</td>
</template> <template x-for="t in shots.TIPOS" :key="'f-' + t">
<template x-for="g in shots.GRADOS" :key="'f-' + t + '-' + g">
<td class="text-right text-mono text-bold" x-text="fmtAdena(columnTotals[t + '-' + g])"></td>
</template>
</template>
<td class="text-right text-mono text-bold" x-text="fmtAdena(rowTotal())"></td>
</tr>
</tfoot>
</table>
</div> </div>
</article> </article>
@@ -256,6 +266,7 @@
async loadCharacters() { async loadCharacters() {
try { try {
this.characters = await window.api.listCharacters(); this.characters = await window.api.listCharacters();
this.updateColumnTotals();
} catch (e) { } catch (e) {
this.error = e.message || 'Error cargando personajes'; this.error = e.message || 'Error cargando personajes';
} finally { } finally {
@@ -307,6 +318,30 @@
return window.shots.totalCapacityOf(c); return window.shots.totalCapacityOf(c);
}, },
columnTotals: {},
rowTotal() {
let total = 0;
for (const c of this.characters) {
total += window.shots.totalCapacityOf(c);
}
return total;
},
updateColumnTotals() {
const totals = {};
for (const t of window.shots.TIPOS) {
for (const g of window.shots.GRADOS) {
let sum = 0;
for (const c of this.characters) {
sum += window.shots.capacityOf(c, t, g);
}
totals[t + '-' + g] = sum;
}
}
this.columnTotals = totals;
},
async updateLevel(c) { async updateLevel(c) {
if (c.level <= 0 || c.level > 100) { if (c.level <= 0 || c.level > 100) {
c.level = Math.min(100, Math.max(1, c.level)); c.level = Math.min(100, Math.max(1, c.level));
@@ -325,6 +360,7 @@
c.skillLevel = sk; c.skillLevel = sk;
try { try {
await window.api.updateCharacterWeight(c.id, bw, sk); await window.api.updateCharacterWeight(c.id, bw, sk);
this.updateColumnTotals();
} catch (e) { } catch (e) {
this.error = e.message || 'Error al actualizar peso/skill'; this.error = e.message || 'Error al actualizar peso/skill';
} }