diff --git a/absences/absences.css b/absences/absences.css index 1b0b47a..044da49 100644 --- a/absences/absences.css +++ b/absences/absences.css @@ -29,131 +29,50 @@ body { } .absences-page { - display: grid; - grid-template-columns: 300px 1fr; - grid-template-rows: 1fr; - grid-template-areas: - "sidebar content"; - gap: 24px; - min-height: calc(100vh - 200px); -} - -.absences-sidebar { - grid-area: sidebar; display: flex; flex-direction: column; - gap: 16px; - position: sticky; - top: 24px; - height: fit-content; + gap: 24px; } -.filter-card { +.stats-section { background: var(--card-card); border-radius: 20px; padding: 24px; box-shadow: 0px 1px var(--shadow-blur) 0px var(--accent-shadow); } -.filter-header { +.stats-title { + font-size: 20px; + font-weight: 700; + color: var(--text-primary); margin-bottom: 20px; - display: flex; - align-items: center; - gap: 12px; -} - -.filter-header h2 { - font-size: 18px; - font-weight: 600; - color: var(--text-primary); - margin: 0; - background-color: #00000000 !important; -} - -.filter-content { - display: flex; - flex-direction: column; - gap: 20px; -} - -.filter-group { - display: flex; - flex-direction: column; - gap: 8px; -} - -.filter-group label { - display: flex; - align-items: center; - gap: 10px; - color: var(--text-secondary); - font-size: 14px; - font-weight: 500; -} - -.filter-group label img { - width: 20px; - height: 20px; - opacity: 0.8; -} - -.filter-input { - padding: 12px 16px; - border: 2px solid transparent; - border-radius: 12px; - background: var(--button-secondaryFill); - color: var(--text-primary); - font-family: inherit; - font-size: 14px; - transition: all 0.2s ease; - cursor: pointer; -} - -.filter-input:hover { - background: var(--accent-15); -} - -.filter-input:focus { - outline: none; - border-color: var(--accent-accent); - background: var(--button-secondaryFill); -} - -.stats-section { - grid-area: stats; + background-color: transparent !important; } .stats-grid { display: grid; - grid-template-columns: repeat(2, 1fr); + grid-template-columns: repeat(6, 1fr); gap: 12px; } .stat-card { - background: var(--card-card); + background: var(--button-secondaryFill); border-radius: 16px; - padding: 20px; + padding: 20px 16px; display: flex; flex-direction: column; align-items: center; justify-content: center; text-align: center; - box-shadow: 0px 1px var(--shadow-blur) 0px var(--accent-shadow); transition: transform 0.2s ease, box-shadow 0.2s ease; min-height: 100px; + border: 2px solid transparent; } .stat-card:hover { transform: translateY(-2px); } -.stat-icon { - width: 24px; - height: 24px; - margin-bottom: 8px; - opacity: 0.8; -} - .stat-number { font-size: 32px; font-weight: 700; @@ -166,18 +85,46 @@ body { color: var(--accent-accent); } +.stat-card.total { + border-color: var(--accent-15); +} + +.stat-card.absence .stat-number { + color: var(--accent-accent); +} + +.stat-card.late .stat-number { + color: var(--grades-2); +} + +.stat-card.late { + border-color: var(--grades-background-2); +} + .stat-card.justified .stat-number { color: var(--grades-4); } +.stat-card.justified { + border-color: var(--grades-background-4); +} + .stat-card.unjustified .stat-number { color: var(--grades-1); } +.stat-card.unjustified { + border-color: var(--grades-background-1); +} + .stat-card.pending .stat-number { color: var(--grades-3); } +.stat-card.pending { + border-color: var(--grades-background-3); +} + .stat-label { color: var(--text-secondary); font-size: 12px; @@ -186,163 +133,369 @@ body { letter-spacing: 0.5px; } -.absences-content { - grid-area: content; +.calendar-legend { display: flex; - flex-direction: column; - gap: 24px; + flex-wrap: wrap; + gap: 16px; + padding: 16px 24px; + background: var(--card-card); + border-radius: 16px; + box-shadow: 0px 1px var(--shadow-blur) 0px var(--accent-shadow); } -.day-group { +.legend-item { + display: flex; + align-items: center; + gap: 8px; +} + +.legend-color { + width: 24px; + height: 24px; + border-radius: 8px; +} + +.legend-color.status-justified { + background: var(--grades-background-4); + border: 2px solid var(--grades-4); +} + +.legend-color.status-pending { + background: var(--grades-background-3); + border: 2px solid var(--grades-3); +} + +.legend-color.status-unjustified { + background: var(--grades-background-1); + border: 2px solid var(--grades-1); +} + +.legend-color.type-late-legend { + background: var(--grades-background-2); + border: 2px dashed var(--grades-2); +} + +.legend-item span { + font-size: 13px; + color: var(--text-secondary); + font-weight: 500; +} + +.calendar-section { + display: grid; + grid-template-columns: repeat(auto-fill, minmax(320px, 1fr)); + gap: 20px; +} + +.month-container { background: var(--card-card); border-radius: 20px; overflow: hidden; box-shadow: 0px 1px var(--shadow-blur) 0px var(--accent-shadow); } -.day-header { +.month-header { + background: var(--button-secondaryFill); + color: white; + padding: 16px 20px; + font-size: 16px; + font-weight: 600; + text-align: center; +} + +.calendar-grid { + display: grid; + grid-template-columns: repeat(7, 1fr); + gap: 4px; + padding: 12px; +} + +.calendar-day-header { + text-align: center; + font-size: 12px; + font-weight: 600; + color: var(--text-secondary); + padding: 8px 0; + text-transform: uppercase; +} + +.calendar-day { + aspect-ratio: 1; + display: flex; + flex-direction: column; + align-items: center; + justify-content: center; + border-radius: 10px; + background: var(--button-secondaryFill); + position: relative; + min-height: 40px; + transition: transform 0.15s ease, box-shadow 0.15s ease; +} + +.calendar-day.empty { + background: transparent; +} + +.calendar-day.future { + background: var(--accent-15); + opacity: 0.5; +} + +.calendar-day.future .day-number { + color: var(--text-teritary); +} + +.calendar-day.today .day-number { + color: var(--accent-accent); + font-weight: 700; +} + +.calendar-day .day-number { + font-size: 14px; + font-weight: 500; + color: var(--text-primary); + z-index: 1; +} + +.calendar-day.has-absence { + cursor: pointer; +} + +.calendar-day.has-absence:hover { + transform: scale(1.1); + box-shadow: 0 4px 12px var(--accent-shadow); + z-index: 2; +} + +.calendar-day.status-justified { + background: var(--grades-background-4); + border: 2px solid var(--grades-4); +} + +.calendar-day.status-justified .day-number { + color: var(--grades-4); + font-weight: 700; +} + +.calendar-day.status-pending { + background: var(--grades-background-3); + border: 2px solid var(--grades-3); +} + +.calendar-day.status-pending .day-number { + color: var(--grades-3); + font-weight: 700; +} + +.calendar-day.status-unjustified { + background: var(--grades-background-1); + border: 2px solid var(--grades-1); +} + +.calendar-day.status-unjustified .day-number { + color: var(--grades-1); + font-weight: 700; +} + +.calendar-day.type-late { + border-style: dashed; +} + +.calendar-day.type-mixed { + border-style: double; + border-width: 3px; +} + +.absence-count { + position: absolute; + top: 2px; + right: 2px; background: var(--accent-accent); color: white; - padding: 16px 24px; + font-size: 9px; + font-weight: 700; + width: 16px; + height: 16px; + border-radius: 50%; + display: flex; + align-items: center; + justify-content: center; +} + +.calendar-day.status-justified .absence-count { + background: var(--grades-4); +} + +.calendar-day.status-pending .absence-count { + background: var(--grades-3); +} + +.calendar-day.status-unjustified .absence-count { + background: var(--grades-1); +} + +.absence-modal-overlay { + position: fixed; + top: 0; + left: 0; + right: 0; + bottom: 0; + background: rgba(0, 0, 0, 0.5); + backdrop-filter: blur(4px); + display: flex; + align-items: center; + justify-content: center; + z-index: 10000; + opacity: 0; + transition: opacity 0.2s ease; + padding: 20px; +} + +.absence-modal-overlay.visible { + opacity: 1; +} + +.absence-modal { + background: var(--card-card); + border-radius: 24px; + max-width: 500px; + width: 100%; + max-height: 80vh; + overflow: hidden; + display: flex; + flex-direction: column; + box-shadow: 0 20px 60px rgba(0, 0, 0, 0.3); + transform: scale(0.95); + transition: transform 0.2s ease; +} + +.absence-modal-overlay.visible .absence-modal { + transform: scale(1); +} + +.modal-header { + background: var(--button-secondaryFill); + border-bottom: 1px solid #00000000 !important; + color: white; + padding: 14px 18px !important; display: flex; align-items: center; justify-content: space-between; - font-weight: 600; } -.day-date { - display: flex; - align-items: center; - gap: 12px; +.modal-header h2 { font-size: 16px; + font-weight: 600; + margin: 0; + background: transparent !important; } -.day-date img { - width: 20px; - height: 20px; - filter: brightness(0) invert(1); +.modal-content { + background-color: var(--card-card) !important; + padding: 16px; + overflow-y: auto; + display: flex; + flex-direction: column; + gap: 8px; } -.day-count { - background: rgba(255, 255, 255, 0.2); - padding: 4px 12px; - border-radius: 20px; - font-size: 13px; -} - -.day-absences { - display: grid; - grid-template-columns: repeat(auto-fill, minmax(340px, 1fr)); - gap: 16px; - padding: 20px; -} - -.absence-card { +.modal-absence-card { background: var(--button-secondaryFill); - border-radius: 16px; - padding: 20px; - display: grid; - grid-template-columns: auto 1fr minmax(auto, max-content); - grid-template-rows: auto auto; - grid-template-areas: - "lesson subject status" - "lesson topic status"; - gap: 8px 12px; - transition: transform 0.2s ease, box-shadow 0.2s ease; - border: 1px solid var(--accent-15); + border-radius: 12px; + padding: 12px; + display: flex; + flex-direction: column; + gap: 6px; + border-left: 3px solid transparent; } -.absence-card:hover { - transform: translateY(-2px); - box-shadow: 0 4px 12px var(--accent-shadow); -} - -.absence-lesson { - grid-area: lesson; +.modal-card-header { display: flex; align-items: center; - justify-content: center; - width: 48px; - height: 48px; - background: var(--accent-15); - border-radius: 12px; - font-size: 20px; + gap: 8px; + flex-wrap: wrap; +} + +.modal-lesson { + font-size: 16px; font-weight: 700; color: var(--accent-accent); + min-width: 24px; +} + +.type-indicator { + display: inline-flex; + align-items: center; + padding: 3px 8px 1px 8px; + border-radius: 12px; + font-size: 10px; + font-weight: 600; + text-transform: uppercase; +} + +.type-indicator.absence { + background: var(--accent-15); + color: var(--accent-accent); } -.absence-subject { - grid-area: subject; - font-size: 16px; - font-weight: 600; - color: var(--text-primary); - align-self: end; +.type-indicator.late { + background: var(--grades-background-2); + color: var(--grades-2); } -.absence-topic { - grid-area: topic; - font-size: 13px; - color: var(--text-secondary); - align-self: start; - display: -webkit-box; - -webkit-line-clamp: 2; - line-clamp: 2; - -webkit-box-orient: vertical; - overflow: hidden; - text-overflow: ellipsis; -} - -.absence-status { - grid-area: status; - display: flex; - align-items: center; - justify-content: center; -} - -.status-badge { +.modal-status-badge { display: inline-flex; align-items: center; - gap: 6px; - padding: 8px 14px; - border-radius: 24px; - font-size: 11px; + padding: 3px 8px; + border-radius: 12px; + font-size: 10px; font-weight: 600; - text-transform: uppercase; - letter-spacing: 0.2px; - white-space: nowrap; - flex-shrink: 0; + margin-left: auto; } -.status-badge img { - width: 16px; - height: 16px; -} - -.status-badge.justified { +.modal-status-badge.justified { background: var(--grades-background-4); color: var(--grades-4); } -.status-badge.justified img { - filter: brightness(0) saturate(100%) invert(76%) sepia(43%) saturate(609%) hue-rotate(53deg) brightness(101%) contrast(92%); -} - -.status-badge.unjustified { - background: var(--grades-background-1); - color: var(--grades-1); -} - -.status-badge.unjustified .material-icons-round { - font-size: 16px; -} - -.status-badge.pending { +.modal-status-badge.pending { background: var(--grades-background-3); color: var(--grades-3); } -.status-badge.pending .material-icons-round { - font-size: 16px; +.modal-status-badge.unjustified { + background: var(--grades-background-1); + color: var(--grades-1); +} + +.modal-subject { + font-size: 15px; + font-weight: 600; + color: var(--text-primary); + line-height: 1.3; +} + +.modal-info-row { + display: flex; + flex-wrap: wrap; + gap: 6px; + font-size: 12px; + color: var(--text-secondary); +} + +.modal-info-item { + display: inline-block; +} + +.modal-info-item:not(:last-child)::after { + content: '•'; + margin-left: 6px; + color: var(--text-teritary); +} + +.modal-minutes { + color: var(--grades-2); + font-weight: 600; } .empty-state { @@ -375,14 +528,9 @@ body { color: var(--text-secondary); } -@media (max-width: 1024px) { - .absences-page { - grid-template-columns: 260px 1fr; - gap: 20px; - } - - .day-absences { - grid-template-columns: 1fr; +@media (max-width: 1200px) { + .stats-grid { + grid-template-columns: repeat(3, 1fr); } } @@ -395,41 +543,18 @@ body { padding: 16px; } - .absences-page { - grid-template-columns: 1fr; - grid-template-rows: auto 1fr; - grid-template-areas: - "sidebar" - "content"; - gap: 16px; - } - - .absences-sidebar { - position: static; - } - - .filter-card { + .stats-section { padding: 20px; border-radius: 16px; } - .filter-content { - display: grid; - grid-template-columns: repeat(3, 1fr); - gap: 12px; - } - - .filter-group label { - font-size: 12px; - } - - .filter-input { - padding: 10px 12px; - font-size: 13px; + .stats-title { + font-size: 18px; + margin-bottom: 16px; } .stats-grid { - grid-template-columns: repeat(4, 1fr); + grid-template-columns: repeat(3, 1fr); gap: 10px; } @@ -447,33 +572,78 @@ body { font-size: 10px; } - .day-group { + .calendar-section { + grid-template-columns: 1fr; + } + + .calendar-legend { + gap: 12px; + padding: 14px 18px; + } + + .legend-item span { + font-size: 12px; + } + + .month-container { border-radius: 16px; } - .day-header { - padding: 14px 18px; + .month-header { + padding: 14px 16px; + font-size: 15px; + } + + .calendar-grid { + gap: 3px; + padding: 10px; + } + + .calendar-day { + min-height: 36px; + border-radius: 8px; + } + + .calendar-day .day-number { + font-size: 13px; + } + + .absence-count { + width: 14px; + height: 14px; + font-size: 8px; + } + + .absence-modal { + max-width: 100%; + max-height: 90vh; + border-radius: 20px; + } + + .modal-header { + padding: 12px 16px; + } + + .modal-header h2 { + font-size: 15px; + } + + .modal-content { + padding: 12px; + gap: 6px; + } + + .modal-absence-card { + padding: 10px; + gap: 5px; + } + + .modal-subject { font-size: 14px; } - .day-absences { - padding: 14px; - gap: 12px; - } - - .absence-card { - padding: 16px; - border-radius: 12px; - } - - .absence-lesson { - width: 44px; - height: 44px; - font-size: 18px; - } - - .absence-subject { - font-size: 15px; + .modal-info-row { + font-size: 11px; } } @@ -483,26 +653,13 @@ body { } .absences-page { - gap: 12px; + gap: 16px; } - .filter-card { + .stats-section { padding: 16px; } - .filter-header { - margin-bottom: 16px; - } - - .filter-header h2 { - font-size: 16px; - } - - .filter-content { - grid-template-columns: 1fr; - gap: 14px; - } - .stats-grid { grid-template-columns: repeat(2, 1fr); gap: 8px; @@ -523,63 +680,35 @@ body { letter-spacing: 0.3px; } - .day-header { - padding: 12px 16px; - flex-wrap: wrap; - gap: 8px; - } - - .day-date { - font-size: 14px; - } - - .day-count { - font-size: 12px; - padding: 3px 10px; - } - - .day-absences { - padding: 12px; + .calendar-legend { + flex-direction: column; gap: 10px; } - .absence-card { - padding: 14px; - grid-template-columns: auto 1fr; - grid-template-rows: auto auto auto; - grid-template-areas: - "lesson subject" - "lesson topic" - "status status"; - gap: 6px 12px; + .calendar-grid { + gap: 2px; + padding: 8px; } - .absence-lesson { - width: 40px; - height: 40px; - font-size: 16px; - grid-row: span 2; + .calendar-day { + min-height: 32px; } - .absence-status { - justify-content: flex-start; - margin-top: 8px; - padding-top: 10px; - border-top: 1px solid var(--accent-15); - } - - .status-badge { - padding: 6px 12px; - font-size: 11px; - } - - .absence-subject { - font-size: 14px; - } - - .absence-topic { + .calendar-day .day-number { font-size: 12px; } + + .absence-modal-overlay { + padding: 12px; + } + + .modal-absence-card { + padding: 14px; + } + + .modal-subject { + font-size: 16px; + } } @keyframes fadeIn { @@ -593,17 +722,15 @@ body { } } -.day-group { +.month-container { animation: fadeIn 0.3s ease forwards; } -.day-group:nth-child(1) { animation-delay: 0.05s; } -.day-group:nth-child(2) { animation-delay: 0.1s; } -.day-group:nth-child(3) { animation-delay: 0.15s; } -.day-group:nth-child(4) { animation-delay: 0.2s; } -.day-group:nth-child(5) { animation-delay: 0.25s; } - - +.month-container:nth-child(1) { animation-delay: 0.05s; } +.month-container:nth-child(2) { animation-delay: 0.1s; } +.month-container:nth-child(3) { animation-delay: 0.15s; } +.month-container:nth-child(4) { animation-delay: 0.2s; } +.month-container:nth-child(5) { animation-delay: 0.25s; } .loading-overlay { position: fixed; diff --git a/absences/absences.js b/absences/absences.js index c72686e..3fc0411 100644 --- a/absences/absences.js +++ b/absences/absences.js @@ -15,7 +15,7 @@ async function collectAbsencesData() { try { const currentDomain = window.location.hostname; const response = await fetch( - `https://${currentDomain}/api/HianyzasokApi/GetHianyzasGrid?sort=MulasztasDatum-desc&page=1&pageSize=100&group=&filter=&data=%7B%7D&_=${Date.now()}`, + `https://${currentDomain}/api/HianyzasokApi/GetHianyzasGrid?sort=MulasztasDatum-desc&page=1&pageSize=500&group=&filter=&data=%7B%7D&_=${Date.now()}`, { method: "GET", credentials: "include", @@ -45,359 +45,414 @@ async function collectAbsencesData() { justificationStatus = "unjustified"; } + const absenceType = item.MulasztasTipus === 1500 ? 'absence' : item.MulasztasTipus === 1499 ? 'late' : 'other'; + absences.push({ date: formattedDate, rawDate: date, + dateKey: `${date.getFullYear()}-${(date.getMonth() + 1).toString().padStart(2, "0")}-${date.getDate().toString().padStart(2, "0")}`, lesson: item.Oraszam?.toString() || "", subject: item.Targy || "", topic: item.Tema || "", type: item.MulasztasTipus_DNAME || "", + absenceType: absenceType, + absenceTypeId: item.MulasztasTipus, justified: item.Igazolt_BOOL === true, justificationStatus: justificationStatus, purposeful: item.TanoraiCeluMulasztas_BNAME || "", justificationType: item.IgazolasTipus_DNAME || "", + minutes: item.KesesPercben || 0, }); }); } - - const groupedAbsences = absences.reduce((groups, absence) => { - const date = absence.date; - if (!groups[date]) { - groups[date] = []; + const groupedByDate = absences.reduce((groups, absence) => { + const key = absence.dateKey; + if (!groups[key]) { + groups[key] = []; } - groups[date].push(absence); + groups[key].push(absence); return groups; }, {}); - - Object.keys(groupedAbsences).forEach(date => { - groupedAbsences[date].sort((a, b) => parseInt(a.lesson) - parseInt(b.lesson)); + Object.keys(groupedByDate).forEach(date => { + groupedByDate[date].sort((a, b) => parseInt(a.lesson) - parseInt(b.lesson)); }); - return { basicData, absences, groupedAbsences }; + return { basicData, absences, groupedByDate }; } catch (error) { console.error("Hiba az API hívás során:", error); - return { basicData, absences: [], groupedAbsences: {} }; + return { basicData, absences: [], groupedByDate: {} }; } } -function createFilterCard(absences) { - const filterCard = document.createElement('div'); - filterCard.className = 'filter-card'; - - const filterHeader = document.createElement('div'); - filterHeader.className = 'filter-header'; - const h2 = document.createElement('h2'); - h2.textContent = LanguageManager.t('absences.filter_title'); - filterHeader.appendChild(h2); - - const filterContent = document.createElement('div'); - filterContent.className = 'filter-content'; - - const dateGroup = document.createElement('div'); - dateGroup.className = 'filter-group'; - - const dateLabel = document.createElement('label'); - const dateImg = document.createElement('img'); - dateImg.src = chrome.runtime.getURL('icons/Calendar.svg'); - dateImg.alt = 'Dátum'; - dateLabel.appendChild(dateImg); - dateLabel.appendChild(document.createTextNode(' ' + LanguageManager.t('absences.date'))); - - const dateInput = document.createElement('input'); - dateInput.type = 'date'; - dateInput.id = 'dateFilter'; - dateInput.className = 'filter-input'; - - dateGroup.appendChild(dateLabel); - dateGroup.appendChild(dateInput); - filterContent.appendChild(dateGroup); - - const subjectGroup = document.createElement('div'); - subjectGroup.className = 'filter-group'; - - const subjectLabel = document.createElement('label'); - const subjectImg = document.createElement('img'); - subjectImg.src = chrome.runtime.getURL('icons/Subject.svg'); - subjectImg.alt = 'Tantárgy'; - subjectLabel.appendChild(subjectImg); - subjectLabel.appendChild(document.createTextNode(' ' + LanguageManager.t('absences.subject'))); - - const subjectSelect = document.createElement('select'); - subjectSelect.id = 'subjectFilter'; - subjectSelect.className = 'filter-input'; - - const defaultSubjectOption = document.createElement('option'); - defaultSubjectOption.value = ''; - defaultSubjectOption.textContent = LanguageManager.t('absences.all_subjects'); - subjectSelect.appendChild(defaultSubjectOption); - - const subjects = [...new Set(absences.map(a => a.subject))].sort(); - subjects.forEach(subject => { - const option = document.createElement('option'); - option.value = subject; - option.textContent = subject; - subjectSelect.appendChild(option); - }); - - subjectGroup.appendChild(subjectLabel); - subjectGroup.appendChild(subjectSelect); - filterContent.appendChild(subjectGroup); - - const justificationGroup = document.createElement('div'); - justificationGroup.className = 'filter-group'; - - const justificationLabel = document.createElement('label'); - const justificationImg = document.createElement('img'); - justificationImg.src = chrome.runtime.getURL('icons/BadgeCheck.svg'); - justificationImg.alt = 'Igazolás'; - justificationLabel.appendChild(justificationImg); - justificationLabel.appendChild(document.createTextNode(' ' + LanguageManager.t('absences.justification'))); - - const justificationSelect = document.createElement('select'); - justificationSelect.id = 'justificationFilter'; - justificationSelect.className = 'filter-input'; - - const justificationOptions = [ - { value: '', text: LanguageManager.t('absences.all_types') }, - { value: 'justified', text: LanguageManager.t('absences.justified') }, - { value: 'unjustified', text: LanguageManager.t('absences.unjustified') }, - { value: 'pending', text: LanguageManager.t('absences.pending') } - ]; - - justificationOptions.forEach(optionData => { - const option = document.createElement('option'); - option.value = optionData.value; - option.textContent = optionData.text; - justificationSelect.appendChild(option); - }); - - justificationGroup.appendChild(justificationLabel); - justificationGroup.appendChild(justificationSelect); - filterContent.appendChild(justificationGroup); - - filterCard.appendChild(filterHeader); - filterCard.appendChild(filterContent); - - return filterCard; -} - function createStatsSection(absences) { const statsSection = document.createElement('div'); statsSection.className = 'stats-section'; - + + const statsTitle = document.createElement('h2'); + statsTitle.className = 'stats-title'; + statsTitle.textContent = LanguageManager.t('absences.title'); + statsSection.appendChild(statsTitle); + const statsGrid = document.createElement('div'); statsGrid.className = 'stats-grid'; - + + const totalAbsences = absences.filter(a => a.absenceType === 'absence').length; + const totalLates = absences.filter(a => a.absenceType === 'late').length; + const justified = absences.filter(a => a.justificationStatus === 'justified').length; + const unjustified = absences.filter(a => a.justificationStatus === 'unjustified').length; + const pending = absences.filter(a => a.justificationStatus === 'pending').length; + const stats = [ - { - type: 'total', - number: absences.length, - label: LanguageManager.t('absences.total_absences') - }, - { - type: 'justified', - number: absences.filter(a => a.justificationStatus === 'justified').length, - label: LanguageManager.t('absences.justified') - }, - { - type: 'unjustified', - number: absences.filter(a => a.justificationStatus === 'unjustified').length, - label: LanguageManager.t('absences.unjustified') - }, - { - type: 'pending', - number: absences.filter(a => a.justificationStatus === 'pending').length, - label: LanguageManager.t('absences.pending') - } + { type: 'total', number: absences.length, label: LanguageManager.t('absences.total_absences') }, + { type: 'absence', number: totalAbsences, label: LanguageManager.t('absences.absence_type') }, + { type: 'late', number: totalLates, label: LanguageManager.t('absences.late_type') }, + { type: 'justified', number: justified, label: LanguageManager.t('absences.justified') }, + { type: 'unjustified', number: unjustified, label: LanguageManager.t('absences.unjustified') }, + { type: 'pending', number: pending, label: LanguageManager.t('absences.pending') }, ]; - + stats.forEach(stat => { const statCard = document.createElement('div'); statCard.className = `stat-card ${stat.type}`; - statCard.dataset.type = stat.type; - + const statNumber = document.createElement('div'); statNumber.className = 'stat-number'; statNumber.textContent = stat.number; - + const statLabel = document.createElement('div'); statLabel.className = 'stat-label'; statLabel.textContent = stat.label; - + statCard.appendChild(statNumber); statCard.appendChild(statLabel); statsGrid.appendChild(statCard); }); - + statsSection.appendChild(statsGrid); return statsSection; } -function createDayGroup(date, dayAbsences) { - const dayGroup = document.createElement('div'); - dayGroup.className = 'day-group'; - dayGroup.dataset.date = date; - - - const dayHeader = document.createElement('div'); - dayHeader.className = 'day-header'; - - const dayDate = document.createElement('div'); - dayDate.className = 'day-date'; - - const calendarIcon = document.createElement('img'); - calendarIcon.src = chrome.runtime.getURL('icons/Calendar.svg'); - calendarIcon.alt = 'Dátum'; - - const dateText = document.createElement('span'); - dateText.textContent = formatDateWithDay(date); - - dayDate.appendChild(calendarIcon); - dayDate.appendChild(dateText); - - const dayCount = document.createElement('div'); - dayCount.className = 'day-count'; - dayCount.textContent = `${dayAbsences.length} ${LanguageManager.t('absences.hours')}`; - - dayHeader.appendChild(dayDate); - dayHeader.appendChild(dayCount); - - const dayAbsencesContainer = document.createElement('div'); - dayAbsencesContainer.className = 'day-absences'; - - dayAbsences.forEach(absence => { - const absenceCard = createAbsenceCard(absence); - dayAbsencesContainer.appendChild(absenceCard); - }); - - dayGroup.appendChild(dayHeader); - dayGroup.appendChild(dayAbsencesContainer); - - return dayGroup; +function getSchoolYearStart() { + const now = new Date(); + const year = now.getMonth() >= 8 ? now.getFullYear() : now.getFullYear() - 1; + return new Date(year, 8, 1); } -function formatDateWithDay(dateStr) { - const parts = dateStr.split('.'); - const year = parseInt(parts[0]); - const month = parseInt(parts[1]) - 1; - const day = parseInt(parts[2]); - - const date = new Date(year, month, day); - const days = [ - LanguageManager.t('common.sunday'), - LanguageManager.t('common.monday'), - LanguageManager.t('common.tuesday'), - LanguageManager.t('common.wednesday'), - LanguageManager.t('common.thursday'), - LanguageManager.t('common.friday'), - LanguageManager.t('common.saturday') - ]; - - const dayName = days[date.getDay()]; - return `${dateStr} - ${dayName.charAt(0).toUpperCase() + dayName.slice(1)}`; -} +function createCalendarSection(groupedByDate, absences) { + const calendarSection = document.createElement('div'); + calendarSection.className = 'calendar-section'; -function createAbsenceCard(absence) { - const card = document.createElement('div'); - card.className = 'absence-card'; - card.dataset.subject = absence.subject; - card.dataset.status = absence.justificationStatus; - card.dataset.date = absence.date; + const schoolYearStart = getSchoolYearStart(); + const now = new Date(); - const lessonDiv = document.createElement('div'); - lessonDiv.className = 'absence-lesson'; - lessonDiv.textContent = absence.lesson + '.'; + const months = []; + let currentDate = new Date(schoolYearStart); - const subjectDiv = document.createElement('div'); - subjectDiv.className = 'absence-subject'; - subjectDiv.textContent = absence.subject; - - const topicDiv = document.createElement('div'); - topicDiv.className = 'absence-topic'; - topicDiv.textContent = absence.topic || '-'; - topicDiv.title = absence.topic; - - const statusDiv = document.createElement('div'); - statusDiv.className = 'absence-status'; - - const statusBadge = document.createElement('span'); - statusBadge.className = `status-badge ${absence.justificationStatus}`; - - if (absence.justificationStatus === 'justified') { - const img = document.createElement('img'); - img.src = chrome.runtime.getURL('icons/BadgeCheck.svg'); - img.alt = 'Igazolt'; - statusBadge.appendChild(img); - statusBadge.appendChild(document.createTextNode(' ' + LanguageManager.t('absences.justified'))); - } else if (absence.justificationStatus === 'unjustified') { - const span = document.createElement('span'); - span.className = 'material-icons-round'; - span.textContent = 'cancel'; - statusBadge.appendChild(span); - statusBadge.appendChild(document.createTextNode(' ' + LanguageManager.t('absences.unjustified'))); - } else { - const img = document.createElement('img'); - img.src = chrome.runtime.getURL('icons/pending.svg'); - img.alt = 'Függőben'; - statusBadge.appendChild(img); - statusBadge.appendChild(document.createTextNode(' ' + LanguageManager.t('absences.pending'))); - } - - statusDiv.appendChild(statusBadge); - - card.appendChild(lessonDiv); - card.appendChild(subjectDiv); - card.appendChild(topicDiv); - card.appendChild(statusDiv); - - return card; -} - -function createAbsencesContent(groupedAbsences) { - const content = document.createElement('div'); - content.className = 'absences-content'; - - const sortedDates = Object.keys(groupedAbsences).sort((a, b) => { - const dateA = new Date(a.replace(/\./g, '-').slice(0, -1)); - const dateB = new Date(b.replace(/\./g, '-').slice(0, -1)); - return dateB - dateA; - }); - - if (sortedDates.length === 0) { - const emptyState = document.createElement('div'); - emptyState.className = 'empty-state'; - - const emptyIcon = document.createElement('img'); - emptyIcon.src = chrome.runtime.getURL('icons/BadgeCheck.svg'); - emptyIcon.alt = 'Nincs hiányzás'; - - const emptyTitle = document.createElement('h3'); - emptyTitle.textContent = LanguageManager.t('absences.title'); - - const emptyText = document.createElement('p'); - emptyText.textContent = LanguageManager.t('dashboard.not_supported'); - - emptyState.appendChild(emptyIcon); - emptyState.appendChild(emptyTitle); - emptyState.appendChild(emptyText); - content.appendChild(emptyState); - } else { - sortedDates.forEach(date => { - const dayGroup = createDayGroup(date, groupedAbsences[date]); - content.appendChild(dayGroup); + while (currentDate <= now) { + months.push({ + year: currentDate.getFullYear(), + month: currentDate.getMonth() }); + currentDate.setMonth(currentDate.getMonth() + 1); } - - return content; + + months.forEach(({ year, month }) => { + const monthCalendar = createMonthCalendar(year, month, groupedByDate, absences); + calendarSection.appendChild(monthCalendar); + }); + + return calendarSection; +} + +function createMonthCalendar(year, month, groupedByDate, absences) { + const monthContainer = document.createElement('div'); + monthContainer.className = 'month-container'; + + const monthHeader = document.createElement('div'); + monthHeader.className = 'month-header'; + + const monthNames = [ + LanguageManager.t('common.january') || 'Január', + LanguageManager.t('common.february') || 'Február', + LanguageManager.t('common.march') || 'Március', + LanguageManager.t('common.april') || 'Április', + LanguageManager.t('common.may') || 'Május', + LanguageManager.t('common.june') || 'Június', + LanguageManager.t('common.july') || 'Július', + LanguageManager.t('common.august') || 'Augusztus', + LanguageManager.t('common.september') || 'Szeptember', + LanguageManager.t('common.october') || 'Október', + LanguageManager.t('common.november') || 'November', + LanguageManager.t('common.december') || 'December' + ]; + + monthHeader.textContent = `${monthNames[month]} ${year}`; + monthContainer.appendChild(monthHeader); + + const calendarGrid = document.createElement('div'); + calendarGrid.className = 'calendar-grid'; + + const dayNames = [ + LanguageManager.t('common.mon') || 'H', + LanguageManager.t('common.tue') || 'K', + LanguageManager.t('common.wed') || 'Sze', + LanguageManager.t('common.thu') || 'Cs', + LanguageManager.t('common.fri') || 'P', + LanguageManager.t('common.sat') || 'Szo', + LanguageManager.t('common.sun') || 'V' + ]; + + dayNames.forEach(day => { + const dayHeader = document.createElement('div'); + dayHeader.className = 'calendar-day-header'; + dayHeader.textContent = day; + calendarGrid.appendChild(dayHeader); + }); + + const firstDay = new Date(year, month, 1); + const lastDay = new Date(year, month + 1, 0); + const daysInMonth = lastDay.getDate(); + + let startDay = firstDay.getDay() - 1; + if (startDay < 0) startDay = 6; + + for (let i = 0; i < startDay; i++) { + const emptyCell = document.createElement('div'); + emptyCell.className = 'calendar-day empty'; + calendarGrid.appendChild(emptyCell); + } + + const today = new Date(); + today.setHours(0, 0, 0, 0); + + for (let day = 1; day <= daysInMonth; day++) { + const dateKey = `${year}-${(month + 1).toString().padStart(2, "0")}-${day.toString().padStart(2, "0")}`; + const dayAbsences = groupedByDate[dateKey] || []; + const currentDayDate = new Date(year, month, day); + currentDayDate.setHours(0, 0, 0, 0); + + const dayCell = document.createElement('div'); + dayCell.className = 'calendar-day'; + + if (currentDayDate > today) { + dayCell.classList.add('future'); + } + + if (currentDayDate.getTime() === today.getTime()) { + dayCell.classList.add('today'); + } + + if (dayAbsences.length > 0) { + dayCell.classList.add('has-absence'); + + const hasUnjustified = dayAbsences.some(a => a.justificationStatus === 'unjustified'); + const hasPending = dayAbsences.some(a => a.justificationStatus === 'pending'); + const hasJustified = dayAbsences.some(a => a.justificationStatus === 'justified'); + const hasAbsence = dayAbsences.some(a => a.absenceType === 'absence'); + const hasLate = dayAbsences.some(a => a.absenceType === 'late'); + + if (hasUnjustified) { + dayCell.classList.add('status-unjustified'); + } else if (hasPending) { + dayCell.classList.add('status-pending'); + } else if (hasJustified) { + dayCell.classList.add('status-justified'); + } + + if (hasAbsence && hasLate) { + dayCell.classList.add('type-mixed'); + } else if (hasLate) { + dayCell.classList.add('type-late'); + } + + dayCell.addEventListener('click', () => { + openAbsenceModal(dateKey, dayAbsences); + }); + + const countBadge = document.createElement('span'); + countBadge.className = 'absence-count'; + countBadge.textContent = dayAbsences.length; + dayCell.appendChild(countBadge); + } + + const dayNumber = document.createElement('span'); + dayNumber.className = 'day-number'; + dayNumber.textContent = day; + dayCell.appendChild(dayNumber); + + calendarGrid.appendChild(dayCell); + } + + monthContainer.appendChild(calendarGrid); + return monthContainer; +} + +function openAbsenceModal(dateKey, dayAbsences) { + const existingModal = document.querySelector('.absence-modal-overlay'); + if (existingModal) { + existingModal.remove(); + } + + const overlay = document.createElement('div'); + overlay.className = 'absence-modal-overlay'; + + const modal = document.createElement('div'); + modal.className = 'absence-modal'; + + const modalHeader = document.createElement('div'); + modalHeader.className = 'modal-header'; + + const dateParts = dateKey.split('-'); + const displayDate = new Date(parseInt(dateParts[0]), parseInt(dateParts[1]) - 1, parseInt(dateParts[2])); + const dayNames = [ + LanguageManager.t('common.sunday') || 'Vasárnap', + LanguageManager.t('common.monday') || 'Hétfő', + LanguageManager.t('common.tuesday') || 'Kedd', + LanguageManager.t('common.wednesday') || 'Szerda', + LanguageManager.t('common.thursday') || 'Csütörtök', + LanguageManager.t('common.friday') || 'Péntek', + LanguageManager.t('common.saturday') || 'Szombat' + ]; + + const modalTitle = document.createElement('h2'); + modalTitle.textContent = `${dateParts[0]}.${dateParts[1]}.${dateParts[2]}. - ${dayNames[displayDate.getDay()]}`; + + modalHeader.appendChild(modalTitle); + + const modalContent = document.createElement('div'); + modalContent.className = 'modal-content'; + + dayAbsences.forEach(absence => { + const absenceCard = document.createElement('div'); + absenceCard.className = `modal-absence-card ${absence.justificationStatus}`; + + const headerRow = document.createElement('div'); + headerRow.className = 'modal-card-header'; + + const lessonSpan = document.createElement('span'); + lessonSpan.className = 'modal-lesson'; + lessonSpan.textContent = `${absence.lesson}.`; + + const typeIndicator = document.createElement('span'); + typeIndicator.className = `type-indicator ${absence.absenceType}`; + typeIndicator.textContent = absence.absenceType === 'late' + ? (LanguageManager.t('absences.late_type') || 'Késés') + : (LanguageManager.t('absences.absence_type') || 'Hiányzás'); + + const statusBadge = document.createElement('span'); + statusBadge.className = `modal-status-badge ${absence.justificationStatus}`; + let statusText = ''; + if (absence.justificationStatus === 'justified') { + statusText = LanguageManager.t('absences.justified') || 'Igazolt'; + } else if (absence.justificationStatus === 'unjustified') { + statusText = LanguageManager.t('absences.unjustified') || 'Igazolatlan'; + } else { + statusText = LanguageManager.t('absences.pending') || 'Igazolásra vár'; + } + statusBadge.textContent = statusText; + + headerRow.appendChild(lessonSpan); + headerRow.appendChild(typeIndicator); + headerRow.appendChild(statusBadge); + + const subjectDiv = document.createElement('div'); + subjectDiv.className = 'modal-subject'; + subjectDiv.textContent = absence.subject; + + const infoRow = document.createElement('div'); + infoRow.className = 'modal-info-row'; + + if (absence.topic) { + const topicSpan = document.createElement('span'); + topicSpan.className = 'modal-info-item'; + topicSpan.textContent = absence.topic; + infoRow.appendChild(topicSpan); + } + + if (absence.justificationType) { + const justificationSpan = document.createElement('span'); + justificationSpan.className = 'modal-info-item'; + justificationSpan.textContent = absence.justificationType; + infoRow.appendChild(justificationSpan); + } + + if (absence.absenceType === 'late' && absence.minutes > 0) { + const minutesSpan = document.createElement('span'); + minutesSpan.className = 'modal-info-item modal-minutes'; + minutesSpan.textContent = `${absence.minutes} ${LanguageManager.t('absences.minutes') || 'perc'}`; + infoRow.appendChild(minutesSpan); + } + + absenceCard.appendChild(headerRow); + absenceCard.appendChild(subjectDiv); + if (infoRow.children.length > 0) { + absenceCard.appendChild(infoRow); + } + + modalContent.appendChild(absenceCard); + }); + + modal.appendChild(modalHeader); + modal.appendChild(modalContent); + overlay.appendChild(modal); + + overlay.addEventListener('click', (e) => { + if (e.target === overlay) { + overlay.remove(); + } + }); + + const handleEscape = (e) => { + if (e.key === 'Escape') { + overlay.remove(); + document.removeEventListener('keydown', handleEscape); + } + }; + document.addEventListener('keydown', handleEscape); + + document.body.appendChild(overlay); + + requestAnimationFrame(() => { + overlay.classList.add('visible'); + }); +} + +function createLegend() { + const legend = document.createElement('div'); + legend.className = 'calendar-legend'; + + const legendItems = [ + { class: 'status-justified', label: LanguageManager.t('absences.justified') || 'Igazolt' }, + { class: 'status-pending', label: LanguageManager.t('absences.pending') || 'Igazolásra vár' }, + { class: 'status-unjustified', label: LanguageManager.t('absences.unjustified') || 'Igazolatlan' }, + { class: 'type-late-legend', label: LanguageManager.t('absences.late_type') || 'Késés', isType: true }, + ]; + + legendItems.forEach(item => { + const legendItem = document.createElement('div'); + legendItem.className = 'legend-item'; + + const legendColor = document.createElement('div'); + legendColor.className = `legend-color ${item.class}`; + + const legendLabel = document.createElement('span'); + legendLabel.textContent = item.label; + + legendItem.appendChild(legendColor); + legendItem.appendChild(legendLabel); + legend.appendChild(legendItem); + }); + + return legend; } async function transformAbsencesPage() { - const { basicData, absences, groupedAbsences } = await collectAbsencesData(); - + const { basicData, absences, groupedByDate } = await collectAbsencesData(); + document.body.textContent = ''; - + const container = document.createElement('div'); container.className = 'kreta-container'; @@ -409,166 +464,30 @@ async function transformAbsencesPage() { headerDiv.appendChild(tempDiv.firstChild); } container.appendChild(headerDiv); - + const main = document.createElement('main'); main.className = 'kreta-main'; - - const pageGrid = document.createElement('div'); - pageGrid.className = 'absences-page'; - - const sidebar = document.createElement('div'); - sidebar.className = 'absences-sidebar'; - const filterCard = createFilterCard(absences); - sidebar.appendChild(filterCard); - + + const pageContent = document.createElement('div'); + pageContent.className = 'absences-page'; + const statsSection = createStatsSection(absences); - sidebar.appendChild(statsSection); - - const absencesContent = createAbsencesContent(groupedAbsences); - - pageGrid.appendChild(sidebar); - pageGrid.appendChild(absencesContent); - - main.appendChild(pageGrid); + pageContent.appendChild(statsSection); + + const legend = createLegend(); + pageContent.appendChild(legend); + + const calendarSection = createCalendarSection(groupedByDate, absences); + pageContent.appendChild(calendarSection); + + main.appendChild(pageContent); container.appendChild(main); document.body.appendChild(container); setupUserDropdown(); - setupFilters(groupedAbsences); - loadingScreen.hide(); } -function setupFilters(originalGroupedAbsences) { - try { - const dateFilter = document.getElementById("dateFilter"); - const subjectFilter = document.getElementById("subjectFilter"); - const justificationFilter = document.getElementById("justificationFilter"); - - if (!dateFilter || !subjectFilter || !justificationFilter) { - console.warn("Some filter elements were not found in the DOM"); - return; - } - - const filterAbsences = () => { - try { - const dateFilterValue = dateFilter.value; - const subject = subjectFilter.value; - const justified = justificationFilter.value; - const selectedDate = dateFilterValue ? new Date(dateFilterValue) : null; - - document.querySelectorAll(".absence-card").forEach((card) => { - const dateStr = card.dataset.date; - const dateParts = dateStr.split("."); - - if (dateParts.length < 3) { - return; - } - - const parsedYear = parseInt(dateParts[0].trim(), 10); - const parsedMonth = parseInt(dateParts[1].trim(), 10) - 1; - const parsedDay = parseInt(dateParts[2].trim(), 10); - - const cardDate = new Date(parsedYear, parsedMonth, parsedDay); - - let showCard = true; - - if (selectedDate) { - if ( - cardDate.getFullYear() !== selectedDate.getFullYear() || - cardDate.getMonth() !== selectedDate.getMonth() || - cardDate.getDate() !== selectedDate.getDate() - ) { - showCard = false; - } - } - - if (subject && card.dataset.subject !== subject) { - showCard = false; - } - - if (justified && card.dataset.status !== justified) { - showCard = false; - } - - card.style.display = showCard ? "" : "none"; - }); - - updateDayGroupsVisibility(); - - updateStatistics(); - } catch (err) { - console.error("Error during filtering absences:", err); - } - }; - - [dateFilter, subjectFilter, justificationFilter].forEach((filter) => { - if (filter) { - filter.addEventListener("change", filterAbsences); - } - }); - - } catch (err) { - console.error("Error setting up filters:", err); - } -} - -function updateDayGroupsVisibility() { - document.querySelectorAll(".day-group").forEach((group) => { - const visibleCards = group.querySelectorAll('.absence-card:not([style*="display: none"])'); - const dayCount = group.querySelector('.day-count'); - - if (visibleCards.length > 0) { - group.style.display = ""; - if (dayCount) { - dayCount.textContent = `${visibleCards.length} ${LanguageManager.t('absences.hours')}`; - } - } else { - group.style.display = "none"; - } - }); -} - -function updateStatistics() { - try { - const visibleCards = document.querySelectorAll('.absence-card:not([style*="display: none"])'); - const totalVisible = visibleCards.length; - const justifiedVisible = Array.from(visibleCards).filter( - card => card.dataset.status === 'justified' - ).length; - const unjustifiedVisible = Array.from(visibleCards).filter( - card => card.dataset.status === 'unjustified' - ).length; - const pendingVisible = Array.from(visibleCards).filter( - card => card.dataset.status === 'pending' - ).length; - - const statCards = document.querySelectorAll(".stat-card"); - statCards.forEach(card => { - const type = card.dataset.type; - const numberEl = card.querySelector('.stat-number'); - if (numberEl) { - switch(type) { - case 'total': - numberEl.textContent = totalVisible; - break; - case 'justified': - numberEl.textContent = justifiedVisible; - break; - case 'unjustified': - numberEl.textContent = unjustifiedVisible; - break; - case 'pending': - numberEl.textContent = pendingVisible; - break; - } - } - }); - } catch (err) { - console.error("Error updating statistics:", err); - } -} - if (window.location.href.includes("/Hianyzas/Hianyzasok")) { transformAbsencesPage().catch((error) => { console.error(LanguageManager.t("absences.page_transform_error"), error); diff --git a/i18n/de.json b/i18n/de.json index bec488a..bd48576 100644 --- a/i18n/de.json +++ b/i18n/de.json @@ -266,7 +266,10 @@ "last_30_days": "Letzte 30 Tage", "total_absences": "Alle Fehlzeiten", "topic": "Thema", - "status": "Status" + "status": "Status", + "absence_type": "Abwesenheit", + "late_type": "Verspätung", + "minutes": "Minuten" }, "profile": { "title": "Profil", @@ -418,8 +421,27 @@ "friday": "Freitag", "saturday": "Samstag", "sunday": "Sonntag", + "mon": "M", + "tue": "D", + "wed": "M", + "thu": "D", + "fri": "F", + "sat": "S", + "sun": "S", "today": "Heute", - "tomorrow": "Morgen" + "tomorrow": "Morgen", + "january": "Januar", + "february": "Februar", + "march": "März", + "april": "April", + "may": "Mai", + "june": "Juni", + "july": "Juli", + "august": "August", + "september": "September", + "october": "Oktober", + "november": "November", + "december": "Dezember" }, "months": { "january": "Januar", diff --git a/i18n/en.json b/i18n/en.json index b5080a0..49a1602 100644 --- a/i18n/en.json +++ b/i18n/en.json @@ -266,7 +266,10 @@ "last_30_days": "Last 30 days", "total_absences": "Total absences", "topic": "Topic", - "status": "Status" + "status": "Status", + "absence_type": "Absence", + "late_type": "Late", + "minutes": "minutes" }, "profile": { "title": "Profile", @@ -418,8 +421,27 @@ "friday": "Friday", "saturday": "Saturday", "sunday": "Sunday", + "mon": "M", + "tue": "T", + "wed": "W", + "thu": "T", + "fri": "F", + "sat": "S", + "sun": "S", "today": "Today", - "tomorrow": "Tomorrow" + "tomorrow": "Tomorrow", + "january": "January", + "february": "February", + "march": "March", + "april": "April", + "may": "May", + "june": "June", + "july": "July", + "august": "August", + "september": "September", + "october": "October", + "november": "November", + "december": "December" }, "months": { "january": "January", diff --git a/i18n/hu.json b/i18n/hu.json index 984e861..dead2dc 100644 --- a/i18n/hu.json +++ b/i18n/hu.json @@ -266,9 +266,12 @@ "last_month": "Előző hónap", "current_semester": "Aktuális félév", "last_30_days": "Utolsó 30 nap", - "total_absences": "Összes hiányzás", + "total_absences": "Összes mulasztás", "topic": "Téma", - "status": "Állapot" + "status": "Állapot", + "absence_type": "Hiányzás", + "late_type": "Késés", + "minutes": "perc" }, "profile": { "title": "Profil", @@ -420,8 +423,27 @@ "friday": "péntek", "saturday": "szombat", "sunday": "vasárnap", + "mon": "H", + "tue": "K", + "wed": "Sze", + "thu": "Cs", + "fri": "P", + "sat": "Szo", + "sun": "V", "today": "Ma", - "tomorrow": "Holnap" + "tomorrow": "Holnap", + "january": "Január", + "february": "Február", + "march": "Március", + "april": "Április", + "may": "Május", + "june": "Június", + "july": "Július", + "august": "Augusztus", + "september": "Szeptember", + "october": "Október", + "november": "November", + "december": "December" }, "months": { "january": "január",