diff --git a/apps/web/src/app/logout/page.tsx b/apps/web/src/app/logout/page.tsx index 0e22c00f..43338fc9 100644 --- a/apps/web/src/app/logout/page.tsx +++ b/apps/web/src/app/logout/page.tsx @@ -1,6 +1,6 @@ 'use client' -import { redirect, RedirectType } from 'next/navigation' +// import { redirect, RedirectType } from 'next/navigation' import { useEffect } from 'react' import { useAuthenticatedAgentic } from '@/components/agentic-provider' @@ -12,7 +12,6 @@ export default function LogoutPage() { ;(async () => { if (ctx) { ctx.logout() - redirect('/', RedirectType.replace) } })() }, [ctx]) diff --git a/apps/web/src/components/agentic-provider.tsx b/apps/web/src/components/agentic-provider.tsx index 82a86bd8..96e7898a 100644 --- a/apps/web/src/components/agentic-provider.tsx +++ b/apps/web/src/components/agentic-provider.tsx @@ -11,7 +11,6 @@ import { useCallback, useContext, useEffect, - useRef, useState } from 'react' import { useLocalStorage } from 'react-use' @@ -20,6 +19,7 @@ import * as config from '@/lib/config' type AgenticContextType = { api: AgenticApiClient + isAuthenticated: boolean logout: () => void } @@ -29,90 +29,117 @@ export function AgenticProvider({ children }: { children: ReactNode }) { const [authSession, setAuthSession] = useLocalStorage( 'agentic-auth-session' ) + const logout = useCallback(() => { setAuthSession(null) }, [setAuthSession]) - const agenticContext = useRef({ + const onUpdateAuth = useCallback( + (updatedAuthSession?: AuthSession | null) => { + // console.log('onUpdateAuth', { + // authSession: structuredClone(authSession), + // updatedAuthSession: structuredClone(updatedAuthSession), + // isCurrentlyAuthenticated: agenticContext.isAuthenticated + // }) + + if ( + !!authSession !== !!updatedAuthSession || + authSession?.token !== updatedAuthSession?.token || + agenticContext.isAuthenticated !== !!updatedAuthSession + ) { + setAuthSession(updatedAuthSession) + } + }, + // eslint-disable-next-line react-hooks/exhaustive-deps + [authSession, setAuthSession] + ) + + const [agenticContext, setAgenticContext] = useState({ api: new AgenticApiClient({ apiBaseUrl: config.apiBaseUrl, - onUpdateAuth: (updatedAuthSession) => { - // console.log('onUpdateAuth', updatedAuthSession) - - if ( - !!authSession !== !!updatedAuthSession && - authSession?.token !== updatedAuthSession?.token - ) { - // console.log('setAuthSession', updatedAuthSession) - setAuthSession(updatedAuthSession) - } else { - // console.log('auth session not updated') - } - } + onUpdateAuth }), + isAuthenticated: !!authSession, logout }) useEffect(() => { // console.log('updating session from localStorage', authSession?.token) - if (agenticContext.current) { - if (authSession) { - agenticContext.current.api.authSession = authSession - } else { - agenticContext.current.api.authSession = undefined + if (authSession) { + // console.log('setting auth session to truthy', { + // authSession: structuredClone(authSession), + // isAuthenticated: agenticContext.isAuthenticated, + // setAgenticContext: !agenticContext.isAuthenticated + // }) + + agenticContext.api.authSession = authSession + if (!agenticContext.isAuthenticated) { + setAgenticContext({ + ...agenticContext, + isAuthenticated: true + }) + } + } else { + // console.log('setting auth session to falsy', { + // authSession: structuredClone(authSession), + // isAuthenticated: agenticContext.isAuthenticated, + // setAgenticContext: !!agenticContext.isAuthenticated + // }) + + agenticContext.api.authSession = undefined + + if (agenticContext.isAuthenticated) { + setAgenticContext({ + ...agenticContext, + isAuthenticated: false + }) } } }, [agenticContext, authSession]) return ( - + {children} ) } -export function useAgentic(): AgenticContextType { +export function useAgentic(): AgenticContextType | undefined { const ctx = useContext(AgenticContext) + const [isMounted, setIsMounted] = useState(false) + + useEffect(() => { + if (!isMounted) { + setIsMounted(true) + return + } + }, [isMounted, setIsMounted]) if (!ctx) { throw new Error('useAgentic must be used within an AgenticProvider') } - return ctx + return isMounted ? ctx : undefined } export function useUnauthenticatedAgentic(): AgenticContextType | undefined { const ctx = useAgentic() - const [isMounted, setIsMounted] = useState(false) - useEffect(() => { - if (!isMounted) { - setIsMounted(true) - return - } + if (ctx && ctx.isAuthenticated) { + // console.log('REQUIRES UNAUTHENTICATED: redirecting to /app') + redirect('/app', RedirectType.replace) + } - if (ctx.api.isAuthenticated) { - redirect('/app', RedirectType.replace) - } - }, [isMounted, setIsMounted, ctx]) - - return isMounted ? ctx : undefined + return ctx } export function useAuthenticatedAgentic(): AgenticContextType | undefined { const ctx = useAgentic() - const [isMounted, setIsMounted] = useState(false) - useEffect(() => { - if (!isMounted) { - setIsMounted(true) - return - } + if (ctx && !ctx.isAuthenticated) { + // console.log('REQUIRES AUTHENTICATED: redirecting to /login') + redirect('/login', RedirectType.replace) + } - if (!ctx.api.isAuthenticated) { - redirect('/login', RedirectType.replace) - } - }, [isMounted, setIsMounted, ctx]) - - return isMounted ? ctx : undefined + return ctx } diff --git a/apps/web/src/components/dark-mode-toggle.tsx b/apps/web/src/components/dark-mode-toggle.tsx index 7db1d21b..6d68c2c1 100644 --- a/apps/web/src/components/dark-mode-toggle.tsx +++ b/apps/web/src/components/dark-mode-toggle.tsx @@ -11,8 +11,9 @@ import { TooltipProvider, TooltipTrigger } from '@/components/ui/tooltip' +import { cn } from '@/lib/utils' -export function DarkModeToggle() { +export function DarkModeToggle({ className }: { className?: string }) { const { setTheme, resolvedTheme } = useTheme() return ( @@ -22,7 +23,7 @@ export function DarkModeToggle() {