This commit is contained in:
Zan
2025-08-31 20:53:36 +02:00
parent d722740bdf
commit a39295ae68
42 changed files with 8719 additions and 7412 deletions

View File

@@ -1,551 +1,484 @@
* {
box-sizing: border-box;
margin: 0;
padding: 0;
box-sizing:border-box;
margin:0;
padding:0;
}
body {
margin: 0;
padding: 0;
color: var(--text-primary);
background-color: var(--background) !important;
font-family: "Montserrat", serif !important;
min-height: 100vh;
font-size: 16px;
margin:0;
padding:0;
color:var(--text-primary);
background-color:var(--background) !important;
font-family:"Montserrat",serif !important;
min-height:100vh;
font-size:16px;
}
@media (max-width: 768px) {
@media (max-width:768px) {
body {
font-size: 14px;
}
font-size:14px;
}
.kreta-container {
min-height: 100vh;
display: flex;
flex-direction: column;
}.kreta-container {
min-height:100vh;
display:flex;
flex-direction:column;
}
.kreta-header {
padding: clamp(1rem, 3vw, 2rem);
display: grid;
grid-template-columns: minmax(300px, 400px) 1fr minmax(200px, 300px);
align-items: center;
gap: 1rem;
padding:clamp(1rem,3vw,2rem);
display:grid;
grid-template-columns:minmax(300px,400px) 1fr minmax(200px,300px);
align-items:center;
gap:1rem;
}
@media (max-width: 1200px) {
@media (max-width:1200px) {
.kreta-header {
grid-template-columns: minmax(250px, 350px) 1fr minmax(180px, 250px);
}
grid-template-columns:minmax(250px,350px) 1fr minmax(180px,250px);
}
@media (max-width: 768px) {
}@media (max-width:768px) {
.kreta-header {
grid-template-columns: 1fr auto auto;
grid-template-areas:
"school toggle user"
grid-template-columns:1fr auto auto;
grid-template-areas:"school toggle user"
"nav nav nav";
padding: 1rem;
gap: 0.5rem;
}
padding:1rem;
gap:0.5rem;
}
.school-info {
margin: 0;
}.school-info {
margin:0;
}
@media (max-width: 768px) {
@media (max-width:768px) {
.school-info {
grid-area: school;
max-width: none;
display: flex;
align-items: center;
gap: 0.5rem;
}
grid-area:school;
max-width:none;
display:flex;
align-items:center;
gap:0.5rem;
}
.logo-text {
color: var(--text-primary);
font-size: 24px;
font-weight: 600;
margin: 0 0 0.5rem;
display: flex;
align-items: center;
}.logo-text {
color:var(--text-primary);
font-size:24px;
font-weight:600;
margin:0 0 0.5rem;
display:flex;
align-items:center;
}
@media (max-width: 768px) {
@media (max-width:768px) {
.logo-text {
margin: 0;
font-size: 20px;
}
margin:0;
font-size:20px;
}
.logo {
width: 24px;
border-radius: 8px;
margin-right: 0.5rem;
}.logo {
width:24px;
border-radius:8px;
margin-right:0.5rem;
}
.school-details {
color: var(--text-secondary);
font-size: 14px;
color:var(--text-secondary);
font-size:14px;
}
.school-details span {
display: block;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
max-width: 300px;
display:block;
white-space:nowrap;
overflow:hidden;
text-overflow:ellipsis;
max-width:300px;
}
@media (max-width: 768px) {
@media (max-width:768px) {
.school-details span {
max-width: 200px;
}
.school-details {
font-size: 12px;
}
max-width:200px;
}
.user-profile {
position: relative;
justify-self: flex-end;
.school-details {
font-size:12px;
}
@media (max-width: 768px) {
}.user-profile {
position:relative;
justify-self:flex-end;
}
@media (max-width:768px) {
.user-profile {
grid-area: user;
}
grid-area:user;
}
.user-dropdown-btn {
display: flex;
align-items: center;
gap: 1rem;
background: none;
border: none;
cursor: pointer;
padding: 0.5rem;
border-radius: 8px;
transition: background-color 0.2s;
}.user-dropdown-btn {
display:flex;
align-items:center;
gap:1rem;
background:none;
border:none;
cursor:pointer;
padding:0.5rem;
border-radius:8px;
transition:background-color 0.2s;
}
.user-dropdown-btn:hover {
background: var(--card-card);
background:var(--card-card);
}
.user-info {
text-align: right;
text-align:right;
}
.user-dropdown {
position: absolute;
top: 100%;
right: 0;
margin-top: 0.5rem;
background: var(--card-card);
border-radius: 12px;
box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1);
width: 200px;
display: none;
z-index: 1000;
position:absolute;
top:100%;
right:0;
margin-top:0.5rem;
background:var(--card-card);
border-radius:12px;
box-shadow:0 4px 6px -1px rgba(0,0,0,0.1);
width:200px;
display:none;
z-index:1000;
}
.user-dropdown.show {
display: block;
animation: dropdownShow 0.2s ease;
display:block;
animation:dropdownShow 0.2s ease;
}
.dropdown-item {
display: flex;
align-items: center;
gap: 0.75rem;
padding: 0.75rem 1rem;
color: var(--text-primary);
text-decoration: none;
transition: background-color 0.2s;
display:flex;
align-items:center;
gap:0.75rem;
padding:0.75rem 1rem;
color:var(--text-primary);
text-decoration:none;
transition:background-color 0.2s;
}
.dropdown-item:hover {
background: var(--button-secondaryFill);
background:var(--button-secondaryFill);
}
.kreta-main {
flex: 1;
padding: clamp(1rem, 3vw, 2rem);
max-width: 1200px;
margin: 0 auto;
width: 100%;
flex:1;
padding:clamp(1rem,3vw,2rem);
max-width:1200px;
margin:0 auto;
width:100%;
}
.filter-card {
background: var(--card-card);
border-radius: 24px;
padding: 20px;
margin-bottom: 24px;
box-shadow: 0px 1px var(--shadow-blur) 0px var(--accent-shadow);
background:var(--card-card);
border-radius:24px;
padding:20px;
margin-bottom:24px;
box-shadow:0px 1px var(--shadow-blur) 0px var(--accent-shadow);
}
.filter-header {
margin-bottom: 16px;
margin-bottom:16px;
}
.filter-header h2 {
font-size: 18px;
font-weight: 600;
color: var(--text-primary);
background-color: var(--card-card);
font-size:18px;
font-weight:600;
color:var(--text-primary);
background-color:var(--card-card);
}
.filter-content {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
gap: 16px;
display:grid;
grid-template-columns:repeat(auto-fit,minmax(200px,1fr));
gap:16px;
}
.filter-group {
display: flex;
flex-direction: column;
gap: 8px;
display:flex;
flex-direction:column;
gap:8px;
}
.filter-group label {
display: flex;
align-items: center;
gap: 8px;
color: var(--text-secondary);
font-size: 14px;
display:flex;
align-items:center;
gap:8px;
color:var(--text-secondary);
font-size:14px;
}
.filter-input {
padding: 10px;
border: none;
border-radius: 8px;
background: var(--button-secondaryFill);
color: var(--text-primary);
font-family: inherit;
font-size: 14px;
transition: all 0.2s ease;
padding:10px;
border:none;
border-radius:8px;
background:var(--button-secondaryFill);
color:var(--text-primary);
font-family:inherit;
font-size:14px;
transition:all 0.2s ease;
}
.filter-input:focus {
outline: none;
box-shadow: 0 0 0 2px var(--accent-accent);
outline:none;
box-shadow:0 0 0 2px var(--accent-accent);
}
.stats-overview {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
gap: 16px;
margin-bottom: 24px;
display:grid;
grid-template-columns:repeat(auto-fit,minmax(200px,1fr));
gap:16px;
margin-bottom:24px;
}
.stat-card {
background: var(--card-card);
border-radius: 16px;
padding: 20px;
text-align: center;
box-shadow: 0px 1px var(--shadow-blur) 0px var(--accent-shadow);
transition: transform 0.2s ease;
background:var(--card-card);
border-radius:16px;
padding:20px;
text-align:center;
box-shadow:0px 1px var(--shadow-blur) 0px var(--accent-shadow);
transition:transform 0.2s ease;
}
.stat-card:hover {
transform: translateY(-2px);
transform:translateY(-2px);
}
.stat-number {
font-size: 32px;
font-weight: 700;
color: var(--accent-accent);
margin-bottom: 8px;
font-size:32px;
font-weight:700;
color:var(--accent-accent);
margin-bottom:8px;
}
.stat-label {
color: var(--text-secondary);
font-size: 14px;
font-weight: 500;
color:var(--text-secondary);
font-size:14px;
font-weight:500;
}
.absences-container {
background: var(--card-card);
border-radius: 16px;
overflow: hidden;
box-shadow: 0px 1px var(--shadow-blur) 0px var(--accent-shadow);
background:var(--card-card);
border-radius:16px;
overflow:hidden;
box-shadow:0px 1px var(--shadow-blur) 0px var(--accent-shadow);
}
.absences-table {
width: 100%;
border-collapse: collapse;
width:100%;
border-collapse:collapse;
}
.table-header {
background: var(--accent-15);
border-bottom: 1px solid var(--accent-30);
background:var(--accent-15);
border-bottom:1px solid var(--accent-30);
}
.table-header th {
padding: 16px;
text-align: left;
font-weight: 600;
color: var(--text-primary);
font-size: 14px;
text-transform: uppercase;
letter-spacing: 0.5px;
padding:16px;
text-align:left;
font-weight:600;
color:var(--text-primary);
font-size:14px;
text-transform:uppercase;
letter-spacing:0.5px;
}
.table-row {
border-bottom: 1px solid var(--accent-15);
transition: background-color 0.2s ease;
border-bottom:1px solid var(--accent-15);
transition:background-color 0.2s ease;
}
.table-row:hover {
background: var(--accent-10);
background:var(--accent-10);
}
.table-row:last-child {
border-bottom: none;
border-bottom:none;
}
.table-cell {
padding: 16px;
color: var(--text-primary);
vertical-align: middle;
padding:16px;
color:var(--text-primary);
vertical-align:middle;
}
.date-cell {
font-weight: 600;
color: var(--accent-accent);
font-weight:600;
color:var(--accent-accent);
}
.lesson-cell {
text-align: center;
font-weight: 500;
text-align:center;
font-weight:500;
}
.subject-cell {
font-weight: 600;
font-weight:600;
}
.topic-cell {
color: var(--text-secondary);
font-size: 14px;
max-width: 200px;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
color:var(--text-secondary);
font-size:14px;
max-width:200px;
overflow:hidden;
text-overflow:ellipsis;
white-space:nowrap;
}
.status-cell {
text-align: center;
text-align:center;
}
.status-badge {
display: inline-flex;
align-items: center;
gap: 4px;
padding: 6px 12px;
border-radius: 20px;
font-size: 12px;
font-weight: 600;
text-transform: uppercase;
letter-spacing: 0.5px;
display:inline-flex;
align-items:center;
gap:4px;
padding:6px 12px;
border-radius:20px;
font-size:12px;
font-weight:600;
text-transform:uppercase;
letter-spacing:0.5px;
}
.status-badge.justified {
background: var(--grades-4-bg);
color: var(--grades-4);
background:var(--grades-4-bg);
color:var(--grades-4);
}
.status-badge.unjustified {
background: var(--grades-1-bg);
color: var(--grades-1);
background:var(--grades-1-bg);
color:var(--grades-1);
}
.status-badge.pending {
background: var(--grades-3-bg);
color: var(--grades-3);
background:var(--grades-3-bg);
color:var(--grades-3);
}
@media (max-width: 768px) {
@media (max-width:768px) {
.absences-table {
font-size: 14px;
}
.table-header th,
.table-cell {
padding: 12px 8px;
}
.topic-cell {
max-width: 120px;
}
.stats-overview {
grid-template-columns: repeat(2, 1fr);
}
font-size:14px;
}
@media (max-width: 480px) {
.absences-table,
.table-header,
.table-row {
display: block;
}
.table-header {
display: none;
}
.table-row {
margin-bottom: 16px;
border: 1px solid var(--accent-15);
border-radius: 12px;
padding: 16px;
background: var(--card-card);
}
.table-cell {
display: flex;
justify-content: space-between;
align-items: center;
padding: 8px 0;
border-bottom: 1px solid var(--accent-15);
}
.table-cell:last-child {
border-bottom: none;
}
.table-cell::before {
content: attr(data-label);
font-weight: 600;
color: var(--text-secondary);
font-size: 12px;
text-transform: uppercase;
}
.stats-overview {
grid-template-columns: 1fr;
}
.table-header th,.table-cell {
padding:12px 8px;
}
.absence-details {
display: flex;
flex-direction: column;
gap: 4px;
.topic-cell {
max-width:120px;
}
.stats-overview {
grid-template-columns:repeat(2,1fr);
}
}@media (max-width:480px) {
.absences-table,.table-header,.table-row {
display:block;
}
.table-header {
display:none;
}
.date-group {
margin-bottom:24px;
}
.date-group-header {
background:var(--accent-accent);
color:white;
padding:12px 16px;
border-radius:12px 12px 0 0;
font-weight:600;
font-size:16px;
margin-bottom:0;
}
.date-group-content {
background:var(--card-card);
border:1px solid var(--accent-15);
border-radius:0 0 12px 12px;
overflow:hidden;
}
.table-row {
width:100%;
margin-bottom:0;
border:none;
border-bottom:1px solid var(--accent-15);
border-radius:0;
padding:16px;
background:transparent;
}
.table-row:last-child {
border-bottom:none;
}
.table-cell {
display:flex;
justify-content:space-between;
align-items:flex-start;
padding:6px 0;
border-bottom:1px solid var(--accent-15);
}
.table-cell:last-child {
border-bottom:none;
}
.table-cell::before {
content:attr(data-label);
font-weight:600;
color:var(--text-secondary);
font-size:12px;
text-transform:uppercase;
flex-shrink:0;
}
.topic-cell {
max-width:none;
white-space:normal;
text-overflow:initial;
overflow:visible;
text-align:right;
flex:1;
}
.stats-overview {
grid-template-columns:1fr;
}
}.absence-details {
display:flex;
flex-direction:column;
gap:4px;
}
.absence-subject {
font-weight: 600;
color: var(--text-primary);
font-weight:600;
color:var(--text-primary);
}
.absence-topic {
color: var(--text-secondary);
font-size: 14px;
color:var(--text-secondary);
font-size:14px;
}
.absence-status {
display: flex;
align-items: center;
gap: 4px;
font-size: 14px;
font-weight: 500;
display:flex;
align-items:center;
gap:4px;
font-size:14px;
font-weight:500;
}
.absence-status.justified {
color: var(--grades-4);
color:var(--grades-4);
}
.absence-status.unjustified {
color: var(--grades-1);
color:var(--grades-1);
}
.absence-status.pending {
color: var(--grades-3);
color:var(--grades-3);
}
.loading-overlay {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
background: var(--background);
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
z-index: 9999;
position:fixed;
top:0;
left:0;
width:100%;
height:100%;
background:var(--background);
display:flex;
flex-direction:column;
align-items:center;
justify-content:center;
z-index:9999;
}
.loading-container {
display: flex;
flex-direction: column;
align-items: center;
gap: 1rem;
padding: 2rem;
border-radius: 24px;
display:flex;
flex-direction:column;
align-items:center;
gap:1rem;
padding:2rem;
border-radius:24px;
}
.loading-text {
color: var(--Text-Primary);
text-align: center;
font-family: Montserrat;
font-size: 20px;
font-style: normal;
font-weight: 700;
line-height: normal;
color:var(--Text-Primary);
text-align:center;
font-family:Montserrat;
font-size:20px;
font-style:normal;
font-weight:700;
line-height:normal;
}
.loading-text2 {
align-self: stretch;
color: var(--Text-Secondary);
text-align: center;
font-family: Figtree;
font-size: 16px;
font-style: normal;
font-weight: 500;
line-height: 130%;
align-self:stretch;
color:var(--Text-Secondary);
text-align:center;
font-family:Figtree;
font-size:16px;
font-style:normal;
font-weight:500;
line-height:130%;
}
.loading-logo {
width: 48px;
height: 48px;
margin-bottom: 1rem;
border-radius: 8px;
width:48px;
height:48px;
margin-bottom:1rem;
border-radius:8px;
}
@keyframes fadeIn {
from {
opacity: 0;
transform: translateY(-10px);
}
to {
opacity: 1;
transform: translateY(0);
}
opacity:0;
transform:translateY(-10px);
}
@keyframes dropdownShow {
to {
opacity:1;
transform:translateY(0);
}
}@keyframes dropdownShow {
from {
opacity: 0;
transform: translateY(-10px);
}
to {
opacity: 1;
transform: translateY(0);
}
opacity:0;
transform:translateY(-10px);
}
to {
opacity:1;
transform:translateY(0);
}
}@keyframes spin {
to {
transform:rotate(360deg);
}
@keyframes spin {
to { transform: rotate(360deg); }
}

View File

@@ -1,25 +1,30 @@
async function collectAbsencesData() {
const basicData = {
schoolInfo: {
name: cookieManager.get('schoolName') || 'Iskola',
id: cookieManager.get('schoolCode') || ''
name: cookieManager.get("schoolName") || "Iskola",
id: cookieManager.get("schoolCode") || "",
},
userData: {
name: cookieManager.get('userName') || 'Felhasználó',
time: document.querySelector('.usermenu_timer')?.textContent?.trim() || '45:00'
}
name: cookieManager.get("userName") || "Felhasználó",
time:
document.querySelector(".usermenu_timer")?.textContent?.trim() ||
"45:00",
},
};
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()}`, {
method: 'GET',
credentials: 'include',
headers: {
'Accept': 'application/json, text/javascript, */*; q=0.01',
'X-Requested-With': 'XMLHttpRequest'
}
});
const response = await fetch(
`https://${currentDomain}/api/HianyzasokApi/GetHianyzasGrid?sort=MulasztasDatum-desc&page=1&pageSize=100&group=&filter=&data=%7B%7D&_=${Date.now()}`,
{
method: "GET",
credentials: "include",
headers: {
Accept: "application/json, text/javascript, */*; q=0.01",
"X-Requested-With": "XMLHttpRequest",
},
},
);
if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`);
@@ -29,33 +34,33 @@ async function collectAbsencesData() {
const absences = [];
if (apiData.Data && Array.isArray(apiData.Data)) {
apiData.Data.forEach(item => {
apiData.Data.forEach((item) => {
const date = new Date(item.MulasztasDatum);
const formattedDate = `${date.getFullYear()}.${(date.getMonth() + 1).toString().padStart(2, '0')}.${date.getDate().toString().padStart(2, '0')}.`;
const formattedDate = `${date.getFullYear()}.${(date.getMonth() + 1).toString().padStart(2, "0")}.${date.getDate().toString().padStart(2, "0")}.`;
let justificationStatus = 'pending';
let justificationStatus = "pending";
if (item.Igazolt_BOOL === true) {
justificationStatus = 'justified';
justificationStatus = "justified";
} else if (item.Igazolt_BOOL === false && item.IgazolasTipus !== null) {
justificationStatus = 'unjustified';
justificationStatus = "unjustified";
}
absences.push({
date: formattedDate,
lesson: item.Oraszam?.toString() || '',
subject: item.Targy || '',
topic: item.Tema || '',
type: item.MulasztasTipus_DNAME || '',
lesson: item.Oraszam?.toString() || "",
subject: item.Targy || "",
topic: item.Tema || "",
type: item.MulasztasTipus_DNAME || "",
justified: item.Igazolt_BOOL === true,
justificationStatus: justificationStatus,
purposeful: item.TanoraiCeluMulasztas_BNAME || '',
justificationType: item.IgazolasTipus_DNAME || ''
purposeful: item.TanoraiCeluMulasztas_BNAME || "",
justificationType: item.IgazolasTipus_DNAME || "",
});
});
}
const groupedAbsences = {};
absences.forEach(absence => {
absences.forEach((absence) => {
if (!groupedAbsences[absence.date]) {
groupedAbsences[absence.date] = [];
}
@@ -64,7 +69,7 @@ async function collectAbsencesData() {
return { basicData, absences, groupedAbsences };
} catch (error) {
console.error('Hiba az API hívás során:', error);
console.error("Hiba az API hívás során:", error);
return { basicData, absences: [], groupedAbsences: {} };
}
}
@@ -79,38 +84,42 @@ async function transformAbsencesPage() {
<main class="kreta-main">
<div class="filter-card">
<div class="filter-header">
<h2>${LanguageManager.t('absences.filter_title')}</h2>
<h2>${LanguageManager.t("absences.filter_title")}</h2>
</div>
<div class="filter-content">
<div class="filter-group">
<label>
<span class="material-icons-round">date_range</span>
${LanguageManager.t('absences.date')}
${LanguageManager.t("absences.date")}
</label>
<input type="date" id="dateFilter" class="filter-input">
</div>
<div class="filter-group">
<label>
<span class="material-icons-round">school</span>
${LanguageManager.t('absences.subject')}
${LanguageManager.t("absences.subject")}
</label>
<select id="subjectFilter" class="filter-input">
<option value="">${LanguageManager.t('absences.all_subjects')}</option>
${[...new Set(absences.map(a => a.subject))].sort().map(subject =>
`<option value="${subject}">${subject}</option>`
).join('')}
<option value="">${LanguageManager.t("absences.all_subjects")}</option>
${[...new Set(absences.map((a) => a.subject))]
.sort()
.map(
(subject) =>
`<option value="${subject}">${subject}</option>`,
)
.join("")}
</select>
</div>
<div class="filter-group">
<label>
<span class="material-icons-round">check_circle</span>
${LanguageManager.t('absences.justification')}
${LanguageManager.t("absences.justification")}
</label>
<select id="justificationFilter" class="filter-input">
<option value="">${LanguageManager.t('absences.all_types')}</option>
<option value="justified">${LanguageManager.t('absences.justified')}</option>
<option value="unjustified">${LanguageManager.t('absences.unjustified')}</option>
<option value="pending">${LanguageManager.t('absences.pending')}</option>
<option value="">${LanguageManager.t("absences.all_types")}</option>
<option value="justified">${LanguageManager.t("absences.justified")}</option>
<option value="unjustified">${LanguageManager.t("absences.unjustified")}</option>
<option value="pending">${LanguageManager.t("absences.pending")}</option>
</select>
</div>
</div>
@@ -119,19 +128,19 @@ async function transformAbsencesPage() {
<div class="stats-overview">
<div class="stat-card">
<div class="stat-number">${absences.length}</div>
<div class="stat-label">${LanguageManager.t('absences.total_absences')}</div>
<div class="stat-label">${LanguageManager.t("absences.total_absences")}</div>
</div>
<div class="stat-card">
<div class="stat-number">${absences.filter(a => a.justificationStatus === 'justified').length}</div>
<div class="stat-label">${LanguageManager.t('absences.justified')}</div>
<div class="stat-number">${absences.filter((a) => a.justificationStatus === "justified").length}</div>
<div class="stat-label">${LanguageManager.t("absences.justified")}</div>
</div>
<div class="stat-card">
<div class="stat-number">${absences.filter(a => a.justificationStatus === 'unjustified').length}</div>
<div class="stat-label">${LanguageManager.t('absences.unjustified')}</div>
<div class="stat-number">${absences.filter((a) => a.justificationStatus === "unjustified").length}</div>
<div class="stat-label">${LanguageManager.t("absences.unjustified")}</div>
</div>
<div class="stat-card">
<div class="stat-number">${absences.filter(a => a.justificationStatus === 'pending').length}</div>
<div class="stat-label">${LanguageManager.t('absences.pending')}</div>
<div class="stat-number">${absences.filter((a) => a.justificationStatus === "pending").length}</div>
<div class="stat-label">${LanguageManager.t("absences.pending")}</div>
</div>
</div>
@@ -139,42 +148,15 @@ async function transformAbsencesPage() {
<table class="absences-table">
<thead class="table-header">
<tr>
<th>${LanguageManager.t('absences.date')}</th>
<th>${LanguageManager.t('absences.lesson')}</th>
<th>${LanguageManager.t('absences.subject')}</th>
<th>${LanguageManager.t('absences.topic')}</th>
<th>${LanguageManager.t('absences.status')}</th>
<th>${LanguageManager.t("absences.date")}</th>
<th>${LanguageManager.t("absences.lesson")}</th>
<th>${LanguageManager.t("absences.subject")}</th>
<th>${LanguageManager.t("absences.topic")}</th>
<th>${LanguageManager.t("absences.status")}</th>
</tr>
</thead>
<tbody>
${absences.map(absence => `
<tr class="table-row"
data-subject="${absence.subject}"
data-justified="${absence.justified}"
data-date="${absence.date}">
<td class="table-cell date-cell" data-label="${LanguageManager.t('absences.date')}">
${absence.date}
</td>
<td class="table-cell lesson-cell" data-label="${LanguageManager.t('absences.lesson')}">
${absence.lesson}.
</td>
<td class="table-cell subject-cell" data-label="${LanguageManager.t('absences.subject')}">
${absence.subject}
</td>
<td class="table-cell topic-cell" data-label="${LanguageManager.t('absences.topic')}" title="${absence.topic}">
${absence.topic}
</td>
<td class="table-cell status-cell" data-label="${LanguageManager.t('absences.status')}">
<span class="status-badge ${absence.justificationStatus}">
${absence.justificationStatus === 'justified' ?
`<span class="material-icons-round">check_circle</span> ${LanguageManager.t('absences.justified')}` :
absence.justificationStatus === 'unjustified' ?
`<span class="material-icons-round">cancel</span> ${LanguageManager.t('absences.unjustified')}` :
`<span class="material-icons-round">pending</span> ${LanguageManager.t('absences.pending')}`}
</span>
</td>
</tr>
`).join('')}
${generateAbsencesHTML(absences)}
</tbody>
</table>
</div>
@@ -182,30 +164,180 @@ async function transformAbsencesPage() {
</div>
`;
createTemplate.importFonts();
setupUserDropdown();
setupMobileNavigation();
setupEventListeners();
setupFilters();
loadingScreen.hide();
}
function generateAbsencesHTML(absences) {
const groupedByDate = absences.reduce((groups, absence) => {
const date = absence.date;
if (!groups[date]) {
groups[date] = [];
}
groups[date].push(absence);
return groups;
}, {});
const sortedDates = Object.keys(groupedByDate).sort(
(a, b) => new Date(b) - new Date(a),
);
let html = "";
sortedDates.forEach((date) => {
const dateAbsences = groupedByDate[date];
html += `<tr class="date-group-divider" style="display: none;"></tr>`;
dateAbsences.forEach((absence) => {
html += `
<tr class="table-row"
data-subject="${absence.subject}"
data-justified="${absence.justified}"
data-date="${absence.date}"
data-date-group="${date}">
<td class="table-cell date-cell" data-label="${LanguageManager.t("absences.date")}">
${absence.date}
</td>
<td class="table-cell lesson-cell" data-label="${LanguageManager.t("absences.lesson")}">
${absence.lesson}.
</td>
<td class="table-cell subject-cell" data-label="${LanguageManager.t("absences.subject")}">
${absence.subject}
</td>
<td class="table-cell topic-cell" data-label="${LanguageManager.t("absences.topic")}" title="${absence.topic}">
${absence.topic}
</td>
<td class="table-cell status-cell" data-label="${LanguageManager.t("absences.status")}">
<span class="status-badge ${absence.justificationStatus}">
${
absence.justificationStatus === "justified"
? `<span class="material-icons-round">check_circle</span> ${LanguageManager.t("absences.justified")}`
: absence.justificationStatus === "unjustified"
? `<span class="material-icons-round">cancel</span> ${LanguageManager.t("absences.unjustified")}`
: `<span class="material-icons-round">pending</span> ${LanguageManager.t("absences.pending")}`
}
</span>
</td>
</tr>
`;
});
});
return html;
}
function setupEventListeners() {
function setupMobileGrouping() {
if (window.innerWidth <= 480) {
createMobileGroups();
} else {
removeMobileGroups();
}
}
window.addEventListener("resize", setupMobileGrouping);
setupMobileGrouping();
}
function createMobileGroups() {
const tbody = document.querySelector(".absences-table tbody");
if (!tbody) return;
removeMobileGroups();
const rows = Array.from(tbody.querySelectorAll(".table-row"));
const groupedRows = {};
rows.forEach((row) => {
const date = row.dataset.date;
if (!groupedRows[date]) {
groupedRows[date] = [];
}
groupedRows[date].push(row);
});
const sortedDates = Object.keys(groupedRows).sort(
(a, b) => new Date(b) - new Date(a),
);
tbody.innerHTML = "";
sortedDates.forEach((date) => {
const dateRows = groupedRows[date];
const dateGroup = document.createElement("div");
dateGroup.className = "date-group";
const dateHeader = document.createElement("div");
dateHeader.className = "date-group-header";
dateHeader.textContent = date;
const dateContent = document.createElement("div");
dateContent.className = "date-group-content";
dateRows.forEach((row) => {
dateContent.appendChild(row);
});
dateGroup.appendChild(dateHeader);
dateGroup.appendChild(dateContent);
tbody.appendChild(dateGroup);
});
}
function removeMobileGroups() {
const tbody = document.querySelector(".absences-table tbody");
if (!tbody) return;
const dateGroups = tbody.querySelectorAll(".date-group");
if (dateGroups.length === 0) return;
const allRows = [];
dateGroups.forEach((group) => {
const rows = group.querySelectorAll(".table-row");
rows.forEach((row) => allRows.push(row));
});
tbody.innerHTML = "";
allRows.forEach((row) => tbody.appendChild(row));
}
function updateDateGroupsVisibility() {
if (window.innerWidth > 480) return;
const dateGroups = document.querySelectorAll(".date-group");
dateGroups.forEach((group) => {
const visibleRows = group.querySelectorAll(
'.table-row[style=""], .table-row:not([style])',
);
if (visibleRows.length > 0) {
group.style.display = "";
} else {
group.style.display = "none";
}
});
}
function setupFilters() {
try {
const filters = {
dateFilter: document.getElementById('dateFilter'),
subject: document.getElementById('subjectFilter'),
justified: document.getElementById('justificationFilter')
dateFilter: document.getElementById("dateFilter"),
subject: document.getElementById("subjectFilter"),
justified: document.getElementById("justificationFilter"),
};
if (!filters.dateFilter || !filters.subject || !filters.justified) {
console.warn('Some filter elements were not found in the DOM');
console.warn("Some filter elements were not found in the DOM");
return;
}
@@ -216,32 +348,34 @@ function setupFilters() {
const justified = filters.justified.value;
const selectedDate = dateFilterValue ? new Date(dateFilterValue) : null;
document.querySelectorAll('.table-row').forEach(row => {
document.querySelectorAll(".table-row").forEach((row) => {
const dateStr = row.dataset.date;
const dateParts = dateStr.split('.');
const dateParts = dateStr.split(".");
if (dateParts.length < 3) {
console.error(`Invalid date format: ${dateStr}`);
return;
}
const parsedYear = parseInt(dateParts[0].trim(), 10);
const parsedMonth = parseInt(dateParts[1].trim(), 10) - 1;
const parsedDay = parseInt(dateParts[2].trim(), 10);
if (isNaN(parsedDay) || isNaN(parsedMonth) || isNaN(parsedYear)) {
console.error(`Invalid date components: ${dateStr}`);
return;
}
const rowDate = new Date(parsedYear, parsedMonth, parsedDay);
let showRow = true;
if (selectedDate) {
if (rowDate.getFullYear() !== selectedDate.getFullYear() ||
rowDate.getMonth() !== selectedDate.getMonth() ||
rowDate.getDate() !== selectedDate.getDate()) {
if (
rowDate.getFullYear() !== selectedDate.getFullYear() ||
rowDate.getMonth() !== selectedDate.getMonth() ||
rowDate.getDate() !== selectedDate.getDate()
) {
showRow = false;
}
}
@@ -251,72 +385,83 @@ function setupFilters() {
}
if (justified) {
const statusElement = row.querySelector('.status-badge');
const statusElement = row.querySelector(".status-badge");
const hasStatus = statusElement.classList.contains(justified);
if (!hasStatus) showRow = false;
}
row.style.display = showRow ? '' : 'none';
row.style.display = showRow ? "" : "none";
});
updateDateGroupsVisibility();
updateStatistics();
} catch (err) {
console.error('Error during filtering absences:', err);
console.error("Error during filtering absences:", err);
}
};
Object.values(filters).forEach(filter => {
Object.values(filters).forEach((filter) => {
try {
if (filter) {
filter.addEventListener('change', filterAbsences);
filter.addEventListener("change", filterAbsences);
}
} catch (err) {
if (err.message && err.message.includes('Extension context invalidated')) {
console.warn('Extension context invalidated during event listener setup');
if (
err.message &&
err.message.includes("Extension context invalidated")
) {
console.warn(
"Extension context invalidated during event listener setup",
);
} else {
console.error('Error setting up filter event listener:', err);
console.error("Error setting up filter event listener:", err);
}
}
});
filterAbsences();
} catch (err) {
if (err.message && err.message.includes('Extension context invalidated')) {
console.warn('Extension context invalidated during filter setup');
if (err.message && err.message.includes("Extension context invalidated")) {
console.warn("Extension context invalidated during filter setup");
} else {
console.error('Error setting up filters:', err);
console.error("Error setting up filters:", err);
}
}
}
function updateStatistics() {
try {
const visibleRows = document.querySelectorAll('.table-row:not([style*="display: none"])');
const visibleRows = document.querySelectorAll(
'.table-row:not([style*="display: none"])',
);
const totalVisible = visibleRows.length;
const justifiedVisible = Array.from(visibleRows).filter(row =>
row.querySelector('.status-badge.justified')).length;
const unjustifiedVisible = Array.from(visibleRows).filter(row =>
row.querySelector('.status-badge.unjustified')).length;
const pendingVisible = Array.from(visibleRows).filter(row =>
row.querySelector('.status-badge.pending')).length;
const justifiedVisible = Array.from(visibleRows).filter((row) =>
row.querySelector(".status-badge.justified"),
).length;
const unjustifiedVisible = Array.from(visibleRows).filter((row) =>
row.querySelector(".status-badge.unjustified"),
).length;
const pendingVisible = Array.from(visibleRows).filter((row) =>
row.querySelector(".status-badge.pending"),
).length;
const statCards = document.querySelectorAll('.stat-card');
if (statCards[0]) statCards[0].querySelector('.stat-number').textContent = totalVisible;
if (statCards[1]) statCards[1].querySelector('.stat-number').textContent = justifiedVisible;
if (statCards[2]) statCards[2].querySelector('.stat-number').textContent = unjustifiedVisible;
if (statCards[3]) statCards[3].querySelector('.stat-number').textContent = pendingVisible;
const statCards = document.querySelectorAll(".stat-card");
if (statCards[0])
statCards[0].querySelector(".stat-number").textContent = totalVisible;
if (statCards[1])
statCards[1].querySelector(".stat-number").textContent = justifiedVisible;
if (statCards[2])
statCards[2].querySelector(".stat-number").textContent =
unjustifiedVisible;
if (statCards[3])
statCards[3].querySelector(".stat-number").textContent = pendingVisible;
} catch (err) {
console.error('Error updating statistics:', 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);
if (window.location.href.includes("/Hianyzas/Hianyzasok")) {
transformAbsencesPage().catch((error) => {
console.error(LanguageManager.t("absences.page_transform_error"), error);
});
}

View File

@@ -1,44 +1,63 @@
const DashboardUtils = {
formatGradeValue(value) {
const trimmedValue = value?.trim() || '';
if (trimmedValue.toLowerCase() === 'szöveges') {
return 'Sz';
const trimmedValue = value?.trim() || "";
if (trimmedValue.toLowerCase() === "szöveges") {
return "Sz";
}
return trimmedValue;
},
parseDate(dateStr) {
return dateStr?.trim() || '';
return dateStr?.trim() || "";
},
formatHungarianDate(dateStr) {
if (!dateStr) return '';
const dateParts = dateStr.trim().split('.');
if (!dateStr) return "";
const dateParts = dateStr.trim().split(".");
if (dateParts.length < 3) return dateStr;
const month = parseInt(dateParts[1], 10);
const day = parseInt(dateParts[2], 10);
if (isNaN(month) || month < 1 || month > 12) return dateStr;
if (typeof window.LanguageManager !== 'undefined') {
if (typeof window.LanguageManager !== "undefined") {
const monthKeys = [
'months.january', 'months.february', 'months.march', 'months.april',
'months.may', 'months.june', 'months.july', 'months.august',
'months.september', 'months.october', 'months.november', 'months.december'
"months.january",
"months.february",
"months.march",
"months.april",
"months.may",
"months.june",
"months.july",
"months.august",
"months.september",
"months.october",
"months.november",
"months.december",
];
const monthName = window.LanguageManager.t(monthKeys[month - 1]);
return `${monthName} ${day}.`;
}
const monthKeys = [
'months.january', 'months.february', 'months.march', 'months.april', 'months.may', 'months.june',
'months.july', 'months.august', 'months.september', 'months.october', 'months.november', 'months.december'
"months.january",
"months.february",
"months.march",
"months.april",
"months.may",
"months.june",
"months.july",
"months.august",
"months.september",
"months.october",
"months.november",
"months.december",
];
return `${LanguageManager.t(monthKeys[month - 1])} ${day}.`;
}
},
};
class DashboardDataManager {
@@ -48,175 +67,216 @@ class DashboardDataManager {
absences: [],
notes: [],
upcomingExams: [],
news: []
news: [],
};
}
extractGradeData() {
const gradeRows = document.querySelectorAll('#legutobbiErtekelesek tr:not(:first-child)');
this.dashboardData.grades = Array.from(gradeRows).map(row => {
const gradeValue = row.querySelector('span[style*="font-size: 200%"]')?.textContent;
const gradeInfo = row.querySelector('span[style*="float: right"]')?.textContent;
if (!gradeValue || !gradeInfo) return null;
const gradeRows = document.querySelectorAll(
"#legutobbiErtekelesek tr:not(:first-child)",
);
const [fullSubject, date] = gradeInfo.split('\n').map(str => str.trim());
const { subject, type, dateInSubject } = this.parseSubjectInformation(fullSubject);
this.dashboardData.grades = Array.from(gradeRows)
.map((row) => {
const gradeValue = row.querySelector(
'span[style*="font-size: 200%"]',
)?.textContent;
const gradeInfo = row.querySelector(
'span[style*="float: right"]',
)?.textContent;
return {
value: DashboardUtils.formatGradeValue(gradeValue),
subject,
date: DashboardUtils.parseDate(date),
type: type || LanguageManager.t('dashboard.evaluation'),
dateInSubject: dateInSubject || null
};
}).filter(Boolean);
if (!gradeValue || !gradeInfo) return null;
const [fullSubject, date] = gradeInfo
.split("\n")
.map((str) => str.trim());
const { subject, type, dateInSubject } =
this.parseSubjectInformation(fullSubject);
return {
value: DashboardUtils.formatGradeValue(gradeValue),
subject,
date: DashboardUtils.parseDate(date),
type: type || LanguageManager.t("dashboard.evaluation"),
dateInSubject: dateInSubject || null,
};
})
.filter(Boolean);
}
parseSubjectInformation(fullSubject) {
const hungarianMonths = ['január', 'február', 'március', 'április', 'május', 'június',
'július', 'augusztus', 'szeptember', 'október', 'november', 'december'];
const monthPattern = hungarianMonths.join('|');
const datePattern = new RegExp(`(${monthPattern})\\s+(\\d{1,2})\\.?$`, 'i');
const hungarianMonths = [
"január",
"február",
"március",
"április",
"május",
"június",
"július",
"augusztus",
"szeptember",
"október",
"november",
"december",
];
const monthPattern = hungarianMonths.join("|");
const datePattern = new RegExp(`(${monthPattern})\\s+(\\d{1,2})\\.?$`, "i");
const dateMatch = fullSubject.match(datePattern);
if (dateMatch) {
const subjectPart = fullSubject.substring(0, dateMatch.index).trim();
const datePart = dateMatch[0].trim();
return {
subject: subjectPart,
type: '',
dateInSubject: datePart
type: "",
dateInSubject: datePart,
};
}
const months = [
LanguageManager.t('months.january'), LanguageManager.t('months.february'), LanguageManager.t('months.march'),
LanguageManager.t('months.april'), LanguageManager.t('months.may'), LanguageManager.t('months.june'),
LanguageManager.t('months.july'), LanguageManager.t('months.august'), LanguageManager.t('months.september'),
LanguageManager.t('months.october'), LanguageManager.t('months.november'), LanguageManager.t('months.december')
LanguageManager.t("months.january"),
LanguageManager.t("months.february"),
LanguageManager.t("months.march"),
LanguageManager.t("months.april"),
LanguageManager.t("months.may"),
LanguageManager.t("months.june"),
LanguageManager.t("months.july"),
LanguageManager.t("months.august"),
LanguageManager.t("months.september"),
LanguageManager.t("months.october"),
LanguageManager.t("months.november"),
LanguageManager.t("months.december"),
];
const fallbackMonthPattern = new RegExp(months.join('|'), 'i');
const fallbackMonthPattern = new RegExp(months.join("|"), "i");
const monthMatch = fullSubject.match(fallbackMonthPattern);
if (monthMatch) {
const monthIndex = fullSubject.lastIndexOf(monthMatch[0]);
return {
subject: fullSubject.substring(0, monthIndex).trim(),
type: fullSubject.substring(monthIndex).trim()
type: fullSubject.substring(monthIndex).trim(),
};
}
return { subject: fullSubject, type: '' };
return { subject: fullSubject, type: "" };
}
extractAbsenceData() {
const absenceRows = document.querySelectorAll('#legutobbiMulasztasok tr:not(:first-child)');
this.dashboardData.absences = Array.from(absenceRows).map(row => {
const spans = row.querySelectorAll('span');
if (spans.length < 4) return null;
const absenceRows = document.querySelectorAll(
"#legutobbiMulasztasok tr:not(:first-child)",
);
return {
date: spans[0]?.textContent?.trim() || '',
day: spans[2]?.textContent?.trim() || '',
type: spans[1]?.textContent?.trim() || '',
count: spans[3]?.textContent?.trim() || ''
};
}).filter(Boolean);
this.dashboardData.absences = Array.from(absenceRows)
.map((row) => {
const spans = row.querySelectorAll("span");
if (spans.length < 4) return null;
return {
date: spans[0]?.textContent?.trim() || "",
day: spans[2]?.textContent?.trim() || "",
type: spans[1]?.textContent?.trim() || "",
count: spans[3]?.textContent?.trim() || "",
};
})
.filter(Boolean);
}
extractNoteData() {
const noteRows = document.querySelectorAll('#legutobbiFeljegyzesek tr:not(:first-child)');
this.dashboardData.notes = Array.from(noteRows).map(row => {
const spans = row.querySelectorAll('span');
if (spans.length < 3) return null;
const noteRows = document.querySelectorAll(
"#legutobbiFeljegyzesek tr:not(:first-child)",
);
return {
title: spans[0]?.textContent?.trim() || '',
author: spans[1]?.textContent?.trim() || '',
date: spans[2]?.textContent?.trim() || ''
};
}).filter(Boolean);
this.dashboardData.notes = Array.from(noteRows)
.map((row) => {
const spans = row.querySelectorAll("span");
if (spans.length < 3) return null;
return {
title: spans[0]?.textContent?.trim() || "",
author: spans[1]?.textContent?.trim() || "",
date: spans[2]?.textContent?.trim() || "",
};
})
.filter(Boolean);
}
extractExamData() {
const examRows = document.querySelectorAll('#legutobbiBejelentettSzamonkeres tr:not(:first-child)');
this.dashboardData.upcomingExams = Array.from(examRows).map(row => {
const spans = row.querySelectorAll('span');
if (spans.length < 4) return null;
const examRows = document.querySelectorAll(
"#legutobbiBejelentettSzamonkeres tr:not(:first-child)",
);
return {
date: spans[0]?.textContent?.trim() || '',
subject: spans[1]?.textContent?.trim() || '',
day: spans[2]?.textContent?.trim() || '',
type: spans[3]?.textContent?.trim() || ''
};
}).filter(Boolean);
this.dashboardData.upcomingExams = Array.from(examRows)
.map((row) => {
const spans = row.querySelectorAll("span");
if (spans.length < 4) return null;
return {
date: spans[0]?.textContent?.trim() || "",
subject: spans[1]?.textContent?.trim() || "",
day: spans[2]?.textContent?.trim() || "",
type: spans[3]?.textContent?.trim() || "",
};
})
.filter(Boolean);
}
async extractNewsData() {
try {
const timestamp = Date.now();
const apiUrl = `https://${window.location.hostname}/Intezmeny/Faliujsag/GetMoreEntries?startindex=0&range=10&_=${timestamp}`;
const response = await fetch(apiUrl, {
method: 'GET',
credentials: 'include',
method: "GET",
credentials: "include",
headers: {
'Accept': 'application/json, text/javascript, */*; q=0.01',
'X-Requested-With': 'XMLHttpRequest'
}
Accept: "application/json, text/javascript, */*; q=0.01",
"X-Requested-With": "XMLHttpRequest",
},
});
if (!response.ok) {
throw new Error(`API request failed with status: ${response.status}`);
}
const data = await response.json();
if (!data.FaliujsagElemek || !Array.isArray(data.FaliujsagElemek)) {
return;
}
data.FaliujsagElemek.forEach((item, index) => {
let formattedDate = '';
let formattedDate = "";
if (item.DatumNap && item.DatumHonap && item.DatumEv) {
formattedDate = `${item.DatumEv}. ${item.DatumHonap} ${item.DatumNap}.`;
} else if (item.Idopont) {
const match = item.Idopont.match(/\/Date\((\d+)\)\//);
const match = item.Idopont.match(/\/Date\((\d+)\)\//);
if (match) {
const timestamp = parseInt(match[1]);
const date = new Date(timestamp);
formattedDate = date.toLocaleDateString('hu-HU');
formattedDate = date.toLocaleDateString("hu-HU");
}
}
if (!formattedDate) {
formattedDate = new Date().toLocaleDateString('hu-HU');
formattedDate = new Date().toLocaleDateString("hu-HU");
}
let cleanContent = item.EsemenySzovege || '';
cleanContent = cleanContent.replace(/<[^>]*>/g, '');
cleanContent = cleanContent.replace(/\r\n/g, ' ');
cleanContent = cleanContent.replace(/\s+/g, ' ').trim();
let cleanContent = item.EsemenySzovege || "";
cleanContent = cleanContent.replace(/<[^>]*>/g, "");
cleanContent = cleanContent.replace(/\r\n/g, " ");
cleanContent = cleanContent.replace(/\s+/g, " ").trim();
const newsItem = {
title: item.EsemenyCime || `Hír ${index + 1}`,
content: cleanContent || 'Nincs elérhető tartalom',
content: cleanContent || "Nincs elérhető tartalom",
date: formattedDate,
author: `${item.Nev || 'Ismeretlen'} (${item.Munkakor || 'Ismeretlen'})`
author: `${item.Nev || "Ismeretlen"} (${item.Munkakor || "Ismeretlen"})`,
};
this.dashboardData.news.push(newsItem);
});
} catch (error) {
console.error('❌ Error fetching news from API:', error);
console.error("❌ Error fetching news from API:", error);
}
}
@@ -235,13 +295,16 @@ class DashboardRenderer {
this.data = {
...data,
schoolInfo: {
name: cookieManager.get(COOKIE_KEYS.SCHOOL_NAME) || DEFAULT_VALUES.SCHOOL,
id: cookieManager.get(COOKIE_KEYS.SCHOOL_CODE) || ''
name:
cookieManager.get(COOKIE_KEYS.SCHOOL_NAME) || DEFAULT_VALUES.SCHOOL,
id: cookieManager.get(COOKIE_KEYS.SCHOOL_CODE) || "",
},
userData: {
name: cookieManager.get(COOKIE_KEYS.USER_NAME) || DEFAULT_VALUES.USER,
time: document.querySelector('.usermenu_timer')?.textContent?.trim() || DEFAULT_VALUES.TIMER
}
time:
document.querySelector(".usermenu_timer")?.textContent?.trim() ||
DEFAULT_VALUES.TIMER,
},
};
this.schoolNameFull = `${this.data.schoolInfo.id} - ${this.data.schoolInfo.name}`;
this.shortenedSchoolName = helper.shortenSchoolName(this.schoolNameFull);
@@ -261,7 +324,9 @@ class DashboardRenderer {
`;
}
createNewsCard() {
const newsItems = this.data.news.map(news => `
const newsItems = this.data.news
.map(
(news) => `
<div class="widget-item news-item">
<div class="widget-row">
<div class="widget-details news-details">
@@ -269,18 +334,27 @@ class DashboardRenderer {
<div class="widget-content news-content">${news.content}</div>
</div>
<div class="widget-meta">
${news.date ? `<div class="widget-date news-date">${news.date}</div>` : ''}
${news.author ? `<div class="widget-author news-author">${news.author}</div>` : ''}
${news.date ? `<div class="widget-date news-date">${news.date}</div>` : ""}
${news.author ? `<div class="widget-author news-author">${news.author}</div>` : ""}
</div>
</div>
</div>
`).join('');
`,
)
.join("");
return this.createCard(LanguageManager.t('dashboard.news'), newsItems || LanguageManager.t('dashboard.not_supported'), '/Intezmeny/Faliujsag', LanguageManager.t('dashboard.all_news'));
return this.createCard(
LanguageManager.t("dashboard.news"),
newsItems || LanguageManager.t("dashboard.not_supported"),
"/Intezmeny/Faliujsag",
LanguageManager.t("dashboard.all_news"),
);
}
createGradeCard() {
const gradeItems = this.data.grades.map(grade => `
const gradeItems = this.data.grades
.map(
(grade) => `
<div class="widget-item grade-item">
<div class="widget-row grade-row">
<div class="grade grade-${grade.value}">${grade.value}</div>
@@ -288,62 +362,96 @@ class DashboardRenderer {
<div class="widget-title subject-name">${grade.subject}</div>
<div class="grade-type-with-date">
<div class="widget-subtitle grade-type">${grade.type}</div>
${grade.dateInSubject || grade.date ? `<div class="widget-subtitle grade-date">${grade.dateInSubject || grade.date}</div>` : ''}
${grade.dateInSubject || grade.date ? `<div class="widget-subtitle grade-date">${grade.dateInSubject || grade.date}</div>` : ""}
</div>
</div>
</div>
</div>
`).join('');
`,
)
.join("");
return this.createCard(LanguageManager.t('dashboard.grades'), gradeItems, '/TanuloErtekeles/Osztalyzatok', LanguageManager.t('dashboard.all_grades'));
return this.createCard(
LanguageManager.t("dashboard.grades"),
gradeItems,
"/TanuloErtekeles/Osztalyzatok",
LanguageManager.t("dashboard.all_grades"),
);
}
createAbsenceCard() {
const absenceItems = this.data.absences.map(absence => `
const absenceItems = this.data.absences
.map(
(absence) => `
<div class="widget-item absence-item">
<div class="widget-row">
<div class="widget-details absence-details">
<div class="widget-title absence-type">${absence.type}</div>
<div class="widget-subtitle absence-date">${absence.date}</div>
</div>
${absence.day ? `<div class="widget-date">${absence.day}</div>` : ''}
${absence.day ? `<div class="widget-date">${absence.day}</div>` : ""}
</div>
</div>
`).join('');
`,
)
.join("");
return this.createCard(LanguageManager.t('dashboard.absences'), absenceItems, '/Hianyzas/Hianyzasok', LanguageManager.t('dashboard.all_absences'));
return this.createCard(
LanguageManager.t("dashboard.absences"),
absenceItems,
"/Hianyzas/Hianyzasok",
LanguageManager.t("dashboard.all_absences"),
);
}
createNoteCard() {
const noteItems = this.data.notes.map(note => `
const noteItems = this.data.notes
.map(
(note) => `
<div class="widget-item note-item">
<div class="widget-row">
<div class="widget-details note-details">
<div class="widget-title note-title">${note.title}</div>
<div class="widget-subtitle note-date">${note.date}</div>
</div>
${note.author ? `<div class="widget-author note-author">${note.author}</div>` : ''}
${note.author ? `<div class="widget-author note-author">${note.author}</div>` : ""}
</div>
</div>
`).join('');
`,
)
.join("");
return this.createCard(LanguageManager.t('dashboard.notes'), noteItems, '/TanuloErtekeles/InformaciokFeljegyzesek', LanguageManager.t('dashboard.all_messages'));
return this.createCard(
LanguageManager.t("dashboard.notes"),
noteItems,
"/TanuloErtekeles/InformaciokFeljegyzesek",
LanguageManager.t("dashboard.all_messages"),
);
}
createExamCard() {
const examItems = this.data.upcomingExams.map(exam => `
const examItems = this.data.upcomingExams
.map(
(exam) => `
<div class="widget-item exam-item">
<div class="widget-row">
<div class="widget-details exam-details">
<div class="widget-title exam-subject">${exam.subject}</div>
<div class="widget-subtitle exam-type">${exam.type || ''}</div>
<div class="widget-subtitle exam-type">${exam.type || ""}</div>
</div>
<div class="widget-date exam-date">${DashboardUtils.formatHungarianDate(exam.date)}</div>
</div>
</div>
`).join('');
`,
)
.join("");
return this.createCard(LanguageManager.t('dashboard.exams'), examItems, '/Tanulo/TanuloBejelentettSzamonkeresek', LanguageManager.t('dashboard.all_exams'));
return this.createCard(
LanguageManager.t("dashboard.exams"),
examItems,
"/Tanulo/TanuloBejelentettSzamonkeresek",
LanguageManager.t("dashboard.all_exams"),
);
}
createCard(title, content, linkHref, linkText) {
@@ -353,7 +461,7 @@ class DashboardRenderer {
<h2 class="widget-card-title">${title}</h2>
</div>
<div class="widget-content card-content">
${content || `<div class="widget-empty">${LanguageManager.t('dashboard.not_supported')}</div>`}
${content || `<div class="widget-empty">${LanguageManager.t("dashboard.not_supported")}</div>`}
</div>
<div class="widget-footer">
<a href="${linkHref}" class="widget-link more-link">
@@ -385,36 +493,40 @@ class DashboardApplication {
}
async init() {
if (!window.location.href.includes('/Intezmeny/Faliujsag')) {
if (!window.location.href.includes("/Intezmeny/Faliujsag")) {
return;
}
while (typeof window.LanguageManager === 'undefined' ||
!window.LanguageManager.t('dashboard.grades') ||
window.LanguageManager.t('dashboard.grades') === 'dashboard.grades') {
await new Promise(resolve => setTimeout(resolve, 50));
while (
typeof window.LanguageManager === "undefined" ||
!window.LanguageManager.t("dashboard.grades") ||
window.LanguageManager.t("dashboard.grades") === "dashboard.grades"
) {
await new Promise((resolve) => setTimeout(resolve, 50));
}
while (!document.querySelector('.faliujsag-lista, #faliujsagLista')) {
await new Promise(resolve => setTimeout(resolve, 100));
while (!document.querySelector(".faliujsag-lista, #faliujsagLista")) {
await new Promise((resolve) => setTimeout(resolve, 100));
}
let newsItemsFound = false;
let attempts = 0;
const maxAttempts = 50;
while (!newsItemsFound && attempts < maxAttempts) {
const newsContainer = document.querySelector('.faliujsag-lista, #faliujsagLista');
const newsContainer = document.querySelector(
".faliujsag-lista, #faliujsagLista",
);
if (newsContainer) {
const possibleSelectors = [
'.nb-item',
'.news-item',
'.faliujsag-item',
'.list-group-item',
'li',
".nb-item",
".news-item",
".faliujsag-item",
".list-group-item",
"li",
'div[class*="item"]',
'div[class*="news"]'
'div[class*="news"]',
];
for (const selector of possibleSelectors) {
const items = newsContainer.querySelectorAll(selector);
if (items.length > 0) {
@@ -422,30 +534,33 @@ class DashboardApplication {
break;
}
}
if (!newsItemsFound) {
if (newsContainer.children.length > 0 || newsContainer.textContent.trim().length > 0) {
if (
newsContainer.children.length > 0 ||
newsContainer.textContent.trim().length > 0
) {
newsItemsFound = true;
}
}
}
if (!newsItemsFound) {
attempts++;
await new Promise(resolve => setTimeout(resolve, 100));
await new Promise((resolve) => setTimeout(resolve, 100));
}
}
try {
const dataManager = new DashboardDataManager();
const dashboardData = await dataManager.extractAllData();
createTemplate.importFonts();
const renderer = new DashboardRenderer(dashboardData);
renderer.render();
} catch (error) {
console.error('Error initializing dashboard:', error);
console.error("Error initializing dashboard:", error);
}
}
}
new DashboardApplication();
new DashboardApplication();

BIN
fonts/Icons.woff2 Normal file

Binary file not shown.

View File

@@ -1,290 +1,57 @@
* {
box-sizing: border-box;
margin: 0;
padding: 0;
body.maintenance-mode {
margin:0;
padding:0;
height:100vh;
display:flex;
align-items:center;
justify-content:center;
background-color:var(--background);
color:var(--text-primary);
font-family:'Figtree',sans-serif;
}
body {
margin: 0;
padding: 0;
color: var(--text-primary);
background-color: var(--background) !important;
font-family: "Montserrat", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif !important;
min-height: 100vh;
font-size: 16px;
display: flex;
align-items: center;
justify-content: center;
background-color:var(--background) !important;
}
.forgot-container {
width: 90%;
max-width: 500px;
padding: 20px;
margin: 0 auto;
.maintenance-container {
text-align:center;
padding:2rem;
border-radius:8px;
background-color:var(--card-card);
box-shadow:0 var(--shadow-blur) 6px var(--accent-shadow);
max-width:600px;
width:90%;
}
.forgot-card {
background: var(--card-card);
padding: 24px;
margin-bottom: 16px;
border-radius: 24px;
box-shadow: 0px 1px var(--shadow-blur) 0px var(--accent-shadow);
.maintenance-logo {
width:128px;
height:128px;
margin:0 auto 2rem;
}
.forgot-header {
display: flex;
flex-direction: column;
align-items: center;
gap: 8px;
margin: 16px 0;
background: var(--card-card) !important;
border-bottom: 1px solid rgba(0, 0, 0, 0) !important;
.maintenance-title {
font-size:1.5rem;
font-weight:600;
margin-bottom:1rem;
color:var(--accent-accent);
font-family:'Montserrat',sans-serif;
}
.logo-text {
color: var(--text-primary);
text-align: center;
font-family: Montserrat;
font-size: 20px;
font-style: normal;
font-weight: 700;
line-height: normal;
display: flex;
align-items: center;
justify-content: center;
gap: 12px;
.maintenance-message {
font-size:1rem;
line-height:1.5;
margin-bottom:1.5rem;
color:var(--text-primary);
font-family:'Figtree',sans-serif;
}
.logo {
width: 48px;
height: 48px;
border-radius: 12px;
.maintenance-footer {
font-size:0.875rem;
color:var(--text-secondary);
margin-top:2rem;
font-family:'Figtree',sans-serif;
}
.forgot-title {
color: var(--text-primary);
text-align: center;
font-family: Montserrat;
font-size: 24px;
font-style: normal;
font-weight: 700;
line-height: normal;
margin-bottom: 24px;
.maintenance-cactus {
position:fixed;
bottom:0px;
right:20px;
width:120px;
height:120px;
opacity:1;
z-index:1000;
}
.forgot-form {
width: 100%;
text-align: center;
margin-bottom: 24px;
}
.logo-text {
color: var(--icon);
font-size: 24px;
font-weight: 600;
margin: 16px 0;
display: flex;
align-items: center;
justify-content: center;
}
.logo {
width: 24px;
border-radius: 8px;
margin-right: 8px;
}
.forgot-card {
background: var(--card);
padding: 24px;
border-radius: 24px;
margin-bottom: 16px;
}
.forgot-title {
font-size: 18px;
font-weight: 600;
color: var(--primary);
margin-bottom: 24px;
text-align: center;
}
.form-group {
margin-bottom: 16px;
}
.form-label {
display: block;
margin-bottom: 8px;
color: var(--text-primary);
font-family: Montserrat;
font-size: 14px;
font-weight: 600;
}
.form-control {
display: flex;
height: 48px;
padding: 0px 14px;
align-items: center;
gap: 10px;
align-self: stretch;
border-radius: 12px;
background: var(--accent-15) !important;
border: 0px solid var(--accent-15) !important;
color: var(--text-primary) !important;
width: 100%;
font-size: 16px;
transition: border-color 0.2s ease;
}
.form-control:focus {
outline: none;
border-color: var(--accent-accent) !important;
}
.form-control::placeholder {
color: var(--text-secondary) !important;
}
.form-control.error {
border-color: var(--error-accent) !important;
background: var(--error-card) !important;
}
.error-message {
color: var(--error-text);
font-size: 14px;
margin-top: 4px;
display: none;
}
.error-message.show {
display: block;
animation: fadeIn 0.2s ease;
border-color: var(--accent);
}
.form-actions {
margin-top: 24px;
display: flex;
flex-direction: column;
gap: 16px;
}
.help-link {
color: var(--text-primary);
font-size: 14px;
font-weight: 500;
text-decoration: none;
transition: color 0.2s ease;
text-align: center;
}
.help-link:hover {
color: var(--text-teritary);
}
.btn-submit {
width: 100%;
padding: 12px;
background: var(--accent-accent);
color: white;
border: none;
border-radius: 12px;
font-size: 16px;
font-weight: 600;
font-family: "Montserrat", serif;
cursor: pointer;
transition: background 0.2s ease;
position: relative;
}
.btn-submit:hover {
background: var(--text-teritary);
}
.btn-submit:disabled {
opacity: 0.7;
cursor: not-allowed;
}
.message {
padding: 12px 16px;
border-radius: 12px;
margin-bottom: 16px;
font-size: 14px;
font-weight: 500;
animation: fadeIn 0.3s ease;
text-align: center;
}
.message.success {
background: var(--success-card);
color: var(--success-text);
border: 1px solid var(--success-accent);
}
.message.error {
background: var(--error-card);
color: var(--error-text);
border: 1px solid var(--error-accent);
}
@keyframes fadeIn {
from { opacity: 0; transform: translateY(-4px); }
to { opacity: 1; transform: translateY(0); }
}
@media (max-width: 480px) {
.forgot-container {
padding: 16px;
}
.forgot-card {
padding: 20px;
}
.forgot-header {
margin-bottom: 20px;
}
.logo-text {
font-size: 18px;
}
.forgot-title {
font-size: 20px;
}
.form-control {
height: 44px;
font-size: 14px;
}
.btn-submit {
padding: 10px;
font-size: 14px;
}
.help-link {
font-size: 12px;
}
}
@media (max-width: 600px) {
.forgot-container {
padding: 16px;
}
.forgot-card {
padding: 20px;
}
.form-actions {
flex-direction: column;
gap: 16px;
align-items: stretch;
}
}

View File

@@ -1,46 +1,47 @@
(() => {
const renderRecaptcha = () => {
const container = document.getElementById('recaptcha-container');
if (container && typeof grecaptcha !== 'undefined' && grecaptcha.render) {
const container = document.getElementById("recaptcha-container");
if (container && typeof grecaptcha !== "undefined" && grecaptcha.render) {
try {
grecaptcha.render('recaptcha-container', {
'sitekey': '6LfKURIqAAAAAD5bF2evQ-_Sf6MRrOkUEBwb_mMy',
'theme': 'light'
grecaptcha.render("recaptcha-container", {
sitekey: "6LfKURIqAAAAAD5bF2evQ-_Sf6MRrOkUEBwb_mMy",
theme: "light",
});
} catch (error) {
console.error('Error rendering reCAPTCHA:', error);
console.error("Error rendering reCAPTCHA:", error);
}
}
};
const loadDependencies = async () => {
if (typeof cookieManager === 'undefined') {
const cookieScript = document.createElement('script');
cookieScript.src = chrome.runtime.getURL('tools/cookieManager.js');
if (typeof cookieManager === "undefined") {
const cookieScript = document.createElement("script");
cookieScript.src = chrome.runtime.getURL("tools/cookieManager.js");
document.head.appendChild(cookieScript);
await new Promise(resolve => {
await new Promise((resolve) => {
cookieScript.onload = resolve;
});
}
if (typeof LanguageManager === 'undefined') {
const langScript = document.createElement('script');
langScript.src = chrome.runtime.getURL('global/language.js');
if (typeof LanguageManager === "undefined") {
const langScript = document.createElement("script");
langScript.src = chrome.runtime.getURL("global/language.js");
document.head.appendChild(langScript);
await new Promise(resolve => {
await new Promise((resolve) => {
langScript.onload = resolve;
});
await new Promise(resolve => setTimeout(resolve, 100));
await new Promise((resolve) => setTimeout(resolve, 100));
}
if (!document.querySelector('script[src*="recaptcha"]')) {
await new Promise((resolve) => {
window.onRecaptchaLoad = resolve;
const script = document.createElement('script');
script.src = 'https://www.google.com/recaptcha/api.js?hl=hu&onload=onRecaptchaLoad&render=explicit';
const script = document.createElement("script");
script.src =
"https://www.google.com/recaptcha/api.js?hl=hu&onload=onRecaptchaLoad&render=explicit";
document.head.appendChild(script);
});
}
@@ -64,7 +65,7 @@
<div class="forgot-card">
<header class="forgot-header">
<p class="logo-text">
<img src="${chrome.runtime.getURL('images/firka_logo.png')}" alt="Firka" class="logo">
<img src="${chrome.runtime.getURL("images/firka_logo.png")}" alt="Firka" class="logo">
Firka
</p>
</header>
@@ -106,14 +107,20 @@
const transformForgotPasswordPage = async () => {
await loadDependencies();
const isDarkMode = localStorage.getItem('darkMode') === 'true';
document.documentElement.setAttribute('data-theme', isDarkMode ? 'dark' : 'light');
const isDarkMode = localStorage.getItem("darkMode") === "true";
document.documentElement.setAttribute(
"data-theme",
isDarkMode ? "dark" : "light",
);
chrome.runtime.onMessage.addListener((message) => {
if (message.action === 'toggleTheme') {
document.documentElement.setAttribute('data-theme', message.darkMode ? 'dark' : 'light');
localStorage.setItem('darkMode', message.darkMode);
if (message.action === "toggleTheme") {
document.documentElement.setAttribute(
"data-theme",
message.darkMode ? "dark" : "light",
);
localStorage.setItem("darkMode", message.darkMode);
}
});
@@ -121,34 +128,34 @@
let attempts = 0;
const maxAttempts = 50;
const waitForLanguageManager = () => {
return new Promise((resolve) => {
const checkLanguageManager = () => {
attempts++;
if (typeof LanguageManager !== 'undefined' && LanguageManager.t) {
if (typeof LanguageManager !== "undefined" && LanguageManager.t) {
setTimeout(resolve, 200);
} else if (attempts < maxAttempts) {
setTimeout(checkLanguageManager, 100);
} else {
console.warn('LanguageManager not available, using fallback texts');
console.warn("LanguageManager not available, using fallback texts");
resolve();
}
};
checkLanguageManager();
});
};
await waitForLanguageManager();
if (typeof LanguageManager !== 'undefined' && LanguageManager.t) {
const elements = document.querySelectorAll('[data-i18n]');
elements.forEach(element => {
const key = element.getAttribute('data-i18n');
if (typeof LanguageManager !== "undefined" && LanguageManager.t) {
const elements = document.querySelectorAll("[data-i18n]");
elements.forEach((element) => {
const key = element.getAttribute("data-i18n");
const translation = LanguageManager.t(key);
if (translation && translation !== key) {
const attr = element.getAttribute('data-i18n-attr');
const attr = element.getAttribute("data-i18n-attr");
if (attr) {
element.setAttribute(attr, translation);
} else {
@@ -157,172 +164,184 @@
}
});
}
setTimeout(() => {
renderRecaptcha();
}, 500);
setupFormValidation();
};
const setupFormValidation = () => {
const form = document.getElementById('forgotForm');
const inputs = form.querySelectorAll('.form-control');
inputs.forEach(input => {
input.addEventListener('input', () => {
validateInput(input);
});
input.addEventListener('blur', () => {
validateInput(input, true);
});
});
form.addEventListener('submit', handleSubmit);
};
const validateInput = (input, showError = false) => {
const isValid = input.value.trim().length > 0;
const errorElement = input.nextElementSibling;
if (!isValid && showError) {
input.classList.add('error');
errorElement?.classList.add('show');
} else {
input.classList.remove('error');
errorElement?.classList.remove('show');
}
return isValid;
};
const showMessage = (message, isError = false) => {
const existingMessage = document.querySelector('.message');
if (existingMessage) {
existingMessage.remove();
}
const messageDiv = document.createElement('div');
messageDiv.className = `message ${isError ? 'error' : 'success'}`;
messageDiv.textContent = message;
const form = document.getElementById('forgotForm');
form.insertBefore(messageDiv, form.firstChild);
const setupFormValidation = () => {
const form = document.getElementById("forgotForm");
const inputs = form.querySelectorAll(".form-control");
setTimeout(() => {
if (messageDiv.parentNode) {
messageDiv.remove();
}
}, 5000);
};
const validateEmail = (email) => {
const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
return emailRegex.test(email);
};
const handleSubmit = async (event) => {
event.preventDefault();
const form = event.target;
const inputs = form.querySelectorAll('.form-control[required]');
let isValid = true;
inputs.forEach(input => {
if (!validateInput(input, true)) {
isValid = false;
}
inputs.forEach((input) => {
input.addEventListener("input", () => {
validateInput(input);
});
const emailInput = form.querySelector('#EmailCim');
if (emailInput.value && !validateEmail(emailInput.value)) {
emailInput.classList.add('error');
const errorElement = emailInput.nextElementSibling;
if (errorElement) {
errorElement.textContent = LanguageManager.t('forgotpassword.invalid_email');
errorElement.classList.add('show');
}
input.addEventListener("blur", () => {
validateInput(input, true);
});
});
form.addEventListener("submit", handleSubmit);
};
const validateInput = (input, showError = false) => {
const isValid = input.value.trim().length > 0;
const errorElement = input.nextElementSibling;
if (!isValid && showError) {
input.classList.add("error");
errorElement?.classList.add("show");
} else {
input.classList.remove("error");
errorElement?.classList.remove("show");
}
return isValid;
};
const showMessage = (message, isError = false) => {
const existingMessage = document.querySelector(".message");
if (existingMessage) {
existingMessage.remove();
}
const messageDiv = document.createElement("div");
messageDiv.className = `message ${isError ? "error" : "success"}`;
messageDiv.textContent = message;
const form = document.getElementById("forgotForm");
form.insertBefore(messageDiv, form.firstChild);
setTimeout(() => {
if (messageDiv.parentNode) {
messageDiv.remove();
}
}, 5000);
};
const validateEmail = (email) => {
const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
return emailRegex.test(email);
};
const handleSubmit = async (event) => {
event.preventDefault();
const form = event.target;
const inputs = form.querySelectorAll(".form-control[required]");
let isValid = true;
inputs.forEach((input) => {
if (!validateInput(input, true)) {
isValid = false;
}
});
let recaptchaResponse = '';
if (typeof grecaptcha !== 'undefined') {
recaptchaResponse = grecaptcha.getResponse();
if (!recaptchaResponse) {
showMessage(LanguageManager.t('forgotpassword.recaptcha_required'), true);
isValid = false;
}
} else {
showMessage('reCAPTCHA nem töltődött be. Kérjük, frissítse az oldalt!', true);
const emailInput = form.querySelector("#EmailCim");
if (emailInput.value && !validateEmail(emailInput.value)) {
emailInput.classList.add("error");
const errorElement = emailInput.nextElementSibling;
if (errorElement) {
errorElement.textContent = LanguageManager.t(
"forgotpassword.invalid_email",
);
errorElement.classList.add("show");
}
isValid = false;
}
let recaptchaResponse = "";
if (typeof grecaptcha !== "undefined") {
recaptchaResponse = grecaptcha.getResponse();
if (!recaptchaResponse) {
showMessage(
LanguageManager.t("forgotpassword.recaptcha_required"),
true,
);
isValid = false;
}
} else {
showMessage(
"reCAPTCHA nem töltődött be. Kérjük, frissítse az oldalt!",
true,
);
isValid = false;
}
if (!isValid) {
return;
if (!isValid) {
return;
}
const submitButton = form.querySelector(".btn-submit");
const originalText = submitButton.textContent;
submitButton.disabled = true;
submitButton.textContent = LanguageManager.t("loading.text") || "Küldés...";
try {
const formData = new FormData(form);
if (typeof grecaptcha !== "undefined") {
formData.append("ReCaptcha", grecaptcha.getResponse());
}
const submitButton = form.querySelector('.btn-submit');
const originalText = submitButton.textContent;
submitButton.disabled = true;
submitButton.textContent = LanguageManager.t('loading.text') || 'Küldés...';
try {
const formData = new FormData(form);
if (typeof grecaptcha !== 'undefined') {
formData.append('ReCaptcha', grecaptcha.getResponse());
}
const response = await fetch('/Adminisztracio/ElfelejtettJelszo/LinkKuldes', {
method: 'POST',
const response = await fetch(
"/Adminisztracio/ElfelejtettJelszo/LinkKuldes",
{
method: "POST",
body: formData,
headers: {
'X-Requested-With': 'XMLHttpRequest'
}
});
"X-Requested-With": "XMLHttpRequest",
},
},
);
if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`);
}
if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`);
}
const result = await response.json();
const result = await response.json();
if (result.Success) {
showMessage(LanguageManager.t('forgotpassword.success_message'));
if (result.Success) {
showMessage(LanguageManager.t("forgotpassword.success_message"));
form.reset();
form.reset();
if (typeof grecaptcha !== 'undefined') {
grecaptcha.reset();
}
setTimeout(() => {
window.location.href = '/Adminisztracio/Login';
}, 3000);
} else {
showMessage(result.Message || LanguageManager.t('forgotpassword.error_message'), true);
if (typeof grecaptcha !== 'undefined') {
grecaptcha.reset();
}
}
} catch (error) {
console.error('Password reset error:', error);
showMessage(LanguageManager.t('forgotpassword.error_message'), true);
if (typeof grecaptcha !== 'undefined') {
if (typeof grecaptcha !== "undefined") {
grecaptcha.reset();
}
setTimeout(() => {
window.location.href = "/Adminisztracio/Login";
}, 3000);
} else {
showMessage(
result.Message || LanguageManager.t("forgotpassword.error_message"),
true,
);
if (typeof grecaptcha !== "undefined") {
grecaptcha.reset();
}
} finally {
submitButton.disabled = false;
submitButton.textContent = originalText;
}
};
if (window.location.href.includes('/Adminisztracio/ElfelejtettJelszo')) {
transformForgotPasswordPage().catch(console.error);
} catch (error) {
console.error("Password reset error:", error);
showMessage(LanguageManager.t("forgotpassword.error_message"), true);
if (typeof grecaptcha !== "undefined") {
grecaptcha.reset();
}
} finally {
submitButton.disabled = false;
submitButton.textContent = originalText;
}
})();
};
if (window.location.href.includes("/Adminisztracio/ElfelejtettJelszo")) {
transformForgotPasswordPage().catch(console.error);
}
})();

View File

@@ -1,131 +1,185 @@
(function() {
let currentLanguage = 'hu';
let translations = {};
async function setLanguage(language) {
(function () {
let currentLanguage = "hu";
let translations = {};
async function setLanguage(language) {
try {
currentLanguage = language;
cookieManager.set("languagePreference", language);
localStorage.setItem("languagePreference", language);
await loadTranslations(language);
applyTranslations();
window.dispatchEvent(
new CustomEvent("languageChanged", {
detail: { language: language },
}),
);
chrome.runtime
.sendMessage({
action: "languageChanged",
language: language,
})
.catch(() => {});
} catch (error) {}
}
async function loadTranslations(language) {
try {
const url = chrome.runtime.getURL(`i18n/${language}.json`);
const response = await fetch(url);
if (!response.ok) {
throw new Error(
`Failed to load ${language}.json - Status: ${response.status}`,
);
}
translations = await response.json();
} catch (error) {
if (language !== "hu") {
try {
currentLanguage = language;
cookieManager.set('languagePreference', language);
localStorage.setItem('languagePreference', language);
await loadTranslations(language);
applyTranslations();
window.dispatchEvent(new CustomEvent('languageChanged', {
detail: { language: language }
}));
chrome.runtime.sendMessage({
action: 'languageChanged',
language: language
}).catch(() => {});
} catch (error) {}
const fallbackUrl = chrome.runtime.getURL("i18n/hu.json");
const response = await fetch(fallbackUrl);
translations = await response.json();
} catch (fallbackError) {}
}
}
async function loadTranslations(language) {
try {
const url = chrome.runtime.getURL(`i18n/${language}.json`);
const response = await fetch(url);
if (!response.ok) {
throw new Error(`Failed to load ${language}.json - Status: ${response.status}`);
}
translations = await response.json();
} catch (error) {
if (language !== 'hu') {
try {
const fallbackUrl = chrome.runtime.getURL('i18n/hu.json');
const response = await fetch(fallbackUrl);
translations = await response.json();
} catch (fallbackError) {}
}
}
function applyTranslations() {
const elements = document.querySelectorAll("[data-i18n]");
elements.forEach((element) => {
const key = element.getAttribute("data-i18n");
const translation = getTranslation(key);
if (translation && translation !== key) {
const attr = element.getAttribute("data-i18n-attr");
if (attr) {
element.setAttribute(attr, translation);
} else {
element.textContent = translation;
}
}
function applyTranslations() {
const elements = document.querySelectorAll('[data-i18n]');
elements.forEach(element => {
const key = element.getAttribute('data-i18n');
const translation = getTranslation(key);
if (translation && translation !== key) {
const attr = element.getAttribute('data-i18n-attr');
if (attr) {
element.setAttribute(attr, translation);
} else {
element.textContent = translation;
}
}
});
}
function getTranslation(keyPath, fallback = '') {
const keys = keyPath.split('.');
let value = translations;
for (const key of keys) {
if (value && typeof value === 'object' && key in value) {
value = value[key];
} else {
return fallback || keyPath;
}
}
return typeof value === 'string' ? value : fallback || keyPath;
}
async function initializeLanguage() {
const cookieLanguage = cookieManager.get('languagePreference');
const localStorageLanguage = localStorage.getItem('languagePreference');
const language = cookieLanguage || localStorageLanguage || 'hu';
await setLanguage(language);
if (cookieLanguage !== localStorageLanguage) {
if (cookieLanguage) {
localStorage.setItem('languagePreference', cookieLanguage);
} else if (localStorageLanguage) {
cookieManager.set('languagePreference', localStorageLanguage);
}
}
}
if (document.readyState === 'loading') {
document.addEventListener('DOMContentLoaded', initializeLanguage);
} else {
initializeLanguage();
}
chrome.runtime.onMessage.addListener((message, sender, sendResponse) => {
if (message.action === 'changeLanguage') {
setLanguage(message.language);
sendResponse({ success: true });
}
if (message.action === 'getLanguage') {
sendResponse({ language: currentLanguage });
}
return true;
}
});
}
window.LanguageManager = {
getCurrentLanguage: () => currentLanguage,
changeLanguage: setLanguage,
t: getTranslation,
getAvailableLanguages: () => [
{ code: 'hu', name: 'Magyar' },
{ code: 'en', name: 'English' }
]
};
})();
function getTranslation(keyPath, fallback = "") {
const keys = keyPath.split(".");
let value = translations;
for (const key of keys) {
if (value && typeof value === "object" && key in value) {
value = value[key];
} else {
return fallback || keyPath;
}
}
return typeof value === "string" ? value : fallback || keyPath;
}
async function initializeLanguage() {
const cookieLanguage = cookieManager.get("languagePreference");
const localStorageLanguage = localStorage.getItem("languagePreference");
const language = cookieLanguage || localStorageLanguage || "hu";
await setLanguage(language);
loadTranslationsForPage();
if (cookieLanguage !== localStorageLanguage) {
if (cookieLanguage) {
localStorage.setItem("languagePreference", cookieLanguage);
} else if (localStorageLanguage) {
cookieManager.set("languagePreference", localStorageLanguage);
}
}
}
if (document.readyState === "loading") {
document.addEventListener("DOMContentLoaded", initializeLanguage);
} else {
initializeLanguage();
}
chrome.runtime.onMessage.addListener((message, sender, sendResponse) => {
if (message.action === "changeLanguage") {
setLanguage(message.language);
sendResponse({ success: true });
}
if (message.action === "getLanguage") {
sendResponse({ language: currentLanguage });
}
return true;
});
function loadTranslationsForPage() {
try {
applyTranslations();
// Figyeljük a DOM változásokat és alkalmazzuk a fordításokat új elemekre
const observer = new MutationObserver((mutations) => {
mutations.forEach((mutation) => {
if (mutation.type === 'childList') {
mutation.addedNodes.forEach((node) => {
if (node.nodeType === Node.ELEMENT_NODE) {
const elementsWithI18n = node.querySelectorAll ? node.querySelectorAll('[data-i18n]') : [];
elementsWithI18n.forEach((element) => {
const key = element.getAttribute('data-i18n');
const translation = getTranslation(key);
if (translation && translation !== key) {
const attr = element.getAttribute('data-i18n-attr');
if (attr) {
element.setAttribute(attr, translation);
} else {
element.textContent = translation;
}
}
});
// Ha maga az elem is tartalmaz data-i18n attribútumot
if (node.hasAttribute && node.hasAttribute('data-i18n')) {
const key = node.getAttribute('data-i18n');
const translation = getTranslation(key);
if (translation && translation !== key) {
const attr = node.getAttribute('data-i18n-attr');
if (attr) {
node.setAttribute(attr, translation);
} else {
node.textContent = translation;
}
}
}
}
});
}
});
});
observer.observe(document.body, {
childList: true,
subtree: true
});
} catch (error) {
console.error('Error loading translations for page:', error);
}
}
window.LanguageManager = {
getCurrentLanguage: () => currentLanguage,
changeLanguage: setLanguage,
t: getTranslation,
loadTranslationsForPage: loadTranslationsForPage,
getAvailableLanguages: () => [
{ code: "hu", name: "Magyar" },
{ code: "en", name: "English" },
],
};
})();

View File

@@ -1,89 +1,57 @@
@font-face {
font-family: 'Montserrat';
src: url('chrome-extension://__MSG_@@extension_id__/fonts/Montserrat-Regular.woff2') format('woff2');
font-weight: 400;
font-style: normal;
}
@font-face {
font-family: 'Montserrat';
src: url('chrome-extension://__MSG_@@extension_id__/fonts/Montserrat-Medium.woff2') format('woff2');
font-weight: 500;
font-style: normal;
}
@font-face {
font-family: 'Montserrat';
src: url('chrome-extension://__MSG_@@extension_id__/fonts/Montserrat-SemiBold.woff2') format('woff2');
font-weight: 600;
font-style: normal;
}
@font-face {
font-family: 'Figtree';
src: url('chrome-extension://__MSG_@@extension_id__/fonts/Figtree-Regular.woff2') format('woff2');
font-weight: 400;
font-style: normal;
}
body.maintenance-mode {
margin: 0;
padding: 0;
height: 100vh;
display: flex;
align-items: center;
justify-content: center;
background-color: var(--background);
color: var(--text-primary);
font-family: 'Figtree', sans-serif;
margin:0;
padding:0;
height:100vh;
display:flex;
align-items:center;
justify-content:center;
background-color:var(--background);
color:var(--text-primary);
font-family:'Figtree',sans-serif;
}
body {
background-color: var(--background) !important;
background-color:var(--background) !important;
}
.maintenance-container {
text-align: center;
padding: 2rem;
border-radius: 8px;
background-color: var(--card-card);
box-shadow: 0 var(--shadow-blur) 6px var(--accent-shadow);
max-width: 600px;
width: 90%;
text-align:center;
padding:2rem;
border-radius:8px;
background-color:var(--card-card);
box-shadow:0 var(--shadow-blur) 6px var(--accent-shadow);
max-width:600px;
width:90%;
}
.maintenance-logo {
width: 128px;
height: 128px;
margin: 0 auto 2rem;
width:128px;
height:128px;
margin:0 auto 2rem;
}
.maintenance-title {
font-size: 1.5rem;
font-weight: 600;
margin-bottom: 1rem;
color: var(--accent-accent);
font-family: 'Montserrat', sans-serif;
font-size:1.5rem;
font-weight:600;
margin-bottom:1rem;
color:var(--accent-accent);
font-family:'Montserrat',sans-serif;
}
.maintenance-message {
font-size: 1rem;
line-height: 1.5;
margin-bottom: 1.5rem;
color: var(--text-primary);
font-family: 'Figtree', sans-serif;
font-size:1rem;
line-height:1.5;
margin-bottom:1.5rem;
color:var(--text-primary);
font-family:'Figtree',sans-serif;
}
.maintenance-footer {
font-size: 0.875rem;
color: var(--text-secondary);
margin-top: 2rem;
font-family: 'Figtree', sans-serif;
font-size:0.875rem;
color:var(--text-secondary);
margin-top:2rem;
font-family:'Figtree',sans-serif;
}
.maintenance-cactus {
position: fixed;
bottom: 0px;
right: 20px;
width: 120px;
height: 120px;
opacity: 1;
z-index: 1000;
}
position:fixed;
bottom:0px;
right:20px;
width:120px;
height:120px;
opacity:1;
z-index:1000;
}

View File

@@ -1,99 +1,111 @@
function loadMaintenanceCSS() {
const maintenanceCSS = document.createElement('link');
maintenanceCSS.rel = 'stylesheet';
maintenanceCSS.href = chrome.runtime.getURL('global/maintenance.css');
document.head.appendChild(maintenanceCSS);
const maintenanceCSS = document.createElement("link");
maintenanceCSS.rel = "stylesheet";
maintenanceCSS.href = chrome.runtime.getURL("global/maintenance.css");
document.head.appendChild(maintenanceCSS);
}
function checkMaintenancePage() {
const maintenanceContent = document.querySelector('.login_content');
const bodyText = document.body ? document.body.textContent : '';
const maintenanceContent = document.querySelector(".login_content");
const bodyText = document.body ? document.body.textContent : "";
const specificMaintenanceMessage = 'Kedves Felhasználók! A KRÉTA rendszer jelenleg frissítés alatt van, hamarosan újra elérhetővé válik. Köszönjük türelmüket és megértésüket! KRÉTA Csapat';
const hasSpecificMessage = bodyText.includes('Kedves Felhasználók!') &&
bodyText.includes('A KRÉTA rendszer jelenleg frissítés alatt van') &&
bodyText.includes('KRÉTA Csapat');
const specificMaintenanceMessage =
"Kedves Felhasználók! A KRÉTA rendszer jelenleg frissítés alatt van, hamarosan újra elérhetővé válik. Köszönjük türelmüket és megértésüket! KRÉTA Csapat";
const hasSpecificMessage =
bodyText.includes("Kedves Felhasználók!") &&
bodyText.includes("A KRÉTA rendszer jelenleg frissítés alatt van") &&
bodyText.includes("KRÉTA Csapat");
const hasGeneralMaintenance = maintenanceContent &&
(maintenanceContent.textContent.includes('frissítés alatt') ||
maintenanceContent.textContent.includes('under maintenance'));
if (hasSpecificMessage || hasGeneralMaintenance) {
const body = document.body;
const mainLogo = chrome.runtime.getURL('images/firka_logo_128.png');
const cactusImage = chrome.runtime.getURL('images/cactus.png');
const hasGeneralMaintenance =
maintenanceContent &&
(maintenanceContent.textContent.includes("frissítés alatt") ||
maintenanceContent.textContent.includes("under maintenance"));
const removeLoadingElements = () => {
const loadingScreen = document.querySelector('.loading-screen');
if (loadingScreen) loadingScreen.remove();
const kretaProgressBar = document.querySelector('#KretaProgressBar');
if (kretaProgressBar) kretaProgressBar.remove();
const modalBackground = document.querySelector('.modalBckgroundMain');
if (modalBackground) modalBackground.remove();
if (hasSpecificMessage || hasGeneralMaintenance) {
const body = document.body;
const mainLogo = chrome.runtime.getURL("images/firka_logo_128.png");
const cactusImage = chrome.runtime.getURL("images/cactus.png");
const overlays = document.querySelectorAll('.modalBckgroundMain, .loading-screen, #KretaProgressBar');
overlays.forEach(overlay => overlay.remove());
};
removeLoadingElements();
setTimeout(removeLoadingElements, 100);
const removeLoadingElements = () => {
const loadingScreen = document.querySelector(".loading-screen");
if (loadingScreen) loadingScreen.remove();
const existingStyles = document.querySelectorAll('link[rel="stylesheet"], style');
existingStyles.forEach(style => style.remove());
const kretaProgressBar = document.querySelector("#KretaProgressBar");
if (kretaProgressBar) kretaProgressBar.remove();
body.innerHTML = '';
body.classList.add('maintenance-mode');
body.classList.add('theme-enabled');
body.classList.add('loaded');
loadMaintenanceCSS();
const container = document.createElement('div');
container.className = 'maintenance-container';
const logo = document.createElement('img');
logo.src = mainLogo;
logo.alt = 'Firka Logo';
logo.className = 'maintenance-logo';
const title = document.createElement('h1');
title.className = 'maintenance-title';
title.textContent = window.LanguageManager ? window.LanguageManager.t('maintenance.title') : 'Karbantartás';
const messageDiv = document.createElement('div');
messageDiv.className = 'maintenance-message';
const paragraph1 = document.createElement('p');
paragraph1.textContent = window.LanguageManager ? window.LanguageManager.t('maintenance.message1') : 'A KRÉTA rendszer jelenleg frissítés alatt van, hamarosan újra elérhetővé válik.';
const paragraph2 = document.createElement('p');
paragraph2.textContent = window.LanguageManager ? window.LanguageManager.t('maintenance.message2') : 'Köszönjük türelmüket és megértésüket!';
const footer = document.createElement('div');
footer.className = 'maintenance-footer';
footer.textContent = window.LanguageManager ? window.LanguageManager.t('maintenance.team') : 'KRÉTA Csapat';
const modalBackground = document.querySelector(".modalBckgroundMain");
if (modalBackground) modalBackground.remove();
const cactus = document.createElement('img');
cactus.src = cactusImage;
cactus.alt = 'Cactus';
cactus.className = 'maintenance-cactus';
messageDiv.appendChild(paragraph1);
messageDiv.appendChild(paragraph2);
container.appendChild(logo);
container.appendChild(title);
container.appendChild(messageDiv);
container.appendChild(footer);
body.appendChild(container);
body.appendChild(cactus);
}
const overlays = document.querySelectorAll(
".modalBckgroundMain, .loading-screen, #KretaProgressBar",
);
overlays.forEach((overlay) => overlay.remove());
};
removeLoadingElements();
setTimeout(removeLoadingElements, 100);
const existingStyles = document.querySelectorAll(
'link[rel="stylesheet"], style',
);
existingStyles.forEach((style) => style.remove());
body.innerHTML = "";
body.classList.add("maintenance-mode");
body.classList.add("theme-enabled");
body.classList.add("loaded");
loadMaintenanceCSS();
const container = document.createElement("div");
container.className = "maintenance-container";
const logo = document.createElement("img");
logo.src = mainLogo;
logo.alt = "Firka Logo";
logo.className = "maintenance-logo";
const title = document.createElement("h1");
title.className = "maintenance-title";
title.textContent = window.LanguageManager
? window.LanguageManager.t("maintenance.title")
: "Karbantartás";
const messageDiv = document.createElement("div");
messageDiv.className = "maintenance-message";
const paragraph1 = document.createElement("p");
paragraph1.textContent = window.LanguageManager
? window.LanguageManager.t("maintenance.message1")
: "A KRÉTA rendszer jelenleg frissítés alatt van, hamarosan újra elérhetővé válik.";
const paragraph2 = document.createElement("p");
paragraph2.textContent = window.LanguageManager
? window.LanguageManager.t("maintenance.message2")
: "Köszönjük türelmüket és megértésüket!";
const footer = document.createElement("div");
footer.className = "maintenance-footer";
footer.textContent = window.LanguageManager
? window.LanguageManager.t("maintenance.team")
: "KRÉTA Csapat";
const cactus = document.createElement("img");
cactus.src = cactusImage;
cactus.alt = "Cactus";
cactus.className = "maintenance-cactus";
messageDiv.appendChild(paragraph1);
messageDiv.appendChild(paragraph2);
container.appendChild(logo);
container.appendChild(title);
container.appendChild(messageDiv);
container.appendChild(footer);
body.appendChild(container);
body.appendChild(cactus);
}
}
document.addEventListener('DOMContentLoaded', checkMaintenancePage);
document.addEventListener("DOMContentLoaded", checkMaintenancePage);

View File

@@ -1,401 +1,331 @@
.kreta-header {
padding: clamp(1rem, 3vw, 2rem);
display: grid;
grid-template-columns: minmax(300px, 400px) 1fr minmax(200px, 300px);
align-items: center;
gap: 1rem;
background-color: var(--background);
padding:clamp(1rem,3vw,2rem);
display:grid;
grid-template-columns:minmax(300px,400px) 1fr minmax(200px,300px);
align-items:center;
gap:1rem;
background-color:var(--background);
}
.school-info {
margin: 0;
display: flex;
flex-direction: column;
margin:0;
display:flex;
flex-direction:column;
}
.logo-text {
color: var(--text-primary);
font-size: 24px;
font-weight: 600;
margin: 0 0 0.5rem;
display: flex;
align-items: center;
color:var(--text-primary);
font-size:24px;
font-weight:600;
margin:0 0 0.5rem;
display:flex;
align-items:center;
}
.logo {
width: 24px;
height: 24px;
border-radius: 8px;
margin-right: 0.5rem;
width:24px;
height:24px;
border-radius:8px;
margin-right:0.5rem;
}
.school-details {
color: var(--text-secondary);
font-size: 14px;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
color:var(--text-secondary);
font-size:14px;
white-space:nowrap;
overflow:hidden;
text-overflow:ellipsis;
}
.kreta-nav {
padding: 0 clamp(0.5rem, 3vw, 1.5rem);
position: sticky;
top: 0;
z-index: 100;
display: flex;
justify-content: center;
padding:0 clamp(0.5rem,3vw,1.5rem);
position:sticky;
top:0;
z-index:100;
display:flex;
justify-content:center;
}
.nav-links {
display: flex;
gap: clamp(0.5rem, 2vw, 1rem);
padding: 0.25rem;
align-items: center;
display:flex;
gap:clamp(0.5rem,2vw,1rem);
padding:0.25rem;
align-items:center;
}
.nav-item {
display: flex;
align-items: center;
padding: clamp(0.5rem, 1.5vw, 1rem) 0.5rem;
color: var(--text-secondary);
text-decoration: none;
font-weight: 500;
white-space: nowrap;
border-radius: 8px;
transition: all 0.2s ease;
gap: 0.5rem;
text-decoration: none;
display:flex;
align-items:center;
padding:clamp(0.5rem,1.5vw,1rem) 0.5rem;
color:var(--text-secondary);
text-decoration:none;
font-weight:500;
white-space:nowrap;
border-radius:8px;
transition:all 0.2s ease;
gap:0.5rem;
text-decoration:none;
}
.nav-item.active {
display: flex;
padding: 8px 14px 8px 12px;
align-items: center;
gap: 8px;
border-radius: 20px;
background: var(--button-secondaryFill);
box-shadow: 0px 1px var(--shadow-blur, 2px) 0px var(--accent-shadow);
display:flex;
padding:8px 14px 8px 12px;
align-items:center;
gap:8px;
border-radius:20px;
background:var(--button-secondaryFill);
box-shadow:0px 1px var(--shadow-blur,2px) 0px var(--accent-shadow);
}
.nav-item:hover {
color: var(--text-primary);
background-color: var(--hover);
border-radius: 8px;
text-decoration: none;
color:var(--text-primary);
background-color:var(--hover);
border-radius:8px;
text-decoration:none;
}
.nav-item.active:hover {
color: var(--accent-accent);
background-color: var(--accent-hover);
text-decoration: none;
color:var(--accent-accent);
background-color:var(--accent-hover);
text-decoration:none;
}
.nav-item img,
.nav-item svg {
width: 24px;
height: 24px;
.nav-item img,.nav-item svg {
width:24px;
height:24px;
}
.nav-item.active svg path {
fill: var(--accent-accent);
fill:var(--accent-accent);
}
.user-profile {
position: relative;
justify-self: flex-end;
position:relative;
justify-self:flex-end;
}
.user-dropdown-btn {
display: flex;
align-items: center;
gap: 1rem;
background: none;
border: none;
cursor: pointer;
padding: 0.5rem;
border-radius: 8px;
transition: background-color 0.2s;
display:flex;
align-items:center;
gap:1rem;
background:none;
border:none;
cursor:pointer;
padding:0.5rem;
border-radius:8px;
transition:background-color 0.2s;
}
.user-dropdown-btn:hover {
background: var(--hover);
background:var(--hover);
}
.user-info {
text-align: right;
text-align:right;
}
.user-name {
display: block;
color: var(--text-primary);
font-size: 16px;
display:block;
color:var(--text-primary);
font-size:16px;
}
.nav-logout-timer {
display: block;
color: var(--text-secondary);
font-size: 14px;
display:block;
color:var(--text-secondary);
font-size:14px;
}
.user-dropdown {
position: absolute;
top: 100%;
right: 0;
margin-top: 0.5rem;
background: var(--card-card);
border-radius: 12px;
box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1);
width: 200px;
display: none;
z-index: 1000;
position:absolute;
top:100%;
right:0;
margin-top:0.5rem;
background:var(--card-card);
border-radius:12px;
box-shadow:0 4px 6px -1px rgba(0,0,0,0.1);
width:200px;
display:none;
z-index:1000;
}
.user-dropdown.show {
display: block;
animation: dropdownShow 0.2s ease;
display:block;
animation:dropdownShow 0.2s ease;
}
.dropdown-item {
display: flex;
align-items: center;
gap: 0.75rem;
padding: 0.75rem 1rem;
color: var(--text-primary);
text-decoration: none;
transition: background-color 0.2s;
display:flex;
align-items:center;
gap:0.75rem;
padding:0.75rem 1rem;
color:var(--text-primary);
text-decoration:none;
transition:background-color 0.2s;
}
.dropdown-item:hover {
background: var(--hover);
color: var(--accent-accent);
border-radius: 8px;
background:var(--hover);
color:var(--accent-accent);
border-radius:8px;
}
@keyframes dropdownShow {
from {
opacity: 0;
transform: translateY(-10px);
}
to {
opacity: 1;
transform: translateY(0);
}
opacity:0;
transform:translateY(-10px);
}
@media (max-width: 1200px) {
to {
opacity:1;
transform:translateY(0);
}
}@media (max-width:1200px) {
.kreta-header {
grid-template-columns: minmax(250px, 350px) 1fr minmax(180px, 250px);
}
grid-template-columns:minmax(250px,350px) 1fr minmax(180px,250px);
}
/* Hamburger menu styles */
}/* Hamburger menu styles */
.nav-toggle {
display: none;
background: none;
border: none;
cursor: pointer;
padding: 0.5rem;
border-radius: 8px;
transition: background-color 0.2s;
display:none;
background:none;
border:none;
cursor:pointer;
padding:0.5rem;
border-radius:8px;
transition:background-color 0.2s;
}
.nav-toggle:hover {
background: var(--hover);
background:var(--hover);
}
.nav-toggle svg {
width: 24px;
height: 24px;
fill: var(--text-primary);
width:24px;
height:24px;
fill:var(--text-primary);
}
@media (max-width: 768px) {
@media (max-width:768px) {
.kreta-header {
grid-template-columns: 1fr auto auto;
grid-template-areas:
"school toggle user"
grid-template-columns:1fr auto auto;
grid-template-areas:"school toggle user"
"nav nav nav";
padding: 1rem;
gap: 0.5rem;
}
.nav-toggle {
display: block;
grid-area: toggle;
}
.school-info {
grid-area: school;
max-width: none;
display: flex;
align-items: center;
gap: 0.5rem;
}
.logo-text {
margin: 0;
font-size: 18px;
}
.school-details {
font-size: 11px;
max-width: 200px;
}
.kreta-nav {
grid-area: nav;
padding: 0;
margin-top: 0.5rem;
display: none;
}
.kreta-nav.show {
display: flex;
animation: slideDown 0.3s ease;
}
.kreta-nav::-webkit-scrollbar {
display: none;
}
.nav-links {
flex-direction: column;
width: 100%;
gap: 0.5rem;
background: var(--card-card);
border-radius: 12px;
padding: 1rem;
box-shadow: 0px 1px var(--shadow-blur) 0px var(--accent-shadow);
}
.nav-item {
width: 100%;
justify-content: flex-start;
padding: 0.75rem;
font-size: 14px;
}
.user-profile {
grid-area: user;
}
.user-info {
text-align: right;
max-width: 120px;
}
.user-name {
font-size: 13px;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
.nav-logout-timer {
font-size: 11px;
}
padding:1rem;
gap:0.5rem;
}
@media (max-width: 480px) {
.nav-toggle {
display:block;
grid-area:toggle;
}
.school-info {
grid-area:school;
max-width:none;
display:flex;
align-items:center;
gap:0.5rem;
}
.logo-text {
margin:0;
font-size:18px;
}
.school-details {
font-size:11px;
max-width:200px;
}
.kreta-nav {
grid-area:nav;
padding:0;
margin-top:0.5rem;
display:none;
}
.kreta-nav.show {
display:flex;
animation:slideDown 0.3s ease;
}
.kreta-nav::-webkit-scrollbar {
display:none;
}
.nav-links {
flex-direction:column;
width:100%;
gap:0.5rem;
background:var(--card-card);
border-radius:12px;
padding:1rem;
box-shadow:0px 1px var(--shadow-blur) 0px var(--accent-shadow);
}
.nav-item {
width:100%;
justify-content:flex-start;
padding:0.75rem;
font-size:14px;
}
.user-profile {
grid-area:user;
}
.user-info {
text-align:right;
max-width:120px;
}
.user-name {
font-size:13px;
white-space:nowrap;
overflow:hidden;
text-overflow:ellipsis;
}
.nav-logout-timer {
font-size:11px;
}
}@media (max-width:480px) {
.kreta-header {
grid-template-columns: 1fr auto auto;
grid-template-areas:
"school toggle user"
grid-template-columns:1fr auto auto;
grid-template-areas:"school toggle user"
"nav nav nav";
padding: 0.75rem;
gap: 0.25rem;
}
.school-info {
min-width: 0;
flex: 1;
}
.logo-text {
font-size: 16px;
}
.school-details {
font-size: 10px;
max-width: 150px;
}
.kreta-nav {
display: none;
}
.kreta-nav.show {
display: flex;
animation: slideDown 0.3s ease;
}
.nav-links {
flex-direction: column;
width: 100%;
gap: 0.5rem;
background: var(--card-card);
border-radius: 12px;
padding: 1rem;
box-shadow: 0px 1px var(--shadow-blur) 0px var(--accent-shadow);
}
.nav-item {
width: 100%;
justify-content: flex-start;
padding: 0.75rem;
font-size: 14px;
}
.user-info {
max-width: 100px;
}
.user-name {
font-size: 12px;
}
.nav-logout-timer {
font-size: 10px;
}
padding:0.75rem;
gap:0.25rem;
}
@media (max-width: 360px) {
.school-info {
min-width:0;
flex:1;
}
.logo-text {
font-size:16px;
}
.school-details {
font-size:10px;
max-width:150px;
}
.kreta-nav {
display:none;
}
.kreta-nav.show {
display:flex;
animation:slideDown 0.3s ease;
}
.nav-links {
flex-direction:column;
width:100%;
gap:0.5rem;
background:var(--card-card);
border-radius:12px;
padding:1rem;
box-shadow:0px 1px var(--shadow-blur) 0px var(--accent-shadow);
}
.nav-item {
width:100%;
justify-content:flex-start;
padding:0.75rem;
font-size:14px;
}
.user-info {
max-width:100px;
}
.user-name {
font-size:12px;
}
.nav-logout-timer {
font-size:10px;
}
}@media (max-width:360px) {
.kreta-header {
padding: 0.5rem;
}
.logo-text {
font-size: 14px;
}
.school-details {
font-size: 9px;
max-width: 120px;
}
.user-info {
max-width: 80px;
}
.user-name {
font-size: 11px;
}
.nav-logout-timer {
font-size: 9px;
}
padding:0.5rem;
}
@keyframes slideDown {
.logo-text {
font-size:14px;
}
.school-details {
font-size:9px;
max-width:120px;
}
.user-info {
max-width:80px;
}
.user-name {
font-size:11px;
}
.nav-logout-timer {
font-size:9px;
}
}@keyframes slideDown {
from {
opacity: 0;
transform: translateY(-10px);
}
to {
opacity: 1;
transform: translateY(0);
}
opacity:0;
transform:translateY(-10px);
}
to {
opacity:1;
transform:translateY(0);
}
}

View File

@@ -1,122 +1,124 @@
const COOKIE_KEYS = {
SCHOOL_NAME: 'schoolName',
SCHOOL_CODE: 'schoolCode',
USER_NAME: 'userName',
SCHOOL_SUBDOMAIN: 'schoolSubdomain'
SCHOOL_NAME: "schoolName",
SCHOOL_CODE: "schoolCode",
USER_NAME: "userName",
SCHOOL_SUBDOMAIN: "schoolSubdomain",
};
const DEFAULT_VALUES = {
SCHOOL: LanguageManager.t('navigation.school_default'),
USER: LanguageManager.t('navigation.user_default'),
TIMER: '45:00'
SCHOOL: LanguageManager.t("navigation.school_default"),
USER: LanguageManager.t("navigation.user_default"),
TIMER: "45:00",
};
function updateHeaderInfo() {
const schoolName = document.querySelector('.nav-school-name');
const userName = document.querySelector('.nav-user-name');
const logoutTimer = document.querySelector('.nav-logout-timer');
const userData = {
schoolName: cookieManager.get(COOKIE_KEYS.SCHOOL_NAME) || DEFAULT_VALUES.SCHOOL,
schoolId: cookieManager.get(COOKIE_KEYS.SCHOOL_CODE) || '',
name: cookieManager.get(COOKIE_KEYS.USER_NAME) || DEFAULT_VALUES.USER,
time: document.querySelector('.usermenu_timer')?.textContent?.trim() || DEFAULT_VALUES.TIMER
};
if (schoolName) {
schoolName.textContent = `${userData.schoolId} - ${userData.schoolName}`;
}
if (userName) {
userName.textContent = userData.name;
}
if (logoutTimer) {
startLogoutTimer(userData.time);
}
const schoolName = document.querySelector(".nav-school-name");
const userName = document.querySelector(".nav-user-name");
const logoutTimer = document.querySelector(".nav-logout-timer");
const userData = {
schoolName:
cookieManager.get(COOKIE_KEYS.SCHOOL_NAME) || DEFAULT_VALUES.SCHOOL,
schoolId: cookieManager.get(COOKIE_KEYS.SCHOOL_CODE) || "",
name: cookieManager.get(COOKIE_KEYS.USER_NAME) || DEFAULT_VALUES.USER,
time:
document.querySelector(".usermenu_timer")?.textContent?.trim() ||
DEFAULT_VALUES.TIMER,
};
if (schoolName) {
schoolName.textContent = `${userData.schoolId} - ${userData.schoolName}`;
}
if (userName) {
userName.textContent = userData.name;
}
if (logoutTimer) {
startLogoutTimer(userData.time);
}
}
function startLogoutTimer(timeString) {
const startTime = parseInt(timeString?.match(/\d+/)?.[0] || "45");
let timeLeft = startTime * 60;
const timerElement = document.querySelector('.nav-logout-timer');
const updateTimer = () => {
const minutes = Math.floor(timeLeft / 60);
const seconds = timeLeft % 60;
timerElement.textContent = `${minutes}:${seconds.toString().padStart(2, '0')}`;
if (timeLeft <= 0) {
window.location.href = '/Home/Logout';
}
timeLeft--;
};
const startTime = parseInt(timeString?.match(/\d+/)?.[0] || "45");
let timeLeft = startTime * 60;
const timerElement = document.querySelector(".nav-logout-timer");
updateTimer();
setInterval(updateTimer, 1000);
const updateTimer = () => {
const minutes = Math.floor(timeLeft / 60);
const seconds = timeLeft % 60;
timerElement.textContent = `${minutes}:${seconds.toString().padStart(2, "0")}`;
if (timeLeft <= 0) {
window.location.href = "/Home/Logout";
}
timeLeft--;
};
updateTimer();
setInterval(updateTimer, 1000);
}
document.addEventListener('DOMContentLoaded', () => {
updateHeaderInfo();
document.addEventListener("DOMContentLoaded", () => {
updateHeaderInfo();
});
function setupUserDropdown() {
const userBtn = document.querySelector('.user-dropdown-btn');
const userDropdown = document.querySelector('.user-dropdown');
userBtn?.addEventListener('click', (e) => {
e.stopPropagation();
userDropdown?.classList.toggle('show');
});
const userBtn = document.querySelector(".user-dropdown-btn");
const userDropdown = document.querySelector(".user-dropdown");
document.addEventListener('click', () => {
userDropdown?.classList.remove('show');
});
userBtn?.addEventListener("click", (e) => {
e.stopPropagation();
userDropdown?.classList.toggle("show");
});
document.addEventListener("click", () => {
userDropdown?.classList.remove("show");
});
}
function setupSettingsButton() {
document.getElementById('settingsBtn')?.addEventListener('click', (e) => {
e.preventDefault();
e.stopPropagation();
const url = chrome.runtime.getURL('settings/index.html');
window.open(url, '_blank', 'width=400,height=600');
});
document.getElementById("settingsBtn")?.addEventListener("click", (e) => {
e.preventDefault();
e.stopPropagation();
const url = chrome.runtime.getURL("settings/index.html");
window.open(url, "_blank", "width=400,height=600");
});
}
function setupMobileNavigation() {
setTimeout(() => {
const navToggle = document.querySelector('.nav-toggle');
const nav = document.querySelector('.kreta-nav');
if (!navToggle || !nav) {
return;
}
navToggle.addEventListener('click', (e) => {
e.preventDefault();
e.stopPropagation();
nav.classList.toggle('show');
});
setTimeout(() => {
const navToggle = document.querySelector(".nav-toggle");
const nav = document.querySelector(".kreta-nav");
document.addEventListener('click', (e) => {
if (!nav.contains(e.target) && !navToggle.contains(e.target)) {
nav.classList.remove('show');
}
});
if (!navToggle || !nav) {
return;
}
const navItems = document.querySelectorAll('.nav-item');
navItems.forEach(item => {
item.addEventListener('click', () => {
nav.classList.remove('show');
});
});
}, 100);
navToggle.addEventListener("click", (e) => {
e.preventDefault();
e.stopPropagation();
nav.classList.toggle("show");
});
document.addEventListener("click", (e) => {
if (!nav.contains(e.target) && !navToggle.contains(e.target)) {
nav.classList.remove("show");
}
});
const navItems = document.querySelectorAll(".nav-item");
navItems.forEach((item) => {
item.addEventListener("click", () => {
nav.classList.remove("show");
});
});
}, 100);
}
document.addEventListener('DOMContentLoaded', () => {
updateHeaderInfo();
setupUserDropdown();
setupSettingsButton();
setupMobileNavigation();
document.addEventListener("DOMContentLoaded", () => {
updateHeaderInfo();
setupUserDropdown();
setupSettingsButton();
setupMobileNavigation();
});

View File

@@ -1,178 +1,163 @@
:root {
--background: #DAE4F7;
--background-0: #dae4f700;
--success: var(--grades-4);
--shadow-blur: 2px;
--text-primary: #050B15;
--text-secondary: #050b15cc;
--text-teritary: #050b1580;
--card-card: #EDF3FF;
--card-translucent: #edf3ff80;
--button-secondaryFill: #FBFCFF;
--accent-accent: #3673EE;
--accent-secondary: #1C469A;
--accent-shadow: #1c469a26;
--accent-15: #3673ee26;
--warning-accent: var(--grades-2);
--warning-text: #8F531B;
--warning-15: #ffa04626;
--warning-card: #FAEBDC;
--error-accent: var(--grades-1);
--error-text: #8F1B4F;
--error-15: #FF54A126;
--error-card: #FADCE9;
--grades-1: #FF54A1;
--grades-2: #FFA046;
--grades-3: #F9CF00;
--grades-4: #92EA3B;
--grades-5: #22CCAD;
--grades-background-1: #FF54A126;
--grades-background-2: #FFA04626;
--grades-background-3: #F9CF0026;
--grades-background-4: #92EA3B26;
--grades-background-5: #22CCAD26;
--background:#DAE4F7;
--background-0:#dae4f700;
--success:var(--grades-4);
--shadow-blur:2px;
--text-primary:#050B15;
--text-secondary:#050b15cc;
--text-teritary:#050b1580;
--card-card:#EDF3FF;
--card-translucent:#edf3ff80;
--button-secondaryFill:#FBFCFF;
--accent-accent:#3673EE;
--accent-secondary:#1C469A;
--accent-shadow:#1c469a26;
--accent-15:#3673ee26;
--warning-accent:var(--grades-2);
--warning-text:#8F531B;
--warning-15:#ffa04626;
--warning-card:#FAEBDC;
--error-accent:var(--grades-1);
--error-text:#8F1B4F;
--error-15:#FF54A126;
--error-card:#FADCE9;
--grades-1:#FF54A1;
--grades-2:#FFA046;
--grades-3:#F9CF00;
--grades-4:#92EA3B;
--grades-5:#22CCAD;
--grades-background-1:#FF54A126;
--grades-background-2:#FFA04626;
--grades-background-3:#F9CF0026;
--grades-background-4:#92EA3B26;
--grades-background-5:#22CCAD26;
}
:root[data-theme="light-green"] {
--background: #FAFFF0;
--background-0: #fafff000;
--success: var(--grades-4);
--shadow-blur: 2px;
--text-primary: #394C0A;
--text-secondary: #394c0acc;
--text-teritary: #394c0a80;
--card-card: #F3FBDE;
--card-translucent: #f3fbde80;
--button-secondaryFill: #FEFFFD;
--accent-accent: #A7DC22;
--accent-secondary: #6E8F1B;
--accent-shadow: #647e2226;
--accent-15: #a7dc2226;
--warning-accent: var(--grades-2);
--warning-text: #8F531B;
--warning-15: #ffa04626;
--warning-card: #FAEBDC;
--error-accent: var(--grades-1);
--error-text: #8F1B4F;
--error-15: #FF54A126;
--error-card: #FADCE9;
--grades-1: #FF54A1;
--grades-2: #FFA046;
--grades-3: #F9CF00;
--grades-4: #92EA3B;
--grades-5: #22CCAD;
--grades-background-1: #FF54A126;
--grades-background-2: #FFA04626;
--grades-background-3: #F9CF0026;
--grades-background-4: #92EA3B26;
--grades-background-5: #22CCAD26;
--background:#FAFFF0;
--background-0:#fafff000;
--success:var(--grades-4);
--shadow-blur:2px;
--text-primary:#394C0A;
--text-secondary:#394c0acc;
--text-teritary:#394c0a80;
--card-card:#F3FBDE;
--card-translucent:#f3fbde80;
--button-secondaryFill:#FEFFFD;
--accent-accent:#A7DC22;
--accent-secondary:#6E8F1B;
--accent-shadow:#647e2226;
--accent-15:#a7dc2226;
--warning-accent:var(--grades-2);
--warning-text:#8F531B;
--warning-15:#ffa04626;
--warning-card:#FAEBDC;
--error-accent:var(--grades-1);
--error-text:#8F1B4F;
--error-15:#FF54A126;
--error-card:#FADCE9;
--grades-1:#FF54A1;
--grades-2:#FFA046;
--grades-3:#F9CF00;
--grades-4:#92EA3B;
--grades-5:#22CCAD;
--grades-background-1:#FF54A126;
--grades-background-2:#FFA04626;
--grades-background-3:#F9CF0026;
--grades-background-4:#92EA3B26;
--grades-background-5:#22CCAD26;
}
:root[data-theme="dark-blue"] {
--background: #070A0E;
--background-0: #070a0e00;
--success: var(--grades-4);
--shadow-blur: 0;
--text-primary: #EBF1FD;
--text-secondary: #ebf1fdcc;
--text-teritary: #ebf1fd80;
--card-card: #0F131B;
--card-translucent: #0f131b80;
--button-secondaryFill: #131822;
--accent-accent: #3673EE;
--accent-secondary: #AEC8FC;
--accent-shadow: #0000;
--accent-15: #3673ee26;
--warning-accent: var(--grades-2);
--warning-text: #f0b37a;
--warning-15: #ffa04626;
--warning-card: #201203;
--error-accent: var(--grades-1);
--error-text: #f59ec5;
--error-15: #ff54a126;
--error-card: #1e030f;
--grades-1: #FF54A1;
--grades-2: #FFA046;
--grades-3: #F9CF00;
--grades-4: #92EA3B;
--grades-5: #22CCAD;
--grades-background-1: #FF54A126;
--grades-background-2: #FFA04626;
--grades-background-3: #F9CF0026;
--grades-background-4: #92EA3B26;
--grades-background-5: #22CCAD26;
--background:#070A0E;
--background-0:#070a0e00;
--success:var(--grades-4);
--shadow-blur:0;
--text-primary:#EBF1FD;
--text-secondary:#ebf1fdcc;
--text-teritary:#ebf1fd80;
--card-card:#0F131B;
--card-translucent:#0f131b80;
--button-secondaryFill:#131822;
--accent-accent:#3673EE;
--accent-secondary:#AEC8FC;
--accent-shadow:#0000;
--accent-15:#3673ee26;
--warning-accent:var(--grades-2);
--warning-text:#f0b37a;
--warning-15:#ffa04626;
--warning-card:#201203;
--error-accent:var(--grades-1);
--error-text:#f59ec5;
--error-15:#ff54a126;
--error-card:#1e030f;
--grades-1:#FF54A1;
--grades-2:#FFA046;
--grades-3:#F9CF00;
--grades-4:#92EA3B;
--grades-5:#22CCAD;
--grades-background-1:#FF54A126;
--grades-background-2:#FFA04626;
--grades-background-3:#F9CF0026;
--grades-background-4:#92EA3B26;
--grades-background-5:#22CCAD26;
}
:root[data-theme="dark-green"] {
--background: #0D1202;
--background-0: #0E130200;
--success: var(--grades-4);
--shadow-blur: 0;
--text-primary: #EAF7CC;
--text-secondary: #EAF7CCCC;
--text-teritary: #EAF7CC80;
--card-card: #141905;
--card-translucent: #14190580;
--button-secondaryFill: #20290b;
--accent-accent: #A7DC22;
--accent-secondary: #CBEE71;
--accent-shadow: #0000;
--accent-15: #a7dc2226;
--warning-accent: var(--grades-2);
--warning-text: #f0b37a;
--warning-15: #ffa04626;
--warning-card: #201203;
--error-accent: var(--grades-1);
--error-text: #f59ec5;
--error-15: #ff54a126;
--error-card: #1e030f;
--grades-1: #FF54A1;
--grades-2: #FFA046;
--grades-3: #F9CF00;
--grades-4: #92EA3B;
--grades-5: #22CCAD;
--grades-background-1: #FF54A126;
--grades-background-2: #FFA04626;
--grades-background-3: #F9CF0026;
--grades-background-4: #92EA3B26;
--grades-background-5: #22CCAD26;
--background:#0D1202;
--background-0:#0E130200;
--success:var(--grades-4);
--shadow-blur:0;
--text-primary:#EAF7CC;
--text-secondary:#EAF7CCCC;
--text-teritary:#EAF7CC80;
--card-card:#141905;
--card-translucent:#14190580;
--button-secondaryFill:#20290b;
--accent-accent:#A7DC22;
--accent-secondary:#CBEE71;
--accent-shadow:#0000;
--accent-15:#a7dc2226;
--warning-accent:var(--grades-2);
--warning-text:#f0b37a;
--warning-15:#ffa04626;
--warning-card:#201203;
--error-accent:var(--grades-1);
--error-text:#f59ec5;
--error-15:#ff54a126;
--error-card:#1e030f;
--grades-1:#FF54A1;
--grades-2:#FFA046;
--grades-3:#F9CF00;
--grades-4:#92EA3B;
--grades-5:#22CCAD;
--grades-background-1:#FF54A126;
--grades-background-2:#FFA04626;
--grades-background-3:#F9CF0026;
--grades-background-4:#92EA3B26;
--grades-background-5:#22CCAD26;
}
html {
background-color: var(--background) !important;
color: var(--text-primary) !important;
background-color:var(--background) !important;
color:var(--text-primary) !important;
}
body {
background-color: var(--background) !important;
color: var(--text-primary) !important;
transition: background-color 0.2s ease, color 0.2s ease;
min-height: 100vh;
background-color:var(--background) !important;
color:var(--text-primary) !important;
transition:background-color 0.2s ease,color 0.2s ease;
min-height:100vh;
}
* {
transition: background-color 0.2s ease, color 0.2s ease, border-color 0.2s ease;
transition:background-color 0.2s ease,color 0.2s ease,border-color 0.2s ease;
}
::-webkit-scrollbar {
width: clamp(4px, 1vw, 8px);
height: clamp(4px, 1vw, 8px);
width:clamp(4px,1vw,8px);
height:clamp(4px,1vw,8px);
}
::-webkit-scrollbar-track {
background: var(--background);
background:var(--background);
}
::-webkit-scrollbar-thumb {
background: var(--text-secondary);
border-radius: 4px;
background:var(--text-secondary);
border-radius:4px;
}
::-webkit-scrollbar-thumb:hover {
background: var(--text-primary);
}
background:var(--text-primary);
}

View File

@@ -1,132 +1,202 @@
(() => {
function setTheme(theme) {
try {
const actualTheme = theme === 'default' ? 'light-blue' : theme;
document.documentElement.setAttribute('data-theme', actualTheme);
cookieManager.set('themePreference', actualTheme);
localStorage.setItem('themePreference', actualTheme);
chrome.runtime.sendMessage({
action: 'themeChanged',
theme: actualTheme
}).catch(() => {
function setTheme(theme) {
try {
const actualTheme = theme === "default" ? "light-blue" : theme;
});
} catch (error) {
console.error('Error setting theme:', error);
}
document.documentElement.setAttribute("data-theme", actualTheme);
cookieManager.set("themePreference", actualTheme);
localStorage.setItem("themePreference", actualTheme);
chrome.runtime
.sendMessage({
action: "themeChanged",
theme: actualTheme,
})
.catch(() => {});
} catch (error) {
console.error("Error setting theme:", error);
}
function setPageTitleAndFavicon() {
try {
document.title = 'Firka - KRÉTA';
}
const existingFavicons = document.querySelectorAll('link[rel="icon"], link[rel="shortcut icon"]');
existingFavicons.forEach(link => link.remove());
if (typeof chrome !== 'undefined' && chrome.runtime && chrome.runtime.getURL) {
const favicon = document.createElement('link');
favicon.rel = 'icon';
favicon.type = 'image/png';
favicon.href = chrome.runtime.getURL('images/firka_logo_128.png');
document.head.appendChild(favicon);
const shortcutIcon = document.createElement('link');
shortcutIcon.rel = 'shortcut icon';
shortcutIcon.type = 'image/png';
shortcutIcon.href = chrome.runtime.getURL('images/firka_logo_128.png');
document.head.appendChild(shortcutIcon);
}
} catch (error) {
console.error('Error setting page title and favicon:', error);
function importFonts() {
try {
const fontFaces = `
@font-face {
font-family: 'Montserrat';
font-style: normal;
font-weight: 400;
src: url('${chrome.runtime.getURL('fonts/Montserrat-Regular.woff2')}') format('woff2');
font-display: swap;
}
}
function initializeTheme() {
const cookieTheme = cookieManager.get('themePreference');
const localStorageTheme = localStorage.getItem('themePreference');
const theme = cookieTheme || localStorageTheme || 'light-green';
setTheme(theme);
setPageTitleAndFavicon();
if (cookieTheme !== localStorageTheme) {
if (cookieTheme) {
localStorage.setItem('themePreference', cookieTheme);
} else if (localStorageTheme) {
cookieManager.set('themePreference', localStorageTheme);
}
@font-face {
font-family: 'Montserrat';
font-style: normal;
font-weight: 500;
src: url('${chrome.runtime.getURL('fonts/Montserrat-Medium.woff2')}') format('woff2');
font-display: swap;
}
@font-face {
font-family: 'Montserrat';
font-style: normal;
font-weight: 600;
src: url('${chrome.runtime.getURL('fonts/Montserrat-SemiBold.woff2')}') format('woff2');
font-display: swap;
}
@font-face {
font-family: 'Figtree';
font-style: normal;
font-weight: 400;
src: url('${chrome.runtime.getURL('fonts/Figtree-Regular.woff2')}') format('woff2');
font-display: swap;
}
`;
const styleElement = document.createElement('style');
styleElement.textContent = fontFaces;
document.head.appendChild(styleElement);
const iconFontFace = `
@font-face {
font-family: 'Material Icons Round';
font-style: normal;
font-weight: 400;
src: url('${chrome.runtime.getURL('fonts/Icons.woff2')}') format('woff2');
font-display: swap;
}
`;
const iconStyleElement = document.createElement('style');
iconStyleElement.textContent = iconFontFace;
document.head.appendChild(iconStyleElement);
} catch (error) {
console.error("Error importing fonts:", error);
}
if (document.readyState === 'loading') {
document.addEventListener('DOMContentLoaded', initializeTheme);
} else {
initializeTheme();
}
function setPageTitleAndFavicon() {
try {
document.title = "Firka - KRÉTA";
const existingFavicons = document.querySelectorAll(
'link[rel="icon"], link[rel="shortcut icon"]',
);
existingFavicons.forEach((link) => link.remove());
if (
typeof chrome !== "undefined" &&
chrome.runtime &&
chrome.runtime.getURL
) {
const favicon = document.createElement("link");
favicon.rel = "icon";
favicon.type = "image/png";
favicon.href = chrome.runtime.getURL("images/firka_logo_128.png");
document.head.appendChild(favicon);
const shortcutIcon = document.createElement("link");
shortcutIcon.rel = "shortcut icon";
shortcutIcon.type = "image/png";
shortcutIcon.href = chrome.runtime.getURL("images/firka_logo_128.png");
document.head.appendChild(shortcutIcon);
}
} catch (error) {
console.error("Error setting page title and favicon:", error);
}
}
function initializeTheme() {
const cookieTheme = cookieManager.get("themePreference");
const localStorageTheme = localStorage.getItem("themePreference");
const theme = cookieTheme || localStorageTheme || "light-green";
setTheme(theme);
setPageTitleAndFavicon();
importFonts();
if (cookieTheme !== localStorageTheme) {
if (cookieTheme) {
localStorage.setItem("themePreference", cookieTheme);
} else if (localStorageTheme) {
cookieManager.set("themePreference", localStorageTheme);
}
}
}
if (document.readyState === "loading") {
document.addEventListener("DOMContentLoaded", initializeTheme);
} else {
initializeTheme();
}
chrome.runtime.onMessage.addListener((message, sender, sendResponse) => {
if (message.action === "changeTheme") {
setTheme(message.theme);
sendResponse({ success: true });
}
chrome.runtime.onMessage.addListener((message, sender, sendResponse) => {
if (message.action === 'changeTheme') {
setTheme(message.theme);
sendResponse({ success: true });
}
if (message.action === 'getTheme') {
const currentTheme = document.documentElement.getAttribute('data-theme') || 'light-green';
sendResponse({ theme: currentTheme });
}
if (message.action === "getTheme") {
const currentTheme =
document.documentElement.getAttribute("data-theme") || "light-green";
sendResponse({ theme: currentTheme });
}
return true;
return true;
});
let titleCheckTimeout;
const observer = new MutationObserver((mutations) => {
const currentTheme = document.documentElement.getAttribute("data-theme");
const savedTheme =
cookieManager.get("themePreference") ||
localStorage.getItem("themePreference");
if (
(!currentTheme && savedTheme) ||
(currentTheme !== savedTheme && savedTheme)
) {
setTheme(savedTheme);
}
const titleChanged = mutations.some(
(mutation) =>
mutation.type === "childList" &&
mutation.target === document.head &&
Array.from(mutation.addedNodes).some(
(node) => node.tagName === "TITLE",
),
);
if (titleChanged || document.title !== "Firka - KRÉTA") {
clearTimeout(titleCheckTimeout);
titleCheckTimeout = setTimeout(() => {
if (document.title !== "Firka - KRÉTA") {
setPageTitleAndFavicon();
}
}, 100);
}
});
if (document.readyState === "loading") {
document.addEventListener("DOMContentLoaded", () => {
observer.observe(document.documentElement, {
attributes: true,
attributeFilter: ["data-theme"],
});
observer.observe(document.head, {
childList: true,
subtree: true,
});
});
let titleCheckTimeout;
const observer = new MutationObserver((mutations) => {
const currentTheme = document.documentElement.getAttribute('data-theme');
const savedTheme = cookieManager.get('themePreference') || localStorage.getItem('themePreference');
if ((!currentTheme && savedTheme) || (currentTheme !== savedTheme && savedTheme)) {
setTheme(savedTheme);
}
const titleChanged = mutations.some(mutation =>
mutation.type === 'childList' &&
mutation.target === document.head &&
Array.from(mutation.addedNodes).some(node => node.tagName === 'TITLE')
);
if (titleChanged || document.title !== 'Firka - KRÉTA') {
clearTimeout(titleCheckTimeout);
titleCheckTimeout = setTimeout(() => {
if (document.title !== 'Firka - KRÉTA') {
setPageTitleAndFavicon();
}
}, 100);
}
} else {
observer.observe(document.documentElement, {
attributes: true,
attributeFilter: ["data-theme"],
});
if (document.readyState === 'loading') {
document.addEventListener('DOMContentLoaded', () => {
observer.observe(document.documentElement, {
attributes: true,
attributeFilter: ['data-theme']
});
observer.observe(document.head, {
childList: true,
subtree: true
});
});
} else {
observer.observe(document.documentElement, {
attributes: true,
attributeFilter: ['data-theme']
});
observer.observe(document.head, {
childList: true,
subtree: true
});
}
})();
observer.observe(document.head, {
childList: true,
subtree: true,
});
}
})();

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -269,37 +269,145 @@ body {
opacity: 0.9;
}
.homework-list {
display: flex;
flex-direction: column;
.stats-overview {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
gap: 16px;
margin-bottom: 24px;
}
.homework-date-group {
.stat-card {
background: var(--card-card);
border-radius: 16px;
padding: 20px;
text-align: center;
box-shadow: 0px 1px var(--shadow-blur) 0px var(--accent-shadow);
transition: transform 0.2s ease;
}
.stat-card:hover {
transform: translateY(-2px);
}
.stat-number {
font-size: 32px;
font-weight: 700;
color: var(--accent-accent);
margin-bottom: 8px;
}
.stat-label {
font-size: 14px;
color: var(--text-secondary);
font-weight: 500;
}
.stat-card.urgent .stat-number {
color: #ff4757;
}
.stat-card.completed .stat-number {
color: #2ed573;
}
.homework-container {
background: var(--card-card);
border-radius: 24px;
overflow: hidden;
animation: fadeIn 0.3s ease;
box-shadow: 0px 1px var(--shadow-blur) 0px var(--accent-shadow);
}
.date-header {
padding: 16px;
color: var(--text-primary);
font-weight: 600;
display: flex;
align-items: center;
gap: 8px;
.homework-table {
width: 100%;
border-collapse: collapse;
}
.homework-count {
margin-left: auto;
background: var(--accent-accent);
color: var(--button-secondaryFill);
padding: 4px 8px;
border-radius: 12px;
.table-header {
background: var(--accent-15);
font-weight: 600;
color: var(--text-primary);
}
.table-header th {
padding: 16px;
text-align: left;
font-size: 14px;
border-bottom: 1px solid var(--accent-15);
}
.table-row {
border-bottom: 1px solid var(--accent-15);
transition: background-color 0.2s ease;
}
.table-row:hover {
background-color: var(--accent-15);
}
.table-row.due-tomorrow {
background-color: rgba(255, 71, 87, 0.1);
}
.table-row.due-tomorrow:hover {
background-color: rgba(255, 71, 87, 0.2);
}
.table-cell {
padding: 16px;
vertical-align: top;
border-bottom: 1px solid var(--accent-15);
}
.date-cell {
font-weight: 600;
color: var(--text-primary);
min-width: 120px;
}
.subject-cell {
font-weight: 500;
color: var(--accent-accent);
min-width: 120px;
}
.description-cell {
max-width: 300px;
word-wrap: break-word;
line-height: 1.4;
}
.teacher-cell {
color: var(--text-secondary);
font-style: italic;
min-width: 120px;
}
.status-cell {
text-align: center;
min-width: 100px;
}
.status-badge {
padding: 4px 12px;
border-radius: 12px;
font-size: 12px;
font-weight: 500;
text-transform: uppercase;
}
.status-badge.pending {
background-color: rgba(255, 193, 7, 0.2);
color: #ffc107;
}
.status-badge.urgent {
background-color: rgba(255, 71, 87, 0.2);
color: #ff4757;
}
.status-badge.completed {
background-color: rgba(46, 213, 115, 0.2);
color: #2ed573;
}
.homework-list-items {
@@ -398,6 +506,104 @@ body {
flex-direction: column;
gap: 0.25rem;
}
.stats-overview {
grid-template-columns: repeat(2, 1fr);
}
.table-cell {
padding: 12px;
font-size: 14px;
}
.description-cell {
max-width: 200px;
}
}
@media (max-width: 480px) {
.homework-container {
overflow-x: hidden;
}
.homework-table,
.table-header,
.table-row,
.table-cell {
display: block;
}
.table-header {
display: none;
}
.date-group {
margin-bottom: 24px;
}
.date-group-header {
background: var(--accent-accent);
color: white;
padding: 12px 16px;
font-weight: 600;
font-size: 16px;
border-radius: 12px 12px 0 0;
margin-bottom: 0;
}
.date-group-content {
background: var(--card-card);
border: 1px solid var(--accent-15);
border-radius: 0 0 12px 12px;
overflow: hidden;
}
.table-row {
display: block;
width: 100%;
margin-bottom: 0;
padding: 16px;
border-bottom: 1px solid var(--accent-15);
background: var(--card-card);
}
.table-row:last-child {
border-bottom: none;
}
.table-cell {
display: flex;
justify-content: space-between;
align-items: flex-start;
padding: 8px 0;
border-bottom: 1px solid var(--accent-15);
}
.table-cell:last-child {
border-bottom: none;
}
.table-cell::before {
content: attr(data-label);
font-weight: 600;
color: var(--text-secondary);
font-size: 12px;
text-transform: uppercase;
flex-shrink: 0;
}
.description-cell {
max-width: none;
white-space: normal;
text-overflow: initial;
overflow: visible;
text-align: right;
flex: 1;
}
.stats-overview {
grid-template-columns: 1fr;
}
}
@keyframes fadeIn {

View File

@@ -2,62 +2,64 @@ async function fetchHomeworkData() {
try {
const currentDomain = window.location.hostname;
const apiUrl = `https://${currentDomain}/api/TanuloHaziFeladatApi/GetTanulotHaziFeladatGrid?sort=HaziFeladatHatarido-asc&page=1&pageSize=100&group=&filter=&data=%7B%22RegiHaziFeladatokElrejtese%22%3Afalse%7D&_=${Date.now()}`;
const response = await fetch(apiUrl, {
method: 'GET',
credentials: 'include',
method: "GET",
credentials: "include",
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json'
}
Accept: "application/json",
"Content-Type": "application/json",
},
});
if (!response.ok) {
throw new Error('Network response was not ok');
throw new Error("Network response was not ok");
}
const data = await response.json();
return data;
} catch (error) {
console.error('Error fetching homework data:', error);
console.error("Error fetching homework data:", error);
return { Data: [], Total: 0 };
}
}
async function collectHomeworkData() {
const apiData = await fetchHomeworkData();
const basicData = {
schoolInfo: {
name: cookieManager.get('schoolName') || 'Iskola',
id: cookieManager.get('schoolCode') || ''
name: cookieManager.get("schoolName") || "Iskola",
id: cookieManager.get("schoolCode") || "",
},
userData: {
name: cookieManager.get('userName') || 'Felhasználó',
time: document.querySelector('.usermenu_timer')?.textContent?.trim() || '45:00'
}
name: cookieManager.get("userName") || "Felhasználó",
time:
document.querySelector(".usermenu_timer")?.textContent?.trim() ||
"45:00",
},
};
const homeworkItems = [];
if (apiData.Data && Array.isArray(apiData.Data)) {
apiData.Data.forEach(item => {
apiData.Data.forEach((item) => {
homeworkItems.push({
id: item.ID,
subject: item.TantargyNev || '',
teacher: item.TanarNeve || '',
description: item.HaziFeladatSzoveg || '',
subject: item.TantargyNev || "",
teacher: item.TanarNeve || "",
description: item.HaziFeladatSzoveg || "",
createdDate: formatApiDate(item.HaziFeladatRogzitesDatuma),
deadline: formatApiDate(item.HaziFeladatHatarido),
completed: item.MegoldottHF_BOOL || false,
classGroup: item.OsztalyCsoport || ''
classGroup: item.OsztalyCsoport || "",
});
});
}
const groupedHomework = {};
homeworkItems.forEach(homework => {
const deadlineDate = homework.deadline.split(' ')[0];
homeworkItems.forEach((homework) => {
const deadlineDate = homework.deadline.split(" ")[0];
if (!groupedHomework[deadlineDate]) {
groupedHomework[deadlineDate] = [];
}
@@ -68,24 +70,24 @@ async function collectHomeworkData() {
}
function formatApiDate(dateString) {
if (!dateString) return '';
if (!dateString) return "";
try {
const date = new Date(dateString);
const month = String(date.getMonth() + 1).padStart(2, '0');
const day = String(date.getDate()).padStart(2, '0');
const month = String(date.getMonth() + 1).padStart(2, "0");
const day = String(date.getDate()).padStart(2, "0");
const dayNames = [
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')
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 = dayNames[date.getDay()];
return `${month}.${day}. (${dayName})`;
} catch (error) {
return dateString;
@@ -94,32 +96,29 @@ function formatApiDate(dateString) {
function isTomorrow(dateStr) {
if (!dateStr) return false;
const parts = dateStr.split('.');
const parts = dateStr.split(".");
if (parts.length < 3) return false;
const year = parseInt(parts[0].trim());
const month = parseInt(parts[1].trim()) - 1;
const day = parseInt(parts[2].trim());
const homeworkDate = new Date(year, month, day);
const tomorrow = new Date();
tomorrow.setDate(tomorrow.getDate() + 1);
tomorrow.setHours(0, 0, 0, 0);
const dayAfterTomorrow = new Date(tomorrow);
dayAfterTomorrow.setDate(dayAfterTomorrow.getDate() + 1);
return homeworkDate >= tomorrow && homeworkDate < dayAfterTomorrow;
}
async function transformHomeworkPage() {
const { basicData, homeworkItems, groupedHomework } = await collectHomeworkData();
const { basicData, homeworkItems, groupedHomework } =
await collectHomeworkData();
document.body.innerHTML = `
<div class="kreta-container">
@@ -128,52 +127,90 @@ async function transformHomeworkPage() {
<main class="kreta-main">
<div class="filter-card">
<div class="filter-header">
<h2>${LanguageManager.t('homework.filter_title')}</h2>
<h2>${LanguageManager.t("homework.filter_title")}</h2>
</div>
<div class="filter-content">
<div class="filter-group">
<label>
<!--<span class="material-icons-round">subject</span>-->
${LanguageManager.t('homework.subject')}
${LanguageManager.t("homework.subject")}
</label>
<select id="subjectFilter">
<option value="">${LanguageManager.t('homework.all_subjects')}</option>
${[...new Set(homeworkItems.map(item => item.subject))]
<option value="">${LanguageManager.t("homework.all_subjects")}</option>
${[...new Set(homeworkItems.map((item) => item.subject))]
.sort()
.map(subject => `<option value="${subject}">${subject}</option>`)
.join('')}
.map(
(subject) =>
`<option value="${subject}">${subject}</option>`,
)
.join("")}
</select>
</div>
<div class="filter-group">
<label>
<!--<span class="material-icons-round">person</span>-->
${LanguageManager.t('homework.teacher')}
${LanguageManager.t("homework.teacher")}
</label>
<select id="teacherFilter">
<option value="">${LanguageManager.t('homework.all_teachers')}</option>
${[...new Set(homeworkItems.map(item => item.teacher))]
<option value="">${LanguageManager.t("homework.all_teachers")}</option>
${[...new Set(homeworkItems.map((item) => item.teacher))]
.sort()
.map(teacher => `<option value="${teacher}">${teacher}</option>`)
.join('')}
.map(
(teacher) =>
`<option value="${teacher}">${teacher}</option>`,
)
.join("")}
</select>
</div>
<div class="filter-group">
<label>
<!--<span class="material-icons-round">date_range</span>-->
${LanguageManager.t('homework.due_date')}
${LanguageManager.t("homework.due_date")}
</label>
<select id="deadlineFilter">
<option value="">${LanguageManager.t('homework.all_deadlines')}</option>
<option value="tomorrow">${LanguageManager.t('homework.tomorrow_deadline')}</option>
<option value="thisWeek">${LanguageManager.t('homework.this_week')}</option>
<option value="nextWeek">${LanguageManager.t('homework.next_week')}</option>
<option value="">${LanguageManager.t("homework.all_deadlines")}</option>
<option value="tomorrow">${LanguageManager.t("homework.tomorrow_deadline")}</option>
<option value="thisWeek">${LanguageManager.t("homework.this_week")}</option>
<option value="nextWeek">${LanguageManager.t("homework.next_week")}</option>
</select>
</div>
</div>
</div>
<div class="homework-list" id="homeworkList">
${renderHomeworkList(groupedHomework)}
<div class="stats-overview" id="statsOverview">
<div class="stat-card">
<div class="stat-number" id="totalHomework">0</div>
<div class="stat-label">${LanguageManager.t("homework.total_homework")}</div>
</div>
<div class="stat-card urgent">
<div class="stat-number" id="urgentHomework">0</div>
<div class="stat-label">${LanguageManager.t("homework.urgent_homework")}</div>
</div>
<div class="stat-card completed">
<div class="stat-number" id="completedHomework">0</div>
<div class="stat-label">${LanguageManager.t("homework.completed_homework")}</div>
</div>
<div class="stat-card">
<div class="stat-number" id="pendingHomework">0</div>
<div class="stat-label">${LanguageManager.t("homework.pending_homework")}</div>
</div>
</div>
<div class="homework-container">
<table class="homework-table" id="homeworkTable">
<thead class="table-header">
<tr>
<th>${LanguageManager.t("homework.due_date")}</th>
<th>${LanguageManager.t("homework.subject")}</th>
<th>${LanguageManager.t("homework.description")}</th>
<th>${LanguageManager.t("homework.teacher")}</th>
<th>${LanguageManager.t("homework.status")}</th>
</tr>
</thead>
<tbody id="homeworkTableBody">
${generateHomeworkHTML(homeworkItems)}
</tbody>
</table>
</div>
</main>
</div>
@@ -182,253 +219,312 @@ async function transformHomeworkPage() {
setupFilters(homeworkItems, groupedHomework);
setupUserDropdown();
setupMobileNavigation();
setupMobileGrouping();
updateStatistics();
loadingScreen.hide();
}
function renderHomeworkList(groupedHomework) {
const sortedDates = Object.keys(groupedHomework).sort((a, b) => {
const partsA = a.split('.');
const partsB = b.split('.');
const monthA = parseInt(partsA[0]) - 1;
const dayA = parseInt(partsA[1]);
const monthB = parseInt(partsB[0]) - 1;
const dayB = parseInt(partsB[1]);
const currentYear = new Date().getFullYear();
const currentMonth = new Date().getMonth();
const yearA = monthA < currentMonth ? currentYear + 1 : currentYear;
const yearB = monthB < currentMonth ? currentYear + 1 : currentYear;
const dateA = new Date(yearA, monthA, dayA);
const dateB = new Date(yearB, monthB, dayB);
return dateB - dateA;
function generateHomeworkHTML(homeworkItems) {
const sortedHomework = homeworkItems.sort((a, b) => {
const dateA = new Date(
a.deadline.split(" ")[0].split(".").reverse().join("-"),
);
const dateB = new Date(
b.deadline.split(" ")[0].split(".").reverse().join("-"),
);
return dateA - dateB;
});
if (sortedDates.length === 0) {
return `
<div class="empty-state">
<p>${LanguageManager.t('homework.no_homework')}</p>
</div>
`;
}
return sortedHomework
.map((homework) => {
const isUrgent = isTomorrow(homework.deadline);
const status = homework.completed
? "completed"
: isUrgent
? "urgent"
: "pending";
const statusText = homework.completed
? LanguageManager.t("homework.completed")
: isUrgent
? LanguageManager.t("homework.urgent")
: LanguageManager.t("homework.pending");
return sortedDates.map(date => {
const homeworkItems = groupedHomework[date];
return `
<div class="homework-date-group" data-date="${date}">
<div class="date-header">
<h3>${formatDateHeader(date)}</h3>
<span class="homework-count">${homeworkItems.length} ${LanguageManager.t('homework.items') || 'feladat'}</span>
</div>
<div class="homework-list-items">
${homeworkItems.map(homework => {
const isTomorrowClass = isTomorrow(homework.deadline) ? 'due-tomorrow' : '';
const urgentClass = isTomorrow(homework.deadline) ? 'urgent' : '';
return `
<div class="homework-item ${isTomorrowClass}" data-subject="${homework.subject}" data-teacher="${homework.teacher}">
<div class="homework-details">
<div class="homework-subject">${homework.subject}</div>
<div class="homework-content">${homework.description}</div>
<div class="homework-teacher">${homework.teacher}</div>
</div>
</div>
`;
}).join('')}
</div>
</div>
return `
<tr class="table-row ${isUrgent ? "due-tomorrow" : ""}"
data-subject="${homework.subject}"
data-teacher="${homework.teacher}"
data-deadline="${homework.deadline}">
<td class="table-cell date-cell" data-label="${LanguageManager.t("homework.due_date")}:">${homework.deadline}</td>
<td class="table-cell subject-cell" data-label="${LanguageManager.t("homework.subject")}:">${homework.subject}</td>
<td class="table-cell description-cell" data-label="${LanguageManager.t("homework.description")}:">${homework.description}</td>
<td class="table-cell teacher-cell" data-label="${LanguageManager.t("homework.teacher")}:">${homework.teacher}</td>
<td class="table-cell status-cell" data-label="${LanguageManager.t("homework.status")}:">
<span class="status-badge ${status}">${statusText}</span>
</td>
</tr>
`;
}).join('');
})
.join("");
}
function formatDateHeader(dateStr) {
if (!dateStr) return '';
if (!dateStr) return "";
const today = new Date();
today.setHours(0, 0, 0, 0);
const tomorrow = new Date(today);
tomorrow.setDate(tomorrow.getDate() + 1);
const parts = dateStr.split('.');
const parts = dateStr.split(".");
if (parts.length < 2) return dateStr;
const month = parseInt(parts[0].trim()) - 1;
const day = parseInt(parts[1].trim());
const currentYear = today.getFullYear();
const date = new Date(currentYear, month, day);
if (date.toDateString() === today.toDateString()) {
return LanguageManager.t('common.today') + ' - ' + dateStr;
return LanguageManager.t("common.today") + " - " + dateStr;
} else if (date.toDateString() === tomorrow.toDateString()) {
return LanguageManager.t('common.tomorrow') + ' - ' + dateStr;
return LanguageManager.t("common.tomorrow") + " - " + dateStr;
}
const weekdays = [
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')
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"),
];
return `${weekdays[date.getDay()]} - ${dateStr}`;
}
function formatDate(dateStr) {
if (!dateStr) return '';
if (!dateStr) return "";
return dateStr;
}
function setupFilters(homeworkItems, groupedHomework) {
const subjectFilter = document.getElementById('subjectFilter');
const teacherFilter = document.getElementById('teacherFilter');
const deadlineFilter = document.getElementById('deadlineFilter');
const applyFilterBtn = document.getElementById('applyFilterBtn');
const resetFilterBtn = document.getElementById('resetFilterBtn');
const subjectFilter = document.getElementById("subjectFilter");
const teacherFilter = document.getElementById("teacherFilter");
const deadlineFilter = document.getElementById("deadlineFilter");
const applyFilters = () => {
const selectedSubject = subjectFilter.value;
const selectedTeacher = teacherFilter.value;
const selectedDeadline = deadlineFilter.value;
const homeworkElements = document.querySelectorAll('.homework-item');
const dateGroups = document.querySelectorAll('.homework-date-group');
dateGroups.forEach(group => {
group.style.display = 'none';
});
homeworkElements.forEach(item => {
const subject = item.getAttribute('data-subject');
const teacher = item.getAttribute('data-teacher');
const dateGroup = item.closest('.homework-date-group');
const dateStr = dateGroup.getAttribute('data-date');
let showItem = true;
const tableRows = document.querySelectorAll(".table-row");
tableRows.forEach((row) => {
const subject = row.getAttribute("data-subject");
const teacher = row.getAttribute("data-teacher");
const deadline = row.getAttribute("data-deadline");
let showRow = true;
if (selectedSubject && subject !== selectedSubject) {
showItem = false;
showRow = false;
}
if (selectedTeacher && teacher !== selectedTeacher) {
showItem = false;
showRow = false;
}
if (selectedDeadline) {
const parts = dateStr.split('.');
if (parts.length >= 3) {
const year = parseInt(parts[0].trim());
const month = parseInt(parts[1].trim()) - 1;
const day = parseInt(parts[2].trim());
const date = new Date(year, month, day);
const parts = deadline.split(" ")[0].split(".");
if (parts.length >= 2) {
const month = parseInt(parts[0].trim()) - 1;
const day = parseInt(parts[1].trim());
const currentYear = new Date().getFullYear();
const date = new Date(currentYear, month, day);
const today = new Date();
today.setHours(0, 0, 0, 0);
const tomorrow = new Date(today);
tomorrow.setDate(tomorrow.getDate() + 1);
const startOfWeek = new Date(today);
const dayOfWeek = today.getDay() || 7;
startOfWeek.setDate(today.getDate() - dayOfWeek + 1);
const endOfWeek = new Date(startOfWeek);
endOfWeek.setDate(startOfWeek.getDate() + 6);
const startOfNextWeek = new Date(endOfWeek);
startOfNextWeek.setDate(endOfWeek.getDate() + 1);
const endOfNextWeek = new Date(startOfNextWeek);
endOfNextWeek.setDate(startOfNextWeek.getDate() + 6);
if (selectedDeadline === 'tomorrow' && date.toDateString() !== tomorrow.toDateString()) {
showItem = false;
} else if (selectedDeadline === 'thisWeek' && (date < startOfWeek || date > endOfWeek)) {
showItem = false;
} else if (selectedDeadline === 'nextWeek' && (date < startOfNextWeek || date > endOfNextWeek)) {
showItem = false;
if (
selectedDeadline === "tomorrow" &&
date.toDateString() !== tomorrow.toDateString()
) {
showRow = false;
} else if (
selectedDeadline === "thisWeek" &&
(date < startOfWeek || date > endOfWeek)
) {
showRow = false;
} else if (
selectedDeadline === "nextWeek" &&
(date < startOfNextWeek || date > endOfNextWeek)
) {
showRow = false;
}
}
}
item.style.display = showItem ? 'block' : 'none';
if (showItem) {
dateGroup.style.display = 'block';
}
row.style.display = showRow ? "" : "none";
});
const visibleItems = document.querySelectorAll('.homework-item[style="display: block"]');
const homeworkList = document.getElementById('homeworkList');
let emptyState = homeworkList.querySelector('.empty-state');
if (!emptyState) {
emptyState = document.createElement('div');
emptyState.className = 'empty-state';
emptyState.innerHTML = `<p>${LanguageManager.t('homework.no_matching_homework')}</p>`;
homeworkList.appendChild(emptyState);
}
if (visibleItems.length === 0) {
emptyState.style.display = 'block';
} else {
emptyState.style.display = 'none';
}
updateDateGroupsVisibility();
updateStatistics();
};
const resetFilters = () => {
subjectFilter.value = '';
teacherFilter.value = '';
deadlineFilter.value = '';
document.querySelectorAll('.homework-item').forEach(item => {
item.style.display = 'block';
subjectFilter.value = "";
teacherFilter.value = "";
deadlineFilter.value = "";
document.querySelectorAll(".table-row").forEach((row) => {
row.style.display = "";
});
document.querySelectorAll('.homework-date-group').forEach(group => {
group.style.display = 'block';
});
const homeworkList = document.getElementById('homeworkList');
const existingEmptyState = homeworkList.querySelector('.empty-state');
if (existingEmptyState) {
homeworkList.removeChild(existingEmptyState);
}
updateDateGroupsVisibility();
updateStatistics();
};
subjectFilter.addEventListener('change', applyFilters);
teacherFilter.addEventListener('change', applyFilters);
deadlineFilter.addEventListener('change', applyFilters);
subjectFilter.addEventListener("change", applyFilters);
teacherFilter.addEventListener("change", applyFilters);
deadlineFilter.addEventListener("change", applyFilters);
}
function updateStatistics() {
const visibleRows = document.querySelectorAll(
'.table-row:not([style*="display: none"])',
);
let totalCount = 0;
let urgentCount = 0;
let completedCount = 0;
let pendingCount = 0;
if (window.location.href.includes('/Tanulo/TanuloHaziFeladat')) {
transformHomeworkPage().catch(error => {
console.error('Error transforming homework page:', error);
visibleRows.forEach((row) => {
totalCount++;
if (row.classList.contains("due-tomorrow")) {
urgentCount++;
}
const statusBadge = row.querySelector(".status-badge");
if (statusBadge) {
if (statusBadge.classList.contains("completed")) {
completedCount++;
} else if (statusBadge.classList.contains("pending")) {
pendingCount++;
}
}
});
}
document.getElementById("totalHomework").textContent = totalCount;
document.getElementById("urgentHomework").textContent = urgentCount;
document.getElementById("completedHomework").textContent = completedCount;
document.getElementById("pendingHomework").textContent = pendingCount;
}
function setupMobileGrouping() {
function handleResize() {
if (window.innerWidth <= 480) {
createMobileGroups();
} else {
removeMobileGroups();
}
}
window.addEventListener("resize", handleResize);
handleResize();
}
function createMobileGroups() {
const tableBody = document.getElementById("homeworkTableBody");
const rows = Array.from(tableBody.querySelectorAll(".table-row"));
if (rows.length === 0) return;
const groupedByDate = {};
rows.forEach((row) => {
const deadline = row.getAttribute("data-deadline");
const dateKey = deadline.split(" ")[0];
if (!groupedByDate[dateKey]) {
groupedByDate[dateKey] = [];
}
groupedByDate[dateKey].push(row);
});
tableBody.innerHTML = "";
Object.keys(groupedByDate)
.sort()
.forEach((date) => {
const dateGroup = document.createElement("div");
dateGroup.className = "date-group";
dateGroup.setAttribute("data-date", date);
const header = document.createElement("div");
header.className = "date-group-header";
header.textContent = formatDateHeader(date);
const content = document.createElement("div");
content.className = "date-group-content";
groupedByDate[date].forEach((row) => {
content.appendChild(row);
});
dateGroup.appendChild(header);
dateGroup.appendChild(content);
tableBody.appendChild(dateGroup);
});
}
function removeMobileGroups() {
const tableBody = document.getElementById("homeworkTableBody");
const dateGroups = tableBody.querySelectorAll(".date-group");
if (dateGroups.length === 0) return;
const allRows = [];
dateGroups.forEach((group) => {
const rows = group.querySelectorAll(".table-row");
rows.forEach((row) => allRows.push(row));
});
tableBody.innerHTML = "";
allRows.forEach((row) => tableBody.appendChild(row));
}
function updateDateGroupsVisibility() {
const dateGroups = document.querySelectorAll(".date-group");
dateGroups.forEach((group) => {
const visibleRows = group.querySelectorAll(
'.table-row:not([style*="display: none"])',
);
group.style.display = visibleRows.length > 0 ? "block" : "none";
});
}
if (window.location.href.includes("/Tanulo/TanuloHaziFeladat")) {
transformHomeworkPage().catch((error) => {
console.error("Error transforming homework page:", error);
});
}

View File

@@ -115,7 +115,8 @@
"wednesday": "Wednesday",
"thursday": "Thursday",
"friday": "Friday",
"found_current_week": "Found current week"
"found_current_week": "Found current week",
"open_homework": "Open homework"
},
"homework": {
"title": "Homework",
@@ -133,7 +134,15 @@
"no_filtered_homework": "No homework matching the filter criteria.",
"teacher": "Teacher",
"no_matching_homework": "No homework matching the filter criteria.",
"items": "items"
"items": "items",
"status": "Status",
"total_homework": "Total homework",
"urgent_homework": "Urgent homework",
"completed_homework": "Completed homework",
"pending_homework": "Pending homework",
"completed": "Completed",
"urgent": "Urgent",
"pending": "Pending"
},
"absences": {
"title": "Absences",

View File

@@ -115,25 +115,34 @@
"wednesday": "Szerda",
"thursday": "Csütörtök",
"friday": "Péntek",
"found_current_week": "Megtalált jelenlegi hét"
"found_current_week": "Megtalált jelenlegi hét",
"open_homework": "Ugrás a házi feladatokhoz"
},
"homework": {
"title": "Házi feladatok",
"due_date": "Határidő",
"subject": "Tantárgy",
"description": "Leírás",
"filter_title": "Szűrés",
"all_subjects": "Összes tantárgy",
"all_teachers": "Összes tanár",
"all_deadlines": "Összes határidő",
"filter_title": "Szűrő",
"all_subjects": "Minden tantárgy",
"all_teachers": "Minden tanár",
"all_deadlines": "Minden határidő",
"tomorrow_deadline": "Holnapi határidő",
"this_week": "Ezen a héten",
"next_week": "Jövő héten",
"next_week": "Következő héten",
"no_homework": "Nincs megjeleníthető házi feladat.",
"no_filtered_homework": "Nincs a szűrési feltételeknek megfelelő házi feladat.",
"teacher": "Tanár",
"no_matching_homework": "Nincs a szűrési feltételeknek megfelelő házi feladat.",
"items": "feladat"
"items": "elem",
"status": "Állapot",
"total_homework": "Összes feladat",
"urgent_homework": "Sürgős feladat",
"completed_homework": "Befejezett feladat",
"pending_homework": "Függőben lévő feladat",
"completed": "Befejezve",
"urgent": "Sürgős",
"pending": "Függőben"
},
"absences": {
"title": "Hiányzások",

View File

@@ -1,360 +1,313 @@
:root {
--icon-invert: 0.1;
--icon-sepia: 0.1;
--icon-saturate: 0.1;
--icon-hue-rotate: 0deg;
--icon-brightness: 0.1;
--icon-invert:0.1;
--icon-sepia:0.1;
--icon-saturate:0.1;
--icon-hue-rotate:0deg;
--icon-brightness:0.1;
}
:root[data-theme="light-green"] {
--icon-invert: 0.1;
--icon-sepia: 0.1;
--icon-saturate: 0.1;
--icon-hue-rotate: 0deg;
--icon-brightness: 0.1;
--icon-invert:0.1;
--icon-sepia:0.1;
--icon-saturate:0.1;
--icon-hue-rotate:0deg;
--icon-brightness:0.1;
}
:root[data-theme="dark-blue"] {
--icon-invert: 0.9;
--icon-sepia: 0.1;
--icon-saturate: 0.1;
--icon-hue-rotate: 0deg;
--icon-brightness: 1;
--icon-invert:0.9;
--icon-sepia:0.1;
--icon-saturate:0.1;
--icon-hue-rotate:0deg;
--icon-brightness:1;
}
:root[data-theme="dark-green"] {
--icon-invert: 0.9;
--icon-sepia: 0.1;
--icon-saturate: 0.1;
--icon-hue-rotate: 0deg;
--icon-brightness: 1;
--icon-invert:0.9;
--icon-sepia:0.1;
--icon-saturate:0.1;
--icon-hue-rotate:0deg;
--icon-brightness:1;
}
* {
box-sizing: border-box;
margin: 0;
padding: 0;
box-sizing:border-box;
margin:0;
padding:0;
}
body {
margin: 0;
padding: 0;
color: var(--text-primary);
background-color: var(--background) !important;
font-family: "Montserrat", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif !important;
min-height: 100vh;
font-size: 16px;
display: flex;
align-items: center;
justify-content: center;
margin:0;
padding:0;
color:var(--text-primary);
background-color:var(--background) !important;
font-family:"Montserrat",-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,sans-serif !important;
min-height:100vh;
font-size:16px;
display:flex;
align-items:center;
justify-content:center;
}
.login-container {
width: 90%;
max-width: 500px;
padding: 20px;
margin: 0 auto;
width:90%;
max-width:500px;
padding:20px;
margin:0 auto;
}
.login-card {
background: var(--card-card);
padding: 24px;
margin-bottom: 16px;
border-radius: 24px;
box-shadow: 0px 1px var(--shadow-blur) 0px var(--accent-shadow);
background:var(--card-card);
padding:24px;
margin-bottom:16px;
border-radius:24px;
box-shadow:0px 1px var(--shadow-blur) 0px var(--accent-shadow);
}
.card-header {
display: flex;
flex-direction: column;
align-items: center;
gap: 8px;
margin: 16px 0;
background: var(--card-card) !important;
border-bottom: 1px solid rgba(0, 0, 0, 0) !important;
display:flex;
flex-direction:column;
align-items:center;
gap:8px;
margin:16px 0;
background:var(--card-card) !important;
border-bottom:1px solid rgba(0,0,0,0) !important;
}
.logo-text {
color: var(--text-primary);
text-align: center;
font-family: Montserrat;
font-size: 20px;
font-style: normal;
font-weight: 700;
line-height: normal;
color:var(--text-primary);
text-align:center;
font-family:Montserrat;
font-size:20px;
font-style:normal;
font-weight:700;
line-height:normal;
}
.logo {
width: 48px;
height: 48px;
border-radius: 12px;
width:48px;
height:48px;
border-radius:12px;
}
.school-name {
color: var(--text-secondary);
text-align: center;
font-family: Figtree;
font-size: 16px;
font-style: normal;
font-weight: 500;
line-height: 130%;
color:var(--text-secondary);
text-align:center;
font-family:Figtree;
font-size:16px;
font-style:normal;
font-weight:500;
line-height:130%;
}
.school-details {
color: var(--text-secondary);
text-align: center;
font-family: Figtree;
font-size: 16px;
font-style: normal;
font-weight: 500;
line-height: 130%;
color:var(--text-secondary);
text-align:center;
font-family:Figtree;
font-size:16px;
font-style:normal;
font-weight:500;
line-height:130%;
}
.login-form {
width: 100%;
width:100%;
}
.form-group {
margin-bottom: 16px;
margin-bottom:16px;
}
.form-control {
display: flex;
height: 48px;
padding: 0px 14px;
align-items: center;
gap: 10px;
align-self: stretch;
border-radius: 12px;
background: var(--accent-15) !important;
border: 0px solid var(--accent-15) !important;
color: var(--text-primary) !important;
display:flex;
height:48px;
padding:0px 14px;
align-items:center;
gap:10px;
align-self:stretch;
border-radius:12px;
background:var(--accent-15) !important;
border:0px solid var(--accent-15) !important;
color:var(--text-primary) !important;
}
.form-control:focus {
outline: none;
border-color: var(--accent-accent) !important;
outline:none;
border-color:var(--accent-accent) !important;
}
.form-control::placeholder {
color: var(--text-secondary) !important;
color:var(--text-secondary) !important;
}
.password-group {
position: relative;
position:relative;
}
.show-password {
position: absolute;
right: 12px;
top: 50%;
transform: translateY(-50%);
background: none;
border: none;
padding: 4px;
cursor: pointer;
display: flex;
align-items: center;
justify-content: center;
position:absolute;
right:12px;
top:50%;
transform:translateY(-50%);
background:none;
border:none;
padding:4px;
cursor:pointer;
display:flex;
align-items:center;
justify-content:center;
}
.icon-eye {
width: 20px;
height: 20px;
opacity: 0.6;
transition: opacity 0.2s ease;
filter: invert(var(--icon-invert)) sepia(var(--icon-sepia)) saturate(var(--icon-saturate)) hue-rotate(var(--icon-hue-rotate)) brightness(var(--icon-brightness));
width:20px;
height:20px;
opacity:0.6;
transition:opacity 0.2s ease;
filter:invert(var(--icon-invert)) sepia(var(--icon-sepia)) saturate(var(--icon-saturate)) hue-rotate(var(--icon-hue-rotate)) brightness(var(--icon-brightness));
}
.show-password:hover .icon-eye {
opacity: 1;
opacity:1;
}
.form-actions {
margin-top: 24px;
margin-top:24px;
}
.help-links {
margin-top: 16px;
display: flex;
flex-direction: column;
align-items: center;
gap: 8px;
margin-top:16px;
display:flex;
flex-direction:column;
align-items:center;
gap:8px;
}
.help-link {
color: var(--text-primary);
font-size: 14px;
font-weight: 500;
text-decoration: none;
transition: color 0.2s ease;
color:var(--text-primary);
font-size:14px;
font-weight:500;
text-decoration:none;
transition:color 0.2s ease;
}
.help-link:hover {
color: var(--text-teritary);
color:var(--text-teritary);
}
.btn-login {
width: 100%;
padding: 12px;
background: var(--accent-accent);
color: white;
border: none;
border-radius: 12px;
font-size: 16px;
font-weight: 600;
font-family: "Montserrat", serif;
cursor: pointer;
transition: background 0.2s ease;
position: relative;
width:100%;
padding:12px;
background:var(--accent-accent);
color:white;
border:none;
border-radius:12px;
font-size:16px;
font-weight:600;
font-family:"Montserrat",serif;
cursor:pointer;
transition:background 0.2s ease;
position:relative;
}
.btn-login:hover {
background: var(--text-teritary);
background:var(--text-teritary);
}
.btn-login:disabled {
opacity: 0.7;
cursor: not-allowed;
opacity:0.7;
cursor:not-allowed;
}
.btn-text {
color: var(--text-primary);
text-align: center;
font-family: Montserrat;
font-size: 18px;
font-style: normal;
font-weight: 700;
line-height: normal;
letter-spacing: -0.3px;
color:var(--text-primary);
text-align:center;
font-family:Montserrat;
font-size:18px;
font-style:normal;
font-weight:700;
line-height:normal;
letter-spacing:-0.3px;
}
.system-message {
display: flex;
padding: 20px;
flex-direction: column;
align-items: center;
gap: 12px;
align-self: stretch;
border-radius: 24px;
background: var(--card-card);
box-shadow: 0px 1px var(--shadow-blur) 0px var(--accent-shadow);
display:flex;
padding:20px;
flex-direction:column;
align-items:center;
gap:12px;
align-self:stretch;
border-radius:24px;
background:var(--card-card);
box-shadow:0px 1px var(--shadow-blur) 0px var(--accent-shadow);
}
.system-message h4 {
color: var(--text-primary);
text-align: center;
font-family: Montserrat;
font-size: 20px;
font-style: normal;
font-weight: 700;
line-height: normal;
color:var(--text-primary);
text-align:center;
font-family:Montserrat;
font-size:20px;
font-style:normal;
font-weight:700;
line-height:normal;
}
.system-message p {
color: var(--text-secondary);
text-align: center;
font-family: Figtree;
font-size: 16px;
font-style: normal;
font-weight: 500;
line-height: 130%;
color:var(--text-secondary);
text-align:center;
font-family:Figtree;
font-size:16px;
font-style:normal;
font-weight:500;
line-height:130%;
}
.login-footer {
align-self: stretch;
color: var(--text-secondary);
text-align: center;
font-family: Figtree;
font-size: 14px;
font-style: normal;
font-weight: 500;
line-height: 130%;
align-self:stretch;
color:var(--text-secondary);
text-align:center;
font-family:Figtree;
font-size:14px;
font-style:normal;
font-weight:500;
line-height:130%;
}
.privacy-link {
align-self: stretch;
color: var(--text-secondary);
text-align: center;
font-family: Figtree;
font-size: 14px;
font-style: normal;
font-weight: 500;
line-height: 130%;
text-decoration: none;
align-self:stretch;
color:var(--text-secondary);
text-align:center;
font-family:Figtree;
font-size:14px;
font-style:normal;
font-weight:500;
line-height:130%;
text-decoration:none;
}
.privacy-link:hover {
color: var(--text-teritary);
color:var(--text-teritary);
}
.form-control.error {
border-color: var(--error-accent) !important;
background: var(--error-card) !important;
border-color:var(--error-accent) !important;
background:var(--error-card) !important;
}
.error-message {
color: var(--error-text);
font-size: 14px;
margin-top: 4px;
display: none;
color:var(--error-text);
font-size:14px;
margin-top:4px;
display:none;
}
.error-message.show {
display: block;
animation: fadeIn 0.2s ease;
display:block;
animation:fadeIn 0.2s ease;
}
@keyframes fadeIn {
from { opacity: 0; transform: translateY(-4px); }
to { opacity: 1; transform: translateY(0); }
from {
opacity:0;
transform:translateY(-4px);
}
@keyframes spin {
to { transform: translate(-50%, -50%) rotate(360deg); }
to {
opacity:1;
transform:translateY(0);
}
@media (max-width: 480px) {
}@keyframes spin {
to {
transform:translate(-50%,-50%) rotate(360deg);
}
}@media (max-width:480px) {
.login-container {
padding: 16px;
}
.login-card {
padding: 20px;
}
.card-header {
margin-bottom: 20px;
padding-bottom: 16px;
}
.logo-text {
font-size: 20px;
}
.school-name {
font-size: 16px;
}
.school-details {
font-size: 12px;
}
.form-control {
height: 44px;
font-size: 14px;
}
.btn-login {
padding: 10px;
font-size: 14px;
}
.help-link {
font-size: 12px;
}
padding:16px;
}
.login-card {
padding:20px;
}
.card-header {
margin-bottom:20px;
padding-bottom:16px;
}
.logo-text {
font-size:20px;
}
.school-name {
font-size:16px;
}
.school-details {
font-size:12px;
}
.form-control {
height:44px;
font-size:14px;
}
.btn-login {
padding:10px;
font-size:14px;
}
.help-link {
font-size:12px;
}
}

View File

@@ -1,50 +1,59 @@
async function transformLoginPage() {
try {
if (document.readyState !== 'complete') {
await new Promise(resolve => {
window.addEventListener('load', resolve);
if (document.readyState !== "complete") {
await new Promise((resolve) => {
window.addEventListener("load", resolve);
});
}
const existingForm = document.querySelector('form');
const existingForm = document.querySelector("form");
const formData = {
action: existingForm?.getAttribute('action') || '',
returnUrl: document.querySelector('#ReturnUrl')?.value || '',
instituteCode: document.querySelector('#instituteCode')?.value || '',
requestToken: document.querySelector('input[name="__RequestVerificationToken"]')?.value || '',
userName: document.querySelector('#UserName')?.value || '',
password: document.querySelector('#Password')?.value || ''
action: existingForm?.getAttribute("action") || "",
returnUrl: document.querySelector("#ReturnUrl")?.value || "",
instituteCode: document.querySelector("#instituteCode")?.value || "",
requestToken:
document.querySelector('input[name="__RequestVerificationToken"]')
?.value || "",
userName: document.querySelector("#UserName")?.value || "",
password: document.querySelector("#Password")?.value || "",
};
const titleElement = document.querySelector('.page-title');
const titleElement = document.querySelector(".page-title");
const schoolInfo = {
name: titleElement?.querySelector('b')?.textContent?.trim() || '',
kretaId: '',
omCode: ''
name: titleElement?.querySelector("b")?.textContent?.trim() || "",
kretaId: "",
omCode: "",
};
const spanElement = titleElement?.querySelector('span');
const spanElement = titleElement?.querySelector("span");
if (spanElement) {
const lines = spanElement.textContent?.split('\n').map(line => line.trim()) || [];
schoolInfo.kretaId = lines[0] || '';
schoolInfo.omCode = (lines[1] || '').replace(`${LanguageManager.t('login.kreta_id')}: `, '');
const lines =
spanElement.textContent?.split("\n").map((line) => line.trim()) || [];
schoolInfo.kretaId = lines[0] || "";
schoolInfo.omCode = (lines[1] || "").replace(
`${LanguageManager.t("login.kreta_id")}: `,
"",
);
}
const rawSystemMessage = document.querySelector('.alert-primary')?.textContent?.trim() || '';
const systemMessage = rawSystemMessage.replace('Rendszerértesítés', '').trim();
const rawSystemMessage =
document.querySelector(".alert-primary")?.textContent?.trim() || "";
const systemMessage = rawSystemMessage
.replace("Rendszerértesítés", "")
.trim();
const newHTML = `
<div class="login-container">
<div class="login-card">
<div class="card-header">
<p class="logo-text">
<img src=${chrome.runtime.getURL('images/firka_logo.png')} alt="Firka" class="logo">
<img src=${chrome.runtime.getURL("images/firka_logo.png")} alt="Firka" class="logo">
Firka
</p>
<h1 class="school-name">${schoolInfo.name}</h1>
<div class="school-details">
${schoolInfo.kretaId ? `<div>${schoolInfo.kretaId}</div>` : ''}
${schoolInfo.omCode ? `<div>${LanguageManager.t('login.kreta_id')}: ${schoolInfo.omCode}</div>` : ''}
${schoolInfo.kretaId ? `<div>${schoolInfo.kretaId}</div>` : ""}
${schoolInfo.omCode ? `<div>${LanguageManager.t("login.kreta_id")}: ${schoolInfo.omCode}</div>` : ""}
</div>
</div>
@@ -57,133 +66,131 @@ async function transformLoginPage() {
<div class="form-group">
<input class="form-control" type="text" id="UserName" name="UserName"
placeholder="${LanguageManager.t('login.username_placeholder')}" maxlength="256" autocomplete="username" required value="${formData.userName}">
<div class="error-message">${LanguageManager.t('login.username_required')}</div>
placeholder="${LanguageManager.t("login.username_placeholder")}" maxlength="256" autocomplete="username" required value="${formData.userName}">
<div class="error-message">${LanguageManager.t("login.username_required")}</div>
</div>
<div class="form-group password-group">
<input class="form-control" type="password" id="Password" name="Password"
placeholder="${LanguageManager.t('login.password_placeholder')}" maxlength="256" autocomplete="current-password" required value="${formData.password}">
<button type="button" class="show-password" aria-label="${LanguageManager.t('login.show_password')}">
<img src="${chrome.runtime.getURL('icons/eye-off.svg')}" alt="Show password" class="icon-eye">
placeholder="${LanguageManager.t("login.password_placeholder")}" maxlength="256" autocomplete="current-password" required value="${formData.password}">
<button type="button" class="show-password" aria-label="${LanguageManager.t("login.show_password")}">
<img src="${chrome.runtime.getURL("icons/eye-off.svg")}" alt="Show password" class="icon-eye">
</button>
<div class="error-message">${LanguageManager.t('login.password_required')}</div>
<div class="error-message">${LanguageManager.t("login.password_required")}</div>
</div>
<div class="form-actions">
<button type="submit" class="btn-login">
<span class="spinner"></span>
<span class="btn-text">${LanguageManager.t('login.login_button')}</span>
<span class="btn-text">${LanguageManager.t("login.login_button")}</span>
</button>
<div class="help-links">
<a href="https://${schoolInfo.omCode ? `${schoolInfo.omCode}` : ''}.e-kreta.hu/Adminisztracio/ElfelejtettJelszo" class="help-link">${LanguageManager.t('login.forgot_password')}</a>
<a href="https://tudasbazis.ekreta.hu/pages/viewpage.action?pageId=2425086" target="_blank" class="help-link">${LanguageManager.t('login.help_link')}</a>
<a href="https://${schoolInfo.omCode ? `${schoolInfo.omCode}` : ""}.e-kreta.hu/Adminisztracio/ElfelejtettJelszo" class="help-link">${LanguageManager.t("login.forgot_password")}</a>
<a href="https://tudasbazis.ekreta.hu/pages/viewpage.action?pageId=2425086" target="_blank" class="help-link">${LanguageManager.t("login.help_link")}</a>
</div>
</div>
</form>
</div>
${systemMessage ? `
${
systemMessage
? `
<div class="system-message">
<h4>${LanguageManager.t('login.system_message')}</h4>
<h4>${LanguageManager.t("login.system_message")}</h4>
<p>${systemMessage}</p>
</div>
` : ''}
`
: ""
}
<footer class="login-footer">
<a href="https://tudasbazis.ekreta.hu/pages/viewpage.action?pageId=4064926"
target="_blank" class="privacy-link">${LanguageManager.t('login.privacy_policy')}</a>
target="_blank" class="privacy-link">${LanguageManager.t("login.privacy_policy")}</a>
</footer>
</div>
`;
document.body.innerHTML = newHTML;
setupEventListeners();
document.body.innerHTML = newHTML;
setupEventListeners();
} catch (error) {
console.error('Error transforming page:', error);
console.error("Error transforming page:", error);
}
}
function setupEventListeners() {
const loginForm = document.getElementById('loginForm');
const passwordInput = document.getElementById('Password');
const togglePasswordBtn = document.querySelector('.show-password');
const formInputs = document.querySelectorAll('.form-control');
if (togglePasswordBtn && passwordInput) {
togglePasswordBtn.addEventListener('click', () => {
const isPassword = passwordInput.type === 'password';
passwordInput.type = isPassword ? 'text' : 'password';
const icon = togglePasswordBtn.querySelector('.icon-eye');
icon.src = chrome.runtime.getURL(`icons/${isPassword ? 'eye-on' : 'eye-off'}.svg`);
});
}
const loginForm = document.getElementById("loginForm");
const passwordInput = document.getElementById("Password");
const togglePasswordBtn = document.querySelector(".show-password");
const formInputs = document.querySelectorAll(".form-control");
formInputs.forEach(input => {
input.addEventListener('input', () => {
if (togglePasswordBtn && passwordInput) {
togglePasswordBtn.addEventListener("click", () => {
const isPassword = passwordInput.type === "password";
passwordInput.type = isPassword ? "text" : "password";
const icon = togglePasswordBtn.querySelector(".icon-eye");
icon.src = chrome.runtime.getURL(
`icons/${isPassword ? "eye-on" : "eye-off"}.svg`,
);
});
}
formInputs.forEach((input) => {
input.addEventListener("input", () => {
validateInput(input);
});
input.addEventListener('blur', () => {
input.addEventListener("blur", () => {
validateInput(input, true);
});
});
if (loginForm) {
loginForm.addEventListener('submit', handleSubmit);
loginForm.addEventListener("submit", handleSubmit);
}
}
function validateInput(input, showError = false) {
const isValid = input.value.trim().length > 0;
const errorElement = input.nextElementSibling;
if (!isValid && showError) {
input.classList.add('error');
errorElement?.classList.add('show');
input.classList.add("error");
errorElement?.classList.add("show");
} else {
input.classList.remove('error');
errorElement?.classList.remove('show');
input.classList.remove("error");
errorElement?.classList.remove("show");
}
return isValid;
}
function handleSubmit(event) {
event.preventDefault();
const form = event.target;
const inputs = form.querySelectorAll('.form-control[required]');
const inputs = form.querySelectorAll(".form-control[required]");
let isValid = true;
inputs.forEach(input => {
inputs.forEach((input) => {
if (!validateInput(input, true)) {
isValid = false;
}
});
const submitButton = form.querySelector('.btn-login');
const spinner = submitButton.querySelector('.spinner');
const buttonText = submitButton.querySelector('.btn-text');
const submitButton = form.querySelector(".btn-login");
const spinner = submitButton.querySelector(".spinner");
const buttonText = submitButton.querySelector(".btn-text");
submitButton.disabled = true;
spinner.style.display = 'inline-block';
buttonText.style.opacity = '0';
spinner.style.display = "inline-block";
buttonText.style.opacity = "0";
form.submit();
}
if (window.location.href.includes('idp.e-kreta.hu/Account/Login')) {
transformLoginPage().catch(error => {
console.error('Error:', error);
if (window.location.href.includes("idp.e-kreta.hu/Account/Login")) {
transformLoginPage().catch((error) => {
console.error("Error:", error);
});
}
}

View File

@@ -1,301 +1,263 @@
:root {
--icon-invert: 0.1;
--icon-sepia: 0.1;
--icon-saturate: 0.1;
--icon-hue-rotate: 0deg;
--icon-brightness: 0.1;
--icon-invert:0.1;
--icon-sepia:0.1;
--icon-saturate:0.1;
--icon-hue-rotate:0deg;
--icon-brightness:0.1;
}
:root[data-theme="light-green"] {
--icon-invert: 0.1;
--icon-sepia: 0.1;
--icon-saturate: 0.1;
--icon-hue-rotate: 0deg;
--icon-brightness: 0.1;
--icon-invert:0.1;
--icon-sepia:0.1;
--icon-saturate:0.1;
--icon-hue-rotate:0deg;
--icon-brightness:0.1;
}
:root[data-theme="dark-blue"] {
--icon-invert: 0.9;
--icon-sepia: 0.1;
--icon-saturate: 0.1;
--icon-hue-rotate: 0deg;
--icon-brightness: 1;
--icon-invert:0.9;
--icon-sepia:0.1;
--icon-saturate:0.1;
--icon-hue-rotate:0deg;
--icon-brightness:1;
}
:root[data-theme="dark-green"] {
--icon-invert: 0.9;
--icon-sepia: 0.1;
--icon-saturate: 0.1;
--icon-hue-rotate: 0deg;
--icon-brightness: 1;
--icon-invert:0.9;
--icon-sepia:0.1;
--icon-saturate:0.1;
--icon-hue-rotate:0deg;
--icon-brightness:1;
}
* {
box-sizing: border-box;
margin: 0;
padding: 0;
box-sizing:border-box;
margin:0;
padding:0;
}
body {
margin: 0;
padding: 0;
color: var(--text-primary);
background-color: var(--background) !important;
font-family: "Montserrat", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif !important;
min-height: 100vh;
font-size: 16px;
display: flex;
align-items: center;
justify-content: center;
margin:0;
padding:0;
color:var(--text-primary);
background-color:var(--background) !important;
font-family:"Montserrat",-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,sans-serif !important;
min-height:100vh;
font-size:16px;
display:flex;
align-items:center;
justify-content:center;
}
.login-container {
width: 90%;
max-width: 500px;
padding: 20px;
margin: 0 auto;
width:90%;
max-width:500px;
padding:20px;
margin:0 auto;
}
.login-card {
background: var(--card-card);
padding: 24px;
margin-bottom: 16px;
border-radius: 24px;
box-shadow: 0px 1px var(--shadow-blur) 0px var(--accent-shadow);
background:var(--card-card);
padding:24px;
margin-bottom:16px;
border-radius:24px;
box-shadow:0px 1px var(--shadow-blur) 0px var(--accent-shadow);
}
.card-header {
display: flex;
flex-direction: column;
align-items: center;
gap: 8px;
margin: 16px 0;
background: var(--card-card) !important;
border-bottom: 1px solid rgba(0, 0, 0, 0) !important;
display:flex;
flex-direction:column;
align-items:center;
gap:8px;
margin:16px 0;
background:var(--card-card) !important;
border-bottom:1px solid rgba(0,0,0,0) !important;
}
.logo-text {
color: var(--text-primary);
text-align: center;
font-family: Montserrat;
font-size: 20px;
font-style: normal;
font-weight: 700;
line-height: normal;
color:var(--text-primary);
text-align:center;
font-family:Montserrat;
font-size:20px;
font-style:normal;
font-weight:700;
line-height:normal;
}
.logo {
width: 48px;
height: 48px;
border-radius: 12px;
width:48px;
height:48px;
border-radius:12px;
}
.twofactor-title {
color: var(--text-primary);
text-align: center;
font-family: Montserrat;
font-size: 24px;
font-style: normal;
font-weight: 600;
line-height: 130%;
margin-bottom: 16px;
color:var(--text-primary);
text-align:center;
font-family:Montserrat;
font-size:24px;
font-style:normal;
font-weight:600;
line-height:130%;
margin-bottom:16px;
}
.twofactor-form {
width: 100%;
width:100%;
}
.form-group {
margin-bottom: 16px;
margin-bottom:16px;
}
.form-control {
display: flex;
height: 48px;
padding: 0px 14px;
align-items: center;
gap: 10px;
align-self: stretch;
border-radius: 12px;
background: var(--accent-15) !important;
border: 0px solid var(--accent-15) !important;
color: var(--text-primary) !important;
display:flex;
height:48px;
padding:0px 14px;
align-items:center;
gap:10px;
align-self:stretch;
border-radius:12px;
background:var(--accent-15) !important;
border:0px solid var(--accent-15) !important;
color:var(--text-primary) !important;
}
.form-control:focus {
outline: none;
border-color: var(--accent-accent) !important;
outline:none;
border-color:var(--accent-accent) !important;
}
.form-control::placeholder {
color: var(--text-secondary) !important;
color:var(--text-secondary) !important;
}
.password-group {
position: relative;
position:relative;
}
.show-password {
position: absolute;
right: 12px;
top: 50%;
transform: translateY(-50%);
background: none;
border: none;
padding: 4px;
cursor: pointer;
display: flex;
align-items: center;
justify-content: center;
position:absolute;
right:12px;
top:50%;
transform:translateY(-50%);
background:none;
border:none;
padding:4px;
cursor:pointer;
display:flex;
align-items:center;
justify-content:center;
}
.icon-eye {
width: 20px;
height: 20px;
opacity: 0.6;
transition: opacity 0.2s ease;
filter: invert(var(--icon-invert)) sepia(var(--icon-sepia)) saturate(var(--icon-saturate)) hue-rotate(var(--icon-hue-rotate)) brightness(var(--icon-brightness));
width:20px;
height:20px;
opacity:0.6;
transition:opacity 0.2s ease;
filter:invert(var(--icon-invert)) sepia(var(--icon-sepia)) saturate(var(--icon-saturate)) hue-rotate(var(--icon-hue-rotate)) brightness(var(--icon-brightness));
}
.show-password:hover .icon-eye {
opacity: 1;
opacity:1;
}
.form-check {
display: flex;
align-items: center;
margin-top: 16px;
margin-bottom: 16px;
display:flex;
align-items:center;
margin-top:16px;
margin-bottom:16px;
}
.form-check-input {
width: 20px;
height: 20px;
margin-right: 8px;
border-radius: 6px;
border: 2px solid var(--accent-accent);
background-color: var(--card-card);
cursor: pointer;
width:20px;
height:20px;
margin-right:8px;
border-radius:6px;
border:2px solid var(--accent-accent);
background-color:var(--card-card);
cursor:pointer;
}
.form-check-input:checked {
background-color: var(--accent-accent);
border-color: var(--accent-accent);
background-color:var(--accent-accent);
border-color:var(--accent-accent);
}
.form-check-label {
color: var(--text-primary);
font-family: Figtree;
font-size: 14px;
font-style: normal;
font-weight: 400;
line-height: 130%;
cursor: pointer;
color:var(--text-primary);
font-family:Figtree;
font-size:14px;
font-style:normal;
font-weight:400;
line-height:130%;
cursor:pointer;
}
.btn-kreta {
display: flex;
height: 48px;
padding: 0px 24px;
justify-content: center;
align-items: center;
gap: 8px;
border-radius: 12px;
background: var(--accent-accent);
color: white;
font-family: Montserrat;
font-size: 16px;
font-style: normal;
font-weight: 600;
line-height: normal;
border: none;
cursor: pointer;
transition: background-color 0.2s ease;
display:flex;
height:48px;
padding:0px 24px;
justify-content:center;
align-items:center;
gap:8px;
border-radius:12px;
background:var(--accent-accent);
color:white;
font-family:Montserrat;
font-size:16px;
font-style:normal;
font-weight:600;
line-height:normal;
border:none;
cursor:pointer;
transition:background-color 0.2s ease;
}
.btn-kreta:hover {
background-color: var(--accent-secondary);
background-color:var(--accent-secondary);
}
.btn-link {
background: none;
border: none;
color: var(--accent-accent);
font-family: Figtree;
font-size: 14px;
font-style: normal;
font-weight: 400;
line-height: 130%;
text-decoration: underline;
cursor: pointer;
padding: 0;
background:none;
border:none;
color:var(--accent-accent);
font-family:Figtree;
font-size:14px;
font-style:normal;
font-weight:400;
line-height:130%;
text-decoration:underline;
cursor:pointer;
padding:0;
}
.btn-link:hover {
color: var(--accent-secondary);
color:var(--accent-secondary);
}
.subtext {
color: var(--text-primary);
font-family: Figtree;
font-size: 14px;
font-style: normal;
font-weight: 400;
line-height: 130%;
text-align: center;
color:var(--text-primary);
font-family:Figtree;
font-size:14px;
font-style:normal;
font-weight:400;
line-height:130%;
text-align:center;
}
.login-footer {
margin-top: 24px;
text-align: center;
margin-top:24px;
text-align:center;
}
.privacy-link {
color: var(--text-secondary);
font-family: Figtree;
font-size: 14px;
font-style: normal;
font-weight: 400;
line-height: 130%;
text-decoration: none;
color:var(--text-secondary);
font-family:Figtree;
font-size:14px;
font-style:normal;
font-weight:400;
line-height:130%;
text-decoration:none;
}
.privacy-link:hover {
text-decoration: underline;
text-decoration:underline;
}
.error-message {
display: none;
color: var(--error-text);
font-family: Figtree;
font-size: 12px;
font-style: normal;
font-weight: 400;
line-height: 130%;
margin-top: 4px;
display:none;
color:var(--error-text);
font-family:Figtree;
font-size:12px;
font-style:normal;
font-weight:400;
line-height:130%;
margin-top:4px;
}
.error-message.show {
display: block;
display:block;
}
.form-control.error {
border: 1px solid var(--error-accent) !important;
border:1px solid var(--error-accent) !important;
}
/* Hide original elements */
header, main > .container-fluid, footer {
display: none !important;
header,main > .container-fluid,footer {
display:none !important;
}
/* Responsive adjustments */
@media (max-width: 576px) {
@media (max-width:576px) {
.login-container {
width: 100%;
padding: 16px;
}
.login-card {
padding: 16px;
}
width:100%;
padding:16px;
}
.login-card {
padding:16px;
}
}

View File

@@ -1,35 +1,40 @@
async function transformTwoFactorPage() {
try {
if (document.readyState !== 'complete') {
await new Promise(resolve => {
window.addEventListener('load', resolve);
if (document.readyState !== "complete") {
await new Promise((resolve) => {
window.addEventListener("load", resolve);
});
}
if (typeof loadingScreen !== 'undefined') {
if (typeof loadingScreen !== "undefined") {
loadingScreen.show();
}
const existingForm = document.querySelector('form');
const existingForm = document.querySelector("form");
const formData = {
action: existingForm?.getAttribute('action') || '',
clientId: document.querySelector('#ClientId')?.value || '',
rememberLogin: document.querySelector('#RememberLogin')?.value || 'False',
returnUrl: document.querySelector('#ReturnUrl')?.value || '',
isRecoveryCode: document.querySelector('#IsRecoveryCode')?.value || 'False',
requestToken: document.querySelector('input[name="__RequestVerificationToken"]')?.value || '',
trustDeviceValue: document.querySelector('input[name="TrustDevice"][type="hidden"]')?.value || 'false'
action: existingForm?.getAttribute("action") || "",
clientId: document.querySelector("#ClientId")?.value || "",
rememberLogin: document.querySelector("#RememberLogin")?.value || "False",
returnUrl: document.querySelector("#ReturnUrl")?.value || "",
isRecoveryCode:
document.querySelector("#IsRecoveryCode")?.value || "False",
requestToken:
document.querySelector('input[name="__RequestVerificationToken"]')
?.value || "",
trustDeviceValue:
document.querySelector('input[name="TrustDevice"][type="hidden"]')
?.value || "false",
};
const newHTML = `
<div class="login-container">
<div class="login-card">
<div class="card-header">
<p class="logo-text">
<img src=${chrome.runtime.getURL('images/firka_logo.png')} alt="Firka" class="logo">
<img src=${chrome.runtime.getURL("images/firka_logo.png")} alt="Firka" class="logo">
Firka
</p>
<h1 class="twofactor-title">${LanguageManager.t('twofactor.title')}</h1>
<h1 class="twofactor-title">${LanguageManager.t("twofactor.title")}</h1>
</div>
<form class="twofactor-form" action="${formData.action}" method="post" id="twoFactorForm">
@@ -41,30 +46,30 @@ async function transformTwoFactorPage() {
<div class="form-group password-group">
<input class="form-control" type="password" id="VerificationCode" name="VerificationCode"
placeholder="${LanguageManager.t('twofactor.code_placeholder')}" maxlength="256" autocomplete="off" required autofocus>
<button type="button" class="show-password" aria-label="${LanguageManager.t('twofactor.show_code')}">
<img src="${chrome.runtime.getURL('icons/eye-off.svg')}" alt="Show password" class="icon-eye">
placeholder="${LanguageManager.t("twofactor.code_placeholder")}" maxlength="256" autocomplete="off" required autofocus>
<button type="button" class="show-password" aria-label="${LanguageManager.t("twofactor.show_code")}">
<img src="${chrome.runtime.getURL("icons/eye-off.svg")}" alt="Show password" class="icon-eye">
</button>
<div class="error-message">${LanguageManager.t('twofactor.code_required')}</div>
<div class="error-message">${LanguageManager.t("twofactor.code_required")}</div>
</div>
<div class="form-check">
<input class="form-check-input" type="checkbox" id="trustDevice" name="TrustDevice" value="true">
<label class="form-check-label" for="trustDevice">
${LanguageManager.t('twofactor.trust_device')}
${LanguageManager.t("twofactor.trust_device")}
</label>
<input name="TrustDevice" type="hidden" value="false">
</div>
<div class="d-flex justify-content-center mb-3 mt-4">
<button type="submit" class="btn-kreta">${LanguageManager.t('twofactor.verify_button')}</button>
<button type="submit" class="btn-kreta">${LanguageManager.t("twofactor.verify_button")}</button>
</div>
<div class="d-flex justify-content-center mt-3">
<span class="subtext">
${LanguageManager.t('twofactor.no_access')}
${LanguageManager.t("twofactor.no_access")}
<button type="submit" class="btn-link" formaction="/account/loginwithrecoverycode">
${LanguageManager.t('twofactor.recovery_code')}
${LanguageManager.t("twofactor.recovery_code")}
</button>
</span>
</div>
@@ -73,21 +78,20 @@ async function transformTwoFactorPage() {
<footer class="login-footer">
<a href="https://tudasbazis.ekreta.hu/pages/viewpage.action?pageId=4064926"
target="_blank" class="privacy-link">${LanguageManager.t('login.privacy_policy')}</a>
target="_blank" class="privacy-link">${LanguageManager.t("login.privacy_policy")}</a>
</footer>
</div>
`;
document.body.innerHTML = newHTML;
applyTheme();
setupEventListeners();
if (typeof loadingScreen !== 'undefined') {
if (typeof loadingScreen !== "undefined") {
loadingScreen.hide();
}
} catch (error) {
console.error('Error transforming two-factor page:', error);
if (typeof loadingScreen !== 'undefined') {
console.error("Error transforming two-factor page:", error);
if (typeof loadingScreen !== "undefined") {
loadingScreen.hide();
}
}
@@ -95,77 +99,79 @@ async function transformTwoFactorPage() {
function applyTheme() {
try {
if (typeof getCookie === 'function') {
const theme = getCookie('theme') || 'light-blue';
document.documentElement.setAttribute('data-theme', theme);
if (typeof getCookie === "function") {
const theme = getCookie("theme") || "light-blue";
document.documentElement.setAttribute("data-theme", theme);
}
} catch (error) {
console.error('Error applying theme:', error);
console.error("Error applying theme:", error);
}
}
function setupEventListeners() {
const twoFactorForm = document.getElementById('twoFactorForm');
const verificationInput = document.getElementById('VerificationCode');
const togglePasswordBtn = document.querySelector('.show-password');
const formInputs = document.querySelectorAll('.form-control');
const twoFactorForm = document.getElementById("twoFactorForm");
const verificationInput = document.getElementById("VerificationCode");
const togglePasswordBtn = document.querySelector(".show-password");
const formInputs = document.querySelectorAll(".form-control");
if (togglePasswordBtn && verificationInput) {
togglePasswordBtn.addEventListener('click', () => {
const isPassword = verificationInput.type === 'password';
verificationInput.type = isPassword ? 'text' : 'password';
const icon = togglePasswordBtn.querySelector('.icon-eye');
icon.src = chrome.runtime.getURL(`icons/${isPassword ? 'eye-on' : 'eye-off'}.svg`);
togglePasswordBtn.addEventListener("click", () => {
const isPassword = verificationInput.type === "password";
verificationInput.type = isPassword ? "text" : "password";
const icon = togglePasswordBtn.querySelector(".icon-eye");
icon.src = chrome.runtime.getURL(
`icons/${isPassword ? "eye-on" : "eye-off"}.svg`,
);
});
}
formInputs.forEach(input => {
input.addEventListener('input', () => {
formInputs.forEach((input) => {
input.addEventListener("input", () => {
validateInput(input);
});
input.addEventListener('blur', () => {
input.addEventListener("blur", () => {
validateInput(input, true);
});
});
if (twoFactorForm) {
twoFactorForm.addEventListener('submit', handleSubmit);
twoFactorForm.addEventListener("submit", handleSubmit);
}
}
function validateInput(input, showError = false) {
const isValid = input.value.trim().length > 0;
const errorElement = input.nextElementSibling?.nextElementSibling;
if (!isValid && showError) {
input.classList.add('error');
errorElement?.classList.add('show');
input.classList.add("error");
errorElement?.classList.add("show");
} else {
input.classList.remove('error');
errorElement?.classList.remove('show');
input.classList.remove("error");
errorElement?.classList.remove("show");
}
return isValid;
}
function handleSubmit(event) {
event.preventDefault();
const form = event.target;
const inputs = form.querySelectorAll('.form-control[required]');
const inputs = form.querySelectorAll(".form-control[required]");
let isValid = true;
inputs.forEach(input => {
inputs.forEach((input) => {
if (!validateInput(input, true)) {
isValid = false;
}
});
if (isValid) {
const submitButton = form.querySelector('.btn-kreta');
const submitButton = form.querySelector(".btn-kreta");
if (submitButton) {
submitButton.disabled = true;
submitButton.innerHTML = `<span class="spinner"></span><span class="btn-text">${LanguageManager.t('twofactor.verifying')}</span>`;
submitButton.innerHTML = `<span class="spinner"></span><span class="btn-text">${LanguageManager.t("twofactor.verifying")}</span>`;
}
form.submit();
}
}
transformTwoFactorPage();
transformTwoFactorPage();

View File

@@ -1,138 +1,117 @@
* {
box-sizing: border-box;
margin: 0;
padding: 0;
box-sizing:border-box;
margin:0;
padding:0;
}
body {
margin: 0;
padding: 0;
color: var(--text-primary);
background-color: var(--background) !important;
font-family: "Montserrat", serif !important;
min-height: 100vh;
font-size: 16px;
display: flex;
align-items: center;
justify-content: center;
margin:0;
padding:0;
color:var(--text-primary);
background-color:var(--background) !important;
font-family:"Montserrat",serif !important;
min-height:100vh;
font-size:16px;
display:flex;
align-items:center;
justify-content:center;
}
.logout-container {
width: 100%;
max-width: 500px;
padding: 20px;
margin: 0 auto;
width:100%;
max-width:500px;
padding:20px;
margin:0 auto;
}
.logout-header {
text-align: center;
margin-bottom: 24px;
text-align:center;
margin-bottom:24px;
}
.logo-text {
color: var(--text-primary);
font-size: 24px;
font-weight: 600;
margin: 16px 0;
display: flex;
align-items: center;
justify-content: center;
color:var(--text-primary);
font-size:24px;
font-weight:600;
margin:16px 0;
display:flex;
align-items:center;
justify-content:center;
}
.logo {
width: 24px;
border-radius: 8px;
margin-right: 8px;
width:24px;
border-radius:8px;
margin-right:8px;
}
.logout-card {
background: var(--card-card);
padding: 24px;
border-radius: 24px;
text-align: center;
margin-bottom: 16px;
box-shadow: 0px 1px var(--shadow-blur) 0px var(--accent-shadow);
background:var(--card-card);
padding:24px;
border-radius:24px;
text-align:center;
margin-bottom:16px;
box-shadow:0px 1px var(--shadow-blur) 0px var(--accent-shadow);
}
.logout-message {
margin-bottom: 24px;
margin-bottom:24px;
}
.logout-message strong {
font-size: 18px;
color: var(--text-primary);
font-weight: 600;
font-size:18px;
color:var(--text-primary);
font-weight:600;
}
.redirect-timer {
font-size: 48px;
font-weight: 700;
color: var(--accent-accent);
margin-bottom: 24px;
font-size:48px;
font-weight:700;
color:var(--accent-accent);
margin-bottom:24px;
}
.btn-continue {
display: inline-block;
padding: 12px 24px;
background: var(--accent-accent);
color: var(--button-secondaryFill);
text-decoration: none;
border-radius: 12px;
font-weight: 600;
transition: background 0.2s ease, color 0.2s ease;
display:inline-block;
padding:12px 24px;
background:var(--accent-accent);
color:var(--button-secondaryFill);
text-decoration:none;
border-radius:12px;
font-weight:600;
transition:background 0.2s ease,color 0.2s ease;
}
.btn-continue:hover {
background: var(--accent-secondary) !important;
color: var(--button-secondaryFill) !important;
background:var(--accent-secondary) !important;
color:var(--button-secondaryFill) !important;
}
.logout-footer {
text-align: center;
text-align:center;
}
.privacy-link {
color: var(--text-secondary);
text-decoration: none;
font-size: 14px;
display: inline-block;
margin-bottom: 8px;
transition: color 0.2s ease;
color:var(--text-secondary);
text-decoration:none;
font-size:14px;
display:inline-block;
margin-bottom:8px;
transition:color 0.2s ease;
}
.privacy-link:hover {
color: var(--text-primary);
color:var(--text-primary);
}
@media (max-width: 600px) {
@media (max-width:600px) {
.logout-container {
padding: 16px;
}
.logout-card {
padding: 20px;
}
.redirect-timer {
font-size: 36px;
}
.logo-text {
font-size: 20px;
}
.logo {
width: 20px;
}
padding:16px;
}
@keyframes fadeIn {
.logout-card {
padding:20px;
}
.redirect-timer {
font-size:36px;
}
.logo-text {
font-size:20px;
}
.logo {
width:20px;
}
}@keyframes fadeIn {
from {
opacity: 0;
transform: translateY(-10px);
}
to {
opacity: 1;
transform: translateY(0);
}
opacity:0;
transform:translateY(-10px);
}
to {
opacity:1;
transform:translateY(0);
}
}

View File

@@ -1,25 +1,17 @@
(() => {
function loadFonts() {
// Create a new style element
const style = document.createElement('style');
style.textContent = `
@import url('https://fonts.googleapis.com/css2?family=Montserrat:wght@400;500;600;700&display=swap');
@import url('https://fonts.googleapis.com/icon?family=Material+Icons+Round');
`;
document.head.appendChild(style);
}
function transformLogoutPage() {
// Get current theme and school ID from cookies
const theme = cookieManager.get('themePreference') || localStorage.getItem('themePreference') || 'light-green';
const instituteCode = cookieManager.get('schoolSubdomain');
document.documentElement.setAttribute('data-theme', theme);
// Create new HTML structure
const theme =
cookieManager.get("themePreference") ||
localStorage.getItem("themePreference") ||
"light-green";
const instituteCode = cookieManager.get("schoolSubdomain");
document.documentElement.setAttribute("data-theme", theme);
const newHTML = `
<div class="logout-container">
<header class="logout-header">
<p class="logo-text">
<img src=${chrome.runtime.getURL('images/firka_logo.png')} alt="Firka" class="logo">
<img src=${chrome.runtime.getURL("images/firka_logo.png")} alt="Firka" class="logo">
Firka
</p>
</header>
@@ -42,38 +34,33 @@
</footer>
</div>
`;
// Replace body content
document.body.innerHTML = newHTML;
// Start countdown timer
const timerElement = document.getElementById('automaticRedirectTimer');
const timerElement = document.getElementById("automaticRedirectTimer");
let remainingTime = 5;
const countdownInterval = setInterval(() => {
remainingTime--;
if (timerElement) {
timerElement.textContent = remainingTime;
}
if (remainingTime <= 0) {
clearInterval(countdownInterval);
window.location.href = `https://${instituteCode}.e-kreta.hu`;
}
}, 1000);
// Handle manual redirect click
document.querySelector('.btn-continue')?.addEventListener('click', (e) => {
document.querySelector(".btn-continue")?.addEventListener("click", (e) => {
e.preventDefault();
clearInterval(countdownInterval);
window.location.href = `https://${instituteCode}.e-kreta.hu`;
});
}
// Load fonts immediately
loadFonts();
// Run the transformation
if (document.readyState === 'loading') {
document.addEventListener('DOMContentLoaded', transformLogoutPage);
if (document.readyState === "loading") {
document.addEventListener("DOMContentLoaded", transformLogoutPage);
} else {
transformLogoutPage();
}

View File

@@ -18,98 +18,189 @@
"strict_min_version": "58.0"
}
},
"web_accessible_resources": [{
"resources": [
"settings/*",
"global/language.js",
"images/*",
"fonts/*.woff2",
"icons/*.svg",
"grades/chart.js",
"i18n/*.json",
"tools/cookieManager.js"
],
"matches": ["<all_urls>"]
}],
"web_accessible_resources": [
{
"resources": [
"settings/*",
"global/language.js",
"images/*",
"fonts/*.woff2",
"icons/*.svg",
"grades/chart.js",
"i18n/*.json",
"tools/cookieManager.js"
],
"matches": [
"<all_urls>"
]
}
],
"content_scripts": [
{
"matches": ["https://*.e-kreta.hu/*"],
"js": ["tools/loadingScreen.js", "tools/cookieManager.js", "tools/helper.js", "tools/createTemplate.js",
"global/language.js", "global/maintenance.js", "global/theme.js", "global/navigation.js"],
"css": ["tools/loadingScreen.css", "global/theme.css", "global/navigation.css", "global/maintenance.css"],
"matches": [
"https://*.e-kreta.hu/*"
],
"js": [
"global/language.js",
"global/theme.js",
"tools/loadingScreen.js",
"tools/cookieManager.js",
"tools/helper.js",
"tools/createTemplate.js",
"global/maintenance.js",
"global/navigation.js"
],
"css": [
"tools/loadingScreen.css",
"global/theme.css",
"global/navigation.css",
"global/maintenance.css"
],
"run_at": "document_start"
},
{
"matches": ["https://idp.e-kreta.hu/Account/Login*"],
"js": ["login/login.js"],
"css": ["login/login.css"]
},
{
"matches": ["https://idp.e-kreta.hu/account/loginwithtwofactor*"],
"js": ["login/twofactor.js"],
"css": ["login/twofactor.css"]
},
{
"matches": ["https://*.e-kreta.hu/Hianyzas/Hianyzasok*"],
"js": ["absences/absences.js"],
"css": ["absences/absences.css"],
"run_at": "document_end"
},
{
"matches": ["https://idp.e-kreta.hu/Account/Logout*"],
"js": ["logout/logout.js"],
"css": ["logout/logout.css"],
"run_at": "document_end"
},
{
"matches": ["https://*.e-kreta.hu/Adminisztracio/BelepesKezelo*"],
"js": ["roleselect/roleselect.js"],
"css": ["roleselect/roleselect.css"],
"run_at": "document_end"
},
{
"matches": ["https://*.e-kreta.hu/Intezmeny/Faliujsag*"],
"js": ["dashboard/dashboard.js"],
"css": ["dashboard/dashboard.css"],
"run_at": "document_end"
},
{
"matches": [ "https://*.e-kreta.hu/TanuloErtekeles/Osztalyzatok*"
"matches": [
"https://idp.e-kreta.hu/Account/Login*"
],
"js": [
"login/login.js"
],
"css": [
"login/login.css"
],
"run_at": "document_start"
},
{
"matches": [
"https://idp.e-kreta.hu/account/loginwithtwofactor*"
],
"js": [
"login/twofactor.js"
],
"css": [
"login/twofactor.css"
],
"run_at": "document_start"
},
{
"matches": [
"https://*.e-kreta.hu/Hianyzas/Hianyzasok*"
],
"js": [
"absences/absences.js"
],
"css": [
"absences/absences.css"
],
"run_at": "document_end"
},
{
"matches": [
"https://idp.e-kreta.hu/Account/Logout*"
],
"js": [
"logout/logout.js"
],
"css": [
"logout/logout.css"
],
"run_at": "document_start"
},
{
"matches": [
"https://*.e-kreta.hu/Adminisztracio/BelepesKezelo*"
],
"js": [
"roleselect/roleselect.js"
],
"css": [
"roleselect/roleselect.css"
],
"run_at": "document_start"
},
{
"matches": [
"https://*.e-kreta.hu/Intezmeny/Faliujsag*"
],
"js": [
"dashboard/dashboard.js"
],
"css": [
"dashboard/dashboard.css"
],
"run_at": "document_end"
},
{
"matches": [
"https://*.e-kreta.hu/TanuloErtekeles/Osztalyzatok*"
],
"js": [
"grades/grades.js",
"grades/chart.js"
],
"css": [
"grades/grades.css"
],
"js": ["grades/grades.js", "grades/chart.js"],
"css": ["grades/grades.css"],
"run_at": "document_end"
},
{
"matches": [
"https://*.e-kreta.hu/Orarend/InformaciokOrarend*"
],
"js": ["timetable/timetable.js"],
"css": ["timetable/timetable.css"],
"js": [
"timetable/timetable.js"
],
"css": [
"timetable/timetable.css"
],
"run_at": "document_end"
},
{
"matches": [
"https://*.e-kreta.hu/Adminisztracio/Profil*"
],
"js": ["profile/profile.js"],
"css": ["profile/profile.css"],
"js": [
"profile/profile.js"
],
"css": [
"profile/profile.css"
],
"run_at": "document_end"
},
{
"matches": [
"https://*.e-kreta.hu/Tanulo/TanuloHaziFeladat*"
],
"js": ["homework/homework.js"],
"css": ["homework/homework.css"],
"js": [
"homework/homework.js"
],
"css": [
"homework/homework.css"
],
"run_at": "document_end"
},
{
"matches": [
"https://*.e-kreta.hu/Adminisztracio/ElfelejtettJelszo*"
],
"js": [
"forgotPassword/forgotPassword.js"
],
"css": [
"forgotPassword/forgotPassword.css"
],
"run_at": "document_end"
},
{
"matches": [
"https://intezmenykereso.e-kreta.hu/"
],
"js": ["search/search.js"],
"css": ["search/search.css"],
"js": [
"search/search.js"
],
"css": [
"search/search.css"
],
"run_at": "document_end"
}
]

File diff suppressed because it is too large Load Diff

View File

@@ -1,437 +1,362 @@
* {
box-sizing: border-box;
margin: 0;
padding: 0;
box-sizing:border-box;
margin:0;
padding:0;
}
body {
margin: 0;
padding: 0;
color: var(--text-primary);
background-color: var(--background) !important;
font-family: "Montserrat", serif !important;
min-height: 100vh;
font-size: 16px;
margin:0;
padding:0;
color:var(--text-primary);
background-color:var(--background) !important;
font-family:"Montserrat",serif !important;
min-height:100vh;
font-size:16px;
}
.kreta-container {
min-height: 100vh;
display: flex;
flex-direction: column;
min-height:100vh;
display:flex;
flex-direction:column;
}
.kreta-header {
padding: clamp(1rem, 3vw, 2rem);
display: grid;
grid-template-columns: minmax(300px, 400px) 1fr minmax(200px, 300px);
align-items: center;
gap: 1rem;
padding:clamp(1rem,3vw,2rem);
display:grid;
grid-template-columns:minmax(300px,400px) 1fr minmax(200px,300px);
align-items:center;
gap:1rem;
}
.school-info {
display: flex;
flex-direction: column;
gap: 0.5rem;
display:flex;
flex-direction:column;
gap:0.5rem;
}
.logo-text {
color: var(--text-primary);
font-size: 24px;
font-weight: 600;
display: flex;
align-items: center;
margin: 0;
color:var(--text-primary);
font-size:24px;
font-weight:600;
display:flex;
align-items:center;
margin:0;
}
.logo {
width: 24px;
border-radius: 8px;
margin-right: 8px;
width:24px;
border-radius:8px;
margin-right:8px;
}
.school-details {
color: var(--text-secondary);
font-size: 14px;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
max-width: 300px;
color:var(--text-secondary);
font-size:14px;
white-space:nowrap;
overflow:hidden;
text-overflow:ellipsis;
max-width:300px;
}
.user-profile {
position: relative;
justify-self: flex-end;
position:relative;
justify-self:flex-end;
}
.user-dropdown-btn {
display: flex;
align-items: center;
gap: 1rem;
background: none;
border: none;
cursor: pointer;
padding: 0.5rem;
border-radius: 8px;
transition: background-color 0.2s;
display:flex;
align-items:center;
gap:1rem;
background:none;
border:none;
cursor:pointer;
padding:0.5rem;
border-radius:8px;
transition:background-color 0.2s;
}
.user-dropdown-btn:hover {
background: var(--card-card);
background:var(--card-card);
}
.user-info {
text-align: right;
text-align:right;
}
.user-dropdown {
position: absolute;
top: 100%;
right: 0;
margin-top: 0.5rem;
background: var(--card-card);
border-radius: 12px;
box-shadow: 0px 1px var(--shadow-blur) 0px var(--accent-shadow);
width: 200px;
display: none;
z-index: 1000;
position:absolute;
top:100%;
right:0;
margin-top:0.5rem;
background:var(--card-card);
border-radius:12px;
box-shadow:0px 1px var(--shadow-blur) 0px var(--accent-shadow);
width:200px;
display:none;
z-index:1000;
}
.user-dropdown.show {
display: block;
animation: dropdownShow 0.2s ease;
display:block;
animation:dropdownShow 0.2s ease;
}
.dropdown-item {
display: flex;
align-items: center;
gap: 0.75rem;
padding: 0.75rem 1rem;
color: var(--text-primary);
text-decoration: none;
transition: background-color 0.2s;
display:flex;
align-items:center;
gap:0.75rem;
padding:0.75rem 1rem;
color:var(--text-primary);
text-decoration:none;
transition:background-color 0.2s;
}
.dropdown-item:hover {
background: var(--button-secondaryFill);
background:var(--button-secondaryFill);
}
.kreta-main {
flex: 1;
padding: clamp(1rem, 3vw, 2rem);
max-width: 800px;
margin: 0 auto;
width: 100%;
flex:1;
padding:clamp(1rem,3vw,2rem);
max-width:800px;
margin:0 auto;
width:100%;
}
.card {
background: var(--card-card);
border-radius: 24px;
overflow: hidden;
box-shadow: 0px 1px var(--shadow-blur) 0px var(--accent-shadow);
background:var(--card-card);
border-radius:24px;
overflow:hidden;
box-shadow:0px 1px var(--shadow-blur) 0px var(--accent-shadow);
}
.card h2 {
font-size: 18px;
font-weight: 600;
color: var(--text-primary);
padding: 1.5rem;
padding-bottom: 0.5rem;
background-color: var(--card-card);
font-size:18px;
font-weight:600;
color:var(--text-primary);
padding:1.5rem;
padding-bottom:0.5rem;
background-color:var(--card-card);
}
.profile-tabs {
padding: 1.5rem;
padding:1.5rem;
}
.tab-headers {
display: flex;
gap: 0.5rem;
margin-bottom: 1.5rem;
border-bottom: 1px solid var(--card-translucent);
overflow-x: auto;
scrollbar-width: none;
display:flex;
gap:0.5rem;
margin-bottom:1.5rem;
border-bottom:1px solid var(--card-translucent);
overflow-x:auto;
scrollbar-width:none;
}
.tab-headers::-webkit-scrollbar {
display: none;
display:none;
}
.tab-header {
padding: 0.75rem 1rem;
background: none;
border: none;
color: var(--text-secondary);
font-weight: 500;
cursor: pointer;
white-space: nowrap;
border-bottom: 2px solid transparent;
font-size: 14px;
padding:0.75rem 1rem;
background:none;
border:none;
color:var(--text-secondary);
font-weight:500;
cursor:pointer;
white-space:nowrap;
border-bottom:2px solid transparent;
font-size:14px;
}
.tab-header.active {
color: var(--accent-accent);
border-bottom-color: var(--accent-accent);
color:var(--accent-accent);
border-bottom-color:var(--accent-accent);
}
.tab-content {
display: none;
background: var(--button-secondaryFill);
border-radius: 8px;
padding: 1.5rem;
display:none;
background:var(--button-secondaryFill);
border-radius:8px;
padding:1.5rem;
}
.tab-content.active {
display: block;
display:block;
}
.form-group {
margin-bottom: 1rem;
margin-bottom:1rem;
}
.form-label {
display: block;
color: var(--text-secondary);
font-size: 14px;
margin-bottom: 0.5rem;
display:block;
color:var(--text-secondary);
font-size:14px;
margin-bottom:0.5rem;
}
.form-control {
width: 100%;
padding: 0.75rem;
border: 1px solid var(--accent-15);
border-radius: 8px;
background: var(--accent-15);
color: var(--text-primary);
font-size: 14px;
width:100%;
padding:0.75rem;
border:1px solid var(--accent-15);
border-radius:8px;
background:var(--accent-15);
color:var(--text-primary);
font-size:14px;
}
.form-control:focus {
outline: none;
border-color: var(--accent-accent);
outline:none;
border-color:var(--accent-accent);
}
.form-text {
font-size: 12px;
color: var(--text-secondary);
margin-top: 0.25rem;
font-size:12px;
color:var(--text-secondary);
margin-top:0.25rem;
}
.security-content {
display: flex;
flex-direction: column;
gap: 1.5rem;
display:flex;
flex-direction:column;
gap:1.5rem;
}
.step-card {
background: var(--button-secondaryFill);
border-radius: 12px;
padding: 1.5rem;
animation: fadeIn 0.3s ease;
background:var(--button-secondaryFill);
border-radius:12px;
padding:1.5rem;
animation:fadeIn 0.3s ease;
}
.step-card h3 {
color: var(--text-primary);
font-size: 16px;
font-weight: 600;
margin-bottom: 1rem;
color:var(--text-primary);
font-size:16px;
font-weight:600;
margin-bottom:1rem;
}
.step-card p {
color: var(--text-secondary);
font-size: 14px;
margin-bottom: 1rem;
line-height: 1.5;
color:var(--text-secondary);
font-size:14px;
margin-bottom:1rem;
line-height:1.5;
}
.app-grid {
display: grid;
grid-template-columns: 1fr 1fr;
gap: 1.5rem;
margin-top: 1rem;
display:grid;
grid-template-columns:1fr 1fr;
gap:1.5rem;
margin-top:1rem;
}
.app-section h4 {
color: var(--text-primary);
font-size: 14px;
font-weight: 600;
margin-bottom: 0.75rem;
color:var(--text-primary);
font-size:14px;
font-weight:600;
margin-bottom:0.75rem;
}
.app-links {
display: flex;
flex-direction: column;
gap: 0.5rem;
display:flex;
flex-direction:column;
gap:0.5rem;
}
.app-link {
display: flex;
align-items: center;
gap: 0.5rem;
padding: 0.75rem;
background: var(--card-card);
border-radius: 8px;
color: var(--text-primary);
text-decoration: none;
font-size: 14px;
transition: background-color 0.2s;
display:flex;
align-items:center;
gap:0.5rem;
padding:0.75rem;
background:var(--card-card);
border-radius:8px;
color:var(--text-primary);
text-decoration:none;
font-size:14px;
transition:background-color 0.2s;
}
.app-link:hover {
background: var(--button-secondaryFill);
background:var(--button-secondaryFill);
}
.qr-container {
display: flex;
flex-direction: column;
align-items: center;
gap: 1rem;
margin: 1.5rem 0;
display:flex;
flex-direction:column;
align-items:center;
gap:1rem;
margin:1.5rem 0;
}
.qr-container img {
background: white;
padding: 1rem;
border-radius: 8px;
max-width: 200px;
background:white;
padding:1rem;
border-radius:8px;
max-width:200px;
}
.setup-key {
display: flex;
flex-direction: column;
gap: 0.5rem;
width: 100%;
display:flex;
flex-direction:column;
gap:0.5rem;
width:100%;
}
.key-display {
display: flex;
align-items: center;
gap: 0.5rem;
background: var(--card-card);
padding: 0.75rem;
border-radius: 8px;
display:flex;
align-items:center;
gap:0.5rem;
background:var(--card-card);
padding:0.75rem;
border-radius:8px;
}
.key-display code {
font-family: monospace;
color: var(--text-primary);
font-size: 14px;
flex-grow: 1;
text-align: center;
font-family:monospace;
color:var(--text-primary);
font-size:14px;
flex-grow:1;
text-align:center;
}
.btn-copy {
background: none;
border: none;
color: var(--text-secondary);
cursor: pointer;
padding: 0.25rem;
border-radius: 4px;
transition: all 0.2s;
background:none;
border:none;
color:var(--text-secondary);
cursor:pointer;
padding:0.25rem;
border-radius:4px;
transition:all 0.2s;
}
.btn-copy:hover {
color: var(--text-primary);
background: var(--button-secondaryFill);
color:var(--text-primary);
background:var(--button-secondaryFill);
}
.btn-save {
padding: 0.75rem 1.5rem;
background: var(--accent-accent);
color: var(--button-secondaryFill);
border: none;
border-radius: 8px;
font-weight: 500;
cursor: pointer;
font-size: 14px;
transition: background-color 0.2s;
padding:0.75rem 1.5rem;
background:var(--accent-accent);
color:var(--button-secondaryFill);
border:none;
border-radius:8px;
font-weight:500;
cursor:pointer;
font-size:14px;
transition:background-color 0.2s;
}
.btn-save:hover {
background: var(--accent-secondary);
background:var(--accent-secondary);
}
@keyframes fadeIn {
from {
opacity: 0;
transform: translateY(-10px);
}
to {
opacity: 1;
transform: translateY(0);
}
opacity:0;
transform:translateY(-10px);
}
@keyframes dropdownShow {
to {
opacity:1;
transform:translateY(0);
}
}@keyframes dropdownShow {
from {
opacity: 0;
transform: translateY(-10px);
}
to {
opacity: 1;
transform: translateY(0);
}
opacity:0;
transform:translateY(-10px);
}
@media (max-width: 768px) {
to {
opacity:1;
transform:translateY(0);
}
}@media (max-width:768px) {
.kreta-header {
grid-template-columns: 1fr auto auto;
grid-template-areas:
"school toggle user"
grid-template-columns:1fr auto auto;
grid-template-areas:"school toggle user"
"nav nav nav";
padding: 1rem;
gap: 0.5rem;
}
.school-info {
grid-area: school;
}
.user-profile {
grid-area: user;
}
.app-grid {
grid-template-columns: 1fr;
}
.profile-tabs {
padding: 1rem;
}
.tab-content {
padding: 1rem;
}
padding:1rem;
gap:0.5rem;
}
.material-icons-round {
font-size: 20px;
vertical-align: middle;
.school-info {
grid-area:school;
}
.user-profile {
grid-area:user;
}
.app-grid {
grid-template-columns:1fr;
}
.profile-tabs {
padding:1rem;
}
.tab-content {
padding:1rem;
}
}.material-icons-round {
font-size:20px;
vertical-align:middle;
}
::-webkit-scrollbar {
width: 8px;
height: 8px;
width:8px;
height:8px;
}
::-webkit-scrollbar-track {
background: var(--background);
background:var(--background);
}
::-webkit-scrollbar-thumb {
background: var(--text-secondary);
border-radius: 4px;
background:var(--text-secondary);
border-radius:4px;
}
::-webkit-scrollbar-thumb:hover {
background: var(--text-primary);
}
background:var(--text-primary);
}

View File

@@ -1,6 +1,6 @@
(() => {
function createSecurityTab() {
return `
(() => {
function createSecurityTab() {
return `
<div class="security-content">
<div class="setup-steps">
<div class="step-card">
@@ -95,10 +95,10 @@
</div>
</div>
`;
}
}
function createContactTab() {
return `
return `
<div class="contact-form">
<div class="form-group">
<label class="form-label" for="email">E-mail cím</label>
@@ -115,10 +115,10 @@
</div>
</div>
`;
}
function createPasswordTab() {
return `
}
function createPasswordTab() {
return `
<div class="password-form">
<div class="form-group">
<label class="form-label" for="currentPassword">Jelenlegi jelszó</label>
@@ -138,10 +138,10 @@
</div>
</div>
`;
}
function createSettingsTab() {
return `
}
function createSettingsTab() {
return `
<div class="settings-form">
<div class="form-group">
<label class="form-label">
@@ -155,194 +155,215 @@
</div>
</div>
`;
}
function setupContactForm() {
const form = document.querySelector('.contact-form');
if (!form) return;
const emailInput = form.querySelector('#email');
const phoneInput = form.querySelector('#phone');
const saveButton = form.querySelector('#saveContacts');
emailInput.value = cookieManager.get('userEmail') || '';
phoneInput.value = cookieManager.get('userPhone') || '';
saveButton?.addEventListener('click', async () => {
const email = emailInput.value.trim();
const phone = phoneInput.value.trim();
if (!email) {
alert(LanguageManager.t('profile.email_required'));
return;
}
if (email && !isValidEmail(email)) {
alert(LanguageManager.t('profile.invalid_email'));
return;
}
if (phone && !isValidPhone(phone)) {
alert(LanguageManager.t('profile.invalid_phone'));
return;
}
try {
const response = await fetch('/Adminisztracio/Profil/SaveElerhetosegek', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'RequestVerificationToken': document.querySelector('input[name="__RequestVerificationToken"]').value
},
body: JSON.stringify({ email, phone })
});
if (response.ok) {
alert(LanguageManager.t('profile.contacts_saved'));
} else {
throw new Error(LanguageManager.t('profile.contacts_save_error'));
}
} catch (error) {
console.error('Error saving contacts:', error);
alert(LanguageManager.t('profile.save_error'));
}
});
}
function isValidEmail(email) {
return /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(email);
}
function isValidPhone(phone) {
return /^\+?[0-9\s-]{9,}$/.test(phone);
}
function setupEventListeners() {
document.querySelectorAll('.tab-header').forEach(header => {
header.addEventListener('click', () => {
document.querySelectorAll('.tab-header').forEach(h => h.classList.remove('active'));
document.querySelectorAll('.tab-content').forEach(c => c.classList.remove('active'));
header.classList.add('active');
const targetId = header.dataset.tab;
document.getElementById(`${targetId}-content`).classList.add('active');
});
});
const userBtn = document.querySelector('.user-dropdown-btn');
const userDropdown = document.querySelector('.user-dropdown');
userBtn?.addEventListener('click', (e) => {
e.stopPropagation();
userDropdown?.classList.toggle('show');
});
document.addEventListener('click', () => {
userDropdown?.classList.remove('show');
});
document.getElementById('saveSettings')?.addEventListener('click', async () => {
const hideTips = document.getElementById('hideTips').checked;
try {
const response = await fetch('/Adminisztracio/Profil/SaveTippekBeallitasa', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'RequestVerificationToken': document.querySelector('input[name="__RequestVerificationToken"]').value
},
body: JSON.stringify({ hideTips })
});
if (response.ok) {
alert(LanguageManager.t('profile.settings_saved'));
} else {
throw new Error(LanguageManager.t('profile.settings_save_error'));
}
} catch (error) {
console.error('Error saving settings:', error);
alert(LanguageManager.t('profile.save_error'));
}
});
document.getElementById('savePassword')?.addEventListener('click', async () => {
const currentPassword = document.getElementById('currentPassword').value;
const newPassword = document.getElementById('newPassword').value;
const confirmPassword = document.getElementById('confirmPassword').value;
if (!currentPassword || !newPassword || !confirmPassword) {
alert(LanguageManager.t('profile.fill_all_fields'));
return;
}
if (newPassword !== confirmPassword) {
alert(LanguageManager.t('profile.passwords_not_match'));
return;
}
if (newPassword.length < 8) {
alert(LanguageManager.t('profile.password_min_length'));
return;
}
try {
const response = await fetch('/Adminisztracio/Profil/SaveJelszoModositas', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'RequestVerificationToken': document.querySelector('input[name="__RequestVerificationToken"]').value
},
body: JSON.stringify({
currentPassword,
newPassword,
confirmPassword
})
});
if (response.ok) {
alert(LanguageManager.t('profile.password_changed'));
document.getElementById('currentPassword').value = '';
document.getElementById('newPassword').value = '';
document.getElementById('confirmPassword').value = '';
} else {
throw new Error(LanguageManager.t('profile.password_change_error'));
}
} catch (error) {
console.error('Error changing password:', error);
alert(LanguageManager.t('profile.password_change_error'));
}
});
const timerEl = document.getElementById('logoutTimer');
if (timerEl) {
const startTime = parseInt(timerEl.textContent?.match(/\d+/)?.[0] || "45");
let timeLeft = startTime * 60;
const updateTimer = () => {
const minutes = Math.floor(timeLeft / 60);
const seconds = timeLeft % 60;
timerEl.textContent = `${minutes}:${seconds.toString().padStart(2, '0')}`;
if (timeLeft <= 0) {
window.location.href = '/Home/Logout';
} else {
timeLeft--;
}
};
updateTimer();
setInterval(updateTimer, 1000);
}
function setupContactForm() {
const form = document.querySelector(".contact-form");
if (!form) return;
const emailInput = form.querySelector("#email");
const phoneInput = form.querySelector("#phone");
const saveButton = form.querySelector("#saveContacts");
emailInput.value = cookieManager.get("userEmail") || "";
phoneInput.value = cookieManager.get("userPhone") || "";
saveButton?.addEventListener("click", async () => {
const email = emailInput.value.trim();
const phone = phoneInput.value.trim();
if (!email) {
alert(LanguageManager.t("profile.email_required"));
return;
}
if (email && !isValidEmail(email)) {
alert(LanguageManager.t("profile.invalid_email"));
return;
}
if (phone && !isValidPhone(phone)) {
alert(LanguageManager.t("profile.invalid_phone"));
return;
}
try {
const response = await fetch(
"/Adminisztracio/Profil/SaveElerhetosegek",
{
method: "POST",
headers: {
"Content-Type": "application/json",
RequestVerificationToken: document.querySelector(
'input[name="__RequestVerificationToken"]',
).value,
},
body: JSON.stringify({ email, phone }),
},
);
if (response.ok) {
alert(LanguageManager.t("profile.contacts_saved"));
} else {
throw new Error(LanguageManager.t("profile.contacts_save_error"));
}
} catch (error) {
console.error("Error saving contacts:", error);
alert(LanguageManager.t("profile.save_error"));
}
});
}
function isValidEmail(email) {
return /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(email);
}
function isValidPhone(phone) {
return /^\+?[0-9\s-]{9,}$/.test(phone);
}
function setupEventListeners() {
document.querySelectorAll(".tab-header").forEach((header) => {
header.addEventListener("click", () => {
document
.querySelectorAll(".tab-header")
.forEach((h) => h.classList.remove("active"));
document
.querySelectorAll(".tab-content")
.forEach((c) => c.classList.remove("active"));
header.classList.add("active");
const targetId = header.dataset.tab;
document.getElementById(`${targetId}-content`).classList.add("active");
});
});
const userBtn = document.querySelector(".user-dropdown-btn");
const userDropdown = document.querySelector(".user-dropdown");
userBtn?.addEventListener("click", (e) => {
e.stopPropagation();
userDropdown?.classList.toggle("show");
});
document.addEventListener("click", () => {
userDropdown?.classList.remove("show");
});
document
.getElementById("saveSettings")
?.addEventListener("click", async () => {
const hideTips = document.getElementById("hideTips").checked;
try {
const response = await fetch(
"/Adminisztracio/Profil/SaveTippekBeallitasa",
{
method: "POST",
headers: {
"Content-Type": "application/json",
RequestVerificationToken: document.querySelector(
'input[name="__RequestVerificationToken"]',
).value,
},
body: JSON.stringify({ hideTips }),
},
);
if (response.ok) {
alert(LanguageManager.t("profile.settings_saved"));
} else {
throw new Error(LanguageManager.t("profile.settings_save_error"));
}
} catch (error) {
console.error("Error saving settings:", error);
alert(LanguageManager.t("profile.save_error"));
}
});
document
.getElementById("savePassword")
?.addEventListener("click", async () => {
const currentPassword =
document.getElementById("currentPassword").value;
const newPassword = document.getElementById("newPassword").value;
const confirmPassword =
document.getElementById("confirmPassword").value;
if (!currentPassword || !newPassword || !confirmPassword) {
alert(LanguageManager.t("profile.fill_all_fields"));
return;
}
if (newPassword !== confirmPassword) {
alert(LanguageManager.t("profile.passwords_not_match"));
return;
}
if (newPassword.length < 8) {
alert(LanguageManager.t("profile.password_min_length"));
return;
}
try {
const response = await fetch(
"/Adminisztracio/Profil/SaveJelszoModositas",
{
method: "POST",
headers: {
"Content-Type": "application/json",
RequestVerificationToken: document.querySelector(
'input[name="__RequestVerificationToken"]',
).value,
},
body: JSON.stringify({
currentPassword,
newPassword,
confirmPassword,
}),
},
);
if (response.ok) {
alert(LanguageManager.t("profile.password_changed"));
document.getElementById("currentPassword").value = "";
document.getElementById("newPassword").value = "";
document.getElementById("confirmPassword").value = "";
} else {
throw new Error(LanguageManager.t("profile.password_change_error"));
}
} catch (error) {
console.error("Error changing password:", error);
alert(LanguageManager.t("profile.password_change_error"));
}
});
const timerEl = document.getElementById("logoutTimer");
if (timerEl) {
const startTime = parseInt(
timerEl.textContent?.match(/\d+/)?.[0] || "45",
);
let timeLeft = startTime * 60;
const updateTimer = () => {
const minutes = Math.floor(timeLeft / 60);
const seconds = timeLeft % 60;
timerEl.textContent = `${minutes}:${seconds.toString().padStart(2, "0")}`;
if (timeLeft <= 0) {
window.location.href = "/Home/Logout";
} else {
timeLeft--;
}
};
updateTimer();
setInterval(updateTimer, 1000);
}
function createProfileHTML() {
return `
}
function createProfileHTML() {
return `
<div class="kreta-container">
${createTemplate.header()}
@@ -377,20 +398,19 @@
</main>
</div>
`;
}
async function init() {
if (window.location.pathname.includes("/Adminisztracio/Profil")) {
document.body.innerHTML = createProfileHTML();
setupUserDropdown();
setupMobileNavigation();
setupEventListeners();
setupContactForm();
}
async function init() {
if (window.location.pathname.includes('/Adminisztracio/Profil')) {
createTemplate.importFonts();
document.body.innerHTML = createProfileHTML();
setupUserDropdown();
setupMobileNavigation();
setupEventListeners();
setupContactForm();
}
}
init();
})();
}
init();
})();

View File

@@ -1,354 +1,275 @@
* {
box-sizing: border-box;
margin: 0;
padding: 0;
box-sizing:border-box;
margin:0;
padding:0;
}
body {
color: var(--text-primary);
background-color: var(--background) !important;
font-family: "Montserrat", serif !important;
min-height: 100vh;
font-size: 16px;
color:var(--text-primary);
background-color:var(--background) !important;
font-family:"Montserrat",serif !important;
min-height:100vh;
font-size:16px;
}
.kreta-container {
width: 100%;
min-height: 100vh;
display: flex;
flex-direction: column;
padding: clamp(1rem, 3vw, 2rem);
max-width: 1200px;
margin: 0 auto;
width:100%;
min-height:100vh;
display:flex;
flex-direction:column;
padding:clamp(1rem,3vw,2rem);
max-width:1200px;
margin:0 auto;
}
.kreta-header {
display: grid;
grid-template-columns: auto 1fr auto;
align-items: center;
gap: 2rem;
margin-bottom: clamp(2rem, 5vw, 3rem);
display:grid;
grid-template-columns:auto 1fr auto;
align-items:center;
gap:2rem;
margin-bottom:clamp(2rem,5vw,3rem);
}
.school-info {
display: flex;
flex-direction: column;
gap: 0.5rem;
display:flex;
flex-direction:column;
gap:0.5rem;
}
.logo-text {
display: flex;
align-items: center;
font-size: 1.5rem;
font-weight: 600;
color: var(--text-primary);
margin: 0;
display:flex;
align-items:center;
font-size:1.5rem;
font-weight:600;
color:var(--text-primary);
margin:0;
}
.logo {
width: 32px;
height: 32px;
border-radius: 8px;
margin-right: 0.75rem;
width:32px;
height:32px;
border-radius:8px;
margin-right:0.75rem;
}
.school-details {
color: var(--text-secondary);
font-size: 1.1rem;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
max-width: 300px;
padding-left: 2px;
color:var(--text-secondary);
font-size:1.1rem;
white-space:nowrap;
overflow:hidden;
text-overflow:ellipsis;
max-width:300px;
padding-left:2px;
}
.user-profile {
justify-self: flex-end;
text-align: right;
justify-self:flex-end;
text-align:right;
}
.user-info {
display: flex;
flex-direction: column;
align-items: flex-end;
gap: 4px;
display:flex;
flex-direction:column;
align-items:flex-end;
gap:4px;
}
.user-name, .role-text {
color: var(--text-primary);
font-family: Montserrat;
font-weight: 600;
.user-name,.role-text {
color:var(--text-primary);
font-family:Montserrat;
font-weight:600;
}
.user-name {
font-size: 16px;
font-size:16px;
}
.role-text {
font-size: 20px;
text-align: center;
font-size:20px;
text-align:center;
}
.logout-timer, .role-description {
color: var(--text-secondary);
font-family: Figtree;
font-weight: 500;
line-height: 130%;
.logout-timer,.role-description {
color:var(--text-secondary);
font-family:Figtree;
font-weight:500;
line-height:130%;
}
.logout-timer {
font-size: 14px;
text-align: right;
font-size:14px;
text-align:right;
}
.role-description {
font-size: 16px;
text-align: center;
font-size:16px;
text-align:center;
}
.role-container {
flex: 1;
display: flex;
align-items: center;
flex:1;
display:flex;
align-items:center;
}
.role-grid {
display: grid;
grid-template-columns: 1fr minmax(300px, 1fr);
gap: 1.5rem;
width: 100%;
display:grid;
grid-template-columns:1fr minmax(300px,1fr);
gap:1.5rem;
width:100%;
}
.side-roles {
display: grid;
grid-template-rows: 1fr auto;
gap: 1.5rem;
display:grid;
grid-template-rows:1fr auto;
gap:1.5rem;
}
.role-card {
width: 100%;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
gap: 1.5rem;
padding: 2rem;
background: var(--card-card);
border-radius: 1rem;
cursor: pointer;
text-align: center;
border: none;
box-shadow: 0px 1px var(--shadow-blur) 0px var(--accent-shadow);
transition: all 0.2s ease;
width:100%;
display:flex;
flex-direction:column;
align-items:center;
justify-content:center;
gap:1.5rem;
padding:2rem;
background:var(--card-card);
border-radius:1rem;
cursor:pointer;
text-align:center;
border:none;
box-shadow:0px 1px var(--shadow-blur) 0px var(--accent-shadow);
transition:all 0.2s ease;
}
.role-card[data-role="Ellenorzo"] {
height: 480px;
background: var(--card-card);
height:480px;
background:var(--card-card);
}
.role-card[data-role="DKT"] {
height: 280px;
background: var(--card-card);
box-shadow: 0px 1px var(--shadow-blur) 0px var(--accent-shadow);
height:280px;
background:var(--card-card);
box-shadow:0px 1px var(--shadow-blur) 0px var(--accent-shadow);
}
.logout-card {
height: 180px;
background: var(--error-card);
box-shadow: 0px 1px var(--shadow-blur) 0px var(--accent-shadow);
height:180px;
background:var(--error-card);
box-shadow:0px 1px var(--shadow-blur) 0px var(--accent-shadow);
}
.role-icon {
width: 48px;
height: 48px;
display: flex;
align-items: center;
justify-content: center;
border-radius: 12px;
transition: transform 0.2s ease;
background: var(--accent-15);
width:48px;
height:48px;
display:flex;
align-items:center;
justify-content:center;
border-radius:12px;
transition:transform 0.2s ease;
background:var(--accent-15);
}
.role-icon img {
width: 32px;
height: 32px;
transition: transform 0.2s ease;
width:32px;
height:32px;
transition:transform 0.2s ease;
}
.role-card[data-role="DKT"] .role-icon {
background: var(--warning-15);
background:var(--warning-15);
}
.logout-card .role-icon {
background: var(--error-15);
background:var(--error-15);
}
.role-icon img {
width: 32px;
height: 32px;
transition: transform 0.2s ease;
width:32px;
height:32px;
transition:transform 0.2s ease;
}
.role-card:hover {
transform: translateY(-2px);
transform:translateY(-2px);
}
.role-card:hover .role-icon img {
transform: scale(1.2);
transform:scale(1.2);
}
.role-card:active {
transform: translateY(1px);
box-shadow: 0px 0px var(--shadow-blur) 0px var(--accent-shadow);
transform:translateY(1px);
box-shadow:0px 0px var(--shadow-blur) 0px var(--accent-shadow);
}
.role-card[data-role="Ellenorzo"]:hover {
background-color: var(--accent-15);
background-color:var(--accent-15);
}
.role-card[data-role="DKT"]:hover {
background-color: var(--accent-15);
background-color:var(--accent-15);
}
.role-card[data-role="DKT"]:active {
box-shadow: 0px 0px var(--shadow-blur) 0px var(--accent-shadow);
box-shadow:0px 0px var(--shadow-blur) 0px var(--accent-shadow);
}
.logout-card:hover {
background-color: var(--error-15);
background-color:var(--error-15);
}
.logout-card:active {
box-shadow: 0px 0px var(--shadow-blur) 0px var(--error-shadow);
box-shadow:0px 0px var(--shadow-blur) 0px var(--error-shadow);
}
:root[data-theme="light-blue"] .role-card:hover,
:root[data-theme="light-green"] .role-card:hover {
box-shadow: 0px 1px var(--shadow-blur) 0px var(--accent-shadow);
:root[data-theme="light-blue"] .role-card:hover,:root[data-theme="light-green"] .role-card:hover {
box-shadow:0px 1px var(--shadow-blur) 0px var(--accent-shadow);
}
::-webkit-scrollbar {
width: 8px;
height: 8px;
width:8px;
height:8px;
}
::-webkit-scrollbar-track {
background: var(--background);
background:var(--background);
}
::-webkit-scrollbar-thumb {
background: var(--text-secondary);
border-radius: 4px;
background:var(--text-secondary);
border-radius:4px;
}
::-webkit-scrollbar-thumb:hover {
background: var(--text-primary);
background:var(--text-primary);
}
@keyframes fadeIn {
from {
opacity: 0;
transform: translateY(-10px);
}
to {
opacity: 1;
transform: translateY(0);
}
opacity:0;
transform:translateY(-10px);
}
@media (max-width: 1200px) {
to {
opacity:1;
transform:translateY(0);
}
}@media (max-width:1200px) {
.role-grid {
grid-template-columns: 1fr 280px;
}
grid-template-columns:1fr 280px;
}
@media (max-width: 900px) {
}@media (max-width:900px) {
.role-grid {
grid-template-columns: 1fr;
}
.side-roles {
grid-template-columns: 1fr 1fr;
grid-template-rows: none;
}
.role-card[data-role="Ellenorzo"],
.role-card[data-role="DKT"],
.logout-card {
height: 300px;
}
grid-template-columns:1fr;
}
@media (max-width: 768px) {
.side-roles {
grid-template-columns:1fr 1fr;
grid-template-rows:none;
}
.role-card[data-role="Ellenorzo"],.role-card[data-role="DKT"],.logout-card {
height:300px;
}
}@media (max-width:768px) {
.kreta-header {
grid-template-columns: 1fr auto;
gap: 1rem;
}
.school-info {
max-width: 60%;
}
.school-details {
max-width: 200px;
font-size: 1rem;
}
.logo-text {
font-size: 1.2rem;
}
.logo {
width: 24px;
height: 24px;
}
grid-template-columns:1fr auto;
gap:1rem;
}
@media (max-width: 640px) {
.school-info {
max-width:60%;
}
.school-details {
max-width:200px;
font-size:1rem;
}
.logo-text {
font-size:1.2rem;
}
.logo {
width:24px;
height:24px;
}
}@media (max-width:640px) {
.kreta-container {
padding: 1rem;
}
.side-roles {
grid-template-columns: 1fr;
gap: 1rem;
}
.role-card {
padding: 1.5rem;
}
.role-icon {
width: 40px;
height: 40px;
}
.role-icon img {
width: 24px;
height: 24px;
}
.role-text {
font-size: 1.2rem;
}
.role-description {
font-size: 1rem;
}
padding:1rem;
}
.side-roles {
grid-template-columns:1fr;
gap:1rem;
}
.role-card {
padding:1.5rem;
}
.role-icon {
width:40px;
height:40px;
}
.role-icon img {
width:24px;
height:24px;
}
.role-text {
font-size:1.2rem;
}
.role-description {
font-size:1rem;
}
}

View File

@@ -1,17 +1,17 @@
(() => {
const startLogoutTimer = () => {
let timeLeft = 45 * 60;
const timerElement = document.getElementById('logoutTimer');
const timerElement = document.getElementById("logoutTimer");
const updateTimer = () => {
const minutes = Math.floor(timeLeft / 60);
const seconds = timeLeft % 60;
if (timerElement) {
timerElement.textContent = `${minutes}:${seconds.toString().padStart(2, '0')}`;
timerElement.textContent = `${minutes}:${seconds.toString().padStart(2, "0")}`;
}
timeLeft <= 0 ? window.location.href = '/Home/Logout' : timeLeft--;
timeLeft <= 0 ? (window.location.href = "/Home/Logout") : timeLeft--;
};
updateTimer();
@@ -20,21 +20,24 @@
const handleRoleChange = async (role) => {
try {
const response = await fetch('/Adminisztracio/SzerepkorValaszto/ChangeRole', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ Role: role })
});
const response = await fetch(
"/Adminisztracio/SzerepkorValaszto/ChangeRole",
{
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ Role: role }),
},
);
const data = await response.json();
if (data.Success) {
window.location.assign(data.Url);
} else {
throw new Error('Role change failed');
throw new Error("Role change failed");
}
} catch (error) {
console.error('Error changing role:', error);
alert(LanguageManager.t('roleselect.role_change_error'));
console.error("Error changing role:", error);
alert(LanguageManager.t("roleselect.role_change_error"));
}
};
@@ -43,11 +46,11 @@
<header class="kreta-header">
<div class="school-info">
<p class="logo-text">
<img src=${chrome.runtime.getURL('images/firka_logo.png')} alt="Firka" class="logo">
<img src=${chrome.runtime.getURL("images/firka_logo.png")} alt="Firka" class="logo">
Firka
</p>
<div class="school-details">
<span>${schoolCode || ''} - ${fullSchoolName || 'Iskola'}</span>
<span>${schoolCode || ""} - ${fullSchoolName || "Iskola"}</span>
</div>
</div>
<div class="user-profile">
@@ -63,11 +66,11 @@
<div class="main-role">
<div class="role-card" data-role="Ellenorzo">
<div class="role-icon">
<img src="${chrome.runtime.getURL('icons/naplo.svg')}" alt="Napló ikon">
<img src="${chrome.runtime.getURL("icons/naplo.svg")}" alt="Napló ikon">
</div>
<div class="role-text">
${LanguageManager.t('roleselect.student_book')}
<div class="role-description">${LanguageManager.t('roleselect.student_description')}</div>
${LanguageManager.t("roleselect.student_book")}
<div class="role-description">${LanguageManager.t("roleselect.student_description")}</div>
</div>
</div>
</div>
@@ -75,21 +78,21 @@
<div class="side-roles">
<div class="role-card" data-role="DKT">
<div class="role-icon">
<img src="${chrome.runtime.getURL('icons/dkt.svg')}" alt="DKT ikon">
<img src="${chrome.runtime.getURL("icons/dkt.svg")}" alt="DKT ikon">
</div>
<div class="role-text">
${LanguageManager.t('roleselect.dkt_title')}
<div class="role-description">${LanguageManager.t('roleselect.dkt_description')}</div>
${LanguageManager.t("roleselect.dkt_title")}
<div class="role-description">${LanguageManager.t("roleselect.dkt_description")}</div>
</div>
</div>
<div class="role-card logout-card">
<div class="role-icon">
<img src="${chrome.runtime.getURL('icons/logout.svg')}" alt="Kijelentkezés ikon">
<img src="${chrome.runtime.getURL("icons/logout.svg")}" alt="Kijelentkezés ikon">
</div>
<div class="role-text">
${LanguageManager.t('roleselect.logout_title')}
<div class="role-description">${LanguageManager.t('roleselect.logout_description')}</div>
${LanguageManager.t("roleselect.logout_title")}
<div class="role-description">${LanguageManager.t("roleselect.logout_description")}</div>
</div>
</div>
</div>
@@ -100,65 +103,72 @@
const transformRoleSelectPage = async () => {
try {
if (document.readyState !== 'complete') {
await new Promise(resolve => window.addEventListener('load', resolve));
if (document.readyState !== "complete") {
await new Promise((resolve) =>
window.addEventListener("load", resolve),
);
}
const schoolNameEl = document.querySelector('.IntezmenyNev');
const schoolName = schoolNameEl?.textContent.trim() || 'Iskola neve';
const [schoolCode, fullSchoolName] = schoolName.split(' - ');
const schoolNameEl = document.querySelector(".IntezmenyNev");
const schoolName = schoolNameEl?.textContent.trim() || "Iskola neve";
const [schoolCode, fullSchoolName] = schoolName.split(" - ");
const schoolSubdomain = window.location.hostname.split('.')[0];
const schoolSubdomain = window.location.hostname.split(".")[0];
const userNameEl = document.querySelector('.UserName');
const userName = userNameEl?.textContent.trim() || LanguageManager.t('common.username');
const userNameEl = document.querySelector(".UserName");
const userName =
userNameEl?.textContent.trim() || LanguageManager.t("common.username");
if (schoolCode && fullSchoolName) {
cookieManager.set('schoolCode', schoolCode);
cookieManager.set('schoolName', fullSchoolName);
cookieManager.set('schoolSubdomain', schoolSubdomain);
cookieManager.set("schoolCode", schoolCode);
cookieManager.set("schoolName", fullSchoolName);
cookieManager.set("schoolSubdomain", schoolSubdomain);
}
if (userName) {
cookieManager.set('userName', userName);
cookieManager.set("userName", userName);
}
document.body.innerHTML = createHTML(schoolCode, fullSchoolName, userName);
document.body.innerHTML = createHTML(
schoolCode,
fullSchoolName,
userName,
);
createTemplate.importFonts();
const timerInterval = startLogoutTimer();
document.querySelector('.role-card[data-role="Ellenorzo"]')?.addEventListener('click', () => {
handleRoleChange('Ellenorzo');
});
document
.querySelector('.role-card[data-role="Ellenorzo"]')
?.addEventListener("click", () => {
handleRoleChange("Ellenorzo");
});
document.querySelector('.role-card[data-role="DKT"]')?.addEventListener('click', () => {
window.location.href = '/Adminisztracio/BelepesKezelo/DKTTanuloOrGondviselo';
});
document.querySelector('.logout-card')?.addEventListener('click', async () => {
try {
clearInterval(timerInterval);
await fetch('/Home/LogOut', { method: 'POST' });
} catch {
window.location.replace("https://idp.e-kreta.hu/Account/Logout");
} finally {
window.location.replace("https://idp.e-kreta.hu/Account/Logout");
}
});
document
.querySelector('.role-card[data-role="DKT"]')
?.addEventListener("click", () => {
window.location.href =
"/Adminisztracio/BelepesKezelo/DKTTanuloOrGondviselo";
});
document
.querySelector(".logout-card")
?.addEventListener("click", async () => {
try {
clearInterval(timerInterval);
await fetch("/Home/LogOut", { method: "POST" });
} catch {
window.location.replace("https://idp.e-kreta.hu/Account/Logout");
} finally {
window.location.replace("https://idp.e-kreta.hu/Account/Logout");
}
});
} catch (error) {
console.error('Error transforming page:', error);
console.error("Error transforming page:", error);
}
};
if (window.location.href.includes('/Adminisztracio/BelepesKezelo')) {
if (window.location.href.includes("/Adminisztracio/BelepesKezelo")) {
transformRoleSelectPage();
}
})();
})();

View File

@@ -1,222 +1,195 @@
/* Hide original elements */
header, footer, .page-title, .card-kreta {
display: none !important;
header,footer,.page-title,.card-kreta {
display:none !important;
}
* {
box-sizing: border-box;
margin: 0;
padding: 0;
box-sizing:border-box;
margin:0;
padding:0;
}
body {
margin: 0;
padding: 0;
color: var(--text-primary);
background-color: var(--background) !important;
font-family: "Montserrat", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif !important;
min-height: 100vh;
font-size: 16px;
display: flex;
align-items: center;
justify-content: center;
margin:0;
padding:0;
color:var(--text-primary);
background-color:var(--background) !important;
font-family:"Montserrat",-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,sans-serif !important;
min-height:100vh;
font-size:16px;
display:flex;
align-items:center;
justify-content:center;
}
/* Firka search page styling */
.firka-search-wrapper {
width: 90%;
max-width: 500px;
padding: 0;
margin: 0 auto;
display: flex;
flex-direction: column;
align-items: center;
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
width:90%;
max-width:500px;
padding:0;
margin:0 auto;
display:flex;
flex-direction:column;
align-items:center;
position:absolute;
top:50%;
left:50%;
transform:translate(-50%,-50%);
}
/* Firka header styling */
.firka-header {
display: flex;
flex-direction: column;
align-items: center;
gap: 8px;
margin: 0;
background: var(--card-card) !important;
padding: 24px;
border-radius: 24px 24px 0 0;
width: 100%;
box-shadow: 0px 1px var(--shadow-blur) 0px var(--accent-shadow);
display:flex;
flex-direction:column;
align-items:center;
gap:8px;
margin:0;
background:var(--card-card) !important;
padding:24px;
border-radius:24px 24px 0 0;
width:100%;
box-shadow:0px 1px var(--shadow-blur) 0px var(--accent-shadow);
}
.logo-text {
color: var(--text-primary);
text-align: center;
font-family: Montserrat;
font-size: 20px;
font-style: normal;
font-weight: 700;
line-height: normal;
display: flex;
align-items: center;
gap: 8px;
color:var(--text-primary);
text-align:center;
font-family:Montserrat;
font-size:20px;
font-style:normal;
font-weight:700;
line-height:normal;
display:flex;
align-items:center;
gap:8px;
}
.logo {
width: 32px;
height: 32px;
width:32px;
height:32px;
}
.search-title {
color: var(--text-primary);
text-align: center;
font-family: Montserrat;
font-size: 24px;
font-style: normal;
font-weight: 600;
line-height: normal;
margin: 8px 0;
color:var(--text-primary);
text-align:center;
font-family:Montserrat;
font-size:24px;
font-style:normal;
font-weight:600;
line-height:normal;
margin:8px 0;
}
/* Form container styling */
.firka-form-container {
background: var(--card-card);
padding: 0 24px 24px 24px;
border-radius: 0 0 24px 24px;
width: 100%;
box-shadow: 0px 1px var(--shadow-blur) 0px var(--accent-shadow);
background:var(--card-card);
padding:0 24px 24px 24px;
border-radius:0 0 24px 24px;
width:100%;
box-shadow:0px 1px var(--shadow-blur) 0px var(--accent-shadow);
}
/* Form styling */
form {
width: 100%;
width:100%;
}
.form-control {
background-color: var(--button-secondaryFill) !important;
border: 1px solid var(--accent-15) !important;
border-radius: 12px !important;
color: var(--text-primary) !important;
padding: 12px 16px !important;
font-family: Montserrat !important;
font-size: 16px !important;
font-weight: 400 !important;
height: auto !important;
transition: border-color 0.2s ease-in-out, box-shadow 0.2s ease-in-out;
background-color:var(--button-secondaryFill) !important;
border:1px solid var(--accent-15) !important;
border-radius:12px !important;
color:var(--text-primary) !important;
padding:12px 16px !important;
font-family:Montserrat !important;
font-size:16px !important;
font-weight:400 !important;
height:auto !important;
transition:border-color 0.2s ease-in-out,box-shadow 0.2s ease-in-out;
}
.form-control:focus {
border-color: var(--accent-accent) !important;
box-shadow: 0 0 0 2px var(--accent-15) !important;
outline: none !important;
border-color:var(--accent-accent) !important;
box-shadow:0 0 0 2px var(--accent-15) !important;
outline:none !important;
}
.form-control::placeholder {
color: var(--text-teritary) !important;
color:var(--text-teritary) !important;
}
/* Autocomplete dropdown styling */
.dropdown-menu {
background-color: var(--card-card) !important;
border: 1px solid var(--accent-15) !important;
border-radius: 12px !important;
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1) !important;
padding: 8px !important;
max-height: 300px !important;
overflow-y: auto !important;
width: 100% !important;
background-color:var(--card-card) !important;
border:1px solid var(--accent-15) !important;
border-radius:12px !important;
box-shadow:0 4px 8px rgba(0,0,0,0.1) !important;
padding:8px !important;
max-height:300px !important;
overflow-y:auto !important;
width:100% !important;
}
.dropdown-item {
color: var(--text-primary) !important;
padding: 10px 16px !important;
border-radius: 8px !important;
margin-bottom: 4px !important;
font-family: Montserrat !important;
font-size: 14px !important;
transition: background-color 0.2s ease-in-out !important;
color:var(--text-primary) !important;
padding:10px 16px !important;
border-radius:8px !important;
margin-bottom:4px !important;
font-family:Montserrat !important;
font-size:14px !important;
transition:background-color 0.2s ease-in-out !important;
}
li.dropdown-item:hover, li.dropdown-item:focus {
background-color: var(--accent-15) !important;
color: var(--text-primary) !important;
li.dropdown-item:hover,li.dropdown-item:focus {
background-color:var(--accent-15) !important;
color:var(--text-primary) !important;
}
a.dropdown-item:hover, a.dropdown-item:focus {
background-color: #00000000 !important;
a.dropdown-item:hover,a.dropdown-item:focus {
background-color:#00000000 !important;
}
.dropdown-item.active {
background-color: var(--accent-accent) !important;
color: white !important;
background-color:var(--accent-accent) !important;
color:white !important;
}
/* Button styling */
.btn-kreta {
background-color: var(--accent-accent) !important;
color: white !important;
border: none !important;
border-radius: 12px !important;
padding: 12px 24px !important;
font-family: Montserrat !important;
font-size: 16px !important;
font-weight: 600 !important;
cursor: pointer !important;
transition: background-color 0.2s ease-in-out, transform 0.1s ease-in-out !important;
display: inline-flex !important;
align-items: center !important;
justify-content: center !important;
background-color:var(--accent-accent) !important;
color:white !important;
border:none !important;
border-radius:12px !important;
padding:12px 24px !important;
font-family:Montserrat !important;
font-size:16px !important;
font-weight:600 !important;
cursor:pointer !important;
transition:background-color 0.2s ease-in-out,transform 0.1s ease-in-out !important;
display:inline-flex !important;
align-items:center !important;
justify-content:center !important;
}
.btn-kreta:hover {
background-color: var(--accent-secondary) !important;
transform: translateY(-1px) !important;
background-color:var(--accent-secondary) !important;
transform:translateY(-1px) !important;
}
.btn-kreta:active {
transform: translateY(1px) !important;
transform:translateY(1px) !important;
}
.btn-kreta:disabled {
background-color: var(--text-teritary) !important;
cursor: not-allowed !important;
transform: none !important;
background-color:var(--text-teritary) !important;
cursor:not-allowed !important;
transform:none !important;
}
/* Footer styling */
.firka-footer {
margin-top: 16px;
text-align: center;
width: 100%;
margin-top:16px;
text-align:center;
width:100%;
}
.privacy-link {
color: var(--text-secondary);
font-family: Montserrat;
font-size: 14px;
text-decoration: none;
transition: color 0.2s ease-in-out;
color:var(--text-secondary);
font-family:Montserrat;
font-size:14px;
text-decoration:none;
transition:color 0.2s ease-in-out;
}
.privacy-link:hover {
color: var(--accent-accent);
text-decoration: underline;
color:var(--accent-accent);
text-decoration:underline;
}
/* Responsive adjustments */
@media (max-width: 576px) {
@media (max-width:576px) {
.firka-search-wrapper {
width: 95%;
}
.search-title {
font-size: 20px;
}
.btn-kreta {
padding: 10px 20px !important;
font-size: 14px !important;
}
width:95%;
}
.search-title {
font-size:20px;
}
.btn-kreta {
padding:10px 20px !important;
font-size:14px !important;
}
}

View File

@@ -1,7 +1,7 @@
function initializeTransformation() {
const form = document.querySelector('form');
const autocomplete = document.querySelector('.autocomplete');
const form = document.querySelector("form");
const autocomplete = document.querySelector(".autocomplete");
if (form && autocomplete) {
applyFirkaStyling();
} else {
@@ -9,46 +9,54 @@ function initializeTransformation() {
}
}
document.addEventListener('DOMContentLoaded', () => {
document.addEventListener("DOMContentLoaded", () => {
setTimeout(initializeTransformation, 1000);
});
if (document.readyState === 'complete' || document.readyState === 'interactive') {
if (
document.readyState === "complete" ||
document.readyState === "interactive"
) {
setTimeout(initializeTransformation, 1000);
}
function applyFirkaStyling() {
try {
const theme = cookieManager.get('themePreference') || localStorage.getItem('themePreference') || 'light-green';
document.documentElement.setAttribute('data-theme', theme);
if (typeof loadingScreen !== 'undefined') {
const theme =
cookieManager.get("themePreference") ||
localStorage.getItem("themePreference") ||
"light-green";
document.documentElement.setAttribute("data-theme", theme);
if (typeof loadingScreen !== "undefined") {
loadingScreen.hide();
}
const originalForm = document.querySelector('form');
const instituteInput = document.querySelector('.autocomplete');
const redirectButton = document.getElementById('redirectToInstitute');
const instituteCodeInput = document.querySelector('.autocomplete-value');
const requestToken = document.querySelector('input[name="__RequestVerificationToken"]');
const searchWrapper = document.createElement('div');
searchWrapper.className = 'firka-search-wrapper';
const firkaHeader = document.createElement('div');
firkaHeader.className = 'firka-header';
const originalForm = document.querySelector("form");
const instituteInput = document.querySelector(".autocomplete");
const redirectButton = document.getElementById("redirectToInstitute");
const instituteCodeInput = document.querySelector(".autocomplete-value");
const requestToken = document.querySelector(
'input[name="__RequestVerificationToken"]',
);
const searchWrapper = document.createElement("div");
searchWrapper.className = "firka-search-wrapper";
const firkaHeader = document.createElement("div");
firkaHeader.className = "firka-header";
firkaHeader.innerHTML = `
<p class="logo-text">
<img src="${chrome.runtime.getURL('images/firka_logo.png')}" alt="Firka" class="logo">
<img src="${chrome.runtime.getURL("images/firka_logo.png")}" alt="Firka" class="logo">
Firka
</p>
<h1 class="search-title">Válassz iskolát</h1>
`;
const formContainer = document.createElement('div');
formContainer.className = 'firka-form-container';
const firkaFooter = document.createElement('div');
firkaFooter.className = 'firka-footer';
const formContainer = document.createElement("div");
formContainer.className = "firka-form-container";
const firkaFooter = document.createElement("div");
firkaFooter.className = "firka-footer";
firkaFooter.innerHTML = `
<a href="https://tudasbazis.ekreta.hu/pages/viewpage.action?pageId=4064926"
target="_blank" class="privacy-link">Adatkezelési tájékoztató</a>
`;
const existingWrapper = document.querySelector('.firka-search-wrapper');
const existingWrapper = document.querySelector(".firka-search-wrapper");
if (existingWrapper) {
existingWrapper.remove();
}
@@ -61,33 +69,33 @@ function applyFirkaStyling() {
document.body.appendChild(searchWrapper);
setupAutocompleteListeners();
if (redirectButton) {
redirectButton.addEventListener('click', function(event) {
redirectButton.addEventListener("click", function (event) {
if (!instituteCodeInput.value) {
event.preventDefault();
alert(LanguageManager.t('search.select_institution'));
alert(LanguageManager.t("search.select_institution"));
}
});
}
observeAutocompleteValue(instituteCodeInput, redirectButton);
} catch (error) {
console.error('Error applying Firka styling:', error);
console.error("Error applying Firka styling:", error);
}
}
function setupAutocompleteListeners() {
const autocompleteInput = document.querySelector('.autocomplete');
const autocompleteValue = document.querySelector('.autocomplete-value');
const redirectButton = document.getElementById('redirectToInstitute');
const autocompleteInput = document.querySelector(".autocomplete");
const autocompleteValue = document.querySelector(".autocomplete-value");
const redirectButton = document.getElementById("redirectToInstitute");
if (autocompleteInput && autocompleteValue) {
const observer = new MutationObserver((mutations) => {
const dropdown = document.querySelector('.autocomplete-dropdown');
const dropdown = document.querySelector(".autocomplete-dropdown");
if (dropdown) {
dropdown.classList.add('dropdown-menu');
const items = dropdown.querySelectorAll('li');
items.forEach(item => {
item.classList.add('dropdown-item');
item.addEventListener('click', () => {
dropdown.classList.add("dropdown-menu");
const items = dropdown.querySelectorAll("li");
items.forEach((item) => {
item.classList.add("dropdown-item");
item.addEventListener("click", () => {
if (redirectButton) {
redirectButton.disabled = false;
}
@@ -95,10 +103,10 @@ function setupAutocompleteListeners() {
});
}
});
observer.observe(document.body, {
childList: true,
subtree: true
subtree: true,
});
}
}
@@ -112,7 +120,7 @@ function observeAutocompleteValue(valueInput, button) {
observer.observe(valueInput, {
attributes: true,
attributeFilter: ['value']
attributeFilter: ["value"],
});
const checkInterval = setInterval(() => {
@@ -121,4 +129,4 @@ function observeAutocompleteValue(valueInput, button) {
clearInterval(checkInterval);
}
}, 500);
}
}

View File

@@ -1,308 +1,250 @@
* {
box-sizing: border-box;
margin: 0;
padding: 0;
box-sizing:border-box;
margin:0;
padding:0;
}
body {
width: 400px;
margin: 0;
padding: 0;
color: var(--text-primary);
background-color: var(--background) !important;
font-family: "Montserrat", serif;
font-size: 14px;
width:400px;
margin:0;
padding:0;
color:var(--text-primary);
background-color:var(--background) !important;
font-family:"Montserrat",serif;
font-size:14px;
}
* {
scrollbar-width: none;
-ms-overflow-style: none;
scrollbar-width:none;
-ms-overflow-style:none;
}
*::-webkit-scrollbar {
display: none;
display:none;
}
.popup-container {
padding: 16px;
padding:16px;
}
.popup-header {
text-align: center;
margin-bottom: 16px;
text-align:center;
margin-bottom:16px;
}
.logo-text {
color: var(--text-primary);
font-size: 20px;
font-weight: 600;
margin: 8px 0;
display: flex;
align-items: center;
justify-content: center;
color:var(--text-primary);
font-size:20px;
font-weight:600;
margin:8px 0;
display:flex;
align-items:center;
justify-content:center;
}
.logo {
width: 20px;
border-radius: 6px;
margin-right: 8px;
width:20px;
border-radius:6px;
margin-right:8px;
}
.settings-card,
.about-card,
.support-card {
background: var(--card-card);
border-radius: 16px;
padding: 16px;
margin-bottom: 16px;
box-shadow: 0px 1px var(--shadow-blur) 0px var(--accent-shadow);
.settings-card,.about-card,.support-card {
background:var(--card-card);
border-radius:16px;
padding:16px;
margin-bottom:16px;
box-shadow:0px 1px var(--shadow-blur) 0px var(--accent-shadow);
}
h2 {
font-size: 16px;
font-weight: 600;
color: var(--text-primary);
margin-bottom: 12px;
background-color: var(--card-card);
font-size:16px;
font-weight:600;
color:var(--text-primary);
margin-bottom:12px;
background-color:var(--card-card);
}
.settings-group {
display: flex;
flex-direction: column;
gap: 16px;
display:flex;
flex-direction:column;
gap:16px;
}
.setting-section {
display: flex;
flex-direction: column;
gap: 12px;
display:flex;
flex-direction:column;
gap:12px;
}
.setting-header {
display: flex;
align-items: center;
gap: 8px;
color: var(--text-primary);
font-weight: 500;
display:flex;
align-items:center;
gap:8px;
color:var(--text-primary);
font-weight:500;
}
.theme-grid,
.language-grid {
display: grid;
grid-template-columns: repeat(2, 1fr);
gap: 12px;
.theme-grid,.language-grid {
display:grid;
grid-template-columns:repeat(2,1fr);
gap:12px;
}
.theme-option,
.language-option {
background: none;
border: none;
padding: 0;
cursor: pointer;
display: flex;
flex-direction: column;
align-items: center;
gap: 8px;
transition: transform 0.2s ease;
.theme-option,.language-option {
background:none;
border:none;
padding:0;
cursor:pointer;
display:flex;
flex-direction:column;
align-items:center;
gap:8px;
transition:transform 0.2s ease;
}
.theme-option:hover,
.language-option:hover {
transform: translateY(-2px);
.theme-option:hover,.language-option:hover {
transform:translateY(-2px);
}
.theme-option.active .theme-preview {
outline: 2px solid var(--accent-accent);
outline-offset: 2px;
outline:2px solid var(--accent-accent);
outline-offset:2px;
}
.language-option.active .language-preview {
outline: 2px solid var(--accent-accent);
outline-offset: 2px;
outline:2px solid var(--accent-accent);
outline-offset:2px;
}
.theme-preview {
width: 100%;
height: 100px;
border-radius: 8px;
overflow: hidden;
position: relative;
width:100%;
height:100px;
border-radius:8px;
overflow:hidden;
position:relative;
}
.theme-option.disabled {
opacity: 0.5;
cursor: not-allowed;
position: relative;
opacity:0.5;
cursor:not-allowed;
position:relative;
}
.theme-option.disabled::after {
content: "";
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
background-color: rgba(0, 0, 0, 0.1);
border-radius: 8px;
content:"";
position:absolute;
top:0;
left:0;
width:100%;
height:100%;
background-color:rgba(0,0,0,0.1);
border-radius:8px;
}
.language-option {
background: var(--card-card);
border: 1px solid var(--border-border);
border-radius: 8px;
padding: 12px;
transition: all 0.2s ease;
background:var(--card-card);
border:1px solid var(--border-border);
border-radius:8px;
padding:12px;
transition:all 0.2s ease;
}
.language-option:hover {
background: var(--card-hover);
border-color: var(--accent-accent);
background:var(--card-hover);
border-color:var(--accent-accent);
}
.language-option.active {
background: var(--accent-accent);
border-color: var(--accent-accent);
color: white;
background:var(--accent-accent);
border-color:var(--accent-accent);
color:white;
}
.language-name {
color: var(--text-primary);
font-size: 12px;
font-weight: 500;
color:var(--text-primary);
font-size:12px;
font-weight:500;
}
.theme-preview.light-blue {
background: #DAE4F7;
background:#DAE4F7;
}
.theme-preview.light-blue .preview-header {
background: #EDF3FF;
background:#EDF3FF;
}
.theme-preview.light-blue .preview-card {
background: #FBFCFF;
background:#FBFCFF;
}
.theme-preview.light-green {
background: #FAFFF0;
background:#FAFFF0;
}
.theme-preview.light-green .preview-header {
background: #F3FBDE;
background:#F3FBDE;
}
.theme-preview.light-green .preview-card {
background: #FEFFFD;
background:#FEFFFD;
}
.theme-preview.dark-blue {
background: #070A0E;
background:#070A0E;
}
.theme-preview.dark-blue .preview-header {
background: #0F131B;
background:#0F131B;
}
.theme-preview.dark-blue .preview-card {
background: #131822;
background:#131822;
}
.theme-preview.dark-green {
background: #0D1202;
background:#0D1202;
}
.theme-preview.dark-green .preview-header {
background: #141905;
background:#141905;
}
.theme-preview.dark-green .preview-card {
background: #20290b;
background:#20290b;
}
.preview-header {
height: 30%;
width: 100%;
height:30%;
width:100%;
}
.preview-content {
padding: 8px;
padding:8px;
}
.preview-card {
height: 30px;
border-radius: 4px;
height:30px;
border-radius:4px;
}
.theme-name {
color: var(--text-primary);
font-size: 12px;
font-weight: 500;
color:var(--text-primary);
font-size:12px;
font-weight:500;
}
.about-content,
.support-content {
color: var(--text-secondary);
font-size: 14px;
line-height: 1.5;
.about-content,.support-content {
color:var(--text-secondary);
font-size:14px;
line-height:1.5;
}
.about-content p,
.support-content p {
margin-bottom: 12px;
.about-content p,.support-content p {
margin-bottom:12px;
}
.github-link {
display: inline-flex;
align-items: center;
gap: 6px;
color: var(--accent-accent);
text-decoration: none;
font-weight: 500;
transition: color 0.2s;
display:inline-flex;
align-items:center;
gap:6px;
color:var(--accent-accent);
text-decoration:none;
font-weight:500;
transition:color 0.2s;
}
.github-link:hover {
color: var(--accent-secondary);
color:var(--accent-secondary);
}
.support-buttons {
display: flex;
gap: 8px;
margin-top: 12px;
display:flex;
gap:8px;
margin-top:12px;
}
.support-button {
flex: 1;
display: flex;
align-items: center;
justify-content: center;
gap: 6px;
padding: 8px;
background: var(--accent-15);
color: var(--text-primary);
text-decoration: none;
border-radius: 8px;
font-weight: 500;
transition: all 0.2s;
flex:1;
display:flex;
align-items:center;
justify-content:center;
gap:6px;
padding:8px;
background:var(--accent-15);
color:var(--text-primary);
text-decoration:none;
border-radius:8px;
font-weight:500;
transition:all 0.2s;
}
.support-button:hover {
background: var(--accent-accent);
color: var(--button-secondaryFill);
background:var(--accent-accent);
color:var(--button-secondaryFill);
}
.popup-footer {
text-align: center;
margin-top: 16px;
text-align:center;
margin-top:16px;
}
.version-info {
color: var(--text-secondary);
font-size: 12px;
color:var(--text-secondary);
font-size:12px;
}
.material-icons-round {
font-size: 18px;
vertical-align: middle;
}
font-size:18px;
vertical-align:middle;
}

View File

@@ -1,181 +1,189 @@
document.addEventListener('DOMContentLoaded', async () => {
while (typeof window.LanguageManager === 'undefined') {
await new Promise(resolve => setTimeout(resolve, 10));
}
function isThemeDisabled(theme) {
const blueThemesUnlocked = localStorage.getItem('blueThemesUnlocked') === 'true';
return (theme === 'default' || theme === 'light-blue' || theme === 'dark-blue') && !blueThemesUnlocked;
}
function updateThemeAvailability() {
const blueThemesUnlocked = localStorage.getItem('blueThemesUnlocked') === 'true';
document.querySelectorAll('.theme-option').forEach(button => {
const theme = button.dataset.theme;
if (theme === 'default' || theme === 'light-blue' || theme === 'dark-blue') {
if (blueThemesUnlocked) {
button.style.display = 'block';
button.classList.remove('disabled');
button.removeAttribute('disabled');
} else {
button.style.display = 'none';
}
}
});
}
function getCookie(name) {
const cookieName = `${name}=`;
const decodedCookie = decodeURIComponent(document.cookie);
const cookieArray = decodedCookie.split(';');
for(let i = 0; i < cookieArray.length; i++) {
let cookie = cookieArray[i];
while (cookie.charAt(0) === ' ') {
cookie = cookie.substring(1);
}
if (cookie.indexOf(cookieName) === 0) {
return cookie.substring(cookieName.length, cookie.length);
}
}
return null;
document.addEventListener("DOMContentLoaded", async () => {
while (typeof window.LanguageManager === "undefined") {
await new Promise((resolve) => setTimeout(resolve, 10));
}
function isThemeDisabled(theme) {
const blueThemesUnlocked =
localStorage.getItem("blueThemesUnlocked") === "true";
return (
(theme === "default" ||
theme === "light-blue" ||
theme === "dark-blue") &&
!blueThemesUnlocked
);
}
function updateThemeAvailability() {
const blueThemesUnlocked =
localStorage.getItem("blueThemesUnlocked") === "true";
document.querySelectorAll(".theme-option").forEach((button) => {
const theme = button.dataset.theme;
if (
theme === "default" ||
theme === "light-blue" ||
theme === "dark-blue"
) {
if (blueThemesUnlocked) {
button.style.display = "block";
button.classList.remove("disabled");
button.removeAttribute("disabled");
} else {
button.style.display = "none";
}
}
});
}
function getCookie(name) {
const cookieName = `${name}=`;
const decodedCookie = decodeURIComponent(document.cookie);
const cookieArray = decodedCookie.split(";");
for (let i = 0; i < cookieArray.length; i++) {
let cookie = cookieArray[i];
while (cookie.charAt(0) === " ") {
cookie = cookie.substring(1);
}
if (cookie.indexOf(cookieName) === 0) {
return cookie.substring(cookieName.length, cookie.length);
}
}
return null;
}
function setCookie(name, value, days = 365) {
const date = new Date();
date.setTime(date.getTime() + (days * 24 * 60 * 60 * 1000));
const expires = `expires=${date.toUTCString()}`;
document.cookie = `${name}=${value}; ${expires}; path=/; domain=.e-kreta.hu`;
const date = new Date();
date.setTime(date.getTime() + days * 24 * 60 * 60 * 1000);
const expires = `expires=${date.toUTCString()}`;
document.cookie = `${name}=${value}; ${expires}; path=/; domain=.e-kreta.hu`;
}
function getCurrentTheme() {
return localStorage.getItem('themePreference') ||
getCookie('themePreference') ||
'light-green';
return (
localStorage.getItem("themePreference") ||
getCookie("themePreference") ||
"light-green"
);
}
function updateThemeButtons(currentTheme) {
document.querySelectorAll('.theme-option').forEach(button => {
const theme = button.dataset.theme;
button.classList.toggle('active', theme === currentTheme);
});
updateThemeAvailability();
document.querySelectorAll(".theme-option").forEach((button) => {
const theme = button.dataset.theme;
button.classList.toggle("active", theme === currentTheme);
});
updateThemeAvailability();
}
function getCurrentLanguage() {
return localStorage.getItem('languagePreference') ||
getCookie('languagePreference') ||
'hu';
return (
localStorage.getItem("languagePreference") ||
getCookie("languagePreference") ||
"hu"
);
}
function updateLanguageButtons(currentLanguage) {
document.querySelectorAll('.language-option').forEach(button => {
const language = button.dataset.language;
button.classList.toggle('active', language === currentLanguage);
});
document.querySelectorAll(".language-option").forEach((button) => {
const language = button.dataset.language;
button.classList.toggle("active", language === currentLanguage);
});
}
async function applyLanguage(language) {
setCookie('languagePreference', language);
localStorage.setItem('languagePreference', language);
setCookie("languagePreference", language);
localStorage.setItem("languagePreference", language);
updateLanguageButtons(language);
updateLanguageButtons(language);
const tabs = await chrome.tabs.query({});
tabs.forEach(tab => {
chrome.tabs.sendMessage(tab.id, {
action: 'changeLanguage',
language: language
}).catch(() => {
});
});
const tabs = await chrome.tabs.query({});
tabs.forEach((tab) => {
chrome.tabs
.sendMessage(tab.id, {
action: "changeLanguage",
language: language,
})
.catch(() => {});
});
}
async function applyTheme(theme) {
setCookie('themePreference', theme);
localStorage.setItem('themePreference', theme);
document.documentElement.setAttribute('data-theme', theme);
updateThemeButtons(theme);
const tabs = await chrome.tabs.query({});
tabs.forEach(tab => {
chrome.tabs.sendMessage(tab.id, {
action: 'changeTheme',
theme: theme
}).catch(() => {
});
});
setCookie("themePreference", theme);
localStorage.setItem("themePreference", theme);
document.documentElement.setAttribute("data-theme", theme);
updateThemeButtons(theme);
const tabs = await chrome.tabs.query({});
tabs.forEach((tab) => {
chrome.tabs
.sendMessage(tab.id, {
action: "changeTheme",
theme: theme,
})
.catch(() => {});
});
}
const themeButtons = document.querySelectorAll('.theme-option');
themeButtons.forEach(button => {
button.addEventListener('click', () => {
const theme = button.dataset.theme;
if (button.hasAttribute('disabled')) {
alert(window.LanguageManager.t('common.warning') + ': ' + window.LanguageManager.t('settings.theme_not_available'));
return;
}
applyTheme(theme);
});
const themeButtons = document.querySelectorAll(".theme-option");
themeButtons.forEach((button) => {
button.addEventListener("click", () => {
const theme = button.dataset.theme;
if (button.hasAttribute("disabled")) {
alert(
window.LanguageManager.t("common.warning") +
": " +
window.LanguageManager.t("settings.theme_not_available"),
);
return;
}
applyTheme(theme);
});
});
const languageButtons = document.querySelectorAll('.language-option');
languageButtons.forEach(button => {
button.addEventListener('click', () => {
const language = button.dataset.language;
applyLanguage(language);
});
const languageButtons = document.querySelectorAll(".language-option");
languageButtons.forEach((button) => {
button.addEventListener("click", () => {
const language = button.dataset.language;
applyLanguage(language);
});
});
let initialTheme = getCurrentTheme();
if (isThemeDisabled(initialTheme)) {
initialTheme = 'light-green';
initialTheme = "light-green";
}
updateThemeAvailability();
await applyTheme(initialTheme);
const initialLanguage = getCurrentLanguage();
updateLanguageButtons(initialLanguage);
chrome.runtime.onMessage.addListener((message, sender, sendResponse) => {
if (message.action === 'themeChanged') {
updateThemeButtons(message.theme);
document.documentElement.setAttribute('data-theme', message.theme);
}
if (message.action === "themeChanged") {
updateThemeButtons(message.theme);
document.documentElement.setAttribute("data-theme", message.theme);
}
});
const manifest = chrome.runtime.getManifest();
const versionElement = document.getElementById('version');
const versionElement = document.getElementById("version");
versionElement.textContent = `v${manifest.version}`;
let clickCount = 0;
versionElement.addEventListener('click', () => {
clickCount++;
if (clickCount >= 5) {
localStorage.setItem('blueThemesUnlocked', 'true');
updateThemeAvailability();
const notification = document.createElement('div');
notification.style.cssText = `
versionElement.addEventListener("click", () => {
clickCount++;
if (clickCount >= 5) {
localStorage.setItem("blueThemesUnlocked", "true");
updateThemeAvailability();
const notification = document.createElement("div");
notification.style.cssText = `
position: fixed;
top: 20px;
right: 20px;
@@ -189,54 +197,54 @@ document.addEventListener('DOMContentLoaded', async () => {
box-shadow: 0 4px 12px rgba(0,0,0,0.15);
animation: slideIn 0.3s ease-out;
`;
notification.textContent = window.LanguageManager.t('common.success') + ': ' + window.LanguageManager.t('settings.blue_themes_unlocked');
const style = document.createElement('style');
style.textContent = `
notification.textContent =
window.LanguageManager.t("common.success") +
": " +
window.LanguageManager.t("settings.blue_themes_unlocked");
const style = document.createElement("style");
style.textContent = `
@keyframes slideIn {
from { transform: translateX(100%); opacity: 0; }
to { transform: translateX(0); opacity: 1; }
}
`;
document.head.appendChild(style);
document.body.appendChild(notification);
setTimeout(() => {
notification.remove();
style.remove();
}, 3000);
clickCount = 0;
document.head.appendChild(style);
document.body.appendChild(notification);
setTimeout(() => {
notification.remove();
style.remove();
}, 3000);
clickCount = 0;
}
});
themeButtons.forEach((button) => {
button.addEventListener("mouseover", () => {
if (!button.hasAttribute("disabled")) {
button.style.transform = "translateY(-2px)";
}
});
button.addEventListener("mouseout", () => {
button.style.transform = "translateY(0)";
});
});
themeButtons.forEach(button => {
button.addEventListener('mouseover', () => {
if (!button.hasAttribute('disabled')) {
button.style.transform = 'translateY(-2px)';
}
});
button.addEventListener('mouseout', () => {
button.style.transform = 'translateY(0)';
});
languageButtons.forEach((button) => {
button.addEventListener("mouseover", () => {
button.style.transform = "translateY(-2px)";
});
button.addEventListener("mouseout", () => {
button.style.transform = "translateY(0)";
});
});
languageButtons.forEach(button => {
button.addEventListener('mouseover', () => {
button.style.transform = 'translateY(-2px)';
});
button.addEventListener('mouseout', () => {
button.style.transform = 'translateY(0)';
});
window.addEventListener("languageChanged", (event) => {
updateLanguageButtons(event.detail.language);
});
window.addEventListener('languageChanged', (event) => {
updateLanguageButtons(event.detail.language);
});
});
});

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -1,25 +1,25 @@
const cookieManager = {
get(name) {
const cookieName = `${name}=`;
const decodedCookie = decodeURIComponent(document.cookie);
const cookieArray = decodedCookie.split(';');
get(name) {
const cookieName = `${name}=`;
const decodedCookie = decodeURIComponent(document.cookie);
const cookieArray = decodedCookie.split(";");
for(let i = 0; i < cookieArray.length; i++) {
let cookie = cookieArray[i];
while (cookie.charAt(0) === ' ') {
cookie = cookie.substring(1);
}
if (cookie.indexOf(cookieName) === 0) {
return cookie.substring(cookieName.length, cookie.length);
}
}
return null;
},
set(name, value, days = 365) {
const date = new Date();
date.setTime(date.getTime() + (days * 24 * 60 * 60 * 1000));
const expires = `expires=${date.toUTCString()}`;
document.cookie = `${name}=${value}; ${expires}; path=/; domain=.e-kreta.hu`;
for (let i = 0; i < cookieArray.length; i++) {
let cookie = cookieArray[i];
while (cookie.charAt(0) === " ") {
cookie = cookie.substring(1);
}
if (cookie.indexOf(cookieName) === 0) {
return cookie.substring(cookieName.length, cookie.length);
}
}
}
return null;
},
set(name, value, days = 365) {
const date = new Date();
date.setTime(date.getTime() + days * 24 * 60 * 60 * 1000);
const expires = `expires=${date.toUTCString()}`;
document.cookie = `${name}=${value}; ${expires}; path=/; domain=.e-kreta.hu`;
},
};

View File

@@ -1,26 +1,26 @@
const createTemplate = {
header() {
const data = {
schoolInfo: {
name: cookieManager.get('schoolName') || 'Iskola',
id: cookieManager.get('schoolCode') || ''
},
userData: {
name: cookieManager.get('userName') || 'Felhasználó',
time: document.querySelector('.usermenu_timer')?.textContent?.trim() || '45:00',
email: cookieManager.get('userEmail') || ''
}
};
header() {
const data = {
schoolInfo: {
name: cookieManager.get("schoolName") || "Iskola",
id: cookieManager.get("schoolCode") || "",
},
userData: {
name: cookieManager.get("userName") || "Felhasználó",
time:
document.querySelector(".usermenu_timer")?.textContent?.trim() ||
"45:00",
email: cookieManager.get("userEmail") || "",
},
};
const schoolNameFull = `${data.schoolInfo.id} - ${data.schoolInfo.name}`;
const shortenedSchoolName = helper.shortenSchoolName(schoolNameFull);
const schoolNameFull = `${data.schoolInfo.id} - ${data.schoolInfo.name}`;
const shortenedSchoolName = helper.shortenSchoolName(schoolNameFull);
const element = `<header class="kreta-header">
const element = `<header class="kreta-header">
<div class="school-info">
<p class="logo-text">
<img src="${chrome.runtime.getURL('images/firka_logo.png')}" alt="Firka" class="logo">
<img src="${chrome.runtime.getURL("images/firka_logo.png")}" alt="Firka" class="logo">
Firka
</p>
<div class="school-details" title="${schoolNameFull}">
@@ -28,7 +28,7 @@ const createTemplate = {
</div>
</div>
<button class="nav-toggle" aria-label="${LanguageManager.t('navigation.nav_toggle')}">
<button class="nav-toggle" aria-label="${LanguageManager.t("navigation.nav_toggle")}">
<svg viewBox="0 0 24 24">
<path d="M3 18h18v-2H3v2zm0-5h18v-2H3v2zm0-7v2h18V6H3z"/>
</svg>
@@ -36,25 +36,25 @@ const createTemplate = {
<nav class="kreta-nav">
<div class="nav-links">
<a href="/Intezmeny/Faliujsag" data-page="dashboard" class="nav-item ${( location.pathname == '/Intezmeny/Faliujsag' ? 'active' : '')}">
<img src="${chrome.runtime.getURL('icons/dashboard-' + ( location.pathname == '/Intezmeny/Faliujsag' ? 'active' : 'inactive') + '.svg')}" alt="${LanguageManager.t('navigation.dashboard')}">
${LanguageManager.t('navigation.dashboard')}
<a href="/Intezmeny/Faliujsag" data-page="dashboard" class="nav-item ${location.pathname == "/Intezmeny/Faliujsag" ? "active" : ""}">
<img src="${chrome.runtime.getURL("icons/dashboard-" + (location.pathname == "/Intezmeny/Faliujsag" ? "active" : "inactive") + ".svg")}" alt="${LanguageManager.t("navigation.dashboard")}">
${LanguageManager.t("navigation.dashboard")}
</a>
<a href="/TanuloErtekeles/Osztalyzatok" data-page="grades" class="nav-item ${( location.pathname == '/TanuloErtekeles/Osztalyzatok' ? 'active' : '')}">
<img src="${chrome.runtime.getURL('icons/grades-' + ( location.pathname == '/TanuloErtekeles/Osztalyzatok' ? 'active' : 'inactive') + '.svg')}" alt="${LanguageManager.t('navigation.grades')}">
${LanguageManager.t('navigation.grades')}
<a href="/TanuloErtekeles/Osztalyzatok" data-page="grades" class="nav-item ${location.pathname == "/TanuloErtekeles/Osztalyzatok" ? "active" : ""}">
<img src="${chrome.runtime.getURL("icons/grades-" + (location.pathname == "/TanuloErtekeles/Osztalyzatok" ? "active" : "inactive") + ".svg")}" alt="${LanguageManager.t("navigation.grades")}">
${LanguageManager.t("navigation.grades")}
</a>
<a href="/Orarend/InformaciokOrarend" data-page="timetable" class="nav-item ${( location.pathname == '/Orarend/InformaciokOrarend' ? 'active' : '')}">
<img src="${chrome.runtime.getURL('icons/timetable-' + ( location.pathname == '/Orarend/InformaciokOrarend' ? 'active' : 'inactive') + '.svg')}" alt="${LanguageManager.t('navigation.timetable')}">
${LanguageManager.t('navigation.timetable')}
<a href="/Orarend/InformaciokOrarend" data-page="timetable" class="nav-item ${location.pathname == "/Orarend/InformaciokOrarend" ? "active" : ""}">
<img src="${chrome.runtime.getURL("icons/timetable-" + (location.pathname == "/Orarend/InformaciokOrarend" ? "active" : "inactive") + ".svg")}" alt="${LanguageManager.t("navigation.timetable")}">
${LanguageManager.t("navigation.timetable")}
</a>
<a href="/Hianyzas/Hianyzasok" data-page="absences" class="nav-item ${( location.pathname == '/Hianyzas/Hianyzasok' ? 'active' : '')}">
<img src="${chrome.runtime.getURL('icons/absences-' + ( location.pathname == '/Hianyzas/Hianyzasok' ? 'active' : 'inactive') + '.svg')}" alt="${LanguageManager.t('navigation.absences')}">
${LanguageManager.t('navigation.absences')}
<a href="/Hianyzas/Hianyzasok" data-page="absences" class="nav-item ${location.pathname == "/Hianyzas/Hianyzasok" ? "active" : ""}">
<img src="${chrome.runtime.getURL("icons/absences-" + (location.pathname == "/Hianyzas/Hianyzasok" ? "active" : "inactive") + ".svg")}" alt="${LanguageManager.t("navigation.absences")}">
${LanguageManager.t("navigation.absences")}
</a>
<a href="/Tanulo/TanuloHaziFeladat" data-page="other" class="nav-item ${( location.pathname == '/Tanulo/TanuloHaziFeladat' ? 'active' : '')}">
<img src="${chrome.runtime.getURL('icons/others.svg')}" alt="${LanguageManager.t('navigation.other')}">
${LanguageManager.t('navigation.other')}
<a href="/Tanulo/TanuloHaziFeladat" data-page="other" class="nav-item ${location.pathname == "/Tanulo/TanuloHaziFeladat" ? "active" : ""}">
<img src="${chrome.runtime.getURL("icons/others.svg")}" alt="${LanguageManager.t("navigation.other")}">
${LanguageManager.t("navigation.other")}
</a>
</div>
</nav>
@@ -68,73 +68,55 @@ const createTemplate = {
</button>
<div class="user-dropdown">
<a href="https://bmszc-puskas.e-kreta.hu/Home/Uzenetek" data-page="messages" class="dropdown-item">
<img src="${chrome.runtime.getURL('icons/messages.svg')}" alt="${LanguageManager.t('navigation.messages')}">
${LanguageManager.t('navigation.messages')}
<img src="${chrome.runtime.getURL("icons/messages.svg")}" alt="${LanguageManager.t("navigation.messages")}">
${LanguageManager.t("navigation.messages")}
</a>
<a href="/Adminisztracio/Profil" data-page="profile" class="dropdown-item">
<img src="${chrome.runtime.getURL('icons/profile.svg')}" alt="${LanguageManager.t('navigation.profile')}">
${LanguageManager.t('navigation.profile')}
<img src="${chrome.runtime.getURL("icons/profile.svg")}" alt="${LanguageManager.t("navigation.profile")}">
${LanguageManager.t("navigation.profile")}
</a>
<a href="#" class="dropdown-item" id="settingsBtn">
<img src="${chrome.runtime.getURL('icons/settings.svg')}" alt="${LanguageManager.t('navigation.settings')}">
${LanguageManager.t('navigation.settings')}
<img src="${chrome.runtime.getURL("icons/settings.svg")}" alt="${LanguageManager.t("navigation.settings")}">
${LanguageManager.t("navigation.settings")}
</a>
<a href="/Home/Logout" data-page="logout" class="dropdown-item">
<img src="${chrome.runtime.getURL('icons/logout.svg')}" alt="${LanguageManager.t('navigation.logout')}">
${LanguageManager.t('navigation.logout')}
<img src="${chrome.runtime.getURL("icons/logout.svg")}" alt="${LanguageManager.t("navigation.logout")}">
${LanguageManager.t("navigation.logout")}
</a>
</div>
</div>
</header>`
</header>`;
const startTime = parseInt(data.userData.time?.match(/\d+/)?.[0] || "45");
let timeLeft = startTime * 60;
const updateTimer = () => {
const minutes = Math.floor(timeLeft / 60);
const seconds = timeLeft % 60;
const timerEl = document.getElementById('logoutTimer');
if (timerEl) {
timerEl.textContent = `${minutes}:${seconds.toString().padStart(2, '0')}`;
}
if (timeLeft <= 0) {
window.location.href = '/Home/Logout';
} else {
timeLeft--;
}
};
const startTime = parseInt(data.userData.time?.match(/\d+/)?.[0] || "45");
let timeLeft = startTime * 60;
setInterval(updateTimer, 1000);
const updateTimer = () => {
const minutes = Math.floor(timeLeft / 60);
const seconds = timeLeft % 60;
const timerEl = document.getElementById("logoutTimer");
if (timerEl) {
timerEl.textContent = `${minutes}:${seconds.toString().padStart(2, "0")}`;
}
return element;
},
if (timeLeft <= 0) {
window.location.href = "/Home/Logout";
} else {
timeLeft--;
}
};
importFonts() {
const links = [
{ rel: 'preconnect', href: 'https://fonts.googleapis.com' },
{ rel: 'preconnect', href: 'https://fonts.gstatic.com', crossorigin: true },
{ rel: 'stylesheet', href: 'https://fonts.googleapis.com/css2?family=Montserrat:ital,wght@0,100..900;1,100..900&display=swap' },
{ rel: 'stylesheet', href: 'https://fonts.googleapis.com/css2?family=Figtree:ital,wght@0,300..900;1,300..900&display=swap' },
{ rel: 'stylesheet', href: 'https://fonts.googleapis.com/icon?family=Material+Icons+Round' }
];
links.forEach(link => {
const linkElement = document.createElement('link');
Object.entries(link).forEach(([key, value]) => {
linkElement[key] = value;
});
document.head.appendChild(linkElement);
});
}
}
setInterval(updateTimer, 1000);
return element;
},
};
document.addEventListener("DOMContentLoaded", async () => {
await helper.waitForElement('#settingsBtn');
document.querySelector('#settingsBtn').addEventListener('click', (e) => {
e.preventDefault();
e.stopPropagation();
const url = chrome.runtime.getURL('settings/index.html');
window.open(url, '_blank', 'width=400,height=600');
});
});
await helper.waitForElement("#settingsBtn");
document.querySelector("#settingsBtn").addEventListener("click", (e) => {
e.preventDefault();
e.stopPropagation();
const url = chrome.runtime.getURL("settings/index.html");
window.open(url, "_blank", "width=400,height=600");
});
});

View File

@@ -1,40 +1,40 @@
const helper = {
shortenSchoolName(name, maxLength = 50) {
if (!name) return '';
if (name.length <= maxLength) return name;
const parts = name.split(' - ');
if (parts.length === 2) {
const [code, fullName] = parts;
if (fullName.length > maxLength - code.length - 3) {
return `${code} - ${fullName.substring(0, maxLength - code.length - 6)}...`;
}
}
return name.substring(0, maxLength - 3) + '...';
},
async waitForElement(selector) {
return new Promise(resolve => {
if (document.querySelector(selector)) {
return resolve(document.querySelector(selector));
}
shortenSchoolName(name, maxLength = 50) {
if (!name) return "";
if (name.length <= maxLength) return name;
const observer = new MutationObserver(mutations => {
if (document.querySelector(selector)) {
observer.disconnect();
resolve(document.querySelector(selector));
}
});
observer.observe(document.body, {
childList: true,
subtree: true
});
});
},
convertTimeToMinutes(timeStr) {
const [hours, minutes] = timeStr.split(':').map(Number);
return hours * 60 + minutes;
const parts = name.split(" - ");
if (parts.length === 2) {
const [code, fullName] = parts;
if (fullName.length > maxLength - code.length - 3) {
return `${code} - ${fullName.substring(0, maxLength - code.length - 6)}...`;
}
}
}
return name.substring(0, maxLength - 3) + "...";
},
async waitForElement(selector) {
return new Promise((resolve) => {
if (document.querySelector(selector)) {
return resolve(document.querySelector(selector));
}
const observer = new MutationObserver((mutations) => {
if (document.querySelector(selector)) {
observer.disconnect();
resolve(document.querySelector(selector));
}
});
observer.observe(document.body, {
childList: true,
subtree: true,
});
});
},
convertTimeToMinutes(timeStr) {
const [hours, minutes] = timeStr.split(":").map(Number);
return hours * 60 + minutes;
},
};

View File

@@ -1,59 +1,53 @@
.modalBckgroundMain {
display: none !important;
display:none !important;
}
body:not(.loaded) {
opacity: 0 !important;
visibility: hidden !important;
height: 100vh !important;
overflow: hidden !important;
opacity:0 !important;
visibility:hidden !important;
height:100vh !important;
overflow:hidden !important;
}
.loading-screen {
position: fixed;
top: 0;
left: 0;
width: 100vw;
height: 100vh;
background-color: var(--background);
z-index: 9999;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
transition: opacity 0.3s ease;
position:fixed;
top:0;
left:0;
width:100vw;
height:100vh;
background-color:var(--background);
z-index:9999;
display:flex;
flex-direction:column;
align-items:center;
justify-content:center;
transition:opacity 0.3s ease;
}
.loading-content {
display: flex;
flex-direction: column;
align-items: center;
gap: 1rem;
display:flex;
flex-direction:column;
align-items:center;
gap:1rem;
}
.loading-logo {
width: 48px;
height: 48px;
border-radius: 16px;
width:48px;
height:48px;
border-radius:16px;
}
.loading-text {
color: var(--text-primary);
text-align: center;
font-family: Montserrat;
font-size: 20px;
font-style: normal;
font-weight: 700;
line-height: normal;
color:var(--text-primary);
text-align:center;
font-family:Montserrat;
font-size:20px;
font-style:normal;
font-weight:700;
line-height:normal;
}
.loading-text2 {
align-self: stretch;
color: var(--text-secondary);
text-align: center;
font-family: Figtree;
font-size: 16px;
font-style: normal;
font-weight: 500;
line-height: 130%;
align-self:stretch;
color:var(--text-secondary);
text-align:center;
font-family:Figtree;
font-size:16px;
font-style:normal;
font-weight:500;
line-height:130%;
}

View File

@@ -1,53 +1,55 @@
const loadingScreen = {
show() {
document.body.classList.remove('loaded');
const existingLoadingScreen = document.querySelector('.loading-screen');
if (existingLoadingScreen) return;
show() {
document.body.classList.remove("loaded");
const existingLoadingScreen = document.querySelector(".loading-screen");
if (existingLoadingScreen) return;
const loadingScreen = document.createElement('div');
loadingScreen.className = 'loading-screen';
loadingScreen.innerHTML = `
const loadingScreen = document.createElement("div");
loadingScreen.className = "loading-screen";
loadingScreen.innerHTML = `
<div class="loading-content">
<img src="${chrome.runtime.getURL('images/loading.gif')}" alt="Firka" class="loading-logo">
<img src="${chrome.runtime.getURL("images/loading.gif")}" alt="Firka" class="loading-logo">
<div class="loading-text" data-i18n="loading.text">Betöltés alatt...</div>
<div class="loading-text2" data-i18n="loading.subtext">Kis türelmet!</div>
</div>
`;
document.body.appendChild(loadingScreen);
document.body.classList.add('loaded');
},
document.body.appendChild(loadingScreen);
document.body.classList.add("loaded");
},
hide() {
document.body.classList.add('loaded');
const loadingScreen = document.querySelector('.loading-screen');
if (loadingScreen) {
loadingScreen.style.opacity = '0';
hide() {
document.body.classList.add("loaded");
const loadingScreen = document.querySelector(".loading-screen");
if (loadingScreen) {
loadingScreen.style.opacity = "0";
const removeLoadingScreen = () => {
if (loadingScreen && loadingScreen.parentNode) {
loadingScreen.remove();
}
};
loadingScreen.addEventListener('transitionend', removeLoadingScreen, { once: true });
setTimeout(removeLoadingScreen, 500);
const removeLoadingScreen = () => {
if (loadingScreen && loadingScreen.parentNode) {
loadingScreen.remove();
}
}
}
};
window.addEventListener('DOMContentLoaded', () => {
const manifest = chrome.runtime.getManifest();
const urls = [];
if (manifest.content_scripts) {
manifest.content_scripts.forEach(script => {
if (script.matches) {
urls.push(...script.matches);
}
});
loadingScreen.addEventListener("transitionend", removeLoadingScreen, {
once: true,
});
setTimeout(removeLoadingScreen, 500);
}
},
};
if (urls.some(url => url.includes(location.pathname))) {
loadingScreen.show();
}
});
window.addEventListener("DOMContentLoaded", () => {
const manifest = chrome.runtime.getManifest();
const urls = [];
if (manifest.content_scripts) {
manifest.content_scripts.forEach((script) => {
if (script.matches) {
urls.push(...script.matches);
}
});
}
if (urls.some((url) => url.includes(location.pathname))) {
loadingScreen.show();
}
});