feat: 구독 페이지 API 호출 사용량 표시 연동

- UsageApiData에 api_calls 타입 추가
- transformApiToFrontend에서 apiCallsUsed/apiCallsLimit 처리
- 기본 제한값 10,000으로 설정
This commit is contained in:
2025-12-30 22:27:09 +09:00
parent 5011bac596
commit c885844a3a
3 changed files with 39 additions and 7 deletions

View File

@@ -22,6 +22,9 @@ import type { SubscriptionInfo } from './types';
import { PLAN_LABELS } from './types';
import { requestDataExport, cancelSubscription } from './actions';
// ===== 기본 저장공간 (10GB) =====
const DEFAULT_STORAGE_LIMIT = 10 * 1024 * 1024 * 1024; // 10GB in bytes
// ===== 기본값 (API 실패시 사용) =====
const defaultSubscription: SubscriptionInfo = {
lastPaymentDate: '',
@@ -31,9 +34,11 @@ const defaultSubscription: SubscriptionInfo = {
userCount: 0,
userLimit: null,
storageUsed: 0,
storageLimit: 0,
storageLimit: DEFAULT_STORAGE_LIMIT,
storageUsedFormatted: '0 B',
storageLimitFormatted: '10 GB',
apiCallsUsed: 0,
apiCallsLimit: 0,
apiCallsLimit: 10000,
};
// ===== 날짜 포맷 함수 =====
@@ -202,8 +207,8 @@ export function SubscriptionManagement({ initialData }: SubscriptionManagementPr
<div className="flex-1">
<Progress value={storageProgress} className="h-2" />
</div>
<div className="text-sm text-blue-600 min-w-[100px] text-right">
{subscription.storageUsed} TB /{subscription.storageLimit} TB
<div className="text-sm text-blue-600 min-w-[120px] text-right">
{subscription.storageUsedFormatted} / {subscription.storageLimitFormatted}
</div>
</div>

View File

@@ -44,6 +44,11 @@ export interface UsageApiData {
used_formatted: string;
limit_formatted: string;
};
api_calls?: {
used: number;
limit: number;
percentage: number;
};
}
// ===== 플랜 코드 → 타입 변환 =====

View File

@@ -6,6 +6,24 @@ import type {
} from './types';
import { mapPlanCodeToType } from './types';
// ===== 기본 저장공간 제한 (10GB in bytes) =====
const DEFAULT_STORAGE_LIMIT = 10 * 1024 * 1024 * 1024; // 10GB
// ===== 바이트 → 읽기 쉬운 단위 변환 =====
export function formatBytes(bytes: number): string {
if (bytes === 0) return '0 B';
const units = ['B', 'KB', 'MB', 'GB', 'TB', 'PB'];
const k = 1024;
const i = Math.floor(Math.log(bytes) / Math.log(k));
const value = bytes / Math.pow(k, i);
// 소수점 처리: 정수면 소수점 없이, 아니면 최대 2자리
const formatted = value % 1 === 0 ? value.toString() : value.toFixed(2).replace(/\.?0+$/, '');
return `${formatted} ${units[i]}`;
}
// ===== API → Frontend 변환 =====
export function transformApiToFrontend(
subscriptionData: SubscriptionApiData | null,
@@ -50,9 +68,13 @@ export function transformApiToFrontend(
userCount: usageData?.users?.used ?? 0,
userLimit: usageData?.users?.limit === 0 ? null : (usageData?.users?.limit ?? null),
storageUsed: usageData?.storage?.used ?? 0,
storageLimit: usageData?.storage?.limit ?? 0,
storageUsedFormatted: usageData?.storage?.used_formatted ?? '0 GB',
storageLimitFormatted: usageData?.storage?.limit_formatted ?? '0 GB',
storageLimit: usageData?.storage?.limit || DEFAULT_STORAGE_LIMIT,
storageUsedFormatted: usageData?.storage?.used_formatted || formatBytes(usageData?.storage?.used ?? 0),
storageLimitFormatted: usageData?.storage?.limit_formatted || formatBytes(usageData?.storage?.limit || DEFAULT_STORAGE_LIMIT),
// API 호출 사용량 (일간)
apiCallsUsed: usageData?.api_calls?.used ?? 0,
apiCallsLimit: usageData?.api_calls?.limit ?? 10000,
};
}