cards
This commit is contained in:
@@ -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; }
|
||||
|
||||
@@ -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.
|
||||
*
|
||||
|
||||
Reference in New Issue
Block a user