This commit is contained in:
2026-09-03 16:22:48 +05:30
parent bbe313ba48
commit a8fc4bee69
2 changed files with 67 additions and 26 deletions

View File

@@ -170,7 +170,7 @@
.chart-legend i[data-kind="online"] { background: var(--color-brand); }
.chart-legend i[data-kind="counter"] { background: color-mix(in srgb, var(--color-brand) 32%, white); }
.donut-wrap { display: flex; flex-direction: column; align-items: center; gap: 16px; justify-content: center; }
.donut-wrap { display: flex; align-items: center; justify-content: center; }
.donut { position: relative; width: 160px; height: 160px; }
.donut svg { width: 100%; height: 100%; }
.donut-track { fill: none; stroke: var(--color-surface-subtle); stroke-width: 18; }
@@ -179,15 +179,38 @@
.donut-centre span { font: 400 11px/1 var(--font-sans); color: var(--color-ink-3); }
.donut-centre strong { font: 600 18px/1.2 var(--font-sans); color: var(--color-ink-1); font-variant-numeric: tabular-nums; }
.donut-legend { display: flex; flex-direction: column; gap: 12px; width: 100%; }
.donut-legend > div { display: flex; gap: 10px; align-items: flex-start; }
.donut-legend > div > div { display: flex; flex-direction: column; gap: 1px; }
.donut-key { width: 10px; height: 10px; border-radius: 999px; margin-top: 4px; flex: none; }
.donut-key { width: 10px; height: 10px; border-radius: 999px; flex: none; }
.donut-key[data-kind="online"] { background: var(--color-brand); }
.donut-key[data-kind="counter"] { background: color-mix(in srgb, var(--color-brand) 32%, white); }
.donut-label { font: 400 12.5px/1.2 var(--font-sans); color: var(--color-ink-3); }
.donut-pct { font: 600 16px/1.2 var(--font-sans); color: var(--color-ink-1); }
.donut-amt { font: 500 12.5px/1.2 var(--font-sans); color: var(--color-brand); font-variant-numeric: tabular-nums; }
/* The channel split, on one line beneath the card. Two columns so the pair
sits square against each other; stacked only when there is genuinely no room
for both. */
.split-row {
display: grid;
grid-template-columns: repeat(2, minmax(0, 1fr));
gap: 10px;
padding-top: 14px;
border-top: 1px solid var(--color-line);
}
@media (max-width: 520px) { .split-row { grid-template-columns: minmax(0, 1fr); } }
.share {
display: flex; align-items: baseline; gap: 10px; flex-wrap: wrap;
padding: 10px 14px;
border: 1px solid var(--color-line); border-radius: 12px;
background: var(--color-surface-subtle);
}
.share .donut-key { align-self: center; }
.share-label { font: 400 12.5px/1 var(--font-sans); color: var(--color-ink-3); }
/* The percentage leads: the question the split answers is "how much of my
trade comes through each", and the rupee figure is already in the KPI card
above. */
.share-pct { font: 600 18px/1 var(--font-sans); color: var(--color-ink-1); margin-left: auto; }
.share-amt {
font: 500 13px/1 var(--font-sans); color: var(--color-brand);
font-variant-numeric: tabular-nums;
}
/* ── Store health ───────────────────────────────────────────────────────── */
.health-list { display: flex; flex-direction: column; }

View File

@@ -126,31 +126,49 @@ export function SalesOverview({ days, isLoading }: SalesOverviewProps) {
<div className="donut-wrap">
<Donut share={onlineShare} total={format(total)} />
<div className="donut-legend">
<div>
<span className="donut-key" data-kind="online" />
<div>
<span className="donut-label">Online Sales</span>
<strong className="donut-pct">{onlineShare}%</strong>
<span className="donut-amt">{format(online)}</span>
</div>
</div>
<div>
<span className="donut-key" data-kind="counter" />
<div>
<span className="donut-label">Counter Sales</span>
<strong className="donut-pct">{100 - onlineShare}%</strong>
<span className="donut-amt">{format(counter)}</span>
</div>
</div>
</div>
</div>
</div>
)}
{/* The channel split, on one line under the whole card.
It was a stacked column beside the ring, which put the two figures a
shopkeeper compares — online against counter — one above the other in
a narrow gutter. Side by side they can be read against each other at a
glance, and the row runs the full width rather than being squeezed
into whatever the ring left over. */}
{total > 0 ? (
<div className="split-row">
<Share
kind="online"
label="Online Sales"
percent={onlineShare}
amount={format(online)}
/>
<Share
kind="counter"
label="Counter Sales"
percent={100 - onlineShare}
amount={format(counter)}
/>
</div>
) : null}
</section>
);
}
function Share({
kind, label, percent, amount,
}: { kind: 'online' | 'counter'; label: string; percent: number; amount: string }) {
return (
<div className="share">
<span className="donut-key" data-kind={kind} />
<span className="share-label">{label}</span>
<strong className="share-pct">{percent}%</strong>
<span className="share-amt">{amount}</span>
</div>
);
}
/**
* The channel split as a ring.
*