source: src/app/page.tsx@ b67f274

Last change on this file since b67f274 was b67f274, checked in by Stefan-Saveski <stefansaveski19@…>, 9 months ago

Refactor Exams component to fetch passed subjects from API and remove hardcoded data; delete unused JSON data files; implement authentication token management in auth.ts

  • Property mode set to 100644
File size: 7.6 KB
Line 
1"use client"
2
3import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
4import {
5 faUser,
6 faLock,
7 faEye,
8 faEyeSlash,
9 faSignInAlt,
10 faGraduationCap
11} from '@fortawesome/free-solid-svg-icons';
12import { useState } from 'react';
13import { login } from '@/lib/auth';
14
15export default function LoginPage() {
16 const [showPassword, setShowPassword] = useState(false);
17 const [isSubmitting, setIsSubmitting] = useState(false);
18 const [errorMessage, setErrorMessage] = useState<string | null>(null);
19 const [formData, setFormData] = useState({
20 email: '',
21 password: ''
22 });
23
24 const handleInputChange = (e: React.ChangeEvent<HTMLInputElement>) => {
25 const { name, value } = e.target;
26 setFormData(prev => ({
27 ...prev,
28 [name]: value
29 }));
30 };
31
32 const handleSubmit = async (e: React.FormEvent) => {
33 e.preventDefault();
34 setErrorMessage(null);
35 setIsSubmitting(true);
36 try {
37 await login({ email: formData.email, password: formData.password });
38 window.location.href = '/students/profile';
39 } catch (err) {
40 setErrorMessage(err instanceof Error ? err.message : 'Login failed.');
41 } finally {
42 setIsSubmitting(false);
43 }
44 };
45
46 return (
47 <div className="container mx-auto px-4">
48 <div className="min-h-screen ">
49 {/* Login Form */}
50 <div className="flex items-center justify-center min-h-[calc(100vh-160px)] p-4">
51 <div className="w-full max-w-md">
52 {/* Login Card */}
53 <div className="bg-white rounded-2xl shadow-xl border border-gray-100 overflow-hidden">
54 {/* Header */}
55 <div className="bg-primary text-white px-8 py-6 text-center">
56 <div className="mb-4">
57 <div className="inline-flex items-center justify-center w-16 h-16 bg-white bg-opacity-20 rounded-full">
58 <FontAwesomeIcon icon={faUser} className="text-2xl text-primary" />
59 </div>
60 </div>
61 <h1 className="text-2xl font-bold mb-2">Добредојде</h1>
62 <p className="text-blue-100 text-sm">
63 Најавете се во вашиот IKnow акаунт
64 </p>
65 </div>
66
67 {/* Form */}
68 <div className="p-8">
69 <form onSubmit={handleSubmit} className="space-y-6">
70 {/* Email Field */}
71 <div>
72 <label htmlFor="email" className="block text-sm font-medium text-gray-700 mb-2">
73 Внесете е-пошта
74 </label>
75 <div className="relative">
76 <div className="absolute inset-y-0 left-0 pl-3 flex items-center pointer-events-none">
77 <FontAwesomeIcon icon={faUser} className="h-4 w-4 text-gray-400" />
78 </div>
79 <input
80 id="email"
81 name="email"
82 type="email"
83 required
84 value={formData.email}
85 onChange={handleInputChange}
86 className="w-full pl-10 pr-4 py-3 border border-gray-300 rounded-lg focus:outline-none focus:ring-2 focus:ring-primary focus:border-primary transition-colors"
87 placeholder="Внесете е-пошта"
88 />
89 </div>
90 </div>
91
92 {/* Password Field */}
93 <div>
94 <label htmlFor="password" className="block text-sm font-medium text-gray-700 mb-2">
95 Лозинка
96 </label>
97 <div className="relative">
98 <div className="absolute inset-y-0 left-0 pl-3 flex items-center pointer-events-none">
99 <FontAwesomeIcon icon={faLock} className="h-4 w-4 text-gray-400" />
100 </div>
101 <input
102 id="password"
103 name="password"
104 type={showPassword ? "text" : "password"}
105 required
106 value={formData.password}
107 onChange={handleInputChange}
108 className="w-full pl-10 pr-12 py-3 border border-gray-300 rounded-lg focus:outline-none focus:ring-2 focus:ring-primary focus:border-primary transition-colors"
109 placeholder="Внесете лозинка"
110 />
111 <button
112 type="button"
113 onClick={() => setShowPassword(!showPassword)}
114 className="absolute inset-y-0 right-0 pr-3 flex items-center text-gray-400 hover:text-gray-600 transition-colors"
115 >
116 <FontAwesomeIcon
117 icon={showPassword ? faEyeSlash : faEye}
118 className="h-4 w-4"
119 />
120 </button>
121 </div>
122 </div>
123
124 {/* Remember Me & Forgot Password */}
125 <div className="flex items-center justify-between">
126 <div className="flex items-center">
127 <input
128 id="remember"
129 name="remember"
130 type="checkbox"
131 className="h-4 w-4 text-primary focus:ring-primary border-gray-300 rounded"
132 />
133 <label htmlFor="remember" className="ml-2 block text-sm text-gray-700">
134 Запомни ме
135 </label>
136 </div>
137 <button
138 type="button"
139 className="text-sm text-primary hover:text-blue-700 font-medium transition-colors"
140 >
141 Заборавена лозинка?
142 </button>
143 </div>
144
145 {errorMessage && (
146 <div className="rounded-lg border border-red-200 bg-red-50 px-4 py-3 text-sm text-red-700">
147 {errorMessage}
148 </div>
149 )}
150
151 {/* Submit Button */}
152 <button
153 type="submit"
154 disabled={isSubmitting}
155 className="w-full bg-primary hover:bg-blue-700 disabled:opacity-60 disabled:hover:bg-primary text-white font-medium py-3 px-4 rounded-lg transition-colors duration-200 flex items-center justify-center gap-2 shadow-lg hover:shadow-xl"
156 >
157 <FontAwesomeIcon icon={faSignInAlt} className="h-4 w-4" />
158 {isSubmitting ? 'Најави се...' : 'Најави се'}
159 </button>
160 </form>
161 </div>
162
163 {/* Footer */}
164 <div className="bg-gray-50 px-8 py-4 border-t border-gray-100">
165 <p className="text-center text-sm text-gray-600">
166 Немате акаунт?{' '}
167 <button className="text-primary hover:text-blue-700 font-medium transition-colors">
168 Контактирајте ја администрацијата
169 </button>
170 </p>
171 </div>
172 </div>
173
174 {/* Additional Info */}
175 <div className="mt-6 text-center">
176 <div className="inline-flex items-center gap-2 px-4 py-2 bg-white bg-opacity-80 rounded-lg shadow-sm">
177 <FontAwesomeIcon icon={faGraduationCap} className="text-primary" />
178 <span className="text-sm text-gray-600">
179 Студентски информационен систем
180 </span>
181 </div>
182 </div>
183 </div>
184 </div>
185 </div>
186 </div>
187 );
188}
Note: See TracBrowser for help on using the repository browser.