42 lines
1.2 KiB
TypeScript
42 lines
1.2 KiB
TypeScript
'use client';
|
|
|
|
import {ChartCard} from '@/components/charts/ChartCard';
|
|
import {BarChartView} from '@/components/charts/BarChartView';
|
|
import {formatCompact} from '@/lib/format';
|
|
import type {RewardUsagePoint} from '@/lib/api/contracts';
|
|
import type {Resource} from '@/lib/api/useResource';
|
|
|
|
/**
|
|
* Claimed vs used, per reward.
|
|
*
|
|
* The gap between the two bars is the whole point: a reward claimed 700 times
|
|
* and redeemed 130 is an outstanding liability and a broken offer, not a
|
|
* success. Plotting the usage *rate* alone would hide the volume; plotting
|
|
* volume alone would hide the failure. So both bars, side by side.
|
|
*/
|
|
export function RewardUsageChart({
|
|
resource,
|
|
}: {
|
|
resource: Resource<RewardUsagePoint[]>;
|
|
}) {
|
|
return (
|
|
<ChartCard
|
|
title="Reward usage"
|
|
subtitle="Claimed vs actually redeemed — the gap is unspent liability"
|
|
resource={resource}
|
|
>
|
|
{(rows) => (
|
|
<BarChartView
|
|
data={rows}
|
|
xKey="name"
|
|
yFormat={formatCompact}
|
|
series={[
|
|
{key: 'claimed', label: 'Claimed'},
|
|
{key: 'used', label: 'Redeemed'},
|
|
]}
|
|
/>
|
|
)}
|
|
</ChartCard>
|
|
);
|
|
}
|