source: src/app/students/subjects/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: 13.6 KB
Line 
1"use client"
2
3import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
4import {
5 faBook,
6 faChevronDown,
7 faFileInvoice
8} from '@fortawesome/free-solid-svg-icons';
9import { useState } from 'react';
10import subjectsData from '@/data/subjects.json';
11
12interface Subject {
13 id: number;
14 code: string;
15 hours: string;
16 kojPat: number;
17 name: string;
18 semester: number;
19 status: string;
20 signature: string;
21 group: string;
22 professor: string;
23}
24
25interface TableCellProps {
26 children: React.ReactNode;
27 className?: string;
28}
29
30const TableCell = ({ children, className = "" }: TableCellProps) => (
31 <td className={`px-4 py-3 text-sm border-b border-gray-200 ${className}`}>
32 {children}
33 </td>
34);
35
36const StatusBadge = ({ status }: { status: string }) => {
37 const baseClasses = "px-3 py-1 rounded-md text-xs font-medium";
38
39 if (status === "Зад.") {
40 return (
41 <span className={`${baseClasses} bg-blue-100 text-blue-800`}>
42 {status}
43 </span>
44 );
45 } else if (status === "Изб.") {
46 return (
47 <span className={`${baseClasses} bg-green-100 text-green-800`}>
48 {status}
49 </span>
50 );
51 }
52
53 return (
54 <span className={`${baseClasses} bg-gray-100 text-gray-800`}>
55 {status}
56 </span>
57 );
58};
59
60export default function SubjectsPage() {
61 const [selectedSemester, setSelectedSemester] = useState(subjectsData.currentSemester.id);
62 const [isDropdownOpen, setIsDropdownOpen] = useState(false);
63
64 const currentSemesterData = subjectsData.semesters.find(s => s.id === selectedSemester) || subjectsData.currentSemester;
65 const currentSubjects: Subject[] = subjectsData.subjectsBySemester[selectedSemester as keyof typeof subjectsData.subjectsBySemester] || [];
66 const { currentSemester } = subjectsData;
67
68 return (
69 <div className="min-h-screen pb-8">
70 {/* Header */}
71 <div className="bg-primary text-white rounded-xl p-8 mb-8">
72 <div className="flex items-center gap-4">
73 <div className="bg-white bg-opacity-20 rounded-full p-4">
74 <FontAwesomeIcon icon={faBook} className="text-3xl text-primary" />
75 </div>
76 <div>
77 <h1 className="text-3xl font-bold mb-2">Предмети</h1>
78 <p className="text-lg opacity-90">
79 Преглед на запишани предмети по семестри
80 </p>
81 </div>
82 </div>
83 </div>
84
85 {/* Status and Selection Section */}
86 <div className="grid grid-cols-1 lg:grid-cols-3 gap-6 mb-8">
87
88 {/* Left Column - Status and Dropdown */}
89 <div className="lg:col-span-1 space-y-6">
90
91 {/* Status Card */}
92 <div className="bg-white rounded-xl p-6 shadow-sm border border-gray-100">
93 <div className="text-sm text-gray-600 mb-2">
94 Статус: <span className="text-primary font-semibold">Запишан од студент</span>
95 </div>
96 <div className="text-sm text-gray-600">
97 Број на тикет: <span className="font-semibold">{currentSemester.ticketNumber}</span>
98 </div>
99 </div>
100
101 {/* Semester Selection */}
102 <div className="bg-white rounded-xl p-6 shadow-sm border border-gray-100">
103 <div className="text-sm text-gray-600 mb-2">
104 Долг од документи: <span className="font-semibold">{currentSemester.debt}</span>
105 </div>
106
107 <div className="relative mt-4">
108 <label className="block text-sm font-medium text-gray-700 mb-2">
109 Избери семестар:
110 </label>
111 <div className="relative">
112 <button
113 onClick={() => setIsDropdownOpen(!isDropdownOpen)}
114 className="w-full bg-white border border-gray-300 rounded-lg px-4 py-3 text-left focus:outline-none focus:ring-2 focus:ring-primary focus:border-primary"
115 >
116 <div className="flex items-center justify-between">
117 <span className="text-sm font-medium text-primary">
118 {currentSemesterData.name}
119 </span>
120 <FontAwesomeIcon
121 icon={faChevronDown}
122 className={`w-4 h-4 text-gray-400 transition-transform ${isDropdownOpen ? 'rotate-180' : ''}`}
123 />
124 </div>
125 </button>
126
127 {isDropdownOpen && (
128 <div className="absolute z-10 w-full mt-1 bg-white border border-gray-200 rounded-lg shadow-lg">
129 {subjectsData.semesters.map((semester) => (
130 <button
131 key={semester.id}
132 onClick={() => {
133 setSelectedSemester(semester.id);
134 setIsDropdownOpen(false);
135 }}
136 className="w-full px-4 py-3 text-left text-sm hover:bg-gray-50 focus:outline-none focus:bg-gray-50 first:rounded-t-lg last:rounded-b-lg"
137 >
138 <div className="font-medium text-gray-900">{semester.name}</div>
139 <div className="text-xs text-gray-500">Статус: {semester.status}</div>
140 </button>
141 ))}
142 </div>
143 )}
144 </div>
145 </div>
146
147 <div className="mt-4 text-sm">
148 <div className="text-primary font-medium">
149 Сериски број: {currentSemesterData.serviceNumber}
150 </div>
151 </div>
152 </div>
153
154 {/* Enrolled Subjects */}
155 <div className="bg-white rounded-xl p-6 shadow-sm border border-gray-100">
156 <h3 className="font-semibold text-gray-900 mb-3 flex items-center gap-2">
157 <FontAwesomeIcon icon={faBook} className="w-4 h-4 text-primary" />
158 Запишани предмети
159 </h3>
160 <div className="text-3xl font-bold text-primary">
161 {currentSubjects.length}
162 </div>
163 </div>
164 </div>
165
166 {/* Right Column - Financial Information */}
167 <div className="lg:col-span-2">
168 <div className="bg-white rounded-xl shadow-sm border border-gray-100 overflow-hidden">
169 <div className="bg-primary text-white px-6 py-4">
170 <h2 className="text-xl font-bold flex items-center gap-2">
171 <FontAwesomeIcon icon={faFileInvoice} />
172 Финансиски информации
173 </h2>
174 </div>
175
176 <div className="p-6">
177 <div className="grid grid-cols-1 md:grid-cols-2 gap-6">
178
179 {/* Left Financial Column */}
180 <div className="space-y-4">
181 <div className="flex justify-between items-center py-2 border-b border-gray-100">
182 <span className="text-gray-600">Сума:</span>
183 <span className="font-semibold text-primary">{currentSemester.financialInfo.sum}</span>
184 </div>
185 <div className="flex justify-between items-center py-2 border-b border-gray-100">
186 <span className="text-gray-600">Платено:</span>
187 <span className="font-semibold text-green-600">{currentSemester.financialInfo.paid}</span>
188 </div>
189 <div className="flex justify-between items-center py-2 border-b border-gray-100">
190 <span className="text-gray-600">Должи:</span>
191 <span className="font-semibold text-red-600">{currentSemester.financialInfo.due}</span>
192 </div>
193 <div className="mt-4 p-4 bg-blue-50 rounded-lg">
194 <div className="text-sm font-medium text-blue-800 mb-1">Материјални трошоци:</div>
195 <div className="text-sm text-blue-700">{currentSemester.financialInfo.materialCosts}</div>
196 </div>
197 </div>
198
199 {/* Right Financial Column */}
200 <div className="space-y-4">
201 <div className="flex justify-between items-center py-2 border-b border-gray-100">
202 <span className="text-gray-600">Кредити:</span>
203 <span className="font-semibold text-primary">{currentSemester.financialInfo.credits}</span>
204 </div>
205 <div className="flex justify-between items-center py-2 border-b border-gray-100">
206 <span className="text-gray-600">МКСА:</span>
207 <span className="font-semibold">{currentSemester.financialInfo.MKSA}</span>
208 </div>
209 <div className="flex justify-between items-center py-2 border-b border-gray-100">
210 <span className="text-gray-600">Електронско запишување:</span>
211 <span className="font-semibold">{currentSemester.financialInfo.electronicRegistration}</span>
212 </div>
213 <div className="flex justify-between items-center py-2 border-b border-gray-100">
214 <span className="text-gray-600">Е-УКИМ:</span>
215 <span className="font-semibold">{currentSemester.financialInfo.eUKIM}</span>
216 </div>
217 <div className="flex justify-between items-center py-2 border-b border-gray-100">
218 <span className="text-gray-600">Банкарска провизија:</span>
219 <span className="font-semibold">{currentSemester.financialInfo.bankProvision}</span>
220 </div>
221 <div className="flex justify-between items-center py-3 border-t-2 border-primary bg-primary bg-opacity-5 rounded-lg px-4">
222 <span className="font-bold text-white">Тотал:</span>
223 <span className="font-bold text-xl text-white">{currentSemester.financialInfo.total}</span>
224 </div>
225 </div>
226 </div>
227 </div>
228 </div>
229 </div>
230 </div>
231
232 {/* Subjects Table */}
233 <div className="bg-white rounded-xl shadow-sm border border-gray-100 overflow-hidden">
234 <div className="bg-primary text-white px-6 py-4">
235 <h2 className="text-xl font-bold">Листа на предмети</h2>
236 </div>
237
238 <div className="overflow-x-auto">
239 <table className="w-full">
240 <thead className="bg-gray-50">
241 <tr>
242 <th className="px-4 py-4 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">#</th>
243 <th className="px-4 py-4 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Код</th>
244 <th className="px-4 py-4 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Часови</th>
245 <th className="px-4 py-4 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Кој пат</th>
246 <th className="px-4 py-4 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Предмет</th>
247 <th className="px-4 py-4 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Семестар</th>
248 <th className="px-4 py-4 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Статус</th>
249 <th className="px-4 py-4 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Потпис</th>
250 <th className="px-4 py-4 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Група</th>
251 <th className="px-4 py-4 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Професор</th>
252 </tr>
253 </thead>
254 <tbody className="divide-y divide-gray-100">
255 {currentSubjects.map((subject: Subject) => (
256 <tr key={subject.id} className="hover:bg-gray-50 transition-colors">
257 <TableCell className="font-medium text-gray-900">{subject.id}</TableCell>
258 <TableCell className="font-mono text-sm text-primary font-medium">{subject.code}</TableCell>
259 <TableCell className="font-medium">{subject.hours}</TableCell>
260 <TableCell className="text-center font-medium">{subject.kojPat}</TableCell>
261 <TableCell className="font-medium text-gray-900 max-w-xs">
262 <div className="flex items-center gap-2">
263 <FontAwesomeIcon icon={faBook} className="w-4 h-4 text-primary" />
264 {subject.name}
265 </div>
266 </TableCell>
267 <TableCell className="text-center font-medium text-primary">{subject.semester}</TableCell>
268 <TableCell>
269 <StatusBadge status={subject.status} />
270 </TableCell>
271 <TableCell className="text-center">
272 {subject.signature || (
273 <span className="text-gray-400">—</span>
274 )}
275 </TableCell>
276 <TableCell className="text-center">
277 {subject.group || (
278 <span className="text-gray-400">—</span>
279 )}
280 </TableCell>
281 <TableCell>
282 {subject.professor || (
283 <span className="text-gray-400">—</span>
284 )}
285 </TableCell>
286 </tr>
287 ))}
288 </tbody>
289 </table>
290 </div>
291 </div>
292 </div>
293 );
294}
Note: See TracBrowser for help on using the repository browser.