import { createContext, useCallback, useContext, useLayoutEffect, useState } from 'react'; import { type ErrorInfo } from '../components/BackendError'; import useLocalStorage from '../hooks/useLocalStorage'; import { type DataCallback, getAuth, patchPassword,postLogin, postLogout, postSignup } from '../utils/backendAPI'; import { ICurrentUser, IUserLoginData, IUserProfile, IUserSignupData, IUserUpdatePassword } from '../utils/models'; interface IAuthContext { user: ICurrentUser | undefined login: (data: IUserLoginData, callback?: DataCallback) => void logout: (callback?: DataCallback) => void signup: (data: IUserSignupData, callback?: DataCallback) => void updatePassword: (data: IUserUpdatePassword, callback?: () => void) => void loading: boolean error: ErrorInfo setError: (error: ErrorInfo) => void } const AuthContext = createContext(null); export const useAuth = () => { const context = useContext(AuthContext); if (!context) { throw new Error( 'useAuth has to be used within ' ); } return context; } interface AuthStateProps { children: React.ReactNode } export const AuthState = ({ children }: AuthStateProps) => { const [user, setUser] = useLocalStorage('user', undefined); const [loading, setLoading] = useState(false); const [error, setError] = useState(undefined); const reload = useCallback( (callback?: () => void) => { getAuth({ onError: () => setUser(undefined), onSuccess: currentUser => { if (currentUser.id) { setUser(currentUser); } else { setUser(undefined); } if (callback) callback(); } }); }, [setUser]); function login(data: IUserLoginData, callback?: DataCallback) { setError(undefined); postLogin({ data: data, showError: true, setLoading: setLoading, onError: error => setError(error), onSuccess: newData => reload(() => { if (callback) callback(newData); }) }); } function logout(callback?: DataCallback) { setError(undefined); postLogout({ showError: true, onSuccess: newData => reload(() => { if (callback) callback(newData); }) }); } function signup(data: IUserSignupData, callback?: DataCallback) { setError(undefined); postSignup({ data: data, showError: true, setLoading: setLoading, onError: error => setError(error), onSuccess: newData => reload(() => { if (callback) callback(newData); }) }); } const updatePassword = useCallback( (data: IUserUpdatePassword, callback?: () => void) => { setError(undefined); patchPassword({ data: data, showError: true, setLoading: setLoading, onError: error => setError(error), onSuccess: () => reload(() => { if (callback) callback(); }) }); }, [reload]); useLayoutEffect(() => { reload(); }, [reload]) return ( {children} ); };