source: frontend/src/pages/Register.tsx@ 77e572b

main
Last change on this file since 77e572b was 4e5cf92, checked in by Filip Gavrilovski <filipgavrilovski28@…>, 6 months ago

refactor frontend file structure

  • Property mode set to 100644
File size: 4.6 KB
Line 
1import { useEffect, useState } from "react";
2import { useNavigate } from "react-router";
3import axiosInstance, { scheduleTokenRefresh } from "../api/axiosInstance";
4import { useAuth } from "../context/authContext";
5import type { User } from "../utils/types";
6
7const Register = () => {
8 const { setUser } = useAuth();
9 const [username, setUsername] = useState("");
10 const [password, setPassword] = useState("");
11 const [fullname, setFullname] = useState("");
12 const [email, setEmail] = useState("");
13 const [profilePhotoFile, setProfilePhotoFile] = useState<File | null>(null);
14 const [previewProfilePhoto, setPreviewProfilePhoto] = useState<string | null>(
15 null,
16 );
17
18 const navigate = useNavigate();
19
20 useEffect(() => {
21 return () => {
22 if (previewProfilePhoto) {
23 URL.revokeObjectURL(previewProfilePhoto);
24 }
25 };
26 }, [previewProfilePhoto]);
27
28 const handleRegister = async (e: React.FormEvent) => {
29 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
47 try {
48 const response = await axiosInstance.post<{
49 user: User;
50 tokenExpiresIn: number;
51 }>("/auth/register", formData);
52 scheduleTokenRefresh(response.data.tokenExpiresIn);
53 setUser(response.data.user);
54 navigate("/");
55 } catch (error) {
56 console.error("Registration failed:", error);
57 }
58 };
59
60 return (
61 <div className="flex flex-col items-center justify-center min-h-[90vh] bg-gray-100">
62 <h2 className="text-2xl mb-4">Register</h2>
63 <form className="bg-white p-6 rounded shadow-md w-80">
64 <div className="mb-4">
65 <label className="block text-gray-700 mb-2" htmlFor="username">
66 Username
67 </label>
68 <input
69 type="text"
70 id="username"
71 className="w-full p-2 border border-gray-300 rounded"
72 value={username}
73 onChange={(e) => setUsername(e.target.value)}
74 />
75 </div>
76 <div className="mb-4">
77 <label className="block text-gray-700 mb-2" htmlFor="password">
78 Password
79 </label>
80 <input
81 type="password"
82 id="password"
83 className="w-full p-2 border border-gray-300 rounded"
84 value={password}
85 onChange={(e) => setPassword(e.target.value)}
86 />
87 </div>
88 <div className="mb-4">
89 <label className="block text-gray-700 mb-2" htmlFor="fullName">
90 Full Name
91 </label>
92 <input
93 type="text"
94 id="fullName"
95 className="w-full p-2 border border-gray-300 rounded"
96 value={fullname}
97 onChange={(e) => setFullname(e.target.value)}
98 />
99 </div>
100 <div className="mb-4">
101 <label className="block text-gray-700 mb-2" htmlFor="email">
102 Email
103 </label>
104 <input
105 type="email"
106 id="email"
107 className="w-full p-2 border border-gray-300 rounded"
108 value={email}
109 onChange={(e) => setEmail(e.target.value)}
110 />
111 </div>
112 <div className="mb-4">
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>
125 <input
126 type="file"
127 accept="image/*"
128 id="profilePhoto"
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 }}
136 />
137 </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 )}
148 <button
149 type="submit"
150 className="w-full bg-blue-500 text-white p-2 rounded hover:bg-blue-600 cursor-pointer"
151 onClick={handleRegister}
152 >
153 Register
154 </button>
155 </form>
156 </div>
157 );
158};
159
160export default Register;
Note: See TracBrowser for help on using the repository browser.