Skip to content

Commit

Permalink
feat: Update profile (unfinished)
Browse files Browse the repository at this point in the history
  • Loading branch information
TiagoRibeiro25 committed Aug 24, 2023
1 parent 780cedf commit e52add1
Show file tree
Hide file tree
Showing 3 changed files with 236 additions and 0 deletions.
35 changes: 35 additions & 0 deletions src/views/ProfileEdit/components/AccountInfo/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import Input from '../../../../components/Input';

interface AccountInfoProps {
id: number;
email: string;
}

const AccountInfo: React.FC<AccountInfoProps> = ({ id, email }) => {
return (
<section
id="account-info"
className="flex flex-col mt-4 mb-12 space-y-6 sm:space-x-20 sm:flex-row sm:space-y-0 sm:mb-4"
>
<Input
type="number"
id="user-local-id"
name="user-local-id"
value={id.toString()}
disabled
placeholder="Internal User ID"
/>

<Input
type="email"
id="user-email"
name="user-email"
value={email}
disabled
placeholder="Email Address"
/>
</section>
);
};

export default AccountInfo;
103 changes: 103 additions & 0 deletions src/views/ProfileEdit/components/UserPicture/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
import classNames from 'classnames';
import React, { useEffect, useState } from 'react';
import { LazyLoadImage } from 'react-lazy-load-image-component';
import LoadingIcon from '../../../../assets/icons/loading.svg';
import UserNoPicture from '../../../../assets/imgs/user.webp';
import Button from '../../../../components/Button';
import DropZone from '../../../../components/DropZone';
import Reveal from '../../../../components/Reveal';
import { Base64Img } from '../../../../types/types';

interface UserPictureProps {
userImage: string;
}

//TODO: API call to update user image
const UserPicture: React.FC<UserPictureProps> = ({ userImage }) => {
const [updatedImage, setUpdatedImage] = useState<Base64Img[]>([]);
const [isLoading, setIsLoading] = useState<boolean>(false);

const handleSubmit = (e: React.FormEvent<HTMLFormElement>) => {
e.preventDefault();
setIsLoading(true);
};

useEffect(() => {
// Every time an image is added to the array, only keep the last one
if (updatedImage.length > 1) {
setUpdatedImage([updatedImage[updatedImage.length - 1]]);
}
}, [updatedImage]);

return (
<section id="update-user-picture">
<form
className="flex flex-col w-full md:space-x-20 md:flex-row"
onSubmit={handleSubmit}
>
<div className="flex flex-col items-center mb-8 md:w-1/2 md:mb-0">
<Reveal width="100%" animation="slide-right" delay={0.05}>
<h2 className="w-full mb-4 text-2xl font-bellefair text-start">
Update your profile picture
</h2>
</Reveal>
<Reveal width="100%" animation="slide-left" delay={0.05}>
<div className="flex justify-center">
<LazyLoadImage
className="my-4 rounded-full w-60 h-60"
src={updatedImage.length > 0 ? updatedImage[0] : userImage}
placeholderSrc={UserNoPicture}
effect="blur"
alt="User Profile Picture"
/>
</div>
</Reveal>

<Reveal width="100%" animation="slide-bottom">
<div className="flex flex-row justify-center mt-6 space-x-10">
<Button
type="submit"
id="update-user-picture-button"
className={classNames(
'text-white bg-zinc-800 py-1.5 disabled:cursor-not-allowed flex justify-center',
isLoading ? 'w-36' : 'w-32',
)}
icon={isLoading ? LoadingIcon : ''}
iconAlt="Loading Icon"
iconAnimation="spin"
disabled={updatedImage.length === 0}
>
Update Image
</Button>

<Button
type="reset"
id="reset-user-picture-button"
className={classNames(
'text-black bg-white border border-zinc-800 py-1.5 w-32 flex justify-center disabled:cursor-not-allowed',
isLoading ? 'w-36' : 'w-32',
)}
disabled={updatedImage.length === 0}
onClick={() => setUpdatedImage([])}
>
Reset
</Button>
</div>
</Reveal>
</div>

<div className="flex items-center justify-center md:w-1/2">
<Reveal width="100%" animation="slide-right" delay={0.05}>
<DropZone
images={updatedImage}
setImages={setUpdatedImage}
maxAllowedImages={1}
/>
</Reveal>
</div>
</form>
</section>
);
};

export default UserPicture;
98 changes: 98 additions & 0 deletions src/views/ProfileEdit/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
import { useEffect, useState } from 'react';
import requests from '../../api/requests';
import UserNoPicture from '../../assets/imgs/user.webp';
import ErrorOccurred from '../../components/ErrorOccurred';
import Loading from '../../components/Loading';
import Reveal from '../../components/Reveal';
import { IUser } from '../../types/types';
import AccountInfo from './components/AccountInfo';
import UserPicture from './components/UserPicture';

type ExcludedUserProperties =
| 'followers'
| 'following'
| 'isLoggedUser'
| 'isFollowing'
| 'createdAt';

export interface User extends Omit<IUser, ExcludedUserProperties> {}

const ProfileEdit: React.FC = () => {
const [isLoading, setIsLoading] = useState<boolean>(false);
const [errorOccurred, setErrorOccurred] = useState<boolean>(false);
const [user, setUser] = useState<User>({} as User);

useEffect(() => {
setIsLoading(true);

const fetchUserData = async (): Promise<void> => {
try {
const response = await requests.users.getLoggedUser();

if (response.data.success && response.data.data) {
setUser({
id: response.data.data.id,
username: response.data.data.username,
email: response.data.data.email,
userImage: response.data.data.userImage,
description: response.data.data.description ?? '',
blocked: response.data.data.blocked,
isAdmin: response.data.data.isAdmin,
resetPasswordToken: response.data.data.resetPasswordToken,
});
} else {
throw new Error(response.data.message);
}
} catch (error) {
console.log("An error occurred while trying to fetch the user's data: ", error);
setErrorOccurred(true);
} finally {
setIsLoading(false);
}
};

fetchUserData();
}, []);

return (
<div className="flex flex-col items-center justify-center max-w-3xl mx-auto">
<Reveal width="100%" animation="slide-right" delay={0.05}>
<h1 className="w-full my-3 text-3xl font-bellefair">Edit Profile</h1>
</Reveal>

{isLoading && (
<div className="h-[50vh] flex justify-center items-center">
<Reveal width="100%" animation="slide-bottom" delay={0.1}>
<Loading />
</Reveal>
</div>
)}

{!isLoading && errorOccurred && (
<div className="h-[50vh] flex justify-center items-center">
<ErrorOccurred text="An error occurred while trying to fetch the user data." />
</div>
)}

{!isLoading && !errorOccurred && Object.keys(user).length > 0 && (
<div className="w-full my-6">
<Reveal width="100%" animation="slide-bottom" delay={0.05}>
<AccountInfo id={user.id} email={user.email ?? ''} />
</Reveal>

<Reveal width="100%" animation="fade" delay={0.3}>
<hr className="h-px mb-10 bg-gray-200 border-0" />
</Reveal>

<UserPicture userImage={user.userImage?.cloudinaryImage ?? UserNoPicture} />

<Reveal width="100%" animation="fade" delay={0.3}>
<hr className="h-px my-12 mb-10 bg-gray-200 border-0" />
</Reveal>
</div>
)}
</div>
);
};

export default ProfileEdit;

0 comments on commit e52add1

Please sign in to comment.