source: frontend/src/components/LoginForm.tsx@ 700e2f9

main
Last change on this file since 700e2f9 was 700e2f9, checked in by 186079 <matej.milevski@…>, 5 days ago

Init

  • Property mode set to 100644
File size: 3.6 KB
RevLine 
[700e2f9]1import { type Component, createSignal } from "solid-js";
2import { useNavigate } from "@solidjs/router";
3import { useAuth } from "@/context/AuthContext";
4import { authApi } from "@/api/auth";
5
6interface LoginFormProps {
7 onSwitchToRegister: () => void;
8}
9
10const LoginForm: Component<LoginFormProps> = (props) => {
11 const [error, setError] = createSignal("");
12 const [isLoading, setIsLoading] = createSignal(false);
13 const navigate = useNavigate();
14 const { login } = useAuth();
15
16 const [loginUsername, setLoginUsername] = createSignal("");
17 const [loginPassword, setLoginPassword] = createSignal("");
18
19 const handleLogin = async (e: Event) => {
20 e.preventDefault();
21 setError("");
22 setIsLoading(true);
23
24 try {
25 const response = await authApi.login({
26 username: loginUsername().trim(),
27 password: loginPassword(),
28 });
29
30 login(response);
31 navigate("/");
32 } catch (err) {
33 setError(
34 err instanceof Error
35 ? err.message
36 : "Error has occurred while logging in. Please try again.",
37 );
38 } finally {
39 setIsLoading(false);
40 }
41 };
42
43 return (
44 <form class="mt-8 space-y-6" onSubmit={handleLogin}>
45 {error() && (
46 <div class="rounded-md bg-red-50 p-4">
47 <div class="text-sm text-red-700">{error()}</div>
48 </div>
49 )}
50
51 <div class="rounded-md space-y-4">
52 <div>
53 <label
54 for="username"
55 class="block text-sm font-medium text-gray-700 mb-1"
56 >
57 Username
58 </label>
59 <input
60 id="username"
61 name="username"
62 type="text"
63 required
64 class="appearance-none relative block w-full px-3 py-2 border border-gray-300 placeholder-gray-500 text-gray-900 rounded-md focus:outline-none focus:ring-blue-500 focus:border-blue-500 focus:z-10 sm:text-sm"
65 placeholder="Enter your username"
66 value={loginUsername()}
67 onInput={(e) => setLoginUsername(e.currentTarget.value)}
68 />
69 </div>
70
71 <div>
72 <label
73 for="password"
74 class="block text-sm font-medium text-gray-700 mb-1"
75 >
76 Password
77 </label>
78 <input
79 id="password"
80 name="password"
81 type="password"
82 required
83 class="appearance-none relative block w-full px-3 py-2 border border-gray-300 placeholder-gray-500 text-gray-900 rounded-md focus:outline-none focus:ring-blue-500 focus:border-blue-500 focus:z-10 sm:text-sm"
84 placeholder="Enter your password"
85 value={loginPassword()}
86 onInput={(e) => setLoginPassword(e.currentTarget.value)}
87 />
88 </div>
89 </div>
90
91 <div>
92 <button
93 type="submit"
94 disabled={isLoading()}
95 class="group relative w-full flex justify-center py-2 px-4 border border-transparent text-sm font-medium rounded-md text-white bg-blue-600 hover:bg-blue-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-blue-500 disabled:opacity-50 disabled:cursor-not-allowed transition-colors"
96 >
97 {isLoading() ? "Signing in..." : "Sign in"}
98 </button>
99 </div>
100
101 <div class="text-center text-sm">
102 <span class="text-gray-600">Don't have an account? </span>
103 <button
104 type="button"
105 onClick={props.onSwitchToRegister}
106 class="font-medium text-blue-600 hover:text-blue-500"
107 >
108 Sign up
109 </button>
110 </div>
111 </form>
112 );
113};
114
115export default LoginForm;
Note: See TracBrowser for help on using the repository browser.