import { useEffect, useMemo, useState } from 'react'; import { Badge } from '../../components/ui'; import type { AppWithComponents, JobStatus } from '../../types/application'; import { listApps } from './application-api'; import { getStoredSelectedAppId, setStoredSelectedAppId } from '../../lib/selected-app'; import { formatDateTime } from '../../lib/date-format'; export function useApps() { const [apps, setApps] = useState([]); const [selectedAppId, setSelectedAppId] = useState(() => getStoredSelectedAppId()); const [loading, setLoading] = useState(false); const refreshApps = async () => { setLoading(true); try { const nextApps = await listApps(); setApps(nextApps); const storedAppId = getStoredSelectedAppId(); const validAppId = nextApps.some((app) => app.id === storedAppId) ? storedAppId : nextApps[0]?.id ?? ''; if (validAppId) { setSelectedAppId(validAppId); setStoredSelectedAppId(validAppId); } } finally { setLoading(false); } }; useEffect(() => { void refreshApps(); }, []); const selectedApp = useMemo( () => apps.find((app) => app.id === selectedAppId) ?? apps[0] ?? null, [apps, selectedAppId] ); const selectApp = (appId: string) => { setSelectedAppId(appId); setStoredSelectedAppId(appId); }; return { apps, selectedApp, selectedAppId: selectedApp?.id ?? '', loading, refreshApps, selectApp }; } export function AppSelector({ apps, value, onChange, loading }: { apps: AppWithComponents[]; value: string; onChange: (appId: string) => void; loading?: boolean; }) { return (

앱 선택

선택한 앱 기준으로 소스, 빌드, 릴리즈, 배포 데이터를 봅니다.

); } export function StatusBadge({ status }: { status: string }) { const normalized = status.toUpperCase(); const label = { SUCCEEDED: '성공', ACTIVE: '활성', READY: '준비', RUNNING: '실행 중', PENDING: '대기', FAILED: '실패', DISABLED: '비활성', CANCELED: '취소' }[normalized] ?? status; if (normalized === 'SUCCEEDED' || normalized === 'ACTIVE' || normalized === 'READY' || normalized === 'RUNNING' || status === '성공' || status === '활성' || status === '준비' || status === '실행 중') { return {label}; } if (normalized === 'PENDING' || status === '대기') return {label}; if (normalized === 'FAILED' || normalized === 'DISABLED' || normalized === 'CANCELED' || status === '실패' || status === '비활성' || status === '취소') return {label}; return {label}; } export function isBuildDone(status: JobStatus) { return !['PENDING', 'RUNNING'].includes(status); } export function formatDate(value?: string | null) { return formatDateTime(value); } export function EmptyState({ children }: { children: string }) { return
{children}
; }