Skip to content

Commit 2a6f2e4

Browse files
committed
Improve Alpaca config checks and UI responsiveness
Refactored multiple components to consistently check for Alpaca API credentials using hasAlpacaCredentials, preventing unnecessary API calls and improving error handling when credentials are missing. Enhanced UI responsiveness and mobile layouts in PerformanceChart and StandaloneWatchlist, added manual refresh to RebalanceHistoryTable, and improved polling and state management for rebalance and trade updates. Also updated button styles and batch data fetching logic for better user experience.
1 parent 3209544 commit 2a6f2e4

34 files changed

+1354
-594
lines changed

src/components/Header.tsx

Lines changed: 38 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import { Link, useNavigate } from "react-router-dom";
2-
import { useState, useEffect } from "react";
2+
import { useState, useEffect, useMemo } from "react";
33
import { Button } from "@/components/ui/button";
44
import {
55
TrendingUp,
@@ -15,11 +15,11 @@ import {
1515
Menu,
1616
Loader2
1717
} from "lucide-react";
18-
import { useAuth, hasRequiredApiKeys, isSessionValid } from "@/lib/auth";
18+
import { useAuth, hasRequiredApiKeys, hasAlpacaCredentials, isSessionValid } from "@/lib/auth";
1919
import { RoleBadge, RoleGate } from "@/components/RoleBasedAccess";
2020
import { useRBAC } from "@/hooks/useRBAC";
2121
import { supabase } from "@/lib/supabase";
22-
import {
22+
import {
2323
ANALYSIS_STATUS,
2424
convertLegacyAnalysisStatus,
2525
isAnalysisActive,
@@ -41,7 +41,20 @@ export default function Header() {
4141
const [runningAnalyses, setRunningAnalyses] = useState(0);
4242
const [runningRebalances, setRunningRebalances] = useState(0);
4343

44-
const hasApiKeys = hasRequiredApiKeys(apiSettings);
44+
const hasAiConfig = hasRequiredApiKeys(apiSettings);
45+
const hasAlpacaConfig = hasAlpacaCredentials(apiSettings);
46+
const systemStatus = useMemo(() => {
47+
if (hasAiConfig && hasAlpacaConfig) {
48+
return { dotClass: 'bg-buy', message: 'All Agents Ready' };
49+
}
50+
if (hasAiConfig && !hasAlpacaConfig) {
51+
return { dotClass: 'bg-yellow-500', message: 'Alpaca Config Required' };
52+
}
53+
if (!hasAiConfig && hasAlpacaConfig) {
54+
return { dotClass: 'bg-yellow-500', message: 'AI Config Required' };
55+
}
56+
return { dotClass: 'bg-red-500', message: 'Require API Configurations' };
57+
}, [hasAiConfig, hasAlpacaConfig]);
4558
const primaryRole = getPrimaryRole();
4659

4760
// Check for running analyses and rebalances
@@ -59,7 +72,7 @@ export default function Header() {
5972
// Check running analyses - only fetch from last 24 hours
6073
const twentyFourHoursAgo = new Date();
6174
twentyFourHoursAgo.setHours(twentyFourHoursAgo.getHours() - 24);
62-
75+
6376
const { data: analysisData } = await supabase
6477
.from('analysis_history')
6578
.select('id, analysis_status, is_canceled')
@@ -68,14 +81,14 @@ export default function Header() {
6881

6982
if (analysisData) {
7083
const runningCount = analysisData.filter(item => {
71-
const currentStatus = typeof item.analysis_status === 'number'
84+
const currentStatus = typeof item.analysis_status === 'number'
7285
? convertLegacyAnalysisStatus(item.analysis_status)
7386
: item.analysis_status;
74-
87+
7588
if (item.is_canceled || currentStatus === ANALYSIS_STATUS.CANCELLED) {
7689
return false;
7790
}
78-
91+
7992
return isAnalysisActive(currentStatus);
8093
}).length;
8194
setRunningAnalyses(runningCount);
@@ -88,7 +101,7 @@ export default function Header() {
88101
.eq('user_id', user.id);
89102

90103
if (rebalanceData) {
91-
const runningCount = rebalanceData.filter(item =>
104+
const runningCount = rebalanceData.filter(item =>
92105
isRebalanceActive(item.status)
93106
).length;
94107
setRunningRebalances(runningCount);
@@ -157,24 +170,23 @@ export default function Header() {
157170
<DropdownMenu>
158171
<DropdownMenuTrigger asChild className="hidden md:flex">
159172
{isRoleLoading ? (
160-
<Button
161-
variant="ghost"
162-
size="sm"
173+
<Button
174+
variant="ghost"
175+
size="sm"
163176
className="max-w-[150px] sm:max-w-none"
164177
disabled
165178
>
166179
<Loader2 className="h-4 w-4 mr-2 animate-spin" />
167180
<span className="truncate">Loading...</span>
168181
</Button>
169182
) : (
170-
<Button
171-
variant="ghost"
172-
size="sm"
173-
className={`max-w-[150px] sm:max-w-none transition-all duration-200 ${
174-
primaryRole?.color
175-
? `border border-opacity-30 hover:bg-opacity-20`
176-
: 'border border-border hover:bg-accent'
177-
}`}
183+
<Button
184+
variant="ghost"
185+
size="sm"
186+
className={`max-w-[150px] sm:max-w-none transition-all duration-200 ${primaryRole?.color
187+
? `border border-opacity-30 hover:bg-opacity-20`
188+
: 'border border-border hover:bg-accent'
189+
}`}
178190
style={primaryRole?.color ? {
179191
borderColor: `${primaryRole.color}4D`, // 30% opacity
180192
backgroundColor: `${primaryRole.color}1A`, // 10% opacity
@@ -192,8 +204,8 @@ export default function Header() {
192204
}}
193205
>
194206
{primaryRole?.icon_url ? (
195-
<img
196-
src={primaryRole.icon_url}
207+
<img
208+
src={primaryRole.icon_url}
197209
alt={primaryRole.display_name}
198210
className="h-4 w-4 mr-2 object-contain"
199211
/>
@@ -333,9 +345,9 @@ export default function Header() {
333345
<div className="text-right hidden sm:block">
334346
<p className="text-sm font-medium text-foreground">System Status</p>
335347
<div className="flex items-center gap-2">
336-
<div className={`h-2 w-2 rounded-full ${hasApiKeys ? 'bg-buy' : 'bg-yellow-500'} animate-pulse`}></div>
348+
<div className={`h-2 w-2 rounded-full ${systemStatus.dotClass} animate-pulse`}></div>
337349
<span className="text-xs text-muted-foreground">
338-
{hasApiKeys ? 'All Agents Ready' : 'API Keys Required'}
350+
{systemStatus.message}
339351
</span>
340352
</div>
341353
</div>
@@ -364,7 +376,7 @@ export default function Header() {
364376
</div>
365377
</div>
366378
</header>
367-
379+
368380
{/* Running tasks banner */}
369381
{isAuthenticated && (runningAnalyses > 0 || runningRebalances > 0) && (
370382
<div className="bg-primary/10 border-b border-primary/20 backdrop-blur-sm">
@@ -392,4 +404,4 @@ export default function Header() {
392404
)}
393405
</div>
394406
);
395-
}
407+
}

0 commit comments

Comments
 (0)