import { useState } from 'react'; import { StatusCard } from './components/StatusCard'; import { MetricsChart } from './components/MetricsChart'; import { AddRepoModal } from './components/AddRepoModal'; import { usePolling } from './hooks/usePolling'; import type { Repo, RepoStatus, Metrics } from './types'; const API_BASE = '/api'; export function App() { const [selectedRepoId, setSelectedRepoId] = useState(null); const [selectedRange, setSelectedRange] = useState<'hour' | 'day' | 'week' | 'month'>('hour'); const [autoRefresh, setAutoRefresh] = useState(true); const [refreshInterval, setRefreshInterval] = useState(5000); const [showAddModal, setShowAddModal] = useState(false); const { data: repos, loading: reposLoading, refetch: refetchRepos } = usePolling( () => fetch(`${API_BASE}/repos`).then(r => r.json()), refreshInterval, autoRefresh ); const { data: statusData, loading: statusLoading } = usePolling( () => selectedRepoId ? fetch(`${API_BASE}/status?repoId=${selectedRepoId}`).then(r => r.json()) : Promise.resolve(null), refreshInterval, autoRefresh && !!selectedRepoId ); const { data: metricsData, loading: metricsLoading } = usePolling( () => selectedRepoId ? fetch(`${API_BASE}/metrics?repoId=${selectedRepoId}&range=${selectedRange}`).then(r => r.json()) : Promise.resolve(null), refreshInterval, autoRefresh && !!selectedRepoId ); const handleAddRepo = async (namespace: string, repo: string) => { await fetch(`${API_BASE}/repos`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ namespace, repo }), }); refetchRepos(); }; const handleDeleteRepo = async (repoId: string) => { await fetch(`${API_BASE}/repos/${repoId}`, { method: 'DELETE' }); if (selectedRepoId === repoId) setSelectedRepoId(null); refetchRepos(); }; const selectedRepo = repos?.find(r => r.id === selectedRepoId); return (

SpaceProbe

Repositories

{reposLoading ? (
{[1, 2, 3].map(i => (
))}
) : repos?.length === 0 ? (

No repositories added

) : (
{repos?.map(repo => (
setSelectedRepoId(repo.id)} className={`p-3 rounded-lg cursor-pointer transition ${ selectedRepoId === repo.id ? 'bg-blue-600/20 border border-blue-500' : 'bg-gray-700 hover:bg-gray-600' }`} >
{repo.namespace}/{repo.repo}
))}
)}

Settings

Interval (ms)
{!selectedRepoId ? (
Select a repository to view metrics
) : ( <>
{(['hour', 'day', 'week', 'month'] as const).map(range => ( ))}
)}
setShowAddModal(false)} onSubmit={handleAddRepo} />
); }