Update frontend/src/App.jsx

This commit is contained in:
Zac Gaetano 2026-04-04 22:46:16 -04:00
parent 6db713e0c4
commit 8d2a030e2c

View file

@ -14,16 +14,20 @@ const App = () => {
enabled: true
});
const [systemInfo, setSystemInfo] = useState(null);
const [usageStats, setUsageStats] = useState(null);
const [loading, setLoading] = useState(false);
const [activeView, setActiveView] = useState('tasks'); // 'tasks' | 'dashboard'
// Fetch tasks on component mount
useEffect(() => {
fetchTasks();
fetchSystemInfo();
fetchUsageStats();
const interval = setInterval(() => {
fetchTasks();
fetchSystemInfo();
}, 5000); // Refresh every 5 seconds
fetchUsageStats();
}, 10000);
return () => clearInterval(interval);
}, []);
@ -47,6 +51,16 @@ const App = () => {
}
};
const fetchUsageStats = async () => {
try {
const response = await fetch('/api/system/usage');
const data = await response.json();
setUsageStats(data);
} catch (error) {
console.error('Error fetching usage stats:', error);
}
};
const handleCreateTask = async (e) => {
e.preventDefault();
setLoading(true);
@ -118,15 +132,121 @@ const App = () => {
<h1>Claude Persistent Agent</h1>
<p>Scheduled task management & Claude Code runner</p>
</div>
{systemInfo && (
<div className="system-status">
<span className={`status-indicator ${systemInfo.scheduler_running ? 'running' : 'stopped'}`}></span>
<span>{systemInfo.task_count} tasks</span>
</div>
)}
<div className="header-right">
<nav className="header-nav">
<button className={`nav-btn ${activeView === 'tasks' ? 'active' : ''}`} onClick={() => setActiveView('tasks')}>Tasks</button>
<button className={`nav-btn ${activeView === 'dashboard' ? 'active' : ''}`} onClick={() => setActiveView('dashboard')}>Dashboard</button>
</nav>
{systemInfo && (
<div className="system-status">
<span className={`status-indicator ${systemInfo.scheduler_running ? 'running' : 'stopped'}`}></span>
<span>{systemInfo.task_count} tasks · {systemInfo.total_runs || 0} runs</span>
</div>
)}
</div>
</header>
<main className="app-main">
{activeView === 'dashboard' && (
<div className="dashboard-view">
<h2 className="dashboard-title">System Dashboard</h2>
<div className="dashboard-grid">
{systemInfo && (
<>
<div className="dash-card">
<div className="dash-card-icon">📋</div>
<div className="dash-card-value">{systemInfo.task_count}</div>
<div className="dash-card-label">Total Tasks</div>
</div>
<div className="dash-card">
<div className="dash-card-icon"></div>
<div className="dash-card-value">{systemInfo.completed_runs || 0}</div>
<div className="dash-card-label">Completed Runs</div>
</div>
<div className="dash-card">
<div className="dash-card-icon"></div>
<div className="dash-card-value">{systemInfo.failed_runs || 0}</div>
<div className="dash-card-label">Failed Runs</div>
</div>
<div className="dash-card">
<div className="dash-card-icon"></div>
<div className="dash-card-value">{systemInfo.running_runs || 0}</div>
<div className="dash-card-label">Currently Running</div>
</div>
<div className="dash-card">
<div className="dash-card-icon">🔄</div>
<div className="dash-card-value">{systemInfo.total_runs || 0}</div>
<div className="dash-card-label">Total Runs Ever</div>
</div>
<div className="dash-card">
<div className="dash-card-icon">{systemInfo.scheduler_running ? '🟢' : '🔴'}</div>
<div className="dash-card-value">{systemInfo.scheduler_running ? 'Active' : 'Stopped'}</div>
<div className="dash-card-label">Scheduler</div>
</div>
</>
)}
</div>
<div className="dashboard-section">
<h3>Claude API Usage</h3>
<div className="usage-grid">
{usageStats ? (
<>
<div className="usage-row">
<span className="usage-label">Claude Runs (all time)</span>
<span className="usage-value">{usageStats.claude_runs_total ?? '—'}</span>
</div>
<div className="usage-row">
<span className="usage-label">Active Sessions</span>
<span className="usage-value">{usageStats.session_count ?? '—'}</span>
</div>
<div className="usage-row">
<span className="usage-label">First Run</span>
<span className="usage-value">{usageStats.first_run ? new Date(usageStats.first_run).toLocaleString() : '—'}</span>
</div>
<div className="usage-row">
<span className="usage-label">Last Run</span>
<span className="usage-value">{usageStats.last_run ? new Date(usageStats.last_run).toLocaleString() : '—'}</span>
</div>
<div className="usage-row highlight">
<span className="usage-label">🔄 Next Monthly Reset</span>
<span className="usage-value">{usageStats.next_reset ? new Date(usageStats.next_reset).toLocaleDateString() : '—'}</span>
</div>
<div className="usage-row highlight">
<span className="usage-label"> Days Until Reset</span>
<span className="usage-value">{usageStats.days_until_reset ?? '—'}</span>
</div>
{usageStats.note && (
<div className="usage-note">{usageStats.note}</div>
)}
</>
) : (
<div className="usage-loading">Loading usage stats</div>
)}
</div>
</div>
<div className="dashboard-section">
<h3>Task Breakdown</h3>
<div className="task-breakdown">
{tasks.length === 0 ? (
<p className="empty-msg">No tasks yet. Create one in the Tasks view.</p>
) : (
tasks.map(t => (
<div key={t.id} className="breakdown-row">
<span className="breakdown-name">{t.name}</span>
<span className="breakdown-type">{t.schedule_type}</span>
<span className={`breakdown-status status-${t.status}`}>{t.status}</span>
<span className="breakdown-last">{t.last_run ? new Date(t.last_run).toLocaleString() : 'never'}</span>
</div>
))
)}
</div>
</div>
</div>
)}
{activeView === 'tasks' && (
<aside className="sidebar">
<button
className="btn btn-primary btn-create"
@ -341,6 +461,7 @@ const App = () => {
</div>
)}
</section>
)} {/* end activeView === 'tasks' */}
</main>
</div>
);