supermemory/apps/web/hooks/use-token-usage.ts
MaheshtheDev 6448849f77 fix(web): stabilize home recents and improve org plan switcher (#967)
- Keep home Recently saved and suggestions in a stable two-column layout
- Show skeleton while recents load and empty state when none exist
- Cap org switcher dropdown height with scroll for long org lists
- Show plan tier badges on all orgs, sorted by plan rank
2026-05-18 19:36:44 +00:00

89 lines
2.3 KiB
TypeScript

import { getSubscriptionStatus, isAllowedFrom } from "@lib/queries"
import type { useCustomer } from "autumn-js/react"
import { calculateUsagePercent, getDaysRemaining } from "@/lib/billing-utils"
export type PlanType = "free" | "pro" | "scale" | "enterprise"
export const PLAN_DISPLAY_NAMES: Record<PlanType, string> = {
free: "Free",
pro: "Pro",
scale: "Scale",
enterprise: "Enterprise",
}
/** Higher rank sorts first in org lists (enterprise at top). */
export const PLAN_RANK: Record<PlanType, number> = {
free: 0,
pro: 1,
scale: 2,
enterprise: 3,
}
export function normalizePlanType(raw: unknown): PlanType {
if (typeof raw !== "string" || !raw.trim()) return "free"
const normalized = raw.toLowerCase().replace(/^api_/, "")
if (normalized === "enterprise") return "enterprise"
if (normalized === "scale") return "scale"
if (normalized === "pro") return "pro"
return "free"
}
const TOKEN_METER_IDS = [
"sm_tokens_text",
"sm_tokens_rich",
"sm_superrag_text",
"sm_superrag_rich",
] as const
export function useTokenUsage(autumn: ReturnType<typeof useCustomer>) {
const status = getSubscriptionStatus(autumn.data?.subscriptions)
let currentPlan: PlanType = "free"
if (isAllowedFrom(status, "api_enterprise")) {
currentPlan = "enterprise"
} else if (isAllowedFrom(status, "api_scale")) {
currentPlan = "scale"
} else if (isAllowedFrom(status, "api_pro")) {
currentPlan = "pro"
}
const hasPaidPlan = currentPlan !== "free"
const balances = autumn.data?.balances ?? {}
const tokensUsed = TOKEN_METER_IDS.reduce((sum, id) => {
const balance = balances[id]
return sum + (balance?.usage ?? 0)
}, 0)
const searchesBalance = balances.sm_search_queries
const searchesUsed = searchesBalance?.usage ?? 0
const usdBalance = balances.usd_credits
const usdIncluded = usdBalance?.granted ?? 0
const usdSpent = usdBalance?.usage ?? 0
const planUsagePct =
usdIncluded > 0 ? calculateUsagePercent(usdSpent, usdIncluded) : 0
const resetAt =
usdBalance?.nextResetAt ??
balances.sm_tokens_text?.nextResetAt ??
searchesBalance?.nextResetAt ??
undefined
const daysRemaining = getDaysRemaining(resetAt)
const isLoading = autumn.isLoading
return {
tokensUsed,
searchesUsed,
usdIncluded,
usdSpent,
planUsagePct,
currentPlan,
hasPaidPlan,
isLoading,
daysRemaining,
}
}