From 8d2a030e2c841a569ddcdc22205bf37dfb0ec51a Mon Sep 17 00:00:00 2001 From: Zac Gaetano Date: Sat, 4 Apr 2026 22:46:16 -0400 Subject: [PATCH] Update frontend/src/App.jsx --- frontend/src/App.jsx | 135 ++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 128 insertions(+), 7 deletions(-) diff --git a/frontend/src/App.jsx b/frontend/src/App.jsx index 2827207..9a2c460 100644 --- a/frontend/src/App.jsx +++ b/frontend/src/App.jsx @@ -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 = () => {

Claude Persistent Agent

Scheduled task management & Claude Code runner

- {systemInfo && ( -
- - {systemInfo.task_count} tasks -
- )} +
+ + {systemInfo && ( +
+ + {systemInfo.task_count} tasks Β· {systemInfo.total_runs || 0} runs +
+ )} +
+ {activeView === 'dashboard' && ( +
+

System Dashboard

+
+ {systemInfo && ( + <> +
+
πŸ“‹
+
{systemInfo.task_count}
+
Total Tasks
+
+
+
βœ…
+
{systemInfo.completed_runs || 0}
+
Completed Runs
+
+
+
❌
+
{systemInfo.failed_runs || 0}
+
Failed Runs
+
+
+
⚑
+
{systemInfo.running_runs || 0}
+
Currently Running
+
+
+
πŸ”„
+
{systemInfo.total_runs || 0}
+
Total Runs Ever
+
+
+
{systemInfo.scheduler_running ? '🟒' : 'πŸ”΄'}
+
{systemInfo.scheduler_running ? 'Active' : 'Stopped'}
+
Scheduler
+
+ + )} +
+ +
+

Claude API Usage

+
+ {usageStats ? ( + <> +
+ Claude Runs (all time) + {usageStats.claude_runs_total ?? 'β€”'} +
+
+ Active Sessions + {usageStats.session_count ?? 'β€”'} +
+
+ First Run + {usageStats.first_run ? new Date(usageStats.first_run).toLocaleString() : 'β€”'} +
+
+ Last Run + {usageStats.last_run ? new Date(usageStats.last_run).toLocaleString() : 'β€”'} +
+
+ πŸ”„ Next Monthly Reset + {usageStats.next_reset ? new Date(usageStats.next_reset).toLocaleDateString() : 'β€”'} +
+
+ ⏳ Days Until Reset + {usageStats.days_until_reset ?? 'β€”'} +
+ {usageStats.note && ( +
{usageStats.note}
+ )} + + ) : ( +
Loading usage stats…
+ )} +
+
+ +
+

Task Breakdown

+
+ {tasks.length === 0 ? ( +

No tasks yet. Create one in the Tasks view.

+ ) : ( + tasks.map(t => ( +
+ {t.name} + {t.schedule_type} + {t.status} + {t.last_run ? new Date(t.last_run).toLocaleString() : 'never'} +
+ )) + )} +
+
+
+ )} + + {activeView === 'tasks' && (
);