mirror of
https://github.com/rgrgogu/new_starr.git
synced 2026-09-27 00:12:54 +08:00
Initial
This commit is contained in:
@@ -0,0 +1,87 @@
|
||||
// contexts/AuthContext.jsx
|
||||
import { createContext, useContext, useState, useCallback, useRef } from 'react'
|
||||
import api from '../utils/api.util'
|
||||
|
||||
const AuthContext = createContext(null)
|
||||
|
||||
export const decodeToken = (token) => JSON.parse(atob(token.split('.')[1]))
|
||||
|
||||
export function AuthProvider({ children }) {
|
||||
const [accessToken, _setAccessToken] = useState(null) // ← renamed to _setAccessToken
|
||||
const [user, setUser] = useState(null)
|
||||
const [loading, setLoading] = useState(true)
|
||||
const [sessionRestored, setSessionRestored] = useState(false)
|
||||
const [authError, setAuthError] = useState(null)
|
||||
|
||||
const isRestoring = useRef(false)
|
||||
const accessTokenRef = useRef(null)
|
||||
|
||||
// ← Single setter that updates both ref and state
|
||||
const setAccessToken = useCallback((token) => {
|
||||
accessTokenRef.current = token
|
||||
_setAccessToken(token)
|
||||
}, [])
|
||||
|
||||
const login = useCallback(async ({ email, password }) => {
|
||||
setAuthError(null)
|
||||
try {
|
||||
const { data } = await api.post('/auth/login', { email, password })
|
||||
setAccessToken(data.data.accessToken)
|
||||
setUser(data.data.user)
|
||||
return { success: true, user: data.data.user }
|
||||
} catch (err) {
|
||||
const message = err.response?.data?.message || 'Login failed. Please try again.'
|
||||
setAuthError(message)
|
||||
return { success: false, message }
|
||||
}
|
||||
}, [])
|
||||
|
||||
const logout = useCallback(async () => {
|
||||
try {
|
||||
await api.post('/auth/logout')
|
||||
} catch (_) {
|
||||
// ignore
|
||||
} finally {
|
||||
setAccessToken(null)
|
||||
setUser(null)
|
||||
}
|
||||
}, [])
|
||||
|
||||
const restoreSession = useCallback(async () => {
|
||||
if (isRestoring.current) return
|
||||
isRestoring.current = true
|
||||
|
||||
try {
|
||||
if (accessTokenRef.current) return // already have token, skip
|
||||
const { data } = await api.post('/auth/refresh')
|
||||
setAccessToken(data.data.accessToken)
|
||||
setUser(data.data.user)
|
||||
} catch (_) {
|
||||
setAccessToken(null)
|
||||
setUser(null)
|
||||
} finally {
|
||||
setLoading(false) // ← set once, never back to true
|
||||
}
|
||||
}, [])
|
||||
|
||||
return (
|
||||
<AuthContext.Provider value={{
|
||||
accessToken,
|
||||
accessTokenRef, // ← expose ref for interceptor
|
||||
setAccessToken,
|
||||
user,
|
||||
setUser,
|
||||
login,
|
||||
logout,
|
||||
loading,
|
||||
sessionRestored,
|
||||
restoreSession,
|
||||
authError,
|
||||
setAuthError,
|
||||
}}>
|
||||
{children}
|
||||
</AuthContext.Provider>
|
||||
)
|
||||
}
|
||||
|
||||
export const useAuth = () => useContext(AuthContext)
|
||||
Reference in New Issue
Block a user