canadian-alternatives/src/components/auth/auth-provider.tsx

93 lines
2.2 KiB
TypeScript

'use client'
import { createContext, useContext, useEffect, useState } from 'react'
import { Session, User } from '@supabase/supabase-js'
import { useRouter } from 'next/navigation'
import { supabase } from '@/lib/supabase'
type AuthContextType = {
user: User | null
session: Session | null
isLoading: boolean
signOut: () => Promise<void>
}
const AuthContext = createContext<AuthContextType | undefined>(undefined)
export function AuthProvider({ children }: { children: React.ReactNode }) {
const [user, setUser] = useState<User | null>(null)
const [session, setSession] = useState<Session | null>(null)
const [isLoading, setIsLoading] = useState<boolean>(true)
const router = useRouter()
useEffect(() => {
async function getSession() {
setIsLoading(true)
try {
const { data: { session }, error } = await supabase.auth.getSession()
if (error) {
throw error
}
setSession(session)
setUser(session?.user || null)
const { data: authListener } = supabase.auth.onAuthStateChange(
async (event, session) => {
console.log(`Auth event: ${event}`)
setSession(session)
setUser(session?.user || null)
router.refresh()
}
)
return () => {
authListener?.subscription.unsubscribe()
}
} catch (error) {
console.error('Error getting session:', error)
} finally {
setIsLoading(false)
}
}
const unsubscribe = getSession()
return () => {
if (typeof unsubscribe === 'function') {
unsubscribe()
}
}
}, [router])
const signOut = async () => {
try {
await supabase.auth.signOut()
setUser(null)
setSession(null)
} catch (error) {
console.error('Error signing out:', error)
}
}
const value = {
user,
session,
isLoading,
signOut,
}
return (
<AuthContext.Provider value={value}>
{children}
</AuthContext.Provider>
)
}
export const useAuth = () => {
const context = useContext(AuthContext)
if (context === undefined) {
throw new Error('useAuth must be used within an AuthProvider')
}
return context
}