feat: denser market cards — fill the empty space
All checks were successful
deploy / deploy (push) Successful in 1m7s

Each market panel gains a full-width depth-fill meter (depth vs target),
an expanded stat column (spread est, fee/reward/net APR alongside the
existing figures) and a micro-stat stack under the health dial (target,
fill %, ends-in, boost). Fills the previously empty card interior.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
Денис Зефиров 2026-07-12 00:25:58 +04:00
parent c05b185b99
commit 9dae780f30

View file

@ -6,9 +6,10 @@ import { Skeleton } from "@/components/ui/skeleton";
import { HealthRadial } from "@/components/HealthRadial";
import { SlippageCurve } from "@/components/SlippageCurve";
import { DepthHistory } from "@/components/DepthHistory";
import { DepthProgress } from "@/components/DepthProgress";
import { rewardsRemainingUsd } from "@/hooks/useCampaigns";
import { healthScore } from "@/lib/math";
import { fmtUsd, fmtNum } from "@/lib/format";
import { healthScore, feeApr, rewardApr, slippageFor } from "@/lib/math";
import { fmtUsd, fmtNum, fmtAprPct, fmtCountdown } from "@/lib/format";
import { cn } from "@/lib/utils";
import { CyberGrid } from "@/components/fx/CyberGrid";
@ -50,6 +51,12 @@ export default function Markets() {
tvlUsd: c.tvlUsd,
targetDepthUsd: c.targetDepthUsd,
});
const feeAprV = pair ? feeApr(pair.volume24h, pair.liquidityUsd) : 0;
const rewardAprV = rewardApr(c.rewardBudgetUsd, c.durationDays, c.tvlUsd);
const netApr = feeAprV + rewardAprV;
const spreadPct = depth > 0 ? slippageFor(1_000, depth) * 2 * 100 : 0;
const depthFill = c.targetDepthUsd > 0 ? depth / c.targetDepthUsd : 0;
const boostX = c.status === "boost" ? c.boostBps / 10_000 : 1;
return (
<section
key={c.meta.campaignId}
@ -87,6 +94,19 @@ export default function Markets() {
</Link>
</div>
{/* depth-fill meter, full width */}
<div className="border-b border-edge/60 px-5 py-3.5 md:px-7">
<div className="mb-2 flex items-center justify-between font-mono text-[9.5px] uppercase tracking-[0.16em]">
<span className="text-fog-dim">Depth fill // target {fmtUsd(c.targetDepthUsd)}</span>
<span>
<span className="text-snow">{fmtUsd(depth)}</span>
<span className="text-fog-dim"> · </span>
<span className="text-mint">{(depthFill * 100).toFixed(0)}%</span>
</span>
</div>
<DepthProgress progress={depthFill} />
</div>
<div className="grid gap-6 px-5 py-5 md:grid-cols-[1fr_1.25fr_auto] md:px-7">
{pair ? (
<div className="space-y-2 text-sm">
@ -105,10 +125,28 @@ export default function Markets() {
<span className="text-fog">24h volume</span>
<span className="num font-semibold">{fmtUsd(pair.volume24h)}</span>
</div>
<div className="leader">
<span className="text-fog">Spread est</span>
<span className="num font-semibold">{spreadPct.toFixed(2)}%</span>
</div>
<div className="leader">
<span className="text-fog">Total depth</span>
<span className="num font-semibold text-mint">{fmtUsd(depth)}</span>
</div>
<div className="my-1 h-px bg-edge/60" />
<div className="leader">
<span className="text-fog">Fee APR</span>
<span className="num font-semibold">{fmtAprPct(feeAprV)}</span>
</div>
<div className="leader">
<span className="text-fog">Reward APR</span>
<span className="num font-semibold text-lime">{fmtAprPct(rewardAprV)}</span>
</div>
<div className="leader">
<span className="text-fog">Net APR</span>
<span className="num font-semibold text-mint">{fmtAprPct(netApr)}</span>
</div>
<div className="my-1 h-px bg-edge/60" />
<div className="leader">
<span className="text-fog">Active LPs</span>
<span className="num font-semibold">{c.activeLPs}</span>
@ -133,12 +171,34 @@ export default function Markets() {
</div>
</div>
<div className="flex flex-row items-center gap-4 md:flex-col md:items-end md:justify-start md:border-l md:border-edge md:pl-6">
<HealthRadial score={score} />
<span className="fig md:text-right">
Fig. 03
<br className="hidden md:block" /> Health
</span>
<div className="flex flex-col gap-4 md:border-l md:border-edge md:pl-6">
<div className="flex flex-row items-center gap-4 md:flex-col md:items-end">
<HealthRadial score={score} />
<span className="fig md:text-right">
Fig. 03
<br className="hidden md:block" /> Health
</span>
</div>
<dl className="hidden space-y-2 border-t border-edge/60 pt-3 text-[11px] md:block md:min-w-[152px]">
<div className="leader">
<span className="text-fog-dim">Target</span>
<span className="num text-snow">{fmtUsd(c.targetDepthUsd)}</span>
</div>
<div className="leader">
<span className="text-fog-dim">Fill</span>
<span className="num text-mint">{(depthFill * 100).toFixed(0)}%</span>
</div>
<div className="leader">
<span className="text-fog-dim">Ends</span>
<span className="num text-snow">
{c.status === "ended" ? "Closed" : fmtCountdown(c.end)}
</span>
</div>
<div className="leader">
<span className="text-fog-dim">Boost</span>
<span className="num text-lime">{boostX.toFixed(1)}×</span>
</div>
</dl>
</div>
</div>
</section>