74 lines
1.9 KiB
TypeScript
74 lines
1.9 KiB
TypeScript
import { getToken, setRefreshToken, setToken } from '@/config/func'
|
|
import {
|
|
createContext,
|
|
useCallback,
|
|
useContext,
|
|
useEffect,
|
|
useMemo,
|
|
useState,
|
|
type FC,
|
|
type ReactNode,
|
|
} from 'react'
|
|
|
|
export type AuthStatus = 'checking' | 'authenticated' | 'unauthenticated'
|
|
|
|
type AuthContextValue = {
|
|
status: AuthStatus
|
|
isAuthenticated: boolean
|
|
isChecking: boolean
|
|
refreshAuth: () => void
|
|
}
|
|
|
|
const AuthContext = createContext<AuthContextValue | null>(null)
|
|
|
|
type AuthProviderProps = {
|
|
children: ReactNode
|
|
}
|
|
|
|
export const AuthProvider: FC<AuthProviderProps> = ({ children }) => {
|
|
const [status, setStatus] = useState<AuthStatus>('checking')
|
|
|
|
const refreshAuth = useCallback(() => {
|
|
setStatus(getToken() ? 'authenticated' : 'unauthenticated')
|
|
}, [])
|
|
|
|
useEffect(() => {
|
|
const urlParams = new URLSearchParams(window.location.search)
|
|
const tokenFromUrl = urlParams.get('token')
|
|
const refreshTokenFromUrl = urlParams.get('refreshToken')
|
|
|
|
if (tokenFromUrl && refreshTokenFromUrl) {
|
|
setToken(tokenFromUrl)
|
|
setRefreshToken(refreshTokenFromUrl)
|
|
|
|
const newUrl = window.location.pathname
|
|
window.history.replaceState({}, '', newUrl)
|
|
|
|
setStatus('authenticated')
|
|
return
|
|
}
|
|
|
|
refreshAuth()
|
|
}, [refreshAuth])
|
|
|
|
const value = useMemo<AuthContextValue>(
|
|
() => ({
|
|
status,
|
|
isAuthenticated: status === 'authenticated',
|
|
isChecking: status === 'checking',
|
|
refreshAuth,
|
|
}),
|
|
[status, refreshAuth],
|
|
)
|
|
|
|
return <AuthContext.Provider value={value}>{children}</AuthContext.Provider>
|
|
}
|
|
|
|
export const useAuth = (): AuthContextValue => {
|
|
const context = useContext(AuthContext)
|
|
if (!context) {
|
|
throw new Error('useAuth must be used within AuthProvider')
|
|
}
|
|
return context
|
|
}
|