fix(rwallet): chain filter now updates all displayed data + chain proportion bar

- Stats, balance table, and DeFi positions all filter by selected chain
- Added proportional color bar showing each chain's share of total value
- Chain buttons show USD value + percentage on hover
- Bumped JS cache version to v=21

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Jeff Emmett 2026-03-25 17:32:02 -07:00
parent 8d4e1fd0ff
commit f3094f5f88
2 changed files with 33 additions and 5 deletions

View File

@ -1650,7 +1650,9 @@ class FolkWalletViewer extends HTMLElement {
.example-type.eoa { background: rgba(20,184,166,0.1); color: var(--rs-accent); } .example-type.eoa { background: rgba(20,184,166,0.1); color: var(--rs-accent); }
/* ── Dashboard: chains ── */ /* ── Dashboard: chains ── */
.chains { display: flex; gap: 8px; flex-wrap: wrap; margin-bottom: 20px; } .chains { display: flex; gap: 8px; flex-wrap: wrap; margin-bottom: 8px; }
.chain-bar { display: flex; height: 6px; border-radius: 3px; overflow: hidden; margin-bottom: 16px; }
.chain-bar-seg { transition: width 0.3s ease; min-width: 3px; }
.chain-btn { .chain-btn {
padding: 6px 14px; border-radius: 8px; border: 2px solid var(--rs-border); padding: 6px 14px; border-radius: 8px; border: 2px solid var(--rs-border);
background: var(--rs-bg-surface); color: var(--rs-text-secondary); cursor: pointer; font-size: 13px; background: var(--rs-bg-surface); color: var(--rs-text-secondary); cursor: pointer; font-size: 13px;
@ -3120,9 +3122,15 @@ class FolkWalletViewer extends HTMLElement {
} }
if (this.defiPositions.length === 0) return ""; if (this.defiPositions.length === 0) return "";
// Filter by selected chain
const filtered = this.chainFilter
? this.defiPositions.filter(p => p.chainId === this.chainFilter)
: this.defiPositions;
if (filtered.length === 0) return "";
// Group by protocol // Group by protocol
const byProtocol = new Map<string, Array<typeof this.defiPositions[0]>>(); const byProtocol = new Map<string, Array<typeof this.defiPositions[0]>>();
for (const p of this.defiPositions) { for (const p of filtered) {
const existing = byProtocol.get(p.protocol) || []; const existing = byProtocol.get(p.protocol) || [];
existing.push(p); existing.push(p);
byProtocol.set(p.protocol, existing); byProtocol.set(p.protocol, existing);
@ -3166,7 +3174,7 @@ class FolkWalletViewer extends HTMLElement {
<div class="defi-section"> <div class="defi-section">
<div class="defi-header"> <div class="defi-header">
<h3>DeFi Positions</h3> <h3>DeFi Positions</h3>
<span class="defi-total">${this.formatUSD(String(this.defiTotalUSD))}</span> <span class="defi-total">${this.formatUSD(String(filtered.reduce((s, p) => s + p.totalValueUSD, 0)))}</span>
</div> </div>
${cards} ${cards}
</div>`; </div>`;
@ -3296,12 +3304,24 @@ class FolkWalletViewer extends HTMLElement {
return false; return false;
}).length; }).length;
// Compute per-chain USD totals for proportional bar
const allBalancesForBar = this.getUnifiedBalances(true);
const chainTotals = new Map<string, number>();
for (const b of allBalancesForBar) {
const cid = b.chainId;
chainTotals.set(cid, (chainTotals.get(cid) || 0) + parseFloat(b.fiatBalance || "0"));
}
const grandTotal = Array.from(chainTotals.values()).reduce((s, v) => s + v, 0) || 1;
// Build chain buttons with "All" filter // Build chain buttons with "All" filter
const chainButtons = this.detectedChains.map((ch) => { const chainButtons = this.detectedChains.map((ch) => {
const isActive = this.chainFilter === ch.chainId; const isActive = this.chainFilter === ch.chainId;
const chainUSD = chainTotals.get(ch.chainId) || 0;
const pct = grandTotal > 0 ? ((chainUSD / grandTotal) * 100).toFixed(1) : "0";
return ` return `
<div class="chain-btn ${isActive ? "active" : ""}" <div class="chain-btn ${isActive ? "active" : ""}"
data-chain="${ch.chainId}" style="--chain-color: ${ch.color}"> data-chain="${ch.chainId}" style="--chain-color: ${ch.color}"
title="${ch.name}: ${this.formatUSD(String(chainUSD))} (${pct}%)">
<div class="chain-dot" style="background: ${ch.color}"></div> <div class="chain-dot" style="background: ${ch.color}"></div>
${ch.name} ${ch.name}
</div>`; </div>`;
@ -3315,6 +3335,13 @@ class FolkWalletViewer extends HTMLElement {
Local Local
</div>` : ""; </div>` : "";
// Proportional chain bar
const barSegments = this.detectedChains.map((ch) => {
const pct = ((chainTotals.get(ch.chainId) || 0) / grandTotal) * 100;
if (pct < 0.5) return "";
return `<div class="chain-bar-seg" style="width:${pct}%;background:${ch.color}" title="${ch.name}: ${pct.toFixed(1)}%"></div>`;
}).join("");
const isVizView = this.activeView !== "balances"; const isVizView = this.activeView !== "balances";
return ` return `
@ -3326,6 +3353,7 @@ class FolkWalletViewer extends HTMLElement {
${chainButtons} ${chainButtons}
${localBtn} ${localBtn}
</div> </div>
${barSegments ? `<div class="chain-bar">${barSegments}</div>` : ""}
${!isVizView ? `<div class="stats"> ${!isVizView ? `<div class="stats">
<div class="stat-card"> <div class="stat-card">

View File

@ -1274,7 +1274,7 @@ function renderWallet(spaceSlug: string, initialView?: string) {
modules: getModuleInfoList(), modules: getModuleInfoList(),
theme: "dark", theme: "dark",
body: `<folk-wallet-viewer space="${spaceSlug}"${viewAttr}></folk-wallet-viewer>`, body: `<folk-wallet-viewer space="${spaceSlug}"${viewAttr}></folk-wallet-viewer>`,
scripts: `<script type="module" src="/modules/rwallet/folk-wallet-viewer.js?v=20"></script>`, scripts: `<script type="module" src="/modules/rwallet/folk-wallet-viewer.js?v=21"></script>`,
styles: `<link rel="stylesheet" href="/modules/rwallet/wallet.css">`, styles: `<link rel="stylesheet" href="/modules/rwallet/wallet.css">`,
}); });
} }