import { useCallback, type ReactNode } from 'react'; import { useTranslation } from 'react-i18next'; import type { TFunction } from 'i18next'; import { ANTIGRAVITY_CONFIG, CODEX_CONFIG, GEMINI_CLI_CONFIG } from '@/components/quota'; import { useNotificationStore, useQuotaStore } from '@/stores'; import type { AuthFileItem } from '@/types'; import { getStatusFromError } from '@/utils/quota'; import { isRuntimeOnlyAuthFile, resolveQuotaErrorMessage, type QuotaProviderType } from '@/features/authFiles/constants'; import { QuotaProgressBar } from '@/features/authFiles/components/QuotaProgressBar'; import styles from '@/pages/AuthFilesPage.module.scss'; type QuotaState = { status?: string; error?: string; errorStatus?: number } | undefined; const getQuotaConfig = (type: QuotaProviderType) => { if (type === 'antigravity') return ANTIGRAVITY_CONFIG; if (type === 'codex') return CODEX_CONFIG; return GEMINI_CLI_CONFIG; }; export type AuthFileQuotaSectionProps = { file: AuthFileItem; quotaType: QuotaProviderType; disableControls: boolean; }; export function AuthFileQuotaSection(props: AuthFileQuotaSectionProps) { const { file, quotaType, disableControls } = props; const { t } = useTranslation(); const showNotification = useNotificationStore((state) => state.showNotification); const quota = useQuotaStore((state) => { if (quotaType === 'antigravity') return state.antigravityQuota[file.name] as QuotaState; if (quotaType === 'codex') return state.codexQuota[file.name] as QuotaState; return state.geminiCliQuota[file.name] as QuotaState; }); const updateQuotaState = useQuotaStore((state) => { if (quotaType === 'antigravity') return state.setAntigravityQuota as unknown as (updater: unknown) => void; if (quotaType === 'codex') return state.setCodexQuota as unknown as (updater: unknown) => void; return state.setGeminiCliQuota as unknown as (updater: unknown) => void; }); const refreshQuotaForFile = useCallback(async () => { if (disableControls) return; if (isRuntimeOnlyAuthFile(file)) return; if (file.disabled) return; if (quota?.status === 'loading') return; const config = getQuotaConfig(quotaType) as unknown as { i18nPrefix: string; fetchQuota: (file: AuthFileItem, t: TFunction) => Promise; buildLoadingState: () => unknown; buildSuccessState: (data: unknown) => unknown; buildErrorState: (message: string, status?: number) => unknown; renderQuotaItems: (quota: unknown, t: TFunction, helpers: unknown) => unknown; }; updateQuotaState((prev: Record) => ({ ...prev, [file.name]: config.buildLoadingState() })); try { const data = await config.fetchQuota(file, t); updateQuotaState((prev: Record) => ({ ...prev, [file.name]: config.buildSuccessState(data) })); showNotification(t('auth_files.quota_refresh_success', { name: file.name }), 'success'); } catch (err: unknown) { const message = err instanceof Error ? err.message : t('common.unknown_error'); const status = getStatusFromError(err); updateQuotaState((prev: Record) => ({ ...prev, [file.name]: config.buildErrorState(message, status) })); showNotification(t('auth_files.quota_refresh_failed', { name: file.name, message }), 'error'); } }, [disableControls, file, quota?.status, quotaType, showNotification, t, updateQuotaState]); const config = getQuotaConfig(quotaType) as unknown as { i18nPrefix: string; renderQuotaItems: (quota: unknown, t: TFunction, helpers: unknown) => unknown; }; const quotaStatus = quota?.status ?? 'idle'; const canRefreshQuota = !disableControls && !file.disabled; const quotaErrorMessage = resolveQuotaErrorMessage( t, quota?.errorStatus, quota?.error || t('common.unknown_error') ); return (
{quotaStatus === 'loading' ? (
{t(`${config.i18nPrefix}.loading`)}
) : quotaStatus === 'idle' ? ( ) : quotaStatus === 'error' ? (
{t(`${config.i18nPrefix}.load_failed`, { message: quotaErrorMessage })}
) : quota ? ( (config.renderQuotaItems(quota, t, { styles, QuotaProgressBar }) as ReactNode) ) : (
{t(`${config.i18nPrefix}.idle`)}
)}
); }