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 enabled: true
}); });
const [systemInfo, setSystemInfo] = useState(null); const [systemInfo, setSystemInfo] = useState(null);
const [usageStats, setUsageStats] = useState(null);
const [loading, setLoading] = useState(false); const [loading, setLoading] = useState(false);
const [activeView, setActiveView] = useState('tasks'); // 'tasks' | 'dashboard'
// Fetch tasks on component mount // Fetch tasks on component mount
useEffect(() => { useEffect(() => {
fetchTasks(); fetchTasks();
fetchSystemInfo(); fetchSystemInfo();
fetchUsageStats();
const interval = setInterval(() => { const interval = setInterval(() => {
fetchTasks(); fetchTasks();
fetchSystemInfo(); fetchSystemInfo();
}, 5000); // Refresh every 5 seconds fetchUsageStats();
}, 10000);
return () => clearInterval(interval); 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) => { const handleCreateTask = async (e) => {
e.preventDefault(); e.preventDefault();
setLoading(true); setLoading(true);
@ -118,15 +132,121 @@ const App = () => {
<h1>Claude Persistent Agent</h1> <h1>Claude Persistent Agent</h1>
<p>Scheduled task management & Claude Code runner</p> <p>Scheduled task management & Claude Code runner</p>
</div> </div>
{systemInfo && ( <div className="header-right">
<div className="system-status"> <nav className="header-nav">
<span className={`status-indicator ${systemInfo.scheduler_running ? 'running' : 'stopped'}`}></span> <button className={`nav-btn ${activeView === 'tasks' ? 'active' : ''}`} onClick={() => setActiveView('tasks')}>Tasks</button>
<span>{systemInfo.task_count} tasks</span> <button className={`nav-btn ${activeView === 'dashboard' ? 'active' : ''}`} onClick={() => setActiveView('dashboard')}>Dashboard</button>
</div> </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> </header>
<main className="app-main"> <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"> <aside className="sidebar">
<button <button
className="btn btn-primary btn-create" className="btn btn-primary btn-create"
@ -341,6 +461,7 @@ const App = () => {
</div> </div>
)} )}
</section> </section>
)} {/* end activeView === 'tasks' */}
</main> </main>
</div> </div>
); );