Ignore:
Timestamp:
01/26/26 19:03:37 (6 months ago)
Author:
Filip Gavrilovski <filipgavrilovski28@…>
Branches:
main
Children:
d47e225
Parents:
3727852
Message:

add support for profile pictures

File:
1 edited

Legend:

Unmodified
Added
Removed
  • frontend/src/Register.tsx

    r3727852 r484dc3f  
    1 import { useState } from "react";
     1import { useEffect, useState } from "react";
    22import { useNavigate } from "react-router";
    33import axiosInstance, { scheduleTokenRefresh } from "./api/axiosInstance";
     
    1111        const [fullname, setFullname] = useState("");
    1212        const [email, setEmail] = useState("");
    13         const [profilePhoto, setProfilePhoto] = useState<string | null>(null);
     13        const [profilePhotoFile, setProfilePhotoFile] = useState<File | null>(null);
     14        const [previewProfilePhoto, setPreviewProfilePhoto] = useState<string | null>(
     15                null,
     16        );
    1417
    1518        const navigate = useNavigate();
    1619
     20        useEffect(() => {
     21                return () => {
     22                        if (previewProfilePhoto) {
     23                                URL.revokeObjectURL(previewProfilePhoto);
     24                        }
     25                };
     26        }, [previewProfilePhoto]);
     27
    1728        const handleRegister = async (e: React.FormEvent) => {
    1829                e.preventDefault();
     30                // todo: add proper error handling
     31                if (profilePhotoFile && profilePhotoFile.size > 5 * 1024 * 1024) {
     32                        alert("Max file size is 5MB");
     33                        return;
     34                }
     35
     36                if (profilePhotoFile && !profilePhotoFile.type.startsWith("image/")) {
     37                        alert("Only images allowed");
     38                        return;
     39                }
     40                const formData = new FormData();
     41                if (profilePhotoFile) formData.append("profilePhoto", profilePhotoFile);
     42                formData.append("username", username);
     43                formData.append("fullname", fullname);
     44                formData.append("email", email);
     45                formData.append("password", password);
     46
    1947                try {
    2048                        const response = await axiosInstance.post<{
    2149                                user: User;
    2250                                tokenExpiresIn: number;
    23                         }>("/auth/register", {
    24                                 username,
    25                                 fullname,
    26                                 email,
    27                                 password,
    28                                 profilePhoto,
    29                         });
     51                        }>("/auth/register", formData);
    3052                        scheduleTokenRefresh(response.data.tokenExpiresIn);
    3153                        setUser(response.data.user);
     
    89111                                </div>
    90112                                <div className="mb-4">
    91                                         <label className="block text-gray-700 mb-2" htmlFor="profilePhoto">
    92                                                 Profile Photo URL
    93                                         </label>
     113                                        <label className="block text-gray-700 mb-2">Profile Photo</label>
     114                                        <div className="flex items-center gap-3">
     115                                                <label
     116                                                        htmlFor="profilePhoto"
     117                                                        className="px-4 py-2 bg-blue-500 text-white rounded cursor-pointer hover:bg-blue-600 transition-colors text-sm font-medium"
     118                                                >
     119                                                        Choose File
     120                                                </label>
     121                                                <span className="text-gray-600 text-sm">
     122                                                        {profilePhotoFile ? profilePhotoFile.name : "No file chosen"}
     123                                                </span>
     124                                        </div>
    94125                                        <input
    95                                                 placeholder="todo"
    96                                                 type="text"
     126                                                type="file"
     127                                                accept="image/*"
    97128                                                id="profilePhoto"
    98                                                 className="w-full p-2 border border-gray-300 rounded"
    99                                                 value={profilePhoto || ""}
    100                                                 onChange={(e) => setProfilePhoto(e.target.value)}
     129                                                className="hidden"
     130                                                onChange={(e) => {
     131                                                        if (e.target.files && e.target.files[0]) {
     132                                                                setProfilePhotoFile(e.target.files[0]);
     133                                                                setPreviewProfilePhoto(URL.createObjectURL(e.target.files[0]));
     134                                                        }
     135                                                }}
    101136                                        />
    102137                                </div>
     138                                {previewProfilePhoto && (
     139                                        <div className="mb-4">
     140                                                <p className="block text-gray-700 mb-2">Profile Photo Preview:</p>
     141                                                <img
     142                                                        src={previewProfilePhoto}
     143                                                        alt="Profile Preview"
     144                                                        className="w-20 h-20 object-cover rounded-full"
     145                                                />
     146                                        </div>
     147                                )}
    103148                                <button
    104149                                        type="submit"
    105150                                        className="w-full bg-blue-500 text-white p-2 rounded hover:bg-blue-600 cursor-pointer"
    106                                         onClick={(e: React.MouseEvent<HTMLButtonElement>) =>
    107                                                 handleRegister(e)
    108                                         }
     151                                        onClick={handleRegister}
    109152                                >
    110153                                        Register
Note: See TracChangeset for help on using the changeset viewer.