Update frontend/src/App.jsx
This commit is contained in:
parent
a4094f13cf
commit
11e72ebeec
1 changed files with 81 additions and 0 deletions
|
|
@ -15,6 +15,7 @@ const App = () => {
|
|||
});
|
||||
const [systemInfo, setSystemInfo] = useState(null);
|
||||
const [usageStats, setUsageStats] = useState(null);
|
||||
const [authStatus, setAuthStatus] = useState(null);
|
||||
const [loading, setLoading] = useState(false);
|
||||
const [activeView, setActiveView] = useState('tasks'); // 'tasks' | 'dashboard'
|
||||
|
||||
|
|
@ -23,10 +24,12 @@ const App = () => {
|
|||
fetchTasks();
|
||||
fetchSystemInfo();
|
||||
fetchUsageStats();
|
||||
fetchAuthStatus();
|
||||
const interval = setInterval(() => {
|
||||
fetchTasks();
|
||||
fetchSystemInfo();
|
||||
fetchUsageStats();
|
||||
fetchAuthStatus();
|
||||
}, 10000);
|
||||
return () => clearInterval(interval);
|
||||
}, []);
|
||||
|
|
@ -61,6 +64,38 @@ const App = () => {
|
|||
}
|
||||
};
|
||||
|
||||
const fetchAuthStatus = async () => {
|
||||
try {
|
||||
const response = await fetch('/api/auth/status');
|
||||
const data = await response.json();
|
||||
setAuthStatus(data);
|
||||
} catch (error) {
|
||||
console.error('Error fetching auth status:', error);
|
||||
}
|
||||
};
|
||||
|
||||
const handleLogin = async () => {
|
||||
try {
|
||||
const response = await fetch('/api/auth/login', { method: 'POST' });
|
||||
const data = await response.json();
|
||||
setAuthStatus(prev => ({ ...prev, ...data }));
|
||||
if (data.auth_url) {
|
||||
window.open(data.auth_url, '_blank');
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Error initiating login:', error);
|
||||
}
|
||||
};
|
||||
|
||||
const handleLogout = async () => {
|
||||
try {
|
||||
await fetch('/api/auth/logout', { method: 'POST' });
|
||||
fetchAuthStatus();
|
||||
} catch (error) {
|
||||
console.error('Error logging out:', error);
|
||||
}
|
||||
};
|
||||
|
||||
const handleCreateTask = async (e) => {
|
||||
e.preventDefault();
|
||||
setLoading(true);
|
||||
|
|
@ -137,6 +172,15 @@ const App = () => {
|
|||
<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>
|
||||
<div className="auth-badge">
|
||||
{authStatus?.status === 'logged_in' ? (
|
||||
<span className="auth-ok" title={authStatus.account}>● {authStatus.account || 'Logged in'}</span>
|
||||
) : authStatus?.status === 'pending' ? (
|
||||
<span className="auth-pending">⏳ Awaiting login…</span>
|
||||
) : (
|
||||
<button className="auth-login-btn" onClick={handleLogin}>🔐 Login with Claude Max</button>
|
||||
)}
|
||||
</div>
|
||||
{systemInfo && (
|
||||
<div className="system-status">
|
||||
<span className={`status-indicator ${systemInfo.scheduler_running ? 'running' : 'stopped'}`}></span>
|
||||
|
|
@ -187,6 +231,43 @@ const App = () => {
|
|||
)}
|
||||
</div>
|
||||
|
||||
<div className="dashboard-section">
|
||||
<h3>Claude Authentication</h3>
|
||||
<div className="auth-panel">
|
||||
{authStatus?.status === 'logged_in' ? (
|
||||
<div className="auth-connected">
|
||||
<span className="auth-icon">✅</span>
|
||||
<div>
|
||||
<div className="auth-title">Connected to Claude Max</div>
|
||||
<div className="auth-sub">{authStatus.account}</div>
|
||||
</div>
|
||||
<button className="btn btn-secondary btn-sm" onClick={handleLogout}>Log Out</button>
|
||||
</div>
|
||||
) : authStatus?.status === 'pending' ? (
|
||||
<div className="auth-pending-panel">
|
||||
<span className="auth-icon">⏳</span>
|
||||
<div>
|
||||
<div className="auth-title">Waiting for browser login…</div>
|
||||
{authStatus.auth_url && (
|
||||
<a className="auth-url-link" href={authStatus.auth_url} target="_blank" rel="noreferrer">
|
||||
Open login page →
|
||||
</a>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
) : (
|
||||
<div className="auth-disconnected">
|
||||
<span className="auth-icon">🔐</span>
|
||||
<div>
|
||||
<div className="auth-title">Not logged in</div>
|
||||
<div className="auth-sub">Log in with your Claude Max account to run tasks</div>
|
||||
</div>
|
||||
<button className="btn btn-primary btn-sm" onClick={handleLogin}>Login with Claude Max</button>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="dashboard-section">
|
||||
<h3>Claude API Usage</h3>
|
||||
<div className="usage-grid">
|
||||
|
|
|
|||
Reference in a new issue