mirror of
https://github.com/router-for-me/Cli-Proxy-API-Management-Center.git
synced 2026-02-03 03:10:50 +08:00
93 lines
2.6 KiB
TypeScript
93 lines
2.6 KiB
TypeScript
/**
|
|
* Quota management page - coordinates the three quota sections.
|
|
*/
|
|
|
|
import { useCallback, useEffect, useState } from 'react';
|
|
import { useTranslation } from 'react-i18next';
|
|
import { useHeaderRefresh } from '@/hooks/useHeaderRefresh';
|
|
import { useAuthStore } from '@/stores';
|
|
import { authFilesApi, configFileApi } from '@/services/api';
|
|
import {
|
|
QuotaSection,
|
|
ANTIGRAVITY_CONFIG,
|
|
CODEX_CONFIG,
|
|
GEMINI_CLI_CONFIG
|
|
} from '@/components/quota';
|
|
import type { AuthFileItem } from '@/types';
|
|
import styles from './QuotaPage.module.scss';
|
|
|
|
export function QuotaPage() {
|
|
const { t } = useTranslation();
|
|
const connectionStatus = useAuthStore((state) => state.connectionStatus);
|
|
|
|
const [files, setFiles] = useState<AuthFileItem[]>([]);
|
|
const [loading, setLoading] = useState(true);
|
|
const [error, setError] = useState('');
|
|
|
|
const disableControls = connectionStatus !== 'connected';
|
|
|
|
const loadConfig = useCallback(async () => {
|
|
try {
|
|
await configFileApi.fetchConfigYaml();
|
|
} catch (err: unknown) {
|
|
const errorMessage = err instanceof Error ? err.message : t('notification.refresh_failed');
|
|
setError((prev) => prev || errorMessage);
|
|
}
|
|
}, [t]);
|
|
|
|
const loadFiles = useCallback(async () => {
|
|
setLoading(true);
|
|
setError('');
|
|
try {
|
|
const data = await authFilesApi.list();
|
|
setFiles(data?.files || []);
|
|
} catch (err: unknown) {
|
|
const errorMessage = err instanceof Error ? err.message : t('notification.refresh_failed');
|
|
setError(errorMessage);
|
|
} finally {
|
|
setLoading(false);
|
|
}
|
|
}, [t]);
|
|
|
|
const handleHeaderRefresh = useCallback(async () => {
|
|
await Promise.all([loadConfig(), loadFiles()]);
|
|
}, [loadConfig, loadFiles]);
|
|
|
|
useHeaderRefresh(handleHeaderRefresh);
|
|
|
|
useEffect(() => {
|
|
loadFiles();
|
|
loadConfig();
|
|
}, [loadFiles, loadConfig]);
|
|
|
|
return (
|
|
<div className={styles.container}>
|
|
<div className={styles.pageHeader}>
|
|
<h1 className={styles.pageTitle}>{t('quota_management.title')}</h1>
|
|
<p className={styles.description}>{t('quota_management.description')}</p>
|
|
</div>
|
|
|
|
{error && <div className={styles.errorBox}>{error}</div>}
|
|
|
|
<QuotaSection
|
|
config={ANTIGRAVITY_CONFIG}
|
|
files={files}
|
|
loading={loading}
|
|
disabled={disableControls}
|
|
/>
|
|
<QuotaSection
|
|
config={CODEX_CONFIG}
|
|
files={files}
|
|
loading={loading}
|
|
disabled={disableControls}
|
|
/>
|
|
<QuotaSection
|
|
config={GEMINI_CLI_CONFIG}
|
|
files={files}
|
|
loading={loading}
|
|
disabled={disableControls}
|
|
/>
|
|
</div>
|
|
);
|
|
}
|