source: frontend/src/pages/Login.tsx@ 3238007

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

add custom exceptions and proper server side error handling

  • Property mode set to 100644
File size: 2.3 KB
Line 
1import { useState } from "react";
2import { useNavigate } from "react-router-dom";
3import { toast } from "react-toastify";
4import axiosInstance, { scheduleTokenRefresh } from "../api/axiosInstance";
5import { useAuth } from "../context/authContext";
6import type { User } from "../utils/types";
7
8const Login = () => {
9 const [username, setUsername] = useState("");
10 const [password, setPassword] = useState("");
11 const [error, setError] = useState<string | null>(null);
12 const { setUser } = useAuth();
13 const navigate = useNavigate();
14
15 const handleLogin = async (e: React.FormEvent) => {
16 e.preventDefault();
17 try {
18 const response = await axiosInstance.post<{
19 user: User;
20 tokenExpiresIn: number;
21 }>("/auth/login", { username, password });
22 scheduleTokenRefresh(response.data.tokenExpiresIn);
23 setUser(response.data.user);
24 navigate("/");
25 toast.success("Login successful!");
26 } catch (error: any) {
27 const errorMessage =
28 error.response?.data?.error ||
29 "Login failed. Please check your credentials.";
30 setError(`Login failed: ${errorMessage}`);
31 }
32 };
33 return (
34 <div className="flex flex-col items-center justify-center min-h-[90vh] bg-gray-100">
35 <h2 className="text-2xl mb-4">Login</h2>
36 <form
37 onSubmit={handleLogin}
38 className="bg-white p-6 rounded shadow-md w-80"
39 >
40 {error && <p className="text-red-500 mb-4">{error}</p>}
41 <div className="mb-4">
42 <label className="block text-gray-700 mb-2" htmlFor="username">
43 Username
44 </label>
45 <input
46 type="text"
47 id="username"
48 className="w-full p-2 border border-gray-300 rounded"
49 value={username}
50 onChange={(e) => setUsername(e.target.value)}
51 />
52 </div>
53 <div className="mb-4">
54 <label className="block text-gray-700 mb-2" htmlFor="password">
55 Password
56 </label>
57 <input
58 type="password"
59 id="password"
60 className="w-full p-2 border border-gray-300 rounded"
61 value={password}
62 onChange={(e) => setPassword(e.target.value)}
63 />
64 </div>
65 <button
66 type="submit"
67 className="bg-blue-500 hover:bg-blue-600 text-white px-4 py-2 rounded-lg text-sm font-medium transition-colors duration-200 w-full cursor-pointer"
68 >
69 Login
70 </button>
71 </form>
72 </div>
73 );
74};
75
76export default Login;
Note: See TracBrowser for help on using the repository browser.