- Updated the colors of the application;

- Added the ability for a user to partially update their profile
This commit is contained in:
Tiago Ribeiro
2023-07-22 10:11:10 +01:00
parent 6ade34d243
commit 581adbb56e
19 changed files with 152 additions and 52 deletions

View File

@@ -4,13 +4,13 @@ import Navbar from "@/components/Navbar";
import {BsFileEarmarkText, BsPencil, BsStar, BsBook, BsHeadphones, BsPen, BsMegaphone, BsArrowRepeat} from "react-icons/bs";
import {withIronSessionSsr} from "iron-session/next";
import {sessionOptions} from "@/lib/session";
import {useEffect, useState} from "react";
import {ChangeEvent, useEffect, useRef, useState} from "react";
import useStats from "@/hooks/useStats";
import {averageScore, totalExams} from "@/utils/stats";
import useUser from "@/hooks/useUser";
import Sidebar from "@/components/Sidebar";
import Diagnostic from "@/components/Diagnostic";
import {ToastContainer} from "react-toastify";
import {toast, ToastContainer} from "react-toastify";
import {capitalize} from "lodash";
import {Module} from "@/interfaces";
import ProgressBar from "@/components/Low/ProgressBar";
@@ -20,6 +20,8 @@ import Input from "@/components/Low/Input";
import Button from "@/components/Low/Button";
import {useRouter} from "next/router";
import Link from "next/link";
import axios from "axios";
import {ErrorMessage} from "@/constants/errors";
export const getServerSideProps = withIronSessionSsr(({req, res}) => {
const user = req.session.user;
@@ -45,8 +47,12 @@ export default function Home() {
const [name, setName] = useState("");
const [email, setEmail] = useState("");
const [password, setPassword] = useState("");
const [confirmPassword, setConfirmPassword] = useState("");
const [newPassword, setNewPassword] = useState("");
const [isLoading, setIsLoading] = useState(false);
const [profilePicture, setProfilePicture] = useState("");
const profilePictureInput = useRef(null);
const router = useRouter();
const {user} = useUser({redirectTo: "/login"});
@@ -55,9 +61,56 @@ export default function Home() {
setName(user.name);
setEmail(user.email);
setBio(user.bio);
setProfilePicture(user.profilePicture);
}
}, [user]);
const convertBase64 = (file: File) => {
return new Promise((resolve, reject) => {
const fileReader = new FileReader();
fileReader.readAsDataURL(file);
fileReader.onload = () => {
resolve(fileReader.result);
};
fileReader.onerror = (error) => {
reject(error);
};
});
};
const uploadProfilePicture = async (event: ChangeEvent<HTMLInputElement>) => {
if (event.target.files && event.target.files[0]) {
const picture = event.target.files[0];
const base64 = await convertBase64(picture);
setProfilePicture(base64 as string);
}
};
const updateUser = async () => {
setIsLoading(true);
if (email !== user?.email && !password) {
toast.error("To update your e-mail you need to input your password!");
setIsLoading(false);
return;
}
if (newPassword && !password) {
toast.error("To update your password you need to input your current one!");
setIsLoading(false);
return;
}
const request = await axios.post("/api/users/update", {bio, name, email, password, newPassword});
if (request.status === 200) {
toast.success("Your profile has been updated!");
setTimeout(() => router.reload(), 800);
return;
}
toast.error((request.data as ErrorMessage).message);
setIsLoading(false);
};
return (
<>
<Head>
@@ -106,20 +159,20 @@ export default function Home() {
<Input
label="New Password"
type="password"
name="confirmPassword"
onChange={(e) => setConfirmPassword(e)}
placeholder="Confirm your password"
required
name="newPassword"
onChange={(e) => setNewPassword(e)}
placeholder="Enter your new password (optional)"
/>
</form>
</div>
<div className="flex flex-col gap-3 items-center w-48">
<img
src={user.profilePicture}
alt={user.name}
className="aspect-square h-48 w-48 rounded-full drop-shadow-xl self-end"
/>
<span className="cursor-pointer text-mti-purple-light text-sm">Change picture</span>
<img src={profilePicture} alt={user.name} className="aspect-square h-48 w-48 rounded-full drop-shadow-xl self-end" />
<input type="file" className="hidden" onChange={uploadProfilePicture} accept="image/*" ref={profilePictureInput} />
<span
onClick={() => (profilePictureInput.current as any)?.click()}
className="cursor-pointer text-mti-purple-light text-sm">
Change picture
</span>
</div>
</div>
<div className="flex flex-col gap-4 mt-8 mb-20">
@@ -134,11 +187,11 @@ export default function Home() {
<div className="self-end flex justify-between w-full gap-8 absolute bottom-8 left-0 px-8">
<Link href="/" className="max-w-[200px] self-end w-full">
<Button color="green" variant="outline" className="max-w-[200px] self-end w-full">
<Button color="purple" variant="outline" className="max-w-[200px] self-end w-full">
Back
</Button>
</Link>
<Button color="green" className="max-w-[200px] self-end w-full">
<Button color="purple" className="max-w-[200px] self-end w-full" onClick={updateUser} disabled={isLoading}>
Save Changes
</Button>
</div>