Changeset 4fe4582 for src/app/students/documents/page.tsx
- Timestamp:
- 02/16/26 17:38:16 (7 months ago)
- Branches:
- master
- Children:
- 8496f3c
- Parents:
- d7deae5
- File:
-
- 1 edited
-
src/app/students/documents/page.tsx (modified) (7 diffs)
Legend:
- Unmodified
- Added
- Removed
-
src/app/students/documents/page.tsx
rd7deae5 r4fe4582 6 6 faChevronDown, 7 7 faCheckCircle, 8 faClock, 8 9 faMoneyBillWave, 9 10 faFileText, … … 11 12 faChevronRight, 12 13 faAngleDoubleLeft, 13 faAngleDoubleRight 14 faAngleDoubleRight, 15 faSpinner 14 16 } from '@fortawesome/free-solid-svg-icons'; 15 17 import { useState } from 'react'; 16 18 import documentsData from '@/data/documents.json'; 17 19 import { useTranslation } from 'react-i18next'; 20 import { getAccessToken } from '@/lib/auth'; 21 import { downloadDocumentPDF } from '@/lib/pdf-generators'; 18 22 19 23 interface TableCellProps { … … 30 34 const StatusBadge = ({ status }: { status: string }) => { 31 35 const { t } = useTranslation(); 32 if (status === t('approved', 'Одобрено')) {36 if (status === 'approved' || status === t('approved', 'Одобрено')) { 33 37 return ( 34 38 <span className="inline-flex items-center justify-center w-8 h-8 bg-green-100 text-green-600 rounded-full"> 35 39 <FontAwesomeIcon icon={faCheckCircle} className="w-5 h-5" /> 40 </span> 41 ); 42 } 43 if (status === 'pending') { 44 return ( 45 <span className="inline-flex items-center gap-1 text-xs font-medium text-yellow-700 bg-yellow-100 px-2 py-1 rounded-full"> 46 <FontAwesomeIcon icon={faClock} className="w-3 h-3" /> 47 {t('pending', 'Во обработка')} 36 48 </span> 37 49 ); … … 52 64 }; 53 65 66 interface DocumentRecord { 67 id: number; 68 archive: string; 69 date: string; 70 request: string; 71 price: number; 72 paid: string; 73 document: string; 74 payOnline: boolean; 75 status: string; 76 comment: string; 77 } 78 54 79 export default function DocumentsPage() { 55 80 const [selectedDocumentType, setSelectedDocumentType] = useState("select_document"); … … 58 83 const [currentPage, setCurrentPage] = useState(1); 59 84 const [recordsPerPage, setRecordsPerPage] = useState(15); 85 const [downloadingId, setDownloadingId] = useState<number | null>(null); 86 const [documents, setDocuments] = useState<DocumentRecord[]>(documentsData.documents as DocumentRecord[]); 87 const [isSubmitting, setIsSubmitting] = useState(false); 60 88 const { t } = useTranslation(); 61 89 90 const handleDownload = async (docId: number, request: string, archive: string, date: string) => { 91 const token = getAccessToken(); 92 if (!token) { 93 alert(t('not_authenticated', 'Не сте најавени. Ве молиме најавете се повторно.')); 94 return; 95 } 96 setDownloadingId(docId); 97 try { 98 await downloadDocumentPDF(request, archive, date, token); 99 } catch (err) { 100 console.error('PDF generation error:', err); 101 alert(t('pdf_error', 'Грешка при генерирање на документот. Обидете се повторно.')); 102 } finally { 103 setDownloadingId(null); 104 } 105 }; 106 107 const handleSubmit = () => { 108 if (selectedDocumentType === "select_document") return; 109 110 const docType = documentsData.documentTypes.find(d => d.id === selectedDocumentType); 111 if (!docType) return; 112 113 setIsSubmitting(true); 114 115 // Generate archive number (random 5-digit) 116 const archiveNumber = String(90000 + Math.floor(Math.random() * 10000)); 117 118 // Current date in DD.MM.YYYY format 119 const now = new Date(); 120 const dateStr = `${String(now.getDate()).padStart(2, '0')}.${String(now.getMonth() + 1).padStart(2, '0')}.${now.getFullYear()}`; 121 122 const newDoc: DocumentRecord = { 123 id: documents.length > 0 ? Math.max(...documents.map(d => d.id)) + 1 : 1, 124 archive: archiveNumber, 125 date: dateStr, 126 request: docType.name, 127 price: docType.price, 128 paid: "Не", 129 document: "Преземи", 130 payOnline: docType.price > 0, 131 status: "pending", 132 comment: comment, 133 }; 134 135 setDocuments(prev => [newDoc, ...prev]); 136 setSelectedDocumentType("select_document"); 137 setComment(""); 138 setIsSubmitting(false); 139 alert(t('document_submitted', 'Барањето за документ е успешно поднесено!')); 140 }; 141 62 142 const selectedDocument = documentsData.documentTypes.find(d => d.id === selectedDocumentType); 63 const { documents,paymentInfo } = documentsData;143 const { paymentInfo } = documentsData; 64 144 65 145 const totalPages = Math.ceil(documents.length / recordsPerPage); … … 153 233 <div className="flex justify-end mt-6"> 154 234 <button 155 className="bg-primary hover:bg-blue-700 text-white font-medium py-2 px-6 rounded-lg transition-colors duration-200 flex items-center gap-2" 156 disabled={selectedDocumentType === "select_document"} 235 onClick={handleSubmit} 236 className="bg-primary hover:bg-blue-700 text-white font-medium py-2 px-6 rounded-lg transition-colors duration-200 flex items-center gap-2 disabled:opacity-50 disabled:cursor-not-allowed" 237 disabled={selectedDocumentType === "select_document" || isSubmitting} 157 238 > 158 <FontAwesomeIcon icon={ faFileText} className="w-4 h-4"/>159 { t('submit', 'Поднеси')}239 <FontAwesomeIcon icon={isSubmitting ? faSpinner : faFileText} className={`w-4 h-4 ${isSubmitting ? 'animate-spin' : ''}`} /> 240 {isSubmitting ? t('submitting', 'Се поднесува...') : t('submit', 'Поднеси')} 160 241 </button> 161 242 </div> … … 197 278 </TableCell> 198 279 <TableCell className="text-center"> 199 <span className= "text-sm font-medium text-green-600">280 <span className={`text-sm font-medium ${document.paid === 'ДА' ? 'text-green-600' : 'text-red-500'}`}> 200 281 {document.paid} 201 282 </span> 202 283 </TableCell> 203 284 <TableCell className="text-center"> 204 <button className="text-primary hover:text-blue-700 font-medium text-sm underline"> 205 {document.document} 285 <button 286 onClick={() => handleDownload(document.id, document.request, document.archive, document.date)} 287 disabled={downloadingId === document.id} 288 className="text-primary hover:text-blue-700 font-medium text-sm underline disabled:opacity-50 disabled:cursor-wait inline-flex items-center gap-1" 289 > 290 {downloadingId === document.id ? ( 291 <> 292 <FontAwesomeIcon icon={faSpinner} className="w-3 h-3 animate-spin" /> 293 {t('generating', 'Генерира...')} 294 </> 295 ) : ( 296 t('download', document.document) 297 )} 206 298 </button> 207 299 </TableCell>
Note:
See TracChangeset
for help on using the changeset viewer.
