2023-07-25 20:27:29 +03:00
|
|
|
import { createContext, useCallback, useContext, useLayoutEffect, useState } from 'react';
|
2023-07-15 17:46:19 +03:00
|
|
|
|
2023-07-25 20:27:29 +03:00
|
|
|
import { type ErrorInfo } from '../components/BackendError';
|
|
|
|
import useLocalStorage from '../hooks/useLocalStorage';
|
|
|
|
import { type BackendCallback, getAuth, postLogin, postLogout, postSignup } from '../utils/backendAPI';
|
|
|
|
import { type ICurrentUser, type IUserSignupData } from '../utils/models';
|
2023-07-15 17:46:19 +03:00
|
|
|
|
|
|
|
interface IAuthContext {
|
|
|
|
user: ICurrentUser | undefined
|
2023-07-25 20:27:29 +03:00
|
|
|
login: (username: string, password: string, callback?: BackendCallback) => void
|
|
|
|
logout: (callback?: BackendCallback) => void
|
|
|
|
signup: (data: IUserSignupData, callback?: BackendCallback) => void
|
2023-07-15 17:46:19 +03:00
|
|
|
loading: boolean
|
|
|
|
error: ErrorInfo
|
|
|
|
setError: (error: ErrorInfo) => void
|
|
|
|
}
|
|
|
|
|
2023-07-25 00:20:37 +03:00
|
|
|
const AuthContext = createContext<IAuthContext | null>(null);
|
|
|
|
export const useAuth = () => {
|
|
|
|
const context = useContext(AuthContext);
|
|
|
|
if (!context) {
|
|
|
|
throw new Error(
|
|
|
|
'useAuth has to be used within <AuthState.Provider>'
|
|
|
|
);
|
|
|
|
}
|
|
|
|
return context;
|
|
|
|
}
|
2023-07-15 17:46:19 +03:00
|
|
|
|
|
|
|
interface AuthStateProps {
|
|
|
|
children: React.ReactNode
|
|
|
|
}
|
|
|
|
|
|
|
|
export const AuthState = ({ children }: AuthStateProps) => {
|
|
|
|
const [user, setUser] = useLocalStorage<ICurrentUser | undefined>('user', undefined);
|
|
|
|
const [loading, setLoading] = useState(false);
|
|
|
|
const [error, setError] = useState<ErrorInfo>(undefined);
|
|
|
|
|
|
|
|
const loadCurrentUser = useCallback(
|
|
|
|
async () => {
|
2023-07-25 20:27:29 +03:00
|
|
|
await getAuth({
|
|
|
|
onError: () => { setUser(undefined); },
|
2023-07-26 10:59:55 +03:00
|
|
|
onSuccess: response => {
|
2023-07-15 17:57:25 +03:00
|
|
|
if (response.data.id) {
|
|
|
|
setUser(response.data);
|
|
|
|
} else {
|
|
|
|
setUser(undefined)
|
|
|
|
}
|
2023-07-15 17:46:19 +03:00
|
|
|
}
|
|
|
|
});
|
|
|
|
}, [setUser]
|
|
|
|
);
|
2023-07-25 20:27:29 +03:00
|
|
|
|
|
|
|
function login(uname: string, pw: string, callback?: BackendCallback) {
|
2023-07-15 17:46:19 +03:00
|
|
|
setError(undefined);
|
2023-07-15 17:57:25 +03:00
|
|
|
postLogin({
|
2023-07-25 20:27:29 +03:00
|
|
|
data: { username: uname, password: pw },
|
2023-07-15 17:57:25 +03:00
|
|
|
showError: true,
|
2023-07-25 20:27:29 +03:00
|
|
|
setLoading,
|
|
|
|
onError: error => { setError(error); },
|
2023-07-26 10:59:55 +03:00
|
|
|
onSuccess:
|
2023-07-25 20:27:29 +03:00
|
|
|
(response) => {
|
|
|
|
loadCurrentUser()
|
|
|
|
.then(() => { if (callback) callback(response); })
|
|
|
|
.catch(console.error);
|
2023-07-15 17:46:19 +03:00
|
|
|
}
|
2023-07-25 20:27:29 +03:00
|
|
|
}).catch(console.error);
|
2023-07-15 17:46:19 +03:00
|
|
|
}
|
|
|
|
|
2023-07-25 20:27:29 +03:00
|
|
|
function logout(callback?: BackendCallback) {
|
2023-07-15 17:46:19 +03:00
|
|
|
setError(undefined);
|
2023-07-15 17:57:25 +03:00
|
|
|
postLogout({
|
|
|
|
showError: true,
|
2023-07-26 10:59:55 +03:00
|
|
|
onSuccess:
|
2023-07-25 20:27:29 +03:00
|
|
|
(response) => {
|
|
|
|
loadCurrentUser()
|
|
|
|
.then(() => { if (callback) callback(response); })
|
|
|
|
.catch(console.error);
|
2023-07-15 17:46:19 +03:00
|
|
|
}
|
2023-07-25 20:27:29 +03:00
|
|
|
}).catch(console.error);
|
2023-07-15 17:46:19 +03:00
|
|
|
}
|
|
|
|
|
2023-07-25 20:27:29 +03:00
|
|
|
function signup(data: IUserSignupData, callback?: BackendCallback) {
|
2023-07-15 17:46:19 +03:00
|
|
|
setError(undefined);
|
2023-07-15 17:57:25 +03:00
|
|
|
postSignup({
|
2023-07-25 20:27:29 +03:00
|
|
|
data,
|
2023-07-15 17:57:25 +03:00
|
|
|
showError: true,
|
2023-07-25 20:27:29 +03:00
|
|
|
setLoading,
|
|
|
|
onError: error => { setError(error); },
|
2023-07-26 10:59:55 +03:00
|
|
|
onSuccess:
|
2023-07-25 20:27:29 +03:00
|
|
|
(response) => {
|
|
|
|
loadCurrentUser()
|
|
|
|
.then(() => { if (callback) callback(response); })
|
|
|
|
.catch(console.error);
|
2023-07-15 17:46:19 +03:00
|
|
|
}
|
2023-07-25 20:27:29 +03:00
|
|
|
}).catch(console.error);
|
2023-07-15 17:46:19 +03:00
|
|
|
}
|
|
|
|
|
2023-07-25 00:20:37 +03:00
|
|
|
useLayoutEffect(() => {
|
2023-07-25 20:27:29 +03:00
|
|
|
loadCurrentUser().catch(console.error);
|
2023-07-15 17:46:19 +03:00
|
|
|
}, [loadCurrentUser])
|
|
|
|
|
|
|
|
return (
|
|
|
|
<AuthContext.Provider
|
|
|
|
value={{ user, login, logout, signup, loading, error, setError }}
|
|
|
|
>
|
|
|
|
{children}
|
|
|
|
</AuthContext.Provider>
|
|
|
|
);
|
2023-07-25 20:27:29 +03:00
|
|
|
};
|