diff --git a/src/components/form/textInput/index.js b/src/components/form/textInput/index.js index 2957205..0f9058a 100644 --- a/src/components/form/textInput/index.js +++ b/src/components/form/textInput/index.js @@ -13,6 +13,7 @@ const TextInput = ({ readOnly = false, type = 'text', placeholder = '', + onClick, onBlur: onBlurProp, disabled = false, maxLength = 280, @@ -41,6 +42,7 @@ const TextInput = ({ onChange={onChange} onKeyDown={onKeyDown} onBlur={handleBlur} + onClick={onClick} autoComplete={type === 'password' ? 'current-password' : undefined} className={className} disabled={disabled} diff --git a/src/context/auth.js b/src/context/auth.js index d57dc47..809872d 100644 --- a/src/context/auth.js +++ b/src/context/auth.js @@ -4,7 +4,7 @@ import Header from '../components/header'; import Modal from '../components/modal'; import Navigation from '../components/navigation'; import useAuth from '../hooks/useAuth'; -import { patchProfile, login, register, getUserById } from '../service/apiClient'; +import { patchProfile, login, register, getUserById, patchUser } from '../service/apiClient'; import { normalizeClaims } from '../service/tokenDecode'; import Loader from '../components/loader/Loader'; @@ -153,7 +153,7 @@ const AuthProvider = ({ children }) => { const { id, ...body } = updatedUserData; try { - const res = await patchProfile(updatedUserData.id, body); + const res = await patchUser(updatedUserData.id, body); if (!res.ok) { console.error('Failed to created profile:', res.json()); return; diff --git a/src/pages/profile/ProfilePage.jsx b/src/pages/profile/ProfilePage.jsx index 8a183dc..4ccf123 100644 --- a/src/pages/profile/ProfilePage.jsx +++ b/src/pages/profile/ProfilePage.jsx @@ -12,11 +12,19 @@ import { ProfileEditButton } from './editButton'; import { getUserById } from '../../service/apiClient'; import Loader from '../../components/loader/Loader'; +import { + valEightChars, + valCapLetter, + valNumber, + valSpecialChar +} from '../register/registrationValidation'; + const ProfilePage = () => { const { id: pathParamId } = useParams(); - const { user, setUser, onPatchProfile } = useAuth(); + const { user, setUser, onPatchProfile, onCreateProfile } = useAuth(); const [isLoading, setIsLoading] = useState(null); const [isEditing, setIsEditing] = useState(false); + const [canSave, setCanSave] = useState(false); const [originalCurrentUser, setOriginalCurrentUser] = useState(user); // The original, before edit, state of the user we are looking at. const [tempCurrentUser, setTempCurrentUser] = useState(user); // The edited, under/after edit, state of the user we are looking at. @@ -66,12 +74,33 @@ const ProfilePage = () => { setTempCurrentUser((prev) => ({ ...prev, [field]: value })); }; + useEffect(() => { + const password = tempCurrentUser?.password || ''; + + const isValid = + valEightChars(password) && + valCapLetter(password) && + valNumber(password) && + valSpecialChar(password); + + setCanSave(isValid || password === ''); + }, [tempCurrentUser?.password]); + // When edit button gets toggled on/off const toggleEdit = () => { if (isEditing) { tempCurrentUser.id = pathParamId || user.id; + const { cohort, ...tempCurrentUserWithoutCohort } = tempCurrentUser; - onPatchProfile(tempCurrentUserWithoutCohort); + // if the password field is empty then patch without changing password, else patch with new password. + + if (tempCurrentUser.password === '') { + onCreateProfile(tempCurrentUserWithoutCohort); + } else { + onPatchProfile(tempCurrentUserWithoutCohort); + } + + tempCurrentUser.password = ''; if (!pathParamId || String(pathParamId) === String(user.id)) { const { password, ...userWithoutPassword } = tempCurrentUser; @@ -143,7 +172,7 @@ const ProfilePage = () => { /> {/* Edit button */} - + diff --git a/src/pages/profile/contactInfo/index.jsx b/src/pages/profile/contactInfo/index.jsx index 7f52bfb..9b2e8c4 100644 --- a/src/pages/profile/contactInfo/index.jsx +++ b/src/pages/profile/contactInfo/index.jsx @@ -1,13 +1,23 @@ +import { useState } from 'react'; import { useParams } from 'react-router-dom'; import Form from '../../../components/form'; import TextInput from '../../../components/form/textInput'; import useAuth from '../../../hooks/useAuth'; import { getInputClass, canEditField } from '../helpers'; +import { + valEightChars, + valCapLetter, + valNumber, + valSpecialChar +} from '../../register/registrationValidation'; + const ProfileContactInfo = ({ email, mobile, password, onChange, isEditing }) => { const { id: pathParamId } = useParams(); const { user } = useAuth(); + const [passwordCondition, setPasswordCondition] = useState(false); + return (
@@ -32,15 +42,37 @@ const ProfileContactInfo = ({ email, mobile, password, onChange, isEditing }) => /> {String(pathParamId) === String(user.id) ? ( - onChange('password', e.target.value)} - className={getInputClass('password', isEditing, user.role)} - disabled={!canEditField('password', isEditing, user.role)} - /> +
+ onChange('password', e.target.value)} + onClick={() => { + setPasswordCondition(true); + }} + className={getInputClass('password', isEditing, user.role)} + disabled={!canEditField('password', isEditing, user.role)} + /> + {passwordCondition && ( +
+ Password must contain at least:
+
    +
  • + - eight characters +
  • +
  • + - one capital letter +
  • +
  • - one number
  • +
  • + - one special character +
  • +
+
+ )} +
) : null}
diff --git a/src/pages/profile/editButton/index.jsx b/src/pages/profile/editButton/index.jsx index 5483110..eb6526f 100644 --- a/src/pages/profile/editButton/index.jsx +++ b/src/pages/profile/editButton/index.jsx @@ -1,7 +1,7 @@ import { useParams } from 'react-router-dom'; import useAuth from '../../../hooks/useAuth'; -export const ProfileEditButton = ({ isEditing, toggleEdit }) => { +export const ProfileEditButton = ({ isEditing, toggleEdit, canSave }) => { const { id: pathParamId } = useParams(); const { user } = useAuth(); @@ -10,7 +10,12 @@ export const ProfileEditButton = ({ isEditing, toggleEdit }) => { if (user.role !== 1 && !isOwnProfile) return null; return ( - ); diff --git a/src/service/apiClient.js b/src/service/apiClient.js index 0e4a154..3f0744d 100644 --- a/src/service/apiClient.js +++ b/src/service/apiClient.js @@ -28,8 +28,7 @@ async function register(email, password, longLife = false) { } async function patchProfile(userId, userData) { - const { password, ...dataToSend } = userData; - return await patch(`users/${userId}`, dataToSend, true, true); + return await patch(`users/${userId}`, userData, true, true); } // POST @@ -89,8 +88,9 @@ async function getUsersByName(name) { return await get(`users?name=${name}`, true, true); } -async function patchUser(id, photoUrl) { - return await patch(`users/${id}`, { photo: photoUrl }); +async function patchUser(userId, userData) { + const { password, ...dataToSend } = userData; + return await patch(`users/${userId}`, dataToSend, true, true); } // COHORTS