diff --git a/.prettierrc b/.prettierrc
index 639c6972..8be254a5 100644
--- a/.prettierrc
+++ b/.prettierrc
@@ -5,5 +5,5 @@
"singleQuote": true,
"trailingComma": "none",
"jsxBracketSameLine": false,
- "endOfLine": "lf"
+ "endOfLine": "auto"
}
diff --git a/package-lock.json b/package-lock.json
index 6891fbef..4bbf17e4 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -17,6 +17,7 @@
"react-modal": "^3.16.1",
"react-router-dom": "^6.8.0",
"react-scripts": "5.0.1",
+ "validator": "^13.12.0",
"web-vitals": "^3.1.1"
},
"devDependencies": {
@@ -17116,6 +17117,15 @@
"node": ">=10.12.0"
}
},
+ "node_modules/validator": {
+ "version": "13.12.0",
+ "resolved": "https://registry.npmjs.org/validator/-/validator-13.12.0.tgz",
+ "integrity": "sha512-c1Q0mCiPlgdTVVVIJIrBuxNicYE+t/7oKeI9MWLj3fh/uq2Pxh/3eeWbVZ4OcGW1TUf53At0njHw5SMdA3tmMg==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.10"
+ }
+ },
"node_modules/vary": {
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz",
diff --git a/package.json b/package.json
index 249b6b05..6045acce 100644
--- a/package.json
+++ b/package.json
@@ -12,6 +12,7 @@
"react-modal": "^3.16.1",
"react-router-dom": "^6.8.0",
"react-scripts": "5.0.1",
+ "validator": "^13.12.0",
"web-vitals": "^3.1.1"
},
"scripts": {
diff --git a/src/components/form/textInput/index.js b/src/components/form/textInput/index.js
index 39da3cae..c4cdf58e 100644
--- a/src/components/form/textInput/index.js
+++ b/src/components/form/textInput/index.js
@@ -1,8 +1,19 @@
import { useState } from 'react';
-const TextInput = ({ value, onChange, name, label, icon, type = 'text' }) => {
+const TextInput = ({
+ value,
+ onChange,
+ errorResponse = '',
+ name,
+ label,
+ icon,
+ require = false,
+ type = 'text'
+}) => {
const [input, setInput] = useState('');
+ // const [isValidInput, setIsValidInput] = useState(true);
const [showpassword, setShowpassword] = useState(false);
+
if (type === 'password') {
return (
@@ -11,6 +22,7 @@ const TextInput = ({ value, onChange, name, label, icon, type = 'text' }) => {
type={type}
name={name}
value={value}
+ required={require}
onChange={(e) => {
onChange(e);
setInput(e.target.value);
@@ -26,6 +38,7 @@ const TextInput = ({ value, onChange, name, label, icon, type = 'text' }) => {
>
+ {errorResponse && {errorResponse}}
);
} else {
@@ -36,10 +49,12 @@ const TextInput = ({ value, onChange, name, label, icon, type = 'text' }) => {
type={type}
name={name}
value={value}
+ required={require}
onChange={onChange}
className={icon && 'input-has-icon'}
/>
{icon && {icon}}
+ {errorResponse && {errorResponse}}
);
}
diff --git a/src/context/auth.js b/src/context/auth.js
index 47cd66c9..5f0bbdc9 100644
--- a/src/context/auth.js
+++ b/src/context/auth.js
@@ -29,13 +29,15 @@ const AuthProvider = ({ children }) => {
const res = await login(email, password);
if (!res.data.token) {
- return navigate('/login');
+ navigate('/login');
+ return res;
}
localStorage.setItem('token', res.data.token);
setToken(res.token);
navigate(location.state?.from?.pathname || '/');
+ return res;
};
const handleLogout = () => {
@@ -45,9 +47,13 @@ const AuthProvider = ({ children }) => {
const handleRegister = async (email, password) => {
const res = await register(email, password);
- setToken(res.data.token);
+ if (res.status === 'success') {
+ const loginRes = await login(email, password);
+ setToken(loginRes.data.token);
+ navigate('/verification');
+ }
- navigate('/verification');
+ return res;
};
const handleCreateProfile = async (firstName, lastName, githubUrl, bio) => {
diff --git a/src/pages/login/index.js b/src/pages/login/index.js
index 08df7d5a..3bf36bc0 100644
--- a/src/pages/login/index.js
+++ b/src/pages/login/index.js
@@ -8,12 +8,22 @@ import './login.css';
const Login = () => {
const { onLogin } = useAuth();
const [formData, setFormData] = useState({ email: '', password: '' });
+ const [response, setResponse] = useState('');
const onChange = (e) => {
const { name, value } = e.target;
setFormData({ ...formData, [name]: value });
};
+ const submit = async (e) => {
+ e.preventDefault();
+ const data = await onLogin(formData.email, formData.password);
+ if (data.status === 'fail') {
+ setResponse(data.data.email);
+ console.log(data.data.email);
+ }
+ };
+
return (
{
altButtonText="Sign up"
>
-
-
diff --git a/src/pages/register/index.js b/src/pages/register/index.js
index 5cc70e32..cc3f0284 100644
--- a/src/pages/register/index.js
+++ b/src/pages/register/index.js
@@ -4,10 +4,35 @@ import TextInput from '../../components/form/textInput';
import useAuth from '../../hooks/useAuth';
import CredentialsCard from '../../components/credentials';
import './register.css';
+import { validEmail, validPassword } from '../../service/inputValidationService';
const Register = () => {
const { onRegister } = useAuth();
const [formData, setFormData] = useState({ email: '', password: '' });
+ const [emailResponse, setEmailResponse] = useState('');
+ const [passwordReponse, setPasswordResponse] = useState('');
+ const submit = async (e) => {
+ e.preventDefault();
+ setEmailResponse('');
+ setPasswordResponse('');
+ const emailValid = validEmail(formData.email);
+ const passwordValid = validPassword(formData.password);
+ if (!passwordValid.isValid) {
+ setPasswordResponse(passwordValid.message); // Set password error response
+ }
+ if (!emailValid.isValid) {
+ setEmailResponse(emailValid.message); // Set email error response
+ }
+ // Only request if email and password is valid
+ if (passwordValid.isValid && emailValid.isValid) {
+ const data = await onRegister(formData.email, formData.password);
+ console.log(data);
+ if (data.status === 'fail' && data.email !== null) {
+ console.log('email');
+ setEmailResponse(data.data.email);
+ }
+ }
+ };
const onChange = (e) => {
const { name, value } = e.target;
@@ -24,27 +49,32 @@ const Register = () => {
altButtonText="Log in"
>
-
-
diff --git a/src/service/apiClient.js b/src/service/apiClient.js
index 5f3cdbcf..575a7e96 100644
--- a/src/service/apiClient.js
+++ b/src/service/apiClient.js
@@ -5,8 +5,8 @@ async function login(email, password) {
}
async function register(email, password) {
- await post('users', { email, password }, false);
- return await login(email, password);
+ return post('users', { email, password }, false);
+ // return await login(email, password);
}
async function createProfile(userId, firstName, lastName, githubUrl, bio) {
diff --git a/src/service/inputValidationService.js b/src/service/inputValidationService.js
new file mode 100644
index 00000000..dd93e6f0
--- /dev/null
+++ b/src/service/inputValidationService.js
@@ -0,0 +1,53 @@
+import validator from 'validator';
+
+export const validEmail = (email) => {
+ if (validator.isEmail(email)) {
+ return {
+ isValid: true,
+ message: ''
+ };
+ } else {
+ return {
+ isValid: false,
+ message: 'Invalid email format'
+ };
+ }
+};
+
+export const validPassword = (password) => {
+ if (password.length < 8) {
+ return {
+ isValid: false,
+ message: 'Password must be at least 8 characters long'
+ };
+ }
+ if (!/[A-Za-z]/.test(password)) {
+ return {
+ isValid: false,
+ message: 'Password must contain at least one letter'
+ };
+ }
+ if (!/[A-Z]/.test(password)) {
+ return {
+ isValid: false,
+ message: 'Password must contain at least one uppercase letter'
+ };
+ }
+ if (!/\d/.test(password)) {
+ return {
+ isValid: false,
+ message: 'Password must contain at least one number'
+ };
+ }
+ if (!/[@$!%*?&]/.test(password)) {
+ return {
+ isValid: false,
+ message: 'Password must contain at least one special character'
+ };
+ }
+
+ return {
+ isValid: true,
+ message: 'Success'
+ };
+};
diff --git a/src/styles/_form.css b/src/styles/_form.css
index 419cfb63..837ceb7c 100644
--- a/src/styles/_form.css
+++ b/src/styles/_form.css
@@ -31,6 +31,14 @@ form label {
padding-right: 10px;
}
+.input-description{
+ color: var(--color-blue2);
+}
+
+.input-invalid {
+ color: var(--color-red)
+}
+
.showpasswordbutton {
position: absolute;
bottom: 28px;
diff --git a/src/styles/_globals.css b/src/styles/_globals.css
index eb9772c6..6d4d1b3b 100644
--- a/src/styles/_globals.css
+++ b/src/styles/_globals.css
@@ -8,6 +8,7 @@
--color-green: #64dc78;
--color-offwhite: #f0f5fa;
--color-lightgrey: #f5f5f5;
+ --color-red: #F00000;
}
/* global settings here, resetting a lot of defaults */