- Updated the colors of the application;
- Added the ability for a user to partially update their profile
This commit is contained in:
@@ -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>
|
||||
|
||||
Reference in New Issue
Block a user