source: src/app/students/semesters/page.tsx@ 82c9c53

Last change on this file since 82c9c53 was 82c9c53, checked in by stefansaveski <stefansaveski19@…>, 11 months ago

refactor: Remove unused imports and optimize component code across multiple files

  • Property mode set to 100644
File size: 12.6 KB
Line 
1"use client"
2
3import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
4import {
5 faCalendarAlt,
6 faCheck,
7 faTimes,
8 faFileAlt,
9 faMoneyBillWave,
10 faSignature,
11 faCheckCircle,
12 faTimesCircle
13} from '@fortawesome/free-solid-svg-icons';
14import semestersData from '@/data/semesters.json';
15
16interface TableCellProps {
17 children: React.ReactNode;
18 className?: string;
19}
20
21const TableCell = ({ children, className = "" }: TableCellProps) => (
22 <td className={`px-4 py-3 text-sm border-b border-gray-100 ${className}`}>
23 {children}
24 </td>
25);
26
27const StatusBadge = ({ status }: { status: string }) => {
28 const baseClasses = "px-2 py-1 rounded-full text-xs font-medium";
29
30 if (status === "валиден") {
31 return (
32 <span className={`${baseClasses} bg-green-100 text-green-800 flex items-center gap-1`}>
33 <FontAwesomeIcon icon={faCheckCircle} className="w-3 h-3" />
34 {status}
35 </span>
36 );
37 }
38
39 return (
40 <span className={`${baseClasses} bg-gray-100 text-gray-800`}>
41 {status}
42 </span>
43 );
44};
45
46const YesNoBadge = ({ value }: { value: string }) => {
47 if (value === "Да") {
48 return (
49 <span className="inline-flex items-center justify-center w-6 h-6 bg-green-100 text-green-600 rounded-full">
50 <FontAwesomeIcon icon={faCheck} className="w-3 h-3" />
51 </span>
52 );
53 } else if (value === "Не") {
54 return (
55 <span className="inline-flex items-center justify-center w-6 h-6 bg-red-100 text-red-600 rounded-full">
56 <FontAwesomeIcon icon={faTimes} className="w-3 h-3" />
57 </span>
58 );
59 }
60 return <span className="text-gray-400">—</span>;
61};
62
63const SignatureBadge = ({ signatures }: { signatures: string }) => {
64 const [completed, total] = signatures.split('/').map(Number);
65 const percentage = total > 0 ? (completed / total) * 100 : 0;
66
67 let colorClass = "text-red-600 bg-red-100";
68 if (percentage === 100) {
69 colorClass = "text-green-600 bg-green-100";
70 } else if (percentage >= 50) {
71 colorClass = "text-yellow-600 bg-yellow-100";
72 }
73
74 return (
75 <span className={`px-2 py-1 rounded-full text-xs font-medium flex items-center gap-1 ${colorClass}`}>
76 <FontAwesomeIcon icon={faSignature} className="w-3 h-3" />
77 {signatures}
78 </span>
79 );
80};
81
82export default function SemestersPage() {
83 const { semesters } = semestersData;
84
85 return (
86 <div className="min-h-screen pb-8">
87 {/* Header */}
88 <div className="bg-primary text-white rounded-xl p-8 mb-8">
89 <div className="flex items-center gap-4">
90 <div className="bg-white bg-opacity-20 rounded-full p-4">
91 <FontAwesomeIcon icon={faCalendarAlt} className="text-3xl text-primary" />
92 </div>
93 <div>
94 <h1 className="text-3xl font-bold mb-2">Семестри</h1>
95 <p className="text-lg opacity-90">
96 Преглед на сите запишани семестри и нивниот статус
97 </p>
98 </div>
99 </div>
100 </div>
101
102 {/* Table Container */}
103 <div className="bg-white rounded-xl shadow-sm border border-gray-100 overflow-hidden">
104 <div className="bg-primary text-white px-6 py-4">
105 <h2 className="text-xl font-bold">Листа на семестри</h2>
106 </div>
107
108 <div className="overflow-x-auto">
109 <table className="w-full">
110 <thead className="bg-gray-50">
111 <tr>
112 <th className="px-4 py-4 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">#</th>
113 <th className="px-4 py-4 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Семестар</th>
114 <th className="px-4 py-4 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Насока</th>
115 <th className="px-4 py-4 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Квота</th>
116 <th className="px-4 py-4 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Забелешка</th>
117 <th className="px-4 py-4 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Студ.Ком.</th>
118 <th className="px-4 py-4 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Сума</th>
119 <th className="px-4 py-4 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Платено</th>
120 <th className="px-4 py-4 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">УКИМ</th>
121 <th className="px-4 py-4 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Креирано на</th>
122 <th className="px-4 py-4 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Датум промена</th>
123 <th className="px-4 py-4 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Ц.Кр</th>
124 <th className="px-4 py-4 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Тип</th>
125 <th className="px-4 py-4 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Док.</th>
126 <th className="px-4 py-4 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Док1.</th>
127 <th className="px-4 py-4 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Вериф.</th>
128 <th className="px-4 py-4 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Таксени</th>
129 <th className="px-4 py-4 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Потписи</th>
130 <th className="px-4 py-4 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Статус</th>
131 <th className="px-4 py-4 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Зав.</th>
132 </tr>
133 </thead>
134 <tbody className="divide-y divide-gray-100">
135 {semesters.map((semester) => (
136 <tr key={semester.id} className="hover:bg-gray-50 transition-colors">
137 <TableCell className="font-medium text-gray-900">{semester.id}</TableCell>
138 <TableCell className="font-medium text-primary">{semester.semester}</TableCell>
139 <TableCell>{semester.direction}</TableCell>
140 <TableCell className="max-w-xs">
141 <div className="truncate" title={semester.quota}>
142 {semester.quota}
143 </div>
144 </TableCell>
145 <TableCell>
146 {semester.note ? (
147 <span className="text-yellow-600 font-medium" title={semester.note}>
148 {semester.note.length > 10 ? `${semester.note.substring(0, 10)}...` : semester.note}
149 </span>
150 ) : (
151 <span className="text-gray-400">—</span>
152 )}
153 </TableCell>
154 <TableCell>
155 {semester.studentCom ? (
156 <span className="text-blue-600 font-medium" title={semester.studentCom}>
157 {semester.studentCom.length > 10 ? `${semester.studentCom.substring(0, 10)}...` : semester.studentCom}
158 </span>
159 ) : (
160 <span className="text-gray-400">—</span>
161 )}
162 </TableCell>
163 <TableCell className="font-medium">
164 {semester.sum ? (
165 <span className="text-green-600 flex items-center gap-1">
166 <FontAwesomeIcon icon={faMoneyBillWave} className="w-3 h-3" />
167 {semester.sum}
168 </span>
169 ) : (
170 <span className="text-gray-400">—</span>
171 )}
172 </TableCell>
173 <TableCell className="font-medium">
174 {semester.paid ? (
175 <span className="text-green-600 flex items-center gap-1">
176 <FontAwesomeIcon icon={faMoneyBillWave} className="w-3 h-3" />
177 {semester.paid}
178 </span>
179 ) : (
180 <span className="text-gray-400">—</span>
181 )}
182 </TableCell>
183 <TableCell className="font-medium">
184 {semester.ukim ? (
185 <span className="text-blue-600">{semester.ukim}</span>
186 ) : (
187 <span className="text-gray-400">—</span>
188 )}
189 </TableCell>
190 <TableCell className="text-gray-600">{semester.createdOn}</TableCell>
191 <TableCell className="text-gray-600">{semester.dateChanged}</TableCell>
192 <TableCell className="font-medium text-primary">{semester.credits}</TableCell>
193 <TableCell>
194 <span className="px-2 py-1 bg-blue-100 text-blue-800 rounded-full text-xs font-medium">
195 {semester.type}
196 </span>
197 </TableCell>
198 <TableCell className="text-center">
199 <YesNoBadge value={semester.doc} />
200 </TableCell>
201 <TableCell className="text-center">
202 <YesNoBadge value={semester.doc1} />
203 </TableCell>
204 <TableCell className="text-center">
205 <YesNoBadge value={semester.verified} />
206 </TableCell>
207 <TableCell className="font-medium text-green-600">{semester.taxes}</TableCell>
208 <TableCell>
209 <SignatureBadge signatures={semester.signatures} />
210 </TableCell>
211 <TableCell>
212 <StatusBadge status={semester.status} />
213 </TableCell>
214 <TableCell>
215 {semester.completed !== "Не" ? (
216 <span className="text-green-600 font-medium flex items-center gap-1">
217 <FontAwesomeIcon icon={faCheckCircle} className="w-3 h-3" />
218 {semester.completed}
219 </span>
220 ) : (
221 <span className="text-red-600 font-medium flex items-center gap-1">
222 <FontAwesomeIcon icon={faTimesCircle} className="w-3 h-3" />
223 {semester.completed}
224 </span>
225 )}
226 </TableCell>
227 </tr>
228 ))}
229 </tbody>
230 </table>
231 </div>
232 </div>
233
234 {/* Summary Cards */}
235 <div className="grid grid-cols-1 md:grid-cols-3 gap-6 mt-8">
236 <div className="bg-white rounded-xl p-6 shadow-sm border border-gray-100">
237 <div className="flex items-center gap-4">
238 <div className="bg-green-100 text-green-600 rounded-full p-3">
239 <FontAwesomeIcon icon={faCheckCircle} className="text-xl" />
240 </div>
241 <div>
242 <h3 className="text-lg font-bold text-gray-900">Завршени семестри</h3>
243 <p className="text-2xl font-bold text-green-600">
244 {semesters.filter(s => s.completed !== "Не").length}
245 </p>
246 </div>
247 </div>
248 </div>
249
250 <div className="bg-white rounded-xl p-6 shadow-sm border border-gray-100">
251 <div className="flex items-center gap-4">
252 <div className="bg-blue-100 text-blue-600 rounded-full p-3">
253 <FontAwesomeIcon icon={faFileAlt} className="text-xl" />
254 </div>
255 <div>
256 <h3 className="text-lg font-bold text-gray-900">Верифицирани</h3>
257 <p className="text-2xl font-bold text-blue-600">
258 {semesters.filter(s => s.verified === "Да").length}
259 </p>
260 </div>
261 </div>
262 </div>
263
264 <div className="bg-white rounded-xl p-6 shadow-sm border border-gray-100">
265 <div className="flex items-center gap-4">
266 <div className="bg-primary text-white rounded-full p-3">
267 <FontAwesomeIcon icon={faCalendarAlt} className="text-xl" />
268 </div>
269 <div>
270 <h3 className="text-lg font-bold text-gray-900">Вкупно семестри</h3>
271 <p className="text-2xl font-bold text-primary">
272 {semesters.length}
273 </p>
274 </div>
275 </div>
276 </div>
277 </div>
278 </div>
279 );
280}
Note: See TracBrowser for help on using the repository browser.