diff --git a/src/components/AuthGuard.tsx b/src/components/AuthGuard.tsx new file mode 100644 index 0000000..427ec5d --- /dev/null +++ b/src/components/AuthGuard.tsx @@ -0,0 +1,80 @@ +import React, { useEffect, useState } from 'react'; +import { supabase } from '../lib/supabase'; +import type { User } from '@supabase/supabase-js'; +import { Loader2 } from 'lucide-react'; + +interface AuthGuardProps { + children: React.ReactNode; + requireAuth?: boolean; +} + +export function AuthGuard({ children, requireAuth = true }: AuthGuardProps) { + const [user, setUser] = useState(null); + const [loading, setLoading] = useState(true); + + useEffect(() => { + // Get initial session + supabase.auth.getSession().then(({ data: { session } }) => { + setUser(session?.user ?? null); + setLoading(false); + + // Redirect logic + if (requireAuth && !session?.user) { + // User needs to be authenticated but isn't - redirect to login + window.location.href = '/login'; + } else if (!requireAuth && session?.user) { + // User is authenticated but on a public page - redirect to dashboard + const currentPath = window.location.pathname; + if (currentPath === '/login' || currentPath === '/signup') { + window.location.href = '/dashboard'; + } + } + }); + + // Listen for auth changes + const { data: { subscription } } = supabase.auth.onAuthStateChange( + (event, session) => { + setUser(session?.user ?? null); + setLoading(false); + + // Handle auth state changes + if (requireAuth && !session?.user) { + window.location.href = '/login'; + } else if (!requireAuth && session?.user) { + const currentPath = window.location.pathname; + if (currentPath === '/login' || currentPath === '/signup') { + window.location.href = '/dashboard'; + } + } + } + ); + + return () => subscription.unsubscribe(); + }, [requireAuth]); + + if (loading) { + return ( +
+
+ + Loading... +
+
+ ); + } + + // For protected routes, only render if user is authenticated + if (requireAuth && !user) { + return null; // Will redirect in useEffect + } + + // For public routes, only render if user is not authenticated (or if they are, they'll be redirected) + if (!requireAuth && user) { + const currentPath = window.location.pathname; + if (currentPath === '/login' || currentPath === '/signup') { + return null; // Will redirect in useEffect + } + } + + return <>{children}; +} \ No newline at end of file diff --git a/src/components/ProtectedRoute.tsx b/src/components/ProtectedRoute.tsx deleted file mode 100644 index 53f3aeb..0000000 --- a/src/components/ProtectedRoute.tsx +++ /dev/null @@ -1,52 +0,0 @@ -import React, { useEffect, useState } from 'react'; -import { supabase } from '../lib/supabase'; -import type { User } from '@supabase/supabase-js'; -import { Loader2 } from 'lucide-react'; - -interface ProtectedRouteProps { - children: React.ReactNode; -} - -export function ProtectedRoute({ children }: ProtectedRouteProps) { - const [user, setUser] = useState(null); - const [loading, setLoading] = useState(true); - - useEffect(() => { - // Get initial session - supabase.auth.getSession().then(({ data: { session } }) => { - setUser(session?.user ?? null); - setLoading(false); - }); - - // Listen for auth changes - const { data: { subscription } } = supabase.auth.onAuthStateChange( - (event, session) => { - setUser(session?.user ?? null); - setLoading(false); - } - ); - - return () => subscription.unsubscribe(); - }, []); - - if (loading) { - return ( -
-
- - Loading... -
-
- ); - } - - if (!user) { - // Redirect to login if not authenticated - if (typeof window !== 'undefined') { - window.location.href = '/login'; - } - return null; - } - - return <>{children}; -} \ No newline at end of file diff --git a/src/pages/dashboard.astro b/src/pages/dashboard.astro index 1445b35..2f75c1d 100644 --- a/src/pages/dashboard.astro +++ b/src/pages/dashboard.astro @@ -2,14 +2,14 @@ import '@/styles/globals.css' import Layout from '../layouts/Layout.astro'; import { Dashboard } from '../components/Dashboard'; -import { ProtectedRoute } from '../components/ProtectedRoute'; +import { AuthGuard } from '../components/AuthGuard'; import { Navbar } from '../components/Navbar'; --- - + - + \ No newline at end of file diff --git a/src/pages/login.astro b/src/pages/login.astro index 593e6d8..45fb735 100644 --- a/src/pages/login.astro +++ b/src/pages/login.astro @@ -3,19 +3,22 @@ import '@/styles/globals.css' import Layout from '../layouts/Layout.astro'; import { AuthForm } from '../components/AuthForm'; import { Navbar } from '../components/Navbar'; +import { AuthGuard } from '../components/AuthGuard'; --- -
-
-
-

Sign In

-

Access your debt resolution dashboard

+ +
+
+
+

Sign In

+

Access your debt resolution dashboard

+
+ +
- - -
-
+ +
\ No newline at end of file diff --git a/src/pages/signup.astro b/src/pages/signup.astro index 70306a2..b9b37b6 100644 --- a/src/pages/signup.astro +++ b/src/pages/signup.astro @@ -3,19 +3,22 @@ import '@/styles/globals.css' import Layout from '../layouts/Layout.astro'; import { AuthForm } from '../components/AuthForm'; import { Navbar } from '../components/Navbar'; +import { AuthGuard } from '../components/AuthGuard'; --- -
-
-
-

Create Account

-

Start resolving your debts with AI assistance

+ +
+
+
+

Create Account

+

Start resolving your debts with AI assistance

+
+ +
- - -
-
+ +
\ No newline at end of file