From 820a05fa05af73c3e15b07c81e50ed8a1ab0803a Mon Sep 17 00:00:00 2001 From: leonardo messias Date: Sat, 17 Apr 2021 21:27:48 -0300 Subject: [PATCH] feat(user update): implementing user update feat --- src/DTOs/Auth.tsx | 14 ++- src/DTOs/User.tsx | 19 ++-- src/components/FormUpdate/index.tsx | 107 ++++++++++++++++++ src/components/FormUpdate/styles.ts | 38 +++++++ src/contexts/user.tsx | 30 +++-- src/pages/Register/index.tsx | 46 ++------ src/pages/Register/styles.ts | 32 ------ .../UserUpdate/ModalUpdateUser/index.tsx | 35 ++++++ .../UserUpdate/ModalUpdateUser/styles.ts | 33 ++++++ src/pages/UserUpdate/index.tsx | 71 ++++++++++++ src/pages/UserUpdate/styles.ts | 20 ++++ src/routes.tsx | 4 +- src/utils/updateSchemaValidation copy.ts | 9 ++ 13 files changed, 366 insertions(+), 92 deletions(-) create mode 100644 src/components/FormUpdate/index.tsx create mode 100644 src/components/FormUpdate/styles.ts create mode 100644 src/pages/UserUpdate/ModalUpdateUser/index.tsx create mode 100644 src/pages/UserUpdate/ModalUpdateUser/styles.ts create mode 100644 src/pages/UserUpdate/index.tsx create mode 100644 src/pages/UserUpdate/styles.ts create mode 100644 src/utils/updateSchemaValidation copy.ts diff --git a/src/DTOs/Auth.tsx b/src/DTOs/Auth.tsx index 8cbd58d..781e7c3 100644 --- a/src/DTOs/Auth.tsx +++ b/src/DTOs/Auth.tsx @@ -5,8 +5,13 @@ export interface AuthState { user: { id: string; type: string; - email: string; name: string; + email: string; + office: string; + area: string; + company: string; + phone: string; + password: string; }; } @@ -46,8 +51,13 @@ export interface AuthContextData { user: { id: string; type: string; - email: string; name: string; + email: string; + office: string; + area: string; + company: string; + phone: string; + password: string; }; invitation: InvitationData; register: RegisterData; diff --git a/src/DTOs/User.tsx b/src/DTOs/User.tsx index ba8334e..dcef0a0 100644 --- a/src/DTOs/User.tsx +++ b/src/DTOs/User.tsx @@ -1,26 +1,29 @@ import { ReactNode } from 'react'; export interface IUser { - name: string; - username: string; - email: string; -} - -interface UserData { id: string; - name: string; type: string; + name: string; + email: string; + office: string; + area: string; + company: string; + phone: string; + password: string; } export interface UserContextData { - users: Array; + users: Array; updateUserTypeSuccess: boolean; deleteUserLoader: boolean; deleteUserError: string; + updateUserInfoLoader: boolean; + updateUserInfoError: string; getUsers(): void; clearAllSuccessStatus(): void; deleteUser(id: string): void; updateUserType(credentials: { id: string; userType: string }): void; + updateUserInfo(credentials: IUser): void; } export interface UserProviderProps { diff --git a/src/components/FormUpdate/index.tsx b/src/components/FormUpdate/index.tsx new file mode 100644 index 0000000..8add678 --- /dev/null +++ b/src/components/FormUpdate/index.tsx @@ -0,0 +1,107 @@ +import React from 'react'; + +import { Form } from '@unform/web'; + +import InputForm from 'components/InputForm'; +import Button from 'components/Button/Button'; +import Input from 'components/Input/Input'; + +import { Container } from './styles'; + +interface FormUpdateProps { + handleSubmit: any; + formRef: any; + hasPasswordField?: boolean; + inviteInfo: { name: string; email: string }; + user?: { + id: string; + type: string; + name: string; + email: string; + office: string; + area: string; + company: string; + phone: string; + password: string; + }; +} + +function FormUpdate({ + handleSubmit, + formRef, + inviteInfo, + hasPasswordField, + user, +}: FormUpdateProps) { + return ( + +
+
+ + + + + + + + + + + + + {hasPasswordField && ( + <> + + + + + )} +
+ + +
+
+ ); +} + +FormUpdate.defaultProps = { + hasPasswordField: false, + user: { + name: '', + email: '', + office: '', + area: '', + company: '', + phone: '', + password: '', + }, +}; + +export default FormUpdate; diff --git a/src/components/FormUpdate/styles.ts b/src/components/FormUpdate/styles.ts new file mode 100644 index 0000000..19af5f3 --- /dev/null +++ b/src/components/FormUpdate/styles.ts @@ -0,0 +1,38 @@ +import styled from 'styled-components'; + +export const Container = styled.div` + width: 100%; + height: 100%; + + .Content { + display: flex; + flex-direction: column; + flex-wrap: wrap; + justify-content: center; + align-items: center; + width: 100%; + margin: 6rem 0; + + .inputContent { + display: flex; + flex-wrap: wrap; + align-items: center; + justify-content: center; + + width: 100%; + max-width: 90rem; + + > div { + margin: 10px 15px; + } + } + + .input-styled { + margin: 1.25rem; + } + + button { + margin-top: 6rem; + } + } +`; diff --git a/src/contexts/user.tsx b/src/contexts/user.tsx index 2aafdcc..8344481 100644 --- a/src/contexts/user.tsx +++ b/src/contexts/user.tsx @@ -2,23 +2,20 @@ import React, { useCallback, createContext, useState, useContext } from 'react'; import api from 'services/api'; -import { UserContextData, UserProviderProps } from 'DTOs/User'; +import { UserContextData, UserProviderProps, IUser } from 'DTOs/User'; const UsersContext = createContext({} as UserContextData); -interface UserData { - id: string; - name: string; - type: string; -} - const UsersProvider = ({ children }: UserProviderProps) => { - const [users, setUsers] = useState([ - { id: '', name: '', type: '' }, - ]); + const [users, setUsers] = useState([{} as IUser]); const [deleteUserLoader, setDeleteUserLoader] = useState(false); const [deleteUserError, setDeleteUserError] = useState(''); + + const [updateUserInfoError, setUpdateUserInfoError] = useState(''); + const [updateUserInfoLoader, setUpdateUserInfoLoader] = useState( + false, + ); const [updateUserTypeSuccess, setUpdateUserTypeSuccess] = useState( false, ); @@ -29,6 +26,16 @@ const UsersProvider = ({ children }: UserProviderProps) => { setUsers(response.data); }, []); + const updateUserInfo = useCallback(async data => { + setUpdateUserInfoLoader(true); + try { + await api.put('/users/logged', data); + } catch (error) { + setUpdateUserInfoError(error?.response?.data?.validation.body.message); + } + setUpdateUserInfoLoader(false); + }, []); + const updateUserType = useCallback(async ({ id, userType }) => { try { await api.patch(`/users/${id}`, { type: userType }); @@ -60,9 +67,12 @@ const UsersProvider = ({ children }: UserProviderProps) => { updateUserTypeSuccess, deleteUserLoader, deleteUserError, + updateUserInfoError, + updateUserInfoLoader, getUsers, deleteUser, updateUserType, + updateUserInfo, clearAllSuccessStatus, }} > diff --git a/src/pages/Register/index.tsx b/src/pages/Register/index.tsx index b83729c..a2aff1e 100644 --- a/src/pages/Register/index.tsx +++ b/src/pages/Register/index.tsx @@ -2,20 +2,17 @@ import React, { useRef, useCallback, useState } from 'react'; import { useParams } from 'react-router-dom'; import * as Yup from 'yup'; -import { Form } from '@unform/web'; import { FormHandles } from '@unform/core'; import { useAuth } from 'contexts/auth'; import { getInviteInfo } from 'services/auth'; +import FormUpdate from 'components/FormUpdate'; import LogoIcon from 'assets/logo.svg'; -import InputForm from 'components/InputForm'; -import Button from 'components/Button/Button'; import getValidationErrors from 'utils/getValidationErrors'; import registerSchemaValidation from 'utils/registerSchemaValidation'; -import Input from 'components/Input/Input'; import RegisterModal from './components/RegisterModal'; import StyledRegisterNewUser from './styles'; @@ -71,41 +68,12 @@ const RegisterNewUser = () => {
-
-
- - - - - - - - - - - - - - - -
- - -
+
diff --git a/src/pages/Register/styles.ts b/src/pages/Register/styles.ts index 4b03886..7a5a77e 100644 --- a/src/pages/Register/styles.ts +++ b/src/pages/Register/styles.ts @@ -26,38 +26,6 @@ const StyledRegisterNewUser = styled.div` flex-direction: column; justify-content: center; align-items: center; - - .Content { - display: flex; - flex-direction: column; - flex-wrap: wrap; - justify-content: center; - align-items: center; - width: 100%; - margin: 6rem 0; - - .inputContent { - display: flex; - flex-wrap: wrap; - align-items: center; - justify-content: center; - - width: 100%; - max-width: 80rem; - - > div { - margin: 10px 15px; - } - } - - .input-styled { - margin: 1.25rem; - } - - button { - margin-top: 6rem; - } - } } @media (max-width: 840px) { diff --git a/src/pages/UserUpdate/ModalUpdateUser/index.tsx b/src/pages/UserUpdate/ModalUpdateUser/index.tsx new file mode 100644 index 0000000..188f285 --- /dev/null +++ b/src/pages/UserUpdate/ModalUpdateUser/index.tsx @@ -0,0 +1,35 @@ +import React from 'react'; + +import DefaultModal from 'components/DefaultModal'; +import Loader from 'components/Loader'; +import { ReactComponent as LikeIcon } from 'assets/like.svg'; +import { ReactComponent as DislikeIcon } from 'assets/dislike.svg'; +import { useUsers } from 'contexts/user'; + +import { Container } from './styles'; + +interface ModalUpdateUserProps { + onClose: Function; +} + +const ModalUpdateUser = ({ onClose }: ModalUpdateUserProps) => { + const { updateUserInfoError, updateUserInfoLoader } = useUsers(); + + return ( + + + {updateUserInfoLoader ? ( + + ) : ( + <> + {updateUserInfoError ? : } +

{updateUserInfoError || 'ATUALIZADO!'}

+ {!updateUserInfoError &&

VOLTANDO...

} + + )} +
+
+ ); +}; + +export default ModalUpdateUser; diff --git a/src/pages/UserUpdate/ModalUpdateUser/styles.ts b/src/pages/UserUpdate/ModalUpdateUser/styles.ts new file mode 100644 index 0000000..66fe7a6 --- /dev/null +++ b/src/pages/UserUpdate/ModalUpdateUser/styles.ts @@ -0,0 +1,33 @@ +import styled from 'styled-components'; + +export const Container = styled.div` + display: flex; + flex-direction: column; + align-items: center; + justify-content: center; + height: 100%; + width: 100%; + + h1 { + font-family: Roboto; + font-style: normal; + font-weight: bold; + font-size: 4rem; + line-height: 5.9rem; + text-align: center; + color: #373435; + + margin: 1.6rem 0; + } + + p { + font-family: Roboto; + font-style: normal; + font-weight: normal; + font-size: 2.4rem; + line-height: 2.8rem; + text-align: center; + + color: #373435; + } +`; diff --git a/src/pages/UserUpdate/index.tsx b/src/pages/UserUpdate/index.tsx new file mode 100644 index 0000000..615a6de --- /dev/null +++ b/src/pages/UserUpdate/index.tsx @@ -0,0 +1,71 @@ +import React, { useRef, useState, useCallback } from 'react'; + +import * as Yup from 'yup'; + +import { FormHandles } from '@unform/core'; +import { getInviteInfo } from 'services/auth'; +import FormUpdate from 'components/FormUpdate'; + +import { useAuth } from 'contexts/auth'; +import { useUsers } from 'contexts/user'; +import { IUser } from 'DTOs/User'; + +import getValidationErrors from 'utils/getValidationErrors'; +import updateSchemaValidation from 'utils/updateSchemaValidation copy'; + +import ModalUpdateUser from './ModalUpdateUser'; + +import { Container } from './styles'; + +function UserUpdate() { + const { user } = useAuth(); + const { updateUserInfo } = useUsers(); + const formRef = useRef(null); + const inviteInfo = getInviteInfo(); + + const [showUpdateUserModal, setShowUpdateUserModal] = useState( + false, + ); + + const handleSubmit = useCallback( + async (data: IUser) => { + try { + formRef.current?.setErrors({}); + + const schema = Yup.object().shape(updateSchemaValidation); + + await schema.validate(data, { abortEarly: false }); + setShowUpdateUserModal(true); + await updateUserInfo(data); + } catch (err) { + const errors = getValidationErrors(err); + formRef.current?.setErrors(errors); + } + }, + [updateUserInfo], + ); + + const handleCloseUpdateUserModal = useCallback(() => { + setShowUpdateUserModal(false); + }, []); + + return ( + <> + {showUpdateUserModal && ( + + )} + + +

Atualizar informações

+ +
+ + ); +} + +export default UserUpdate; diff --git a/src/pages/UserUpdate/styles.ts b/src/pages/UserUpdate/styles.ts new file mode 100644 index 0000000..002c860 --- /dev/null +++ b/src/pages/UserUpdate/styles.ts @@ -0,0 +1,20 @@ +import styled from 'styled-components'; + +export const Container = styled.div` + display: flex; + flex-direction: column; + align-items: center; + padding: 3rem; + + h1 { + margin-top: 2rem; + + font-family: Roboto; + font-style: normal; + font-weight: 900; + font-size: 50px; + line-height: 59px; + + color: #cecfd0; + } +`; diff --git a/src/routes.tsx b/src/routes.tsx index b751f89..5f0d1e8 100644 --- a/src/routes.tsx +++ b/src/routes.tsx @@ -2,13 +2,13 @@ import React from 'react'; import { Switch, BrowserRouter, Redirect } from 'react-router-dom'; import { getMode } from 'services/api'; -import { getUser } from 'services/auth'; import Route from 'components/Route'; import { useAuth } from 'contexts/auth'; import Recovery from 'pages/Recovery'; +import UserUpdate from 'pages/UserUpdate'; import LandingPage from 'pages/LandingPage'; import ResetPassword from 'pages/ResetPassword'; import Register from 'pages/Register'; @@ -28,6 +28,7 @@ export default function Routes() { {isNotProduction && } + @@ -40,6 +41,7 @@ export default function Routes() { <> + )} diff --git a/src/utils/updateSchemaValidation copy.ts b/src/utils/updateSchemaValidation copy.ts new file mode 100644 index 0000000..b0661ba --- /dev/null +++ b/src/utils/updateSchemaValidation copy.ts @@ -0,0 +1,9 @@ +import * as Yup from 'yup'; + +export default { + name: Yup.string().required('Nome obrigatório'), + office: Yup.string().required('Cargo obrigatório'), + area: Yup.string().required('Área obrigatória'), + phone: Yup.string().required('Telefone obrigatório'), + company: Yup.string().required('Empresa obrigatória'), +};