Skip to content

Commit

Permalink
Merge pull request #70 from Elizabethhub/feature/setting-modal
Browse files Browse the repository at this point in the history
avatar sending
  • Loading branch information
Elizabethhub authored Mar 19, 2024
2 parents ad6222f + c61ca02 commit 79449ad
Show file tree
Hide file tree
Showing 5 changed files with 174 additions and 44 deletions.
146 changes: 111 additions & 35 deletions src/components/SettingModal/SettingModal.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -33,43 +33,87 @@ import UploadingPhoto from './UploadingPhoto';
import { useForm } from 'react-hook-form';
import OpenPassEye from '../../images/AuthImg/OpenPassEye';
import PassEye from '../../images/AuthImg/PassEye';
import { useDispatch, useSelector } from 'react-redux';
import { selectUser } from '../../store/auth/selectors';
import { updateAvatarThunk } from '../../store/auth/thunks';
// import { toast } from 'react-toastify';

const schema = yup
.object({
name: yup
.string()
.max(32, 'Name must contain a maximum of 32 characters')
.required('Name is required'),
email: yup
.string()
.email('Please write valid email')
.matches(/^(?!.*@[^,]*,)/)
.required('Email is required'),
oldPassword: yup
.string()
.min(8, 'Password must be at least 8 characters')
.max(64)
.required('Password is required'),
newPassword: yup
.string()
.min(8, 'Password must be at least 8 characters')
.max(64)
.required('Password is required'),

confirmPassword: yup
.string()
.oneOf(
[yup.ref('newPassword'), null],
"Passwords don't match, please try again."
)
.min(8, 'Password must be at least 8 characters')
.required('Confirm password is required'),
})
.required();
const schema = yup.object({
name: yup.string().max(32, 'Name must contain a maximum of 32 characters'),
// .required('Name is required')
email: yup
.string()
.email('Please write valid email')
.matches(/^(?!.*@[^,]*,)/)
.required('Email is required'),
oldPassword: yup
.string()

// .min(8, 'Password must be at least 8 characters')
.max(64),

// .required('Password is required')
newPassword: yup
.string()
// .min(8, 'Password must be at least 8 characters')
.max(64),
// .required('Password is required')
confirmPassword: yup
.string()
.oneOf(
[yup.ref('newPassword'), null],
"Passwords don't match, please try again."
),
// .min(8, 'Password must be at least 8 characters')
// .required('Confirm password is required')
});

// const schema = yup.object({
// name: yup
// .string()
// .max(32, 'Name must contain a maximum of 32 characters')
// .required('Name is required'),
// email: yup
// .string()
// .email('Please write valid email')
// .matches(/^(?!.*@[^,]*,)/)
// .required('Email is required'),
// oldPassword: yup
// .string()
// .nullable()
// .when('oldPassword', {
// is: (val) => val && val.length > 0,
// then: yup.string().min(8, 'Password must be at least 8 characters').max(64),
// }),
// newPassword: yup
// .string()
// .nullable()
// .when('newPassword', {
// is: (val) => val && val.length > 0,
// then: yup.string().min(8, 'Password must be at least 8 characters').max(64),
// }),
// confirmPassword: yup
// .string()
// .nullable()
// .oneOf(
// [yup.ref('newPassword'), null],
// "Passwords don't match, please try again."
// ),
// });

const SettingModal = ({ onClose }) => {
const user = useSelector(selectUser);
// const [imageUser, setImageUser] = useState('');
// const [name, setName] = useState('');
// const [newEmail, setNewEmail] = useState(email || '');
// const [oldPassword, setoldPassword] = useState('');

// const userProfile = useSelector(selectUser);

const [eyePass, setEyePass] = useState(false);

const dispatch = useDispatch();

const {
register,
handleSubmit,
Expand All @@ -80,7 +124,20 @@ const SettingModal = ({ onClose }) => {
});

function submit(data) {
const formData = new FormData();
formData.append('avatarURL', data.avatarURL[0]);
dispatch(updateAvatarThunk(formData));

console.log(formData);

console.log(data);
// dispatch(updateAvatarThunk(data))
// .unwrap()
// .then((res) => {
// toast.success(`${res.user.username} your avater has been chsanged`);
// // navigate('/home');
// })
// .catch((err) => toast.error(err));
}

function showPass() {
Expand All @@ -99,6 +156,20 @@ const SettingModal = ({ onClose }) => {
setValue(event.target.value);
};

// const handleInputChange = ({ target }) => {
// if (target.name === 'name') {
// setName(target.value);
// }
// if (target.name === 'email') {
// setNewEmail(target.value);
// }
// if (target.name === 'oldPassword') {
// setoldPassword(target.value);
// }

// console.log(target.value);
// };

return (
<Overlay onClick={handleClick}>
<Modal>
Expand All @@ -108,12 +179,12 @@ const SettingModal = ({ onClose }) => {
<ModalTitle>Setting</ModalTitle>
<Form
onSubmit={handleSubmit(submit)}
encType="multipart/form-data"
// encType="multipart/form-data"
$errors={errors}
>
<BlockWrap8>
<BigLabel htmlFor="photo">Your photo</BigLabel>
<UploadingPhoto id="photo" register={register} />
<BigLabel htmlFor="avatarURL">Your photo</BigLabel>
<UploadingPhoto id="avatarURL" register={register} />
</BlockWrap8>

<ExternalBlockWrap24>
Expand Down Expand Up @@ -164,6 +235,8 @@ const SettingModal = ({ onClose }) => {
type="text"
id="name"
placeholder="Your name"
// onChange={handleInputChange}
defaultValue={user?.username}
/>
</BlockWrap8>
<ErrorSpan>{errors.name?.message}</ErrorSpan>
Expand All @@ -177,6 +250,7 @@ const SettingModal = ({ onClose }) => {
type="email"
id="email"
placeholder="E-mail"
defaultValue={user?.email}
/>
</BlockWrap8>
<ErrorSpan>{errors.email?.message}</ErrorSpan>
Expand All @@ -197,6 +271,8 @@ const SettingModal = ({ onClose }) => {
type={eyePass ? 'text' : 'password'}
id="oldPassword"
placeholder="Password"
// onChange={handleInputChange}
// value={oldPassword}
/>
<ErrorSpan>{errors.oldPassword?.message}</ErrorSpan>
<PassShowBtn type="button" onClick={showPass}>
Expand Down
11 changes: 6 additions & 5 deletions src/components/SettingModal/SettingModal.styled.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,15 @@ export const Overlay = styled.div`
position: fixed;
top: 0;
left: 0;
width: 100vw;
height: 100vh;
width: 100%;
height: 100%;
display: flex;
justify-content: center;
align-items: flex-start;
padding: 40px 20px;
background: rgba(0, 0, 0, 0.8);
background: var(--modal-backdrop);
z-index: 1200;
overflow-y: hidden;
@media only screen and (min-width: 768px) {
padding: 40px 32px;
Expand All @@ -31,10 +32,10 @@ export const Modal = styled.div`
@media only screen and (min-width: 768px) {
padding: 32px 24px;
min-width: 704px;
max-width: 704px;
}
@media only screen and (min-width: 1440px) {
width: 1008px;
max-width: 1008px;
min-height: 592px;
}
`;
Expand Down
20 changes: 17 additions & 3 deletions src/components/SettingModal/UploadingPhoto.jsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
import { useState } from 'react';
import { useEffect, useState } from 'react';
import styled from 'styled-components';
import PersonIcon from '../../images/SettingModal/PersonIcon';
import Upload from '../../images/SettingModal/Upload';
import { useSelector } from 'react-redux';
import { selectUser } from '../../store/auth/selectors';

const InputImg = styled.img`
width: 80px;
Expand Down Expand Up @@ -38,6 +40,18 @@ const PInput = styled.p`

const UploadingPhoto = ({ register }) => {
const [imageSrc, setImageSrc] = useState('');
const user = useSelector(selectUser);

useEffect(() => {
if (user && user.avatarURL) {
let avatarURL = user.avatarURL;

if (avatarURL.startsWith('avatars')) {
avatarURL = `https://byte-water-back.onrender.com/${avatarURL}`;
}
setImageSrc(avatarURL);
}
}, [user]);

const handleFileChange = (event) => {
const file = event.target.files[0];
Expand All @@ -55,8 +69,8 @@ const UploadingPhoto = ({ register }) => {
return (
<InputContainer htmlFor="fileInput">
<HiddenInput
{...register('photo')}
name="photo"
{...register('avatarURL')}
name="avatarURL"
id="fileInput"
type="file"
accept="image/*"
Expand Down
19 changes: 18 additions & 1 deletion src/store/auth/slice.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,11 @@
import { createSlice } from '@reduxjs/toolkit';
import { currentThunk, logoutThunk, signInThunk, signUpThunk } from './thunks';
import {
currentThunk,
logoutThunk,
signInThunk,
signUpThunk,
updateAvatarThunk,
} from './thunks';

const authSlice = createSlice({
name: 'Auth',
Expand Down Expand Up @@ -56,6 +62,17 @@ const authSlice = createSlice({
.addCase(logoutThunk.rejected, (state, { payload }) => {
state.error = payload;
state.isLoading = false;
})
.addCase(updateAvatarThunk.pending, (state) => {
state.isLoading = true;
})
.addCase(updateAvatarThunk.fulfilled, (state, { payload }) => {
state.user = payload?.user;
state.isLoading = false;
})
.addCase(updateAvatarThunk.rejected, (state, { payload }) => {
state.error = payload;
state.isLoading = false;
});
},
});
Expand Down
22 changes: 22 additions & 0 deletions src/store/auth/thunks.js
Original file line number Diff line number Diff line change
Expand Up @@ -57,3 +57,25 @@ export const logoutThunk = createAsyncThunk(
}
}
);

export const updateAvatarThunk = createAsyncThunk(
'user/updateAvatar',
async (body, thunkAPI) => {
try {
const token = thunkAPI.getState().auth.token;

if (token) {
setToken(token);
}
// api.defaults.headers.contentType = 'multipart/form-data';
const { data } = await api.patch('users/avatars', body, {
headers: {
'Content-type': 'multipart/form-data',
},
});
return data;
} catch (error) {
thunkAPI.rejectWithValue(error.message);
}
}
);

0 comments on commit 79449ad

Please sign in to comment.