PROFILE PICTURES 🔥

This commit is contained in:
2024-06-28 01:10:50 +08:00
parent f474092e92
commit 286d9fe920
8 changed files with 566 additions and 11 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.5 KiB

View File

@@ -16,8 +16,8 @@ import {
} from "@nextui-org/react";
import { Form, Formik } from "formik";
import NextUIFormikInput from "./NextUIFormikInput";
import { PencilSquareIcon } from "../icons";
import { useNavigate } from "react-router-dom";
import UserProfilePicture from "./UserProfilePicture";
export default function UpdateAccountModule({
accessToken,
@@ -157,7 +157,7 @@ export default function UpdateAccountModule({
</div>
</div>
<div className="flex flex-row gap-8">
<div className="flex-grow flex sm:flex-row flex-col gap-4 *:w-full *:flex *:flex-col *:gap-4">
<div className="flex-grow flex sm:flex-row flex-col gap-4 *:w-full *:flex *:flex-col *:gap-4 *:my-auto">
<div>
<NextUIFormikInput
label="First Name"
@@ -196,12 +196,12 @@ export default function UpdateAccountModule({
/>
</div>
</div>
<div className="w-40 h-40 bg-red-500 hover:bg-red-700 transition-colors rounded-full relative">
<div className="transition-opacity opacity-0 hover:opacity-100 absolute w-full h-full text-white flex flex-col justify-center rounded-full">
<div className=" w-min h-min mx-auto scale-150">
<PencilSquareIcon />
</div>
</div>
<div>
<UserProfilePicture
userId={userInformation.id}
token={accessToken}
editable={true}
/>
</div>
</div>
</Form>

View File

@@ -0,0 +1,93 @@
import axios from "axios";
import React, { useRef, useState } from "react";
import config from "../config";
import { Button, Image } from "@nextui-org/react";
export default function UserProfilePicture({
userId,
token,
editable,
}: {
userId: string;
token: string;
editable: boolean;
}) {
const fileInputRef = useRef<HTMLInputElement>(null);
const [loading, setLoading] = useState(false);
const uploadProfileImage = async (
userId: string,
file: File,
token: string
) => {
const formData = new FormData();
formData.append("image", file);
try {
const response = await axios.put(
`${config.serverAddress}/users/profile-image/${userId}`,
formData,
{
headers: {
"Content-Type": "multipart/form-data",
Authorization: `Bearer ${token}`,
},
}
);
return response.data;
} catch (error) {
throw error;
}
};
const handleButtonClick = () => {
if (fileInputRef.current) {
fileInputRef.current.click();
}
};
const handleFileChange = (event: React.ChangeEvent<HTMLInputElement>) => {
if (event.target.files) {
const file = event.target.files[0];
uploadAndHandleSubmit(file);
}
};
const uploadAndHandleSubmit = async (file: File) => {
setLoading(true);
try {
await uploadProfileImage(userId, file, token);
} catch (error) {
} finally {
setLoading(false);
}
};
return (
<div>
<input
aria-label="profile image selector"
ref={fileInputRef}
className="hidden"
type="file"
accept="image/*"
onChange={handleFileChange}
/>
<Button
className="w-48 h-48 p-0 border-2 border-red-500 shadow-red-500 shadow-2xl"
radius="full"
onPress={editable ? handleButtonClick : () => {}}
isLoading={loading}
>
{loading ? (
<></>
) : (
<Image
src={`${config.serverAddress}/users/profile-image/${userId}`}
radius="full"
/>
)}
</Button>
</div>
);
}

View File

@@ -6,6 +6,7 @@ import { LockClosedIcon, PencilSquareIcon } from "../icons";
import SpringboardButton from "../components/SpringboardButton";
import { getTimeOfDay } from "../utilities";
import { retrieveUserInformation } from "../security/users";
import UserProfilePicture from "../components/UserProfilePicture";
export default function SpringboardPage() {
let { accessToken } = useParams<string>(); // TODO: Replace AT from props with AT from localstorage
@@ -65,7 +66,11 @@ export default function SpringboardPage() {
Manage your account
</Button>
</div>
<div className="bg-red-500 w-40 h-40 rounded-full"></div>
<UserProfilePicture
userId={userInformation.id}
token={accessToken!}
editable={false}
/>
</div>
<div className="flex flex-row justify-stretch *:w-full *:h-56 w-full p-4 pt-0 gap-4">
<SpringboardButton