ConceptPortal-public/rsconcept/frontend/src/context/AuthContext.tsx

208 lines
5.2 KiB
TypeScript
Raw Normal View History

'use client';
2023-07-25 20:27:29 +03:00
import { createContext, useCallback, useContext, useLayoutEffect, useState } from 'react';
2023-07-15 17:46:19 +03:00
2024-03-20 15:27:32 +03:00
import { type ErrorData } from '@/components/info/InfoError';
2024-02-25 20:55:30 +03:00
import { IPasswordTokenData, IRequestPasswordData, IResetPasswordData, IUserLoginData } from '@/models/library';
import { ICurrentUser } from '@/models/library';
import { IUserSignupData } from '@/models/library';
import { IUserProfile } from '@/models/library';
import { IUserInfo } from '@/models/library';
import { IUserUpdatePassword } from '@/models/library';
2024-02-25 20:55:30 +03:00
import {
type DataCallback,
getAuth,
patchPassword,
postLogin,
postLogout,
postRequestPasswordReset,
postResetPassword,
postSignup,
postValidatePasswordToken
2024-04-24 10:27:17 +03:00
} from '@/app/backendAPI';
2023-08-27 15:39:49 +03:00
import { useUsers } from './UsersContext';
2023-07-15 17:46:19 +03:00
interface IAuthContext {
2023-12-28 14:04:44 +03:00
user: ICurrentUser | undefined;
login: (data: IUserLoginData, callback?: DataCallback) => void;
logout: (callback?: DataCallback) => void;
signup: (data: IUserSignupData, callback?: DataCallback<IUserProfile>) => void;
updatePassword: (data: IUserUpdatePassword, callback?: () => void) => void;
2024-02-25 20:55:30 +03:00
requestPasswordReset: (data: IRequestPasswordData, callback?: () => void) => void;
validateToken: (data: IPasswordTokenData, callback?: () => void) => void;
resetPassword: (data: IResetPasswordData, callback?: () => void) => void;
2023-12-28 14:04:44 +03:00
loading: boolean;
error: ErrorData;
setError: (error: ErrorData) => void;
2023-07-15 17:46:19 +03:00
}
const AuthContext = createContext<IAuthContext | null>(null);
export const useAuth = () => {
const context = useContext(AuthContext);
if (!context) {
2023-12-28 14:04:44 +03:00
throw new Error('useAuth has to be used within <AuthState.Provider>');
}
return context;
2023-12-28 14:04:44 +03:00
};
2023-07-15 17:46:19 +03:00
interface AuthStateProps {
2023-12-28 14:04:44 +03:00
children: React.ReactNode;
2023-07-15 17:46:19 +03:00
}
export const AuthState = ({ children }: AuthStateProps) => {
2023-08-27 15:39:49 +03:00
const { users } = useUsers();
const [user, setUser] = useState<ICurrentUser | undefined>(undefined);
2023-07-15 17:46:19 +03:00
const [loading, setLoading] = useState(false);
const [error, setError] = useState<ErrorData>(undefined);
2023-07-15 17:46:19 +03:00
const reload = useCallback(
2023-12-28 14:04:44 +03:00
(callback?: () => void) => {
getAuth({
onError: () => setUser(undefined),
onSuccess: currentUser => {
if (currentUser.id) {
setUser(currentUser);
} else {
setUser(undefined);
}
if (callback) callback();
2023-07-15 17:46:19 +03:00
}
2023-12-28 14:04:44 +03:00
});
},
[setUser]
);
2023-07-25 20:27:29 +03:00
function login(data: IUserLoginData, callback?: DataCallback) {
2023-07-15 17:46:19 +03:00
setError(undefined);
postLogin({
data: data,
2024-02-03 15:58:55 +03:00
showError: false,
setLoading: setLoading,
2024-01-04 22:10:57 +03:00
onError: setError,
2023-12-28 14:04:44 +03:00
onSuccess: newData =>
reload(() => {
if (callback) callback(newData);
})
});
2023-07-15 17:46:19 +03:00
}
function logout(callback?: DataCallback) {
2023-07-15 17:46:19 +03:00
setError(undefined);
postLogout({
showError: true,
2023-12-28 14:04:44 +03:00
onSuccess: newData =>
reload(() => {
if (callback) callback(newData);
})
});
2023-07-15 17:46:19 +03:00
}
function signup(data: IUserSignupData, callback?: DataCallback<IUserProfile>) {
2023-07-15 17:46:19 +03:00
setError(undefined);
postSignup({
data: data,
showError: true,
setLoading: setLoading,
2024-01-04 22:10:57 +03:00
onError: setError,
2023-12-28 14:04:44 +03:00
onSuccess: newData =>
reload(() => {
users.push(newData as IUserInfo);
if (callback) callback(newData);
})
});
2023-07-15 17:46:19 +03:00
}
2023-08-11 17:36:09 +03:00
const updatePassword = useCallback(
2023-12-28 14:04:44 +03:00
(data: IUserUpdatePassword, callback?: () => void) => {
setError(undefined);
patchPassword({
data: data,
showError: true,
setLoading: setLoading,
2024-01-04 22:10:57 +03:00
onError: setError,
2023-12-28 14:04:44 +03:00
onSuccess: () =>
reload(() => {
if (callback) callback();
})
});
},
[reload]
);
2023-08-11 17:36:09 +03:00
2024-02-25 20:55:30 +03:00
const requestPasswordReset = useCallback(
(data: IRequestPasswordData, callback?: () => void) => {
setError(undefined);
postRequestPasswordReset({
data: data,
showError: false,
setLoading: setLoading,
onError: setError,
onSuccess: () =>
reload(() => {
if (callback) callback();
})
});
},
[reload]
);
const validateToken = useCallback(
(data: IPasswordTokenData, callback?: () => void) => {
setError(undefined);
postValidatePasswordToken({
data: data,
showError: false,
setLoading: setLoading,
onError: setError,
onSuccess: () =>
reload(() => {
if (callback) callback();
})
});
},
[reload]
);
const resetPassword = useCallback(
(data: IResetPasswordData, callback?: () => void) => {
setError(undefined);
postResetPassword({
data: data,
showError: false,
setLoading: setLoading,
onError: setError,
onSuccess: () =>
reload(() => {
if (callback) callback();
})
});
},
[reload]
);
useLayoutEffect(() => {
reload();
2023-12-28 14:04:44 +03:00
}, [reload]);
2023-07-15 17:46:19 +03:00
return (
2024-02-25 20:55:30 +03:00
<AuthContext.Provider
value={{
user,
login,
logout,
signup,
loading,
error,
setError,
updatePassword,
requestPasswordReset,
validateToken,
resetPassword
}}
>
2023-12-28 14:04:44 +03:00
{children}
</AuthContext.Provider>
);
};