diff --git a/assets/pr1213-before-after.svg b/assets/pr1213-before-after.svg new file mode 100644 index 00000000..18eff809 --- /dev/null +++ b/assets/pr1213-before-after.svg @@ -0,0 +1,126 @@ + + + + + BEFORE — no filter indicator + + + Rank Miner + + + #01 + miner-alpha + + Eligible + + #02 + miner-beta + + Eligible + + #16 + miner-delta + + Ineligible + + #19 + miner-epsilon + + Ineligible + + #23 + miner-kappa + + Eligible + + + Gaps (16, 19, 23) with no UI explanation → confusing + + + AFTER — shows "·N in view" indicator + + + Rank Miner + + + #01 + miner-alpha + + Eligible + + #02 + miner-beta + + Eligible + + #23 + miner-kappa + ·4 in view + + Eligible + + + #48 + miner-theta + ·4 in view + + Eligible + + + #94 + miner-omega + ·5 in view + + Eligible + + + + Rank #48 → ·4 in view (4th visible after filtering) + + + Card view & List view + + + + miner-theta + ● Eligible + + #48 + ·4 in view + + + Earnings + $1,234 + /day + + + Credibility + + 85% + + + + + + + + #48 + ·4 + miner-theta + $1,234 + + + + + #94 + ·5 + miner-omega + $2,468 + + + List view: Rank icon → "·N" indicator right after rank number + Card view: "·N in view" appears after the rank pill in the header + + + Only shown when a search or eligibility filter is active AND viewRank differs from global rank + diff --git a/src/components/leaderboard/MinerCard.tsx b/src/components/leaderboard/MinerCard.tsx index 88711cb2..82a31b16 100644 --- a/src/components/leaderboard/MinerCard.tsx +++ b/src/components/leaderboard/MinerCard.tsx @@ -286,6 +286,22 @@ export const MinerCard: React.FC = ({ > {formatRank(rank)} + {miner.viewRank != null && miner.viewRank !== miner.rank && ( + ({ + fontFamily: FONTS.mono, + fontSize: '0.58rem', + fontWeight: 500, + color: theme.palette.text.tertiary, + lineHeight: 1, + flexShrink: 0, + ml: 0.75, + })} + > + ·{miner.viewRank} in view + + )} )} diff --git a/src/components/leaderboard/MinersList.tsx b/src/components/leaderboard/MinersList.tsx index 75e85585..1f78fd33 100644 --- a/src/components/leaderboard/MinersList.tsx +++ b/src/components/leaderboard/MinersList.tsx @@ -120,7 +120,24 @@ export const MinersList: React.FC = ({ header: 'Rank', width: '60px', cellSx: { pr: 0 }, - renderCell: (miner) => , + renderCell: (miner) => ( + + + {miner.viewRank != null && miner.viewRank !== miner.rank && ( + + ·{miner.viewRank} + + )} + + ), }, { key: 'miner', diff --git a/src/components/leaderboard/TopMinersTable.tsx b/src/components/leaderboard/TopMinersTable.tsx index dacf92ce..a04c3e74 100644 --- a/src/components/leaderboard/TopMinersTable.tsx +++ b/src/components/leaderboard/TopMinersTable.tsx @@ -366,6 +366,17 @@ const TopMinersTable: React.FC = ({ return passesSingleProgramEligibility(m, eligibleOssFilter); }); + const hasActiveFilter = + searchQuery !== '' || + eligibleOssFilter !== 'all' || + eligibleDiscoveryFilter !== 'all'; + if (hasActiveFilter) { + result = result.map((miner, index) => ({ + ...miner, + viewRank: index + 1, + })); + } + return result; }, [ rankedMiners, diff --git a/src/components/leaderboard/types.ts b/src/components/leaderboard/types.ts index 1980534c..58687bec 100644 --- a/src/components/leaderboard/types.ts +++ b/src/components/leaderboard/types.ts @@ -17,6 +17,10 @@ export interface MinerStats { linesDeleted: number; hotkey: string; rank?: number; + /** Position in the current filtered subset (1-indexed). Only populated + * when a search or eligibility filter is active, so the UI layer can + * show a "· N in view" indicator beside the global rank. */ + viewRank?: number; uniqueReposCount?: number; credibility?: number; isEligible?: boolean;