From f70f8d682bfc150d5bf3c4a3fa001a6a041b7eab Mon Sep 17 00:00:00 2001 From: Zan <62830223+Zan1456@users.noreply.github.com> Date: Tue, 23 Sep 2025 22:05:39 +0200 Subject: [PATCH] Added messages page support --- i18n/en.json | 52 +++- i18n/hu.json | 42 +++- manifest.json | 13 + messages/messages.css | 547 ++++++++++++++++++++++++++++++++++++++++++ messages/messages.js | 340 ++++++++++++++++++++++++++ 5 files changed, 984 insertions(+), 10 deletions(-) create mode 100644 messages/messages.css create mode 100644 messages/messages.js diff --git a/i18n/en.json b/i18n/en.json index 3115ca8..e556e42 100644 --- a/i18n/en.json +++ b/i18n/en.json @@ -52,7 +52,7 @@ "preview": "Preview", "save": "Save", "cancel": "Cancel", - "import_string": "Theme string", + "import_string": "Theme ID", "apply": "Apply", "edit": "Edit", "export": "Export", @@ -100,6 +100,7 @@ "teacher": "Teacher", "average": "Average", "chart_title": "Grades", + "semester_evaluation": "Semester evaluation", "semester_evaluations": "Semester evaluations", "year_end_evaluations": "End of year tickets", "semester_average": "Semester average", @@ -361,10 +362,6 @@ "november": "November", "december": "December" }, - "search": { - "title": "Choose school", - "select_institution": "Please select an institution to continue!" - }, "roleselect": { "student_book": "Student Book", "student_description": "View grades, absences, timetable and other information.", @@ -385,7 +382,7 @@ "description": "Firka is an open source project that creates a custom user interface for the KRÉTA system.", "support_title": "Support", "support_description": "If you like our work and want to support development, you can do so in the following way:", - "version": "v1.1.0" + "version": "v1.3.0" }, "app": { "title": "Firka - KRÉTA", @@ -416,15 +413,52 @@ "cancel": "Cancel", "save": "Save" }, - "grades": { - "semester_evaluation": "Semester evaluation" - }, "search": { + "title": "Choose school", + "select_institution": "Please select an institution to continue!", "choose_school": "Choose school", "privacy_policy": "Privacy policy" }, "icons": { "cancel": "cancel", "pending": "pending" + }, + "messages": { + "title": "Messages", + "back": "Back", + "surveys": "Surveys", + "loading": "Loading messages...", + "error": { + "title": "Error occurred", + "description": "Failed to load messages.", + "retry": "Retry" + }, + "empty": { + "title": "No messages", + "description": "There are currently no received messages." + }, + "sender": "Sender", + "subject": "Subject", + "date": "Date", + "unread": "Unread", + "read": "Read", + "message_detail": { + "title": "Message Details", + "loading": "Loading message...", + "error": "Error loading message.", + "from": "From", + "to": "To", + "subject": "Subject", + "date": "Date", + "content": "Content", + "attachments": "Attachments", + "no_attachments": "No attachments", + "reply": "Reply", + "forward": "Forward", + "delete": "Delete", + "mark_read": "Mark as read", + "mark_unread": "Mark as unread", + "back_to_messages": "Back to messages" + } } } \ No newline at end of file diff --git a/i18n/hu.json b/i18n/hu.json index 1a10168..2518feb 100644 --- a/i18n/hu.json +++ b/i18n/hu.json @@ -8,7 +8,9 @@ "theme": "Téma", "language": "Nyelv", "themes": { + "light_blue": "Világos Kék", "light_green": "Világos Zöld", + "dark_blue": "Sötét Kék", "dark_green": "Sötét Zöld", "dark_red": "Sötét Piros", "dark_purple": "Sötét Lila", @@ -382,7 +384,7 @@ "description": "A Firka egy nyílt forráskódú projekt, amely a KRÉTA rendszerhez készít saját felhasználói felületet.", "support_title": "Támogatás", "support_description": "Ha tetszik a munkánk és szeretnéd támogatni a fejlesztést, az alábbi módon teheted meg:", - "version": "v1.1.0" + "version": "v1.3.0" }, "app": { "title": "Firka - KRÉTA", @@ -422,5 +424,43 @@ "icons": { "cancel": "cancel", "pending": "pending" + }, + "messages": { + "title": "Üzenetek", + "back": "Vissza", + "surveys": "Felmérések", + "loading": "Üzenetek betöltése...", + "error": { + "title": "Hiba történt", + "description": "Nem sikerült betölteni az üzeneteket.", + "retry": "Újrapróbálás" + }, + "empty": { + "title": "Nincsenek üzenetek", + "description": "Jelenleg nincsenek beérkezett üzenetek." + }, + "sender": "Feladó", + "subject": "Tárgy", + "date": "Dátum", + "unread": "Olvasatlan", + "read": "Olvasott", + "message_detail": { + "title": "Üzenet részletei", + "loading": "Üzenet betöltése...", + "error": "Hiba történt az üzenet betöltése során.", + "from": "Feladó", + "to": "Címzett", + "subject": "Tárgy", + "date": "Dátum", + "content": "Tartalom", + "attachments": "Mellékletek", + "no_attachments": "Nincsenek mellékletek", + "reply": "Válasz", + "forward": "Továbbítás", + "delete": "Törlés", + "mark_read": "Olvasottként jelöl", + "mark_unread": "Olvasatlanként jelöl", + "back_to_messages": "Vissza az üzenetekhez" + } } } \ No newline at end of file diff --git a/manifest.json b/manifest.json index 0fea322..13fa54b 100644 --- a/manifest.json +++ b/manifest.json @@ -224,6 +224,19 @@ "search/search.css" ], "run_at": "document_end" + }, + { + "matches": [ + "https://eugyintezes.e-kreta.hu/uzenetek/", + "https://eugyintezes.e-kreta.hu/uzenetek" + ], + "js": [ + "messages/messages.js" + ], + "css": [ + "messages/messages.css" + ], + "run_at": "document_end" } ] } \ No newline at end of file diff --git a/messages/messages.css b/messages/messages.css new file mode 100644 index 0000000..d12d0a2 --- /dev/null +++ b/messages/messages.css @@ -0,0 +1,547 @@ +* { + box-sizing: border-box; + margin: 0; + padding: 0; + font-family: 'Montserrat', sans-serif; +} + +body { + margin: 0; + padding: 0; + color: var(--text-primary); + background-color: var(--background) !important; + min-height: 100vh; + font-size: 16px; +} + +@media (max-width: 768px) { + body { + font-size: 14px; + } +} + +.kreta-container { + min-height: 100vh; + display: flex; + flex-direction: column; +} + +.kreta-main { + flex: 1; + padding: clamp(1rem, 3vw, 2rem); + max-width: 1400px; + margin: 0 auto; + width: 100%; +} + +.messages-container { + background-color: var(--background); + border-radius: 12px; + overflow: hidden; +} + +.messages-grid { + display: grid; + grid-template-columns: repeat(auto-fill, minmax(350px, 1fr)); + gap: 1.5rem; + padding: 1.5rem; +} + +@media (max-width: 768px) { + .messages-grid { + grid-template-columns: 1fr; + gap: 1rem; + padding: 1rem; + } +} + +.message-card { + background-color: var(--card-card); + border: 1px solid var(--border-color); + border-radius: 12px; + padding: 1.5rem; + cursor: pointer; + transition: all 0.2s ease-in-out; + position: relative; + overflow: hidden; +} + +.message-card:hover { + transform: translateY(-2px); + box-shadow: 0 8px 25px rgba(0, 0, 0, 0.1); + border-color: var(--primary-color); +} + +.message-card.unread { + border-left: 4px solid var(--primary-color); + background-color: var(--card-background-hover); +} + +.message-card.unread::before { + content: ''; + position: absolute; + top: 0; + left: 0; + right: 0; + height: 3px; + background: linear-gradient(90deg, var(--primary-color), var(--secondary-color)); +} + +.message-card-header { + display: flex; + justify-content: space-between; + align-items: flex-start; + margin-bottom: 1rem; + gap: 1rem; +} + +.sender-info { + display: flex; + align-items: center; + gap: 0.5rem; + flex: 1; + min-width: 0; +} + +.sender-name { + font-weight: 600; + color: var(--text-primary); + font-size: 0.95rem; + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; +} + +.unread-indicator { + width: 8px; + height: 8px; + background-color: var(--primary-color); + border-radius: 50%; + flex-shrink: 0; + animation: pulse 2s infinite; +} + +@keyframes pulse { + 0%, 100% { + opacity: 1; + transform: scale(1); + } + 50% { + opacity: 0.7; + transform: scale(1.1); + } +} + +.message-date { + font-size: 0.8rem; + color: var(--text-secondary); + white-space: nowrap; + flex-shrink: 0; +} + +.message-subject { + font-size: 1rem; + font-weight: 500; + color: var(--text-primary); + line-height: 1.4; + margin-bottom: 1rem; + display: -webkit-box; + -webkit-line-clamp: 2; + -webkit-box-orient: vertical; + overflow: hidden; + text-overflow: ellipsis; +} + +.attachment-indicator { + position: absolute; + top: 1rem; + right: 1rem; + font-size: 1.2rem; + color: var(--text-secondary); + opacity: 0.7; +} + +.loading-state { + display: flex; + justify-content: center; + align-items: center; + min-height: 400px; + padding: 2rem; +} + +.loading-content { + display: flex; + flex-direction: column; + align-items: center; + gap: 1rem; + text-align: center; +} + +.loading-spinner { + width: 40px; + height: 40px; + border: 3px solid var(--border-color); + border-top: 3px solid var(--primary-color); + border-radius: 50%; + animation: spin 1s linear infinite; +} + +@keyframes spin { + 0% { transform: rotate(0deg); } + 100% { transform: rotate(360deg); } +} + +.loading-content p { + color: var(--text-secondary); + font-size: 0.9rem; + font-weight: 500; +} + +.empty-state { + display: flex; + justify-content: center; + align-items: center; + min-height: 400px; + padding: 2rem; +} + +.empty-content { + text-align: center; + max-width: 400px; +} + +.empty-content h3 { + font-size: 1.5rem; + font-weight: 600; + color: var(--text-primary); + margin-bottom: 0.5rem; +} + +.empty-content p { + color: var(--text-secondary); + font-size: 1rem; + line-height: 1.5; +} + +.error-state { + display: flex; + justify-content: center; + align-items: center; + min-height: 400px; + padding: 2rem; +} + +.error-content { + text-align: center; + max-width: 500px; +} + +.error-content h3 { + font-size: 1.5rem; + font-weight: 600; + color: var(--error-color); + margin-bottom: 0.5rem; +} + +.error-content p { + color: var(--text-secondary); + font-size: 1rem; + line-height: 1.5; + margin-bottom: 1.5rem; +} + +.retry-btn { + padding: 0.75rem 1.5rem; + background-color: var(--primary-color); + color: white; + border: none; + border-radius: 8px; + font-weight: 600; + font-size: 0.9rem; + cursor: pointer; + transition: all 0.2s ease-in-out; +} + +.retry-btn:hover { + background-color: var(--primary-hover); + transform: translateY(-1px); + box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15); +} + +.modal-overlay { + position: fixed; + top: 0; + left: 0; + width: 100%; + height: 100%; + background: rgba(0, 0, 0, 0.8); + backdrop-filter: blur(4px); + display: flex; + justify-content: center; + align-items: center; + z-index: 1000; +} + +/* Prevent background scrolling when modal is open */ +body.modal-open { + overflow: hidden; +} + +.modal-content { + background: var(--card-card); + border-radius: 12px; + max-width: 1200px; + width: 95%; + max-height: 95%; + overflow-y: auto; + box-shadow: 0 8px 32px rgba(0, 0, 0, 0.3); + border: 1px solid var(--background-0); +} + +.modal-header { + display: flex; + justify-content: space-between; + align-items: center; + padding: 20px; + border-bottom: 1px solid var(--background-0); + background: var(--background); + border-radius: 12px 12px 0 0; +} + +.modal-header h2 { + margin: 0; + color: var(--text-primary); + font-size: 1.5em; + font-weight: 600; +} + +.modal-close { + background: none; + border: none; + font-size: 24px; + cursor: pointer; + color: var(--text-secondary); + padding: 0; + width: 32px; + height: 32px; + display: flex; + align-items: center; + justify-content: center; + border-radius: 50%; + transition: all 0.2s ease; +} + +.modal-close:hover { + background: var(--background-0); + color: var(--text-primary); + transform: scale(1.1); +} + +.modal-body { + padding: 20px; + background: var(--card-card); + } + + .modal-body iframe { + min-height: 600px; + border-radius: 12px; + box-shadow: 0 4px 16px rgba(0, 0, 0, 0.1); + border: 1px solid var(--background-0); + } + + .loading-content { + text-align: center; + padding: 40px 20px; + } + + .loading-spinner { + width: 40px; + height: 40px; + border: 4px solid #f3f3f3; + border-top: 4px solid #1976d2; + border-radius: 50%; + animation: spin 1s linear infinite; + margin: 0 auto 20px; + } + + @keyframes spin { + 0% { transform: rotate(0deg); } + 100% { transform: rotate(360deg); } + } + + .error-content { + text-align: center; + padding: 40px 20px; + } + + .error-content h3 { + color: #d32f2f; + margin-bottom: 10px; + } + + .error-content p { + color: #666; + margin-bottom: 20px; + } + + .message-details { + max-width: 100%; + } + +.message-info { + background-color: var(--card-card); + padding: 15px; + border-radius: 6px; + margin-bottom: 20px; + color: var(--text-secondary); +} + +.info-row { + display: flex; + margin-bottom: 10px; + align-items: flex-start; +} + +.info-row:last-child { + margin-bottom: 0; +} + +.info-label { + font-weight: bold; + min-width: 80px; + margin-right: 10px; +} + +.info-value { + flex: 1; + word-break: break-word; +} + +.message-content { + margin-bottom: 20px; +} + +.message-content h4 { + margin: 0 0 15px 0; + color: var(--text-secondary); + font-size: 1.1em; +} + +.message-text { + background-color: var(--card-card); + border-radius: 6px; + padding: 15px; + line-height: 1.6; + color: var(--text-secondary); + max-height: 300px; + overflow-y: auto; +} + +.message-text p { + margin: 0 0 10px 0; +} + +.message-text p:last-child { + margin-bottom: 0; +} + +.message-text a { + color: #1976d2; + text-decoration: none; +} + +.message-text a:hover { + text-decoration: underline; +} + +.message-attachments { + background: #f9f9f9; + padding: 15px; + border-radius: 6px; +} + +.message-attachments h4 { + margin: 0 0 10px 0; + color: #333; + font-size: 1.1em; +} + +.message-attachments ul { + list-style: none; + padding: 0; + margin: 0; +} + +.message-attachments li { + padding: 5px 0; +} + +.message-attachments a { + color: #1976d2; + text-decoration: none; + display: inline-flex; + align-items: center; +} + +.message-attachments a:hover { + text-decoration: underline; +} + +@media (max-width: 1200px) { + .messages-grid { + grid-template-columns: repeat(auto-fill, minmax(300px, 1fr)); + } +} + +@media (max-width: 768px) { + .kreta-main { + padding: 1rem; + } + + .message-card { + padding: 1rem; + } + + .message-card-header { + flex-direction: column; + align-items: flex-start; + gap: 0.5rem; + } + + .message-date { + align-self: flex-end; + margin-top: -0.5rem; + } + + .sender-name { + font-size: 0.9rem; + } + + .message-subject { + font-size: 0.95rem; + } +} + +@media (max-width: 480px) { + .messages-grid { + grid-template-columns: 1fr; + gap: 0.75rem; + padding: 0.75rem; + } + + .message-card { + padding: 0.75rem; + } + + .sender-name { + font-size: 0.85rem; + } + + .message-subject { + font-size: 0.9rem; + } + + .attachment-indicator { + font-size: 1rem; + } +} \ No newline at end of file diff --git a/messages/messages.js b/messages/messages.js new file mode 100644 index 0000000..3195e4f --- /dev/null +++ b/messages/messages.js @@ -0,0 +1,340 @@ +(() => { + function formatDate(dateString) { + if (!dateString) { + return 'Ismeretlen dátum'; + } + + const date = new Date(dateString); + if (isNaN(date.getTime())) { + return 'Érvénytelen dátum'; + } + + const now = new Date(); + const diffTime = Math.abs(now - date); + const diffDays = Math.floor(diffTime / (1000 * 60 * 60 * 24)); + + if (diffDays === 0) { + return 'Ma'; + } else if (diffDays === 1) { + return 'Tegnap'; + } else if (diffDays <= 7) { + return `${diffDays} napja`; + } else { + return date.toLocaleDateString('hu-HU', { + year: 'numeric', + month: 'short', + day: 'numeric' + }); + } + } + + function sanitizeHTML(html) { + const div = document.createElement('div'); + div.textContent = html; + return div.innerHTML; + } + + class APIManager { + static async fetchMessages() { + try { + const response = await fetch('https://eugyintezes.e-kreta.hu/api/v1/kommunikacio/postaladaelemek/beerkezett', { + method: 'GET', + headers: { + 'Accept': 'application/json', + 'Content-Type': 'application/json', + 'Content-Length': '8023', + 'x-csrf': '1', + 'x-uzenet-json-formatum': 'CamelCase' + } + }); + + if (!response.ok) { + throw new Error(`HTTP error! status: ${response.status}`); + } + + const data = await response.json(); + return data; + } catch (error) { + console.error('Error fetching messages:', error); + throw error; + } + } + } + + async function openMessageModal(messageId) { + document.body.classList.add('modal-open'); + try { + const modalOverlay = document.createElement('div'); + modalOverlay.className = 'modal-overlay'; + modalOverlay.onclick = (e) => { + if (e.target === modalOverlay) { + closeMessageModal(); + } + }; + + const modalContent = document.createElement('div'); + modalContent.className = 'modal-content'; + modalContent.innerHTML = ` +
Üzenet betöltése...
+Az üzenet betöltése sikertelen.
+ +${LanguageManager.t('messages.loading', 'Üzenetek betöltése...')}
+${LanguageManager.t('messages.error.description', 'Az üzenetek betöltése sikertelen volt.')}
+ +${LanguageManager.t('messages.empty.description', 'Jelenleg nincsenek elérhető üzenetek.')}
+