diff --git a/src/pages/UserSettings/index.tsx b/src/pages/UserSettings/index.tsx new file mode 100644 index 0000000..9cca628 --- /dev/null +++ b/src/pages/UserSettings/index.tsx @@ -0,0 +1,550 @@ +import * as Yup from 'yup'; +import { useFormik } from 'formik'; +import { Redirect, useHistory, useParams } from 'react-router'; +import { useMutation, useQuery, useReactiveVar } from '@apollo/client'; +import { useState } from 'react'; +import { roleVar } from '../../graphql/state'; +import { + Box, + Button, + Text, + SectionSelector, + Input, + Select, + Alert, + Spinner, + Modal, +} from '../../components'; +import { Wrapper } from './styles'; +import { ArrowLeft, Profile, Security } from '../../assets'; +import { + UpdateUserInfoMutation, + UpdateUserPasswordMutation, + UpdateUserInfoMutationVariables, + UpdateUserPasswordMutationVariables, + GetCountryCodesQuery, + GetCountryCodesQueryVariables, + DeleteUserMutation, + DeleteUserMutationVariables, + GetUserByIdQuery, + GetUserByIdQueryVariables, + UserResponseModel, +} from '../../graphql/types'; +import { + DELETE_USER, + GET_COUNTRY_CODES, + GET_USER_BY_ID, + UPDATE_USER_INFO, + UPDATE_USER_PASSWORD, +} from '../../graphql/auth.api'; + +const UserSettings = () => { + const history = useHistory(); + const role = useReactiveVar(roleVar); + const [userToEdit, setUserToEdit] = useState(); + const { id } = useParams<{ id: string }>(); + const { data: countryCodes, loading: countryCodesLoading } = useQuery< + GetCountryCodesQuery, + GetCountryCodesQueryVariables + >(GET_COUNTRY_CODES); + const { loading: userInfoLoading } = useQuery< + GetUserByIdQuery, + GetUserByIdQueryVariables + >(GET_USER_BY_ID, { + variables: { + id, + }, + onCompleted({ getUserById }) { + setUserToEdit(getUserById); + }, + }); + + const [selectedSection, setSelectedSection] = useState< + 'general' | 'security' + >('general'); + const [error, setError] = useState(''); + const [success, setSuccess] = useState(false); + const [deleteAccountModal, setDeleteAccountModal] = useState(false); + + const [updateUserInfo, { loading: generalLoading }] = useMutation< + UpdateUserInfoMutation, + UpdateUserInfoMutationVariables + >(UPDATE_USER_INFO, { + onCompleted({ updateUserInfo: user }) { + setUserToEdit(user); + generalForm.setFieldValue('firstName', user.firstName); + generalForm.setFieldValue('lastName', user.lastName); + generalForm.setFieldValue('prefix', user.phone.prefix); + generalForm.setFieldValue('number', user.phone.number); + generalForm.setFieldValue('place', user.address.place); + generalForm.setFieldValue('city', user.address.city); + generalForm.setFieldValue('zip', user.address.zip); + generalForm.setFieldValue('country', user.address.country); + setSuccess(true); + setTimeout(() => setSuccess(false), 3000); + }, + onError({ graphQLErrors }) { + setError(graphQLErrors[0]?.extensions?.info); + setTimeout(() => setError(''), 3000); + }, + }); + + const generalForm = useFormik({ + initialValues: { + firstName: userToEdit?.firstName || '', + lastName: userToEdit?.lastName || '', + prefix: userToEdit?.phone.prefix || '', + number: userToEdit?.phone.number || '', + place: userToEdit?.address.place || '', + city: userToEdit?.address.city || '', + zip: userToEdit?.address.zip || '', + country: userToEdit?.address.country || '', + }, + validationSchema: Yup.object().shape({ + firstName: Yup.string().required('First Name is required'), + lastName: Yup.string().required('Last Name is required'), + prefix: Yup.string().required('Prefix is required'), + // prettier-ignore + number: Yup.number().typeError('Phone must be a number').required('Phone is required'), + place: Yup.string().required('Address is required'), + city: Yup.string().required('City is required'), + country: Yup.string().required('Country is required'), + // prettier-ignore + zip: Yup.number().typeError('Zip must be a number').required('Zip is required'), + }), + onSubmit: ({ + firstName, + lastName, + prefix, + number, + place, + city, + country, + zip, + }) => + updateUserInfo({ + variables: { + id: userToEdit?.id!, + email: userToEdit?.email!, + firstName, + lastName, + phone: { prefix, number }, + address: { place, city, country, zip }, + }, + }), + enableReinitialize: true, + }); + + const [updateUserPassword, { loading: securityLoading }] = useMutation< + UpdateUserPasswordMutation, + UpdateUserPasswordMutationVariables + >(UPDATE_USER_PASSWORD, { + onCompleted({ updateUserPassword: user }) { + setUserToEdit(user); + setSuccess(true); + setTimeout(() => setSuccess(false), 3000); + }, + onError({ graphQLErrors }) { + setError(graphQLErrors[0]?.extensions?.info); + setTimeout(() => setError(''), 3000); + }, + }); + + const securityForm = useFormik({ + initialValues: { + oldPassword: '', + newPassword: '', + confirmNewPassword: '', + }, + validationSchema: Yup.object().shape({ + oldPassword: Yup.string() + .required('Old password is required') + .min(6, 'Old password is 6 characters minimum'), + newPassword: Yup.string() + .required('New password is required') + .notOneOf( + [Yup.ref('oldPassword')], + 'New password should not be old password' + ) + .required('New password is required') + .min(6, 'New password is 6 characters minimum'), + confirmNewPassword: Yup.string() + .required('Confirm new password is required') + .oneOf( + [Yup.ref('newPassword')], + "Confirm new password doesn't match with new password" + ), + }), + onSubmit: ({ oldPassword, newPassword }) => + updateUserPassword({ + variables: { + id: userToEdit?.id!, + password: { oldPassword, newPassword }, + }, + }), + }); + + const [deleteUser] = useMutation< + DeleteUserMutation, + DeleteUserMutationVariables + >(DELETE_USER, { + onCompleted() { + setDeleteAccountModal(false); + history.goBack(); + }, + onError({ graphQLErrors }) { + setDeleteAccountModal(false); + setError(graphQLErrors[0]?.extensions?.info); + setTimeout(() => setError(''), 3000); + }, + }); + + const deleteAccountForm = useFormik({ + initialValues: { + password: '', + }, + validationSchema: Yup.object().shape({ + password: Yup.string() + .required('Password is required') + .min(6, 'Password is 6 characters minimum'), + }), + onSubmit: ({ password }, { resetForm }) => { + try { + deleteUser({ variables: { id: userToEdit?.id!, password } }); + } finally { + resetForm(); + } + }, + }); + + return role === 'admin' ? ( + + +