diff --git a/src/components/landing/PortfolioSection.tsx b/src/components/landing/PortfolioSection.tsx index 54ea017e..b68410e1 100644 --- a/src/components/landing/PortfolioSection.tsx +++ b/src/components/landing/PortfolioSection.tsx @@ -167,6 +167,19 @@ function formatBrokerName(broker?: string | null) { return normalized || "broker"; } +function isBrokerAuthError(error: unknown) { + const message = String((error as { message?: string } | null)?.message || "").toLowerCase(); + if (!message) { + return false; + } + return ( + message.includes("401:") || + message.includes("session expired") || + message.includes("please reconnect") || + message.includes("broker session expired") + ); +} + function firstNumber(...values: unknown[]) { for (const value of values) { const parsed = Number(value); @@ -679,19 +692,34 @@ export default function PortfolioSection() { }, [positionsQuery.data]); useEffect(() => { - if ( - brokerStatus?.connected && - (holdingsQuery.isError || fundsQuery.isError || equityCurveQuery.isError || positionsQuery.isError) - ) { + if (!brokerStatus?.connected) { + return; + } + + const authIssue = + isBrokerAuthError(holdingsQuery.error) || + isBrokerAuthError(fundsQuery.error) || + isBrokerAuthError(positionsQuery.error) || + isBrokerAuthError(equityCurveQuery.error); + + if (authIssue) { setSessionExpired(true); } }, [ brokerStatus?.connected, - holdingsQuery.isError, - fundsQuery.isError, - equityCurveQuery.isError, - positionsQuery.isError, + holdingsQuery.error, + fundsQuery.error, + positionsQuery.error, + equityCurveQuery.error, ]); + + useEffect(() => { + const authState = (brokerStatus?.authState || "").trim().toUpperCase(); + if (!isConnected || !authState || authState === "VALID") { + setSessionExpired(false); + setReconnectAttempted(false); + } + }, [isConnected, brokerStatus?.authState]); useEffect(() => { if (!isConnected) { setSessionExpired(false);