mirror of
https://github.com/tiennm99/ccs.git
synced 2026-08-20 00:23:14 +00:00
fix(cliproxy): prefer live entitlement tier in account badges
This commit is contained in:
@@ -59,6 +59,19 @@ function getCompactAudienceBadgeLabel(audience: 'business' | 'personal' | 'unkno
|
|||||||
return '?';
|
return '?';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function resolveEffectiveTier(
|
||||||
|
tier: AccountTier | undefined,
|
||||||
|
quota: UnifiedQuotaResult | undefined
|
||||||
|
): AccountTier | undefined {
|
||||||
|
if (quota && 'entitlement' in quota) {
|
||||||
|
const entitlementTier = quota.entitlement?.normalizedTier;
|
||||||
|
if (entitlementTier && entitlementTier !== 'unknown') {
|
||||||
|
return entitlementTier;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return tier;
|
||||||
|
}
|
||||||
|
|
||||||
export function AccountSurfaceCard({
|
export function AccountSurfaceCard({
|
||||||
mode,
|
mode,
|
||||||
provider,
|
provider,
|
||||||
@@ -85,13 +98,14 @@ export function AccountSurfaceCard({
|
|||||||
const identity = getAccountIdentityPresentation(accountId, email, tokenFile);
|
const identity = getAccountIdentityPresentation(accountId, email, tokenFile);
|
||||||
const title = displayEmail || identity.email || accountId;
|
const title = displayEmail || identity.email || accountId;
|
||||||
const normalizedProvider = provider.toLowerCase();
|
const normalizedProvider = provider.toLowerCase();
|
||||||
|
const effectiveTier = resolveEffectiveTier(tier, quota);
|
||||||
const showTierBadge =
|
const showTierBadge =
|
||||||
(normalizedProvider === 'agy' ||
|
(normalizedProvider === 'agy' ||
|
||||||
normalizedProvider === 'antigravity' ||
|
normalizedProvider === 'antigravity' ||
|
||||||
normalizedProvider === 'gemini') &&
|
normalizedProvider === 'gemini') &&
|
||||||
tier &&
|
effectiveTier &&
|
||||||
tier !== 'unknown' &&
|
effectiveTier !== 'unknown' &&
|
||||||
tier !== 'free';
|
effectiveTier !== 'free';
|
||||||
const isCompact = mode === 'compact';
|
const isCompact = mode === 'compact';
|
||||||
const defaultCompactMetaBadges = (
|
const defaultCompactMetaBadges = (
|
||||||
<>
|
<>
|
||||||
@@ -99,10 +113,10 @@ export function AccountSurfaceCard({
|
|||||||
<span
|
<span
|
||||||
className={cn(
|
className={cn(
|
||||||
'text-[8px] font-semibold px-1.5 py-0.5 rounded-md shrink-0',
|
'text-[8px] font-semibold px-1.5 py-0.5 rounded-md shrink-0',
|
||||||
getTierBadgeClass(tier)
|
getTierBadgeClass(effectiveTier)
|
||||||
)}
|
)}
|
||||||
>
|
>
|
||||||
{tier}
|
{effectiveTier}
|
||||||
</span>
|
</span>
|
||||||
)}
|
)}
|
||||||
{identity.audienceLabel && (
|
{identity.audienceLabel && (
|
||||||
@@ -145,12 +159,12 @@ export function AccountSurfaceCard({
|
|||||||
<span
|
<span
|
||||||
className={cn(
|
className={cn(
|
||||||
'absolute -bottom-0.5 -right-0.5 text-[7px] font-bold uppercase px-1 py-px rounded ring-1 ring-background',
|
'absolute -bottom-0.5 -right-0.5 text-[7px] font-bold uppercase px-1 py-px rounded ring-1 ring-background',
|
||||||
tier === 'ultra'
|
effectiveTier === 'ultra'
|
||||||
? 'bg-violet-500/20 text-violet-600 dark:bg-violet-500/30 dark:text-violet-300'
|
? 'bg-violet-500/20 text-violet-600 dark:bg-violet-500/30 dark:text-violet-300'
|
||||||
: 'bg-yellow-500/20 text-yellow-700 dark:bg-yellow-500/25 dark:text-yellow-400'
|
: 'bg-yellow-500/20 text-yellow-700 dark:bg-yellow-500/25 dark:text-yellow-400'
|
||||||
)}
|
)}
|
||||||
>
|
>
|
||||||
{tier === 'ultra' ? 'U' : 'P'}
|
{effectiveTier === 'ultra' ? 'U' : 'P'}
|
||||||
</span>
|
</span>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -0,0 +1,49 @@
|
|||||||
|
import { render, screen } from '@tests/setup/test-utils';
|
||||||
|
import { describe, expect, it } from 'vitest';
|
||||||
|
import { AccountSurfaceCard } from '@/components/account/shared/account-surface-card';
|
||||||
|
import type { GeminiCliQuotaResult } from '@/lib/api-client';
|
||||||
|
|
||||||
|
function createGeminiQuotaResult(
|
||||||
|
overrides: Partial<GeminiCliQuotaResult> = {}
|
||||||
|
): GeminiCliQuotaResult {
|
||||||
|
return {
|
||||||
|
success: true,
|
||||||
|
buckets: [],
|
||||||
|
projectId: 'project-123',
|
||||||
|
tierLabel: 'Pro',
|
||||||
|
tierId: 'g1-pro-tier',
|
||||||
|
creditBalance: 12,
|
||||||
|
entitlement: {
|
||||||
|
normalizedTier: 'pro',
|
||||||
|
rawTierId: 'g1-pro-tier',
|
||||||
|
rawTierLabel: 'Pro',
|
||||||
|
source: 'runtime_api',
|
||||||
|
confidence: 'high',
|
||||||
|
accessState: 'entitled',
|
||||||
|
capacityState: 'available',
|
||||||
|
lastVerifiedAt: Date.now(),
|
||||||
|
notes: null,
|
||||||
|
},
|
||||||
|
lastUpdated: Date.now(),
|
||||||
|
...overrides,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
describe('AccountSurfaceCard', () => {
|
||||||
|
it('prefers live quota entitlement tier over a stale account tier for Gemini badges', () => {
|
||||||
|
render(
|
||||||
|
<AccountSurfaceCard
|
||||||
|
mode="compact"
|
||||||
|
provider="gemini"
|
||||||
|
accountId="user@example.com"
|
||||||
|
email="user@example.com"
|
||||||
|
displayEmail="user@example.com"
|
||||||
|
tier="unknown"
|
||||||
|
quota={createGeminiQuotaResult()}
|
||||||
|
showQuota={false}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(screen.getByText('pro')).toBeInTheDocument();
|
||||||
|
});
|
||||||
|
});
|
||||||
Reference in New Issue
Block a user