diff --git a/src/components/form/errorMessage.js b/src/components/form/errorMessage.js
new file mode 100644
index 00000000..10e27466
--- /dev/null
+++ b/src/components/form/errorMessage.js
@@ -0,0 +1,11 @@
+const ErrorMessage = ({message}) => {
+ return (
+
+ {message &&
{message}
}
+
+ )
+
+}
+
+export default ErrorMessage
+
diff --git a/src/context/auth.js b/src/context/auth.js
index a7b9462d..a692959b 100644
--- a/src/context/auth.js
+++ b/src/context/auth.js
@@ -5,85 +5,133 @@ import Modal from "../components/modal";
import Navigation from "../components/navigation";
import useAuth from "../hooks/useAuth";
import { createProfile, login, register } from "../service/apiClient";
-import jwt_decode from "jwt-decode"
-
-const AuthContext = createContext()
+import jwt_decode from "jwt-decode";
+import ERR from "../../src/utils/errors.js";
+const AuthContext = createContext();
const AuthProvider = ({ children }) => {
- const navigate = useNavigate()
- const location = useLocation()
- const [token, setToken] = useState(null)
-
- useEffect(() => {
- const storedToken = localStorage.getItem('token')
-
- if (storedToken) {
- setToken(storedToken)
- navigate(location.state?.from?.pathname || "/")
- }
- }, [location.state?.from?.pathname, navigate])
-
- const handleLogin = async (email, password) => {
- const res = await login(email, password)
-
- if (!res.data.token) {
- return navigate("/login")
- }
-
- localStorage.setItem('token', res.data.token)
-
- setToken(res.token)
- navigate(location.state?.from?.pathname || "/")
- };
-
- const handleLogout = () => {
- localStorage.removeItem('token')
- setToken(null)
- };
+ const navigate = useNavigate();
+ const location = useLocation();
+ const [token, setToken] = useState(null);
- const handleRegister = async (email, password) => {
- const res = await register(email, password)
- setToken(res.data.token)
+ useEffect(() => {
+ const storedToken = localStorage.getItem("token");
- navigate("/verification")
+ if (storedToken) {
+ setToken(storedToken);
+ navigate(location.state?.from?.pathname || "/");
}
+ }, [location.state?.from?.pathname, navigate]);
+
+ const handleLogin = async (email, password, setErrors) => {
+ try {
+ const validatedEmail = validationEmail(email);
+ if (!validatedEmail) {
+ throw new Error(ERR.EMAIL_ERROR_MESSAGE);
+ }
+
+ const validatedPassword = validationPassword(password);
+ if (!validatedPassword) {
+ throw new Error(ERR.PASSWORD_REQUIRMENTS);
+ }
+
+ const res = await login(email, password);
+ if (!res.status) {
+ throw new Error(res.error.message);
+ }
+ if (!res.data.token) {
+ return navigate("/login");
+ }
+
+ localStorage.setItem("token", res.data.token);
+
+ setToken(res.data.token);
+ navigate(location.state?.from?.pathname || "/");
+ } catch (error) {
+ setErrors(error.message);
+ }
+ };
+
+ const handleLogout = () => {
+ localStorage.removeItem("token");
+ setToken(null);
+ };
+
+ const handleRegister = async (email, password, setErrors) => {
+ try {
+ const validatedEmail = validationEmail(email);
+ if (!validatedEmail) {
+ throw new Error(ERR.EMAIL_ERROR_MESSAGE);
+ }
+ const validatedPassword = validationPassword(password);
+ if (!validatedPassword) {
+ throw new Error(ERR.PASSWORD_REQUIRMENTS);
+ }
+ const res = await register(email, password, setErrors);
+ if (!res.status) {
+ throw new Error(res.error.message);
+ }
+ setToken(res.data.token);
+ navigate("/verification");
+ } catch (error) {
+ setErrors(error.message);
+ }
+ };
- const handleCreateProfile = async (firstName, lastName, githubUrl, bio) => {
- const { userId } = jwt_decode(token)
+ const handleCreateProfile = async (firstName, lastName, githubUrl, bio) => {
+ const { userId } = jwt_decode(token);
- await createProfile(userId, firstName, lastName, githubUrl, bio)
+ await createProfile(userId, firstName, lastName, githubUrl, bio);
- localStorage.setItem('token', token)
- navigate('/')
- }
+ navigate("/");
+ };
- const value = {
- token,
- onLogin: handleLogin,
- onLogout: handleLogout,
- onRegister: handleRegister,
- onCreateProfile: handleCreateProfile
- };
+ const value = {
+ token,
+ onLogin: handleLogin,
+ onLogout: handleLogout,
+ onRegister: handleRegister,
+ onCreateProfile: handleCreateProfile,
+ };
- return {children}
+ return {children};
};
const ProtectedRoute = ({ children }) => {
- const { token } = useAuth()
- const location = useLocation()
-
- if (!token) {
- return
- }
-
- return (
-
-
-
-
- {children}
-
- )
+ const { token } = useAuth();
+ const location = useLocation();
+
+ if (!token) {
+ return ;
+ }
+
+ return (
+
+
+
+
+ {children}
+
+ );
+};
+function validationEmail(email) {
+ const emailPattern = /^[a-zA-Z0-9_.+-]+@[a-zA-Z0-9-]+\.[a-zA-Z0-9-.]+$/;
+
+ return !email || !emailPattern.test(email) ? false : true;
+}
+
+function validationPassword(password) {
+ const minLength = 8;
+ const hasUppercase = /[A-Z]/.test(password);
+ const hasNumber = /\d/.test(password);
+ const hasSpecialCharacter = /[!@#$%^&*(),.?":{}|<>]/.test(password);
+
+ return password.length < minLength ||
+ !hasUppercase ||
+ !hasNumber ||
+ !hasSpecialCharacter
+ ? false
+ : true;
}
-export { AuthContext, AuthProvider, ProtectedRoute }
+export { AuthContext, AuthProvider, ProtectedRoute };
diff --git a/src/pages/login/index.js b/src/pages/login/index.js
index 60566866..91dcfc0e 100644
--- a/src/pages/login/index.js
+++ b/src/pages/login/index.js
@@ -4,50 +4,55 @@ import TextInput from "../../components/form/textInput";
import useAuth from "../../hooks/useAuth";
import CredentialsCard from "../../components/credentials";
import "./login.css";
+import ErrorMessage from "../../components/form/errorMessage";
const Login = () => {
- const { onLogin } = useAuth();
- const [formData, setFormData] = useState({ email: "", password: "" });
+ const { onLogin } = useAuth();
+ const [formData, setFormData] = useState({ email: "", password: "" });
+ const [errors, setErrors] = useState(null);
+ const onChange = (e) => {
+ const { name, value } = e.target;
+ setFormData({ ...formData, [name]: value });
+ setErrors(null);
+ };
- const onChange = (e) => {
- const { name, value } = e.target;
- setFormData({ ...formData, [name]: value });
- };
-
- return (
-
-
-
-
-
-
-
- );
+ return (
+
+
+
+
+
+
+
+ );
};
export default Login;
diff --git a/src/pages/register/index.js b/src/pages/register/index.js
index 8d0f693d..3bfa0983 100644
--- a/src/pages/register/index.js
+++ b/src/pages/register/index.js
@@ -4,51 +4,58 @@ import TextInput from "../../components/form/textInput";
import useAuth from "../../hooks/useAuth";
import CredentialsCard from "../../components/credentials";
import "./register.css";
+import ErrorMessage from "../../components/form/errorMessage";
const Register = () => {
- const { onRegister } = useAuth();
- const [formData, setFormData] = useState({ email: "", password: "" });
+ const { onRegister } = useAuth();
+ const [formData, setFormData] = useState({ email: "", password: "" });
+ const [errors, setErrors] = useState(null);
- const onChange = (e) => {
- const { name, value } = e.target;
- setFormData({ ...formData, [name]: value });
- };
+ const onChange = (e) => {
+ const { name, value } = e.target;
+ setFormData({ ...formData, [name]: value });
+ setErrors(null);
+ };
- return (
-
-
-
-
-
-
-
- );
+ return (
+
+
+
+
+
+
+
+
+ );
};
export default Register;
diff --git a/src/service/apiClient.js b/src/service/apiClient.js
index ae4d87cf..4a391a4f 100644
--- a/src/service/apiClient.js
+++ b/src/service/apiClient.js
@@ -1,12 +1,34 @@
+
import { API_URL } from "./constants"
async function login(email, password) {
- return await post('login', { email, password }, false)
+ try {
+ const res = await post('login', { email, password }, false)
+ if(res.status !== 'success') {
+ throw new Error(res.data.error)
+ }
+ return res
+ } catch (error) {
+ return { status: false, error : error}
+ }
}
async function register(email, password) {
- await post('users', { email, password }, false)
- return await login(email, password)
+ try {
+ const res = await post('users', { email, password }, false)
+ if(res.status === 'fail') {
+ throw new Error(res.data.error)
+ }
+ return login(email, password)
+ } catch (error) {
+ if(error === 'Email already in use') {
+ return { status : false, error : error}
+ }
+ if ( error === 'Unable to create new user') {
+ return { status : false, error : 'There was an issue creating your account. Please try again later or contact support.'}
+ }
+ return { status : false, error : error}
+ }
}
async function createProfile(userId, firstName, lastName, githubUrl, bio) {
diff --git a/src/utils/errors.js b/src/utils/errors.js
new file mode 100644
index 00000000..077b0117
--- /dev/null
+++ b/src/utils/errors.js
@@ -0,0 +1,5 @@
+export default {
+ PASSWORD_REQUIRMENTS:
+ "Password must be at least 8 characters long and include at least one uppercase letter, one number, and one special character.",
+ EMAIL_ERROR_MESSAGE: "Please enter a valid email",
+};