Skip to content

Commit 045eb95

Browse files
committed
fix remaining credits display
1 parent 10089ba commit 045eb95

1 file changed

Lines changed: 26 additions & 21 deletions

File tree

  • apps/sim/app/workspace/[workspaceId]/home/components/credits-chip

apps/sim/app/workspace/[workspaceId]/home/components/credits-chip/credits-chip.tsx

Lines changed: 26 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -58,30 +58,35 @@ function CreditsChipInner() {
5858
)
5959

6060
/**
61-
* A per-member org credit cap is the authoritative personal remaining for this
62-
* member — show it even when the plan-based chip would otherwise be hidden (e.g.
63-
* external members). Values are dollars (the chip formats via `formatCredits`),
64-
* clamped at 0 so an over-cap member never sees a negative.
61+
* Pooled/plan remaining (dollars): unused plan allowance plus any purchased
62+
* credit balance. Null when the plan-based chip wouldn't show on its own (data
63+
* not ready, or the plan isn't credit-metered). `ON_DEMAND_UNLIMITED` means
64+
* effectively unbounded — rendered as ∞ — so short-circuit instead of
65+
* subtracting usage from the sentinel.
6566
*/
66-
const limitDollars = memberCredits?.limitDollars ?? null
67-
if (limitDollars !== null) {
68-
return renderChip(Math.max(0, limitDollars - (memberCredits?.usedDollars ?? 0)))
69-
}
70-
71-
if (isLoading || !hasData || !data?.data) return null
72-
if (!planView.showCredits) return null
73-
74-
const { usageLimit, currentUsage, creditBalance } = data.data
67+
const pooledData = !isLoading && hasData && planView.showCredits ? (data?.data ?? null) : null
68+
const pooledRemaining =
69+
pooledData === null
70+
? null
71+
: pooledData.usageLimit >= ON_DEMAND_UNLIMITED
72+
? ON_DEMAND_UNLIMITED
73+
: Math.max(0, pooledData.usageLimit + pooledData.creditBalance - pooledData.currentUsage)
7574

7675
/**
77-
* Credits remaining = unused plan allowance plus any purchased credit balance.
78-
* Uncapped plans (limit at/above the on-demand threshold) render as ∞ via
79-
* `formatCredits`, so short-circuit instead of subtracting usage from it.
76+
* A per-member cap is the authoritative personal remaining, but the actor gate
77+
* blocks on the pooled cap first — so show the tighter of the two, or a member
78+
* could see credits left while every action 402s on org/plan usage. Clamp at 0.
79+
* Fall back to personal alone when pooled isn't available/shown, so a capped
80+
* member still sees a balance even where the plan chip would be hidden.
8081
*/
81-
const remainingCredits =
82-
usageLimit >= ON_DEMAND_UNLIMITED
83-
? ON_DEMAND_UNLIMITED
84-
: Math.max(0, usageLimit + creditBalance - currentUsage)
82+
const limitDollars = memberCredits?.limitDollars ?? null
83+
if (limitDollars !== null) {
84+
const personalRemaining = Math.max(0, limitDollars - (memberCredits?.usedDollars ?? 0))
85+
return renderChip(
86+
pooledRemaining === null ? personalRemaining : Math.min(personalRemaining, pooledRemaining)
87+
)
88+
}
8589

86-
return renderChip(remainingCredits)
90+
if (pooledRemaining === null) return null
91+
return renderChip(pooledRemaining)
8792
}

0 commit comments

Comments
 (0)