User page: hash-routed view, full block hash, aligned rewards

The per-user view was an overlay modal, but users asked for an
actual page — focused, scrollable, addressable. Replace the modal
with a hash-routed page: selectUser(addr) sets window.location.hash
to #/user/<addr> and a hashchange listener syncs the selection
state back, so browser back/forward and direct-link refresh all
work without a routing library. App renders the dashboard or the
UserDetailPage based on selection.user.

Make the clickable BTC addresses in the Miners table obviously
interactive: accent colour, always-on dashed underline, brighter on
hover/focus. The previous styling rendered them as dim static text
with a hover underline, so it wasn't obvious they were links.

BlocksTable: show the full 64-char block hash as a link to
mempool.space (auto-picks testnet4/signet based on snap.chain).
word-break: break-all keeps the hash from blowing out the column
width. Reward column is split into a tabular-num number span and a
dim 0.75em "BTC" unit span, matching the Block reward tile in the
overview, so numbers line up cleanly across rows.
This commit is contained in:
satoshi
2026-04-24 01:02:11 +03:00
parent c104c1eefa
commit 49c951f94f
6 changed files with 397 additions and 337 deletions
+4 -2
View File
@@ -1,13 +1,14 @@
<script lang="ts">
import { onMount } from "svelte";
import { connect, snap } from "./stores/snapshot.svelte";
import { selection } from "./stores/selection.svelte";
import Header from "./lib/Header.svelte";
import PoolOverview from "./lib/PoolOverview.svelte";
import HashrateChart from "./lib/HashrateChart.svelte";
import MinersTable from "./lib/MinersTable.svelte";
import BlocksTable from "./lib/BlocksTable.svelte";
import BestShares from "./lib/BestShares.svelte";
import UserDetailModal from "./lib/UserDetailModal.svelte";
import UserDetailPage from "./lib/UserDetailPage.svelte";
import BlockFoundAnimation from "./lib/BlockFoundAnimation.svelte";
onMount(() => {
@@ -26,6 +27,8 @@
<div class="stat-sub bad">{snap.error}</div>
{/if}
</div>
{:else if selection.user}
<UserDetailPage />
{:else}
<PoolOverview />
<HashrateChart />
@@ -35,7 +38,6 @@
{/if}
</main>
<UserDetailModal />
<BlockFoundAnimation />
<style>