2026-04-15 17:02:00 -07:00
|
|
|
"use client";
|
|
|
|
|
|
2026-05-02 03:32:05 +05:30
|
|
|
import { useQuery } from "@rocicorp/zero/react";
|
2026-04-15 17:02:00 -07:00
|
|
|
import { Progress } from "@/components/ui/progress";
|
|
|
|
|
import { useIsAnonymous } from "@/contexts/anonymous-mode";
|
2026-05-02 03:32:05 +05:30
|
|
|
import { queries } from "@/zero/queries";
|
2026-04-15 17:02:00 -07:00
|
|
|
|
2026-05-02 14:34:23 -07:00
|
|
|
/**
|
|
|
|
|
* Premium credit balance shown in the sidebar.
|
|
|
|
|
*
|
|
|
|
|
* Values come from Zero (live-replicated from Postgres) and are stored as
|
|
|
|
|
* integer micro-USD (1_000_000 == $1.00). We render in dollars because
|
|
|
|
|
* users top up at $1/pack and the credit gets debited at actual provider
|
|
|
|
|
* cost.
|
|
|
|
|
*/
|
2026-04-15 17:02:00 -07:00
|
|
|
export function PremiumTokenUsageDisplay() {
|
|
|
|
|
const isAnonymous = useIsAnonymous();
|
2026-05-02 03:32:05 +05:30
|
|
|
const [me] = useQuery(queries.user.me({}));
|
2026-04-15 17:02:00 -07:00
|
|
|
|
2026-05-02 03:32:05 +05:30
|
|
|
if (isAnonymous || !me) return null;
|
2026-04-15 17:02:00 -07:00
|
|
|
|
|
|
|
|
const usagePercentage = Math.min(
|
2026-05-02 14:34:23 -07:00
|
|
|
(me.premiumCreditMicrosUsed / Math.max(me.premiumCreditMicrosLimit, 1)) * 100,
|
2026-04-15 17:02:00 -07:00
|
|
|
100
|
|
|
|
|
);
|
|
|
|
|
|
2026-05-02 14:34:23 -07:00
|
|
|
const formatUsd = (micros: number) => {
|
|
|
|
|
const dollars = micros / 1_000_000;
|
|
|
|
|
if (dollars >= 100) return `$${dollars.toFixed(0)}`;
|
|
|
|
|
if (dollars >= 1) return `$${dollars.toFixed(2)}`;
|
|
|
|
|
// Sub-dollar balances need extra precision so the bar still tells the
|
|
|
|
|
// user what's left ("$0.04 of credit") instead of rounding to "$0".
|
|
|
|
|
if (dollars > 0) return `$${dollars.toFixed(3)}`;
|
|
|
|
|
return "$0";
|
2026-04-15 17:02:00 -07:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
return (
|
|
|
|
|
<div className="space-y-1.5">
|
|
|
|
|
<div className="flex justify-between items-center text-xs">
|
|
|
|
|
<span className="text-muted-foreground">
|
2026-05-02 14:34:23 -07:00
|
|
|
{formatUsd(me.premiumCreditMicrosUsed)} / {formatUsd(me.premiumCreditMicrosLimit)} of
|
|
|
|
|
credit
|
2026-04-15 17:02:00 -07:00
|
|
|
</span>
|
|
|
|
|
<span className="font-medium">{usagePercentage.toFixed(0)}%</span>
|
|
|
|
|
</div>
|
|
|
|
|
<Progress value={usagePercentage} className="h-1.5 [&>div]:bg-purple-500" />
|
|
|
|
|
</div>
|
|
|
|
|
);
|
|
|
|
|
}
|