77 Commits

Author SHA1 Message Date
Zan
f81d821c56 Óra témája és számonkérés megjelenik a modalban (HW WIP) 2025-09-08 23:21:15 +02:00
Zan
0a5439acfd Mark as done, fixes 2025-09-08 23:09:49 +02:00
Zan
dac927cf7d Data collection, firefox 2025-09-08 21:59:59 +02:00
Zan
b4a270a8d2 Firefox addons fix 2025-09-08 21:51:55 +02:00
Zan
110ba0d4fb Delete KRÉTA Iskolai Alaprendszer.html 2025-09-08 19:42:55 +02:00
Zan
1ba976e06e Update manifest.json 2025-09-08 19:35:32 +02:00
Zan
df8adf65de . 2025-09-08 19:32:05 +02:00
Zan
e96c9e1c83 1.3.0 2025-09-01 19:20:21 +02:00
Zan
a3631d749f Navbar open fix and logo fix in settings 2025-09-01 15:52:08 +02:00
Zan
fa7c773393 Added new icons, fixed day notice on timetables 2025-09-01 15:21:15 +02:00
Zan
a39295ae68 test 2025-08-31 20:53:36 +02:00
Zan1456
d722740bdf New layout for absences 2025-08-06 22:56:12 +02:00
Zan1456
1218d3b905 . 2025-08-06 22:48:21 +02:00
Zan1456
bbe8a4b2b3 Minimal fixes 2025-08-06 14:41:22 +02:00
Zan
ec99a3b5c8 Merge pull request #20 from QwIT-Development/firefox
Firefox
2025-08-06 14:12:35 +02:00
Zan
02ffa23e1a Merge branch 'main' into firefox 2025-08-06 14:12:24 +02:00
Zan1456
d7ea449a1b Minimal fixes 2025-08-06 14:06:00 +02:00
Zan1456
e7ec225e18 Updated chart.js 2025-06-14 09:42:33 +02:00
Zan1456
5a9837e655 . 2025-06-14 09:05:07 +02:00
Zan1456
1a340a1950 fixed week select 2025-06-13 14:50:49 +02:00
Zan1456
eef39c28d2 removed unused 2025-06-13 14:49:40 +02:00
Zan1456
89266bc3c9 Fixed week select 2025-06-13 14:41:21 +02:00
Zan1456
5408a1e08a . 2025-06-13 14:02:54 +02:00
Zan1456
6a52c51ece . 2025-06-13 13:59:17 +02:00
Zan1456
107e20f5c1 . 2025-06-13 13:26:21 +02:00
Zan1456
cb54d51b8c Added store logos 2025-06-10 22:58:14 +02:00
Zan1456
8eb7256f5b . 2025-06-10 22:54:27 +02:00
Zan
3510288181 Added firefox addonstore 2025-06-10 22:37:28 +02:00
Zan1456
8c9e1b215f version bump 2025-06-09 16:13:19 +02:00
Zan1456
e930706eb1 Fully working 2025-06-09 16:11:15 +02:00
Zan1456
5340c1dff0 Full rework 2025-06-09 16:10:15 +02:00
Zan1456
f3439a93d0 Merge branch 'main' of https://github.com/QwIT-Development/firka-extension 2025-06-09 13:46:42 +02:00
Zan1456
3e7b7089dd better scrolling 2025-06-09 13:33:44 +02:00
Anchietae
185f486a62 typo 2025-06-09 09:52:03 +02:00
Zan
048f249dc5 Update README.md 2025-06-08 23:29:44 +02:00
Zan1456
5d9ae6971b version dump 2025-06-08 23:24:06 +02:00
Zan1456
42bfa0912f . 2025-06-08 22:47:25 +02:00
Zan1456
0322b31146 Fixed user dropdown 2025-06-08 22:36:02 +02:00
Zan1456
52fc99ca99 navbar fixes 2025-06-08 22:24:13 +02:00
Zan1456
0a65ed3dda Removed logs 2025-06-08 22:23:25 +02:00
Zan1456
5a836947e1 rem cap 2025-06-08 21:42:58 +02:00
Zan1456
ebb291ee87 Title and icon 2025-06-08 21:42:51 +02:00
Zan1456
56dcef30e0 Load back the username at login 2025-06-08 21:32:37 +02:00
Zan1456
cfe6e0fccf search fix 2025-06-04 17:10:55 +02:00
Zan1456
bacf77b506 2fa support 2025-06-04 16:56:54 +02:00
Zan1456
3ee34b90e6 captcha 2025-06-04 16:44:42 +02:00
Zan1456
0e1f97eaaa search 2025-06-04 16:43:32 +02:00
Zan1456
699d2604c6 Update .gitignore 2025-06-04 16:40:14 +02:00
Zan1456
d8f1622b5b search 2025-06-04 16:40:10 +02:00
Zan1456
b69c9f3f6a search 2025-06-04 16:39:50 +02:00
Zan1456
ebf6aa8d61 Revert "typo"
This reverts commit ea5e01ce9c.
2025-06-04 16:38:18 +02:00
Zan1456
0048ebb932 hover fix 2025-06-04 16:35:06 +02:00
Zan1456
a55e40ecf2 rm 2025-06-04 16:30:29 +02:00
Zan1456
ea5e01ce9c typo 2025-06-04 16:29:32 +02:00
Zan1456
c0e738fd8b Merge branch 'main' of https://github.com/QwIT-Development/firka-extension 2025-06-04 16:29:12 +02:00
Zan
842588a0bb Merge pull request #11 from JeromeSchmied/releases-link
ci: add link checker
2025-04-22 15:16:55 +02:00
Jeromos Kovács
be2e7a192b Merge branch 'main' into releases-link 2025-04-21 17:39:09 +02:00
Zan
60ad73ffae Merge pull request #13 from MrS-1302/patch-2
Update build.yml
2025-04-21 09:23:24 +02:00
Mr.S
3a9bbbcb2a Update build.yml 2025-04-03 21:52:39 +02:00
Jeromos Kovács
afb7a3d79b ci: add link checker 2025-03-26 09:40:21 +01:00
Zan
95d50e9297 Merge pull request #12 from JeromeSchmied/firefox-install-docs
add installation instructions for firefox-based browsers
2025-03-25 21:56:33 +01:00
Zan
e88566369a Update README.md 2025-03-25 21:56:04 +01:00
Jeromos Kovács
b9985ccf09 docs(installation): add instructions for firefox-based browsers 2025-03-25 17:46:29 +01:00
Zan
88706017f9 Merge branch 'main' of https://github.com/QwIT-Development/firka-extension 2025-03-25 17:04:44 +01:00
Zan
0aef3950e7 Merge pull request #10 from JeromeSchmied/main
docs: GNU GPLv3 is **not** GNU AGPLv3
2025-03-25 17:01:54 +01:00
Zan
db74cb1a37 Merge pull request #9 from balint1414/main
Hibás fiók linkek szerkesztése
2025-03-25 16:57:05 +01:00
Jeromos Kovács
0d71510c7f docs: GNU GPLv3 is **not** GNU AGPLv3 2025-03-25 16:18:02 +01:00
ee26b6d966 Hibás fiók linkek szerkesztése 2025-03-22 17:12:28 +01:00
Zan
731511d28a gh token fix needed 2025-03-17 21:43:46 +01:00
Zan
79b09cb1ab Automatikus buildelés 2025-03-17 20:49:50 +01:00
Zan
1730c108df Merge pull request #5 from MrS-1302/remove-duplications
duplication fix in css files is not started
removed some enter
2025-03-17 20:34:46 +01:00
MrS-1302
f990e2e899 remove some duplication & faster loading page
duplication fix in css files is not started
removed some enter
2025-03-17 20:03:46 +01:00
Zan
2feef43ef2 Merge pull request #2 from MrS-1302/dev
chart
- fixed incorrect behavior when value is NaN
- the height is don't same with semester grades
subject cards
- i added max height for better appearance
hotfix for grades-overview
- made it responsive
2025-03-17 16:26:41 +01:00
MrS-1302
dfc0c362c7 you can see original teacher too when a substitute is assigned 2025-03-14 22:03:51 +01:00
MrS-1302
367547f67f fix multiple classes in the same hour problem 2025-03-14 19:47:06 +01:00
MrS-1302
003db8569e Fixes for grades page
- chart
   - fixed incorrect behavior when value is NaN
   - the height is don't same with semester grades
- subject cards
  - i added max height for better appearance
- hotfix for grades-overview
  - made it responsive
2025-03-14 18:29:54 +01:00
Zan
4eee8fa7e6 Update README.md 2025-03-14 15:06:41 +01:00
65 changed files with 11436 additions and 7046 deletions

71
.github/workflows/build.yml vendored Normal file
View File

@@ -0,0 +1,71 @@
name: Package and Release Extension
on:
workflow_dispatch:
push:
branches:
- test
jobs:
build-and-release:
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v3
with:
fetch-depth: 0
- name: Get current date
id: date
run: |
echo "DATE=$(date +'%Y.%m.%d. %H:%M')" >> $GITHUB_ENV
echo "DATE_FOR_ZIP=$(date +'%Y%m%d-%H%M')" >> $GITHUB_ENV
- name: Create ZIP file
run: |
zip -r "pre-firxa-${{ env.DATE_FOR_ZIP }}.zip" . -x "*.git*" "*.github*" "*.idea*"
- name: Delete previous pre-release
uses: dev-drprasad/delete-tag-and-release@v0.2.1
with:
delete_release: true
tag_name: pre-release
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
continue-on-error: true
- name: Create new pre-release
id: create_release
uses: softprops/action-gh-release@v1
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
tag_name: pre-release
release_name: Fejlesztői build
body: |
Ez egy kiadás előtti build, amely minden egyes commit után frissül!
A build automatikusan készült ekkor: ${{ env.DATE }}
draft: false
prerelease: true
- name: Upload ZIP to release
if: steps.create_release.outputs.upload_url != ''
uses: actions/upload-release-asset@v1
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
upload_url: ${{ steps.create_release.outputs.upload_url }}
asset_path: ./pre-firxa-${{ env.DATE_FOR_ZIP }}.zip
asset_name: pre-firxa-${{ env.DATE_FOR_ZIP }}.zip
asset_content_type: application/zip
check-links:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Link Checker
id: lychee
uses: lycheeverse/lychee-action@v2
with:
fail: false

2
.gitignore vendored
View File

@@ -7,3 +7,5 @@ META-INF/cose.sig
META-INF/manifest.mf
META-INF/mozilla.sf
dashboard/KRÉTA Iskolai Alaprendszer.html
*.xml
*.xml

View File

@@ -1,9 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<module type="JAVA_MODULE" version="4">
<component name="NewModuleRootManager" inherit-compiler-output="true">
<exclude-output />
<content url="file://$MODULE_DIR$" />
<orderEntry type="inheritedJdk" />
<orderEntry type="sourceFolder" forTests="false" />
</component>
</module>

6
.idea/misc.xml generated
View File

@@ -1,6 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ProjectRootManager">
<output url="file://$PROJECT_DIR$/out" />
</component>
</project>

8
.idea/modules.xml generated
View File

@@ -1,8 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ProjectModuleManager">
<modules>
<module fileurl="file://$PROJECT_DIR$/.idea/Firkaextension.iml" filepath="$PROJECT_DIR$/.idea/Firkaextension.iml" />
</modules>
</component>
</project>

6
.idea/vcs.xml generated
View File

@@ -1,6 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="VcsDirectoryMappings">
<mapping directory="" vcs="Git" />
</component>
</project>

45
.idea/workspace.xml generated
View File

@@ -1,45 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="AutoImportSettings">
<option name="autoReloadType" value="NONE" />
</component>
<component name="ChangeListManager">
<list default="true" id="2540850d-5586-4ef8-a1c0-838ec2731d44" name="Changes" comment="" />
<option name="SHOW_DIALOG" value="false" />
<option name="HIGHLIGHT_CONFLICTS" value="true" />
<option name="HIGHLIGHT_NON_ACTIVE_CHANGELIST" value="false" />
<option name="LAST_RESOLUTION" value="IGNORE" />
</component>
<component name="ClangdSettings">
<option name="formatViaClangd" value="false" />
</component>
<component name="ProjectColorInfo"><![CDATA[{
"associatedIndex": 0
}]]></component>
<component name="ProjectId" id="2uHD20KrXgQVbKPvZ8rqEw44Sjy" />
<component name="ProjectViewState">
<option name="hideEmptyMiddlePackages" value="true" />
<option name="showLibraryContents" value="true" />
</component>
<component name="PropertiesComponent"><![CDATA[{
"keyToString": {
"RunOnceActivity.ShowReadmeOnStart": "true",
"RunOnceActivity.cidr.known.project.marker": "true",
"RunOnceActivity.readMode.enableVisualFormatting": "true",
"cf.first.check.clang-format": "false",
"cidr.known.project.marker": "true",
"kotlin-language-version-configured": "true"
}
}]]></component>
<component name="SpellCheckerSettings" RuntimeDictionaries="0" Folders="0" CustomDictionaries="0" DefaultDictionary="application-level" UseSingleDictionary="true" transferred="true" />
<component name="TaskManager">
<task active="true" id="Default" summary="Default task">
<changelist id="2540850d-5586-4ef8-a1c0-838ec2731d44" name="Changes" comment="" />
<created>1741896394934</created>
<option name="number" value="Default" />
<option name="presentableId" value="Default" />
<updated>1741896394934</updated>
</task>
<servers />
</component>
</project>

View File

@@ -8,14 +8,23 @@
</p>
<p align="center">
<a href="https://github.com/Zan1456/Firkaextension/releases">
<img src="https://img.shields.io/github/downloads-pre/Zan1456/Firkaextension/latest/total?style=for-the-badge&logo=github&logoColor=EAF7CC&label=Let%C3%B6lt%C3%A9sek&labelColor=141905&color=A7DC22" alt="Downloads">
<a href="https://github.com/QwIT-Development/firka-extension/releases">
<img src="https://img.shields.io/github/downloads-pre/QwIT-Development/firka-extension/latest/total?style=for-the-badge&logo=github&logoColor=EAF7CC&label=Let%C3%B6lt%C3%A9sek&labelColor=141905&color=A7DC22" alt="Downloads">
</a>
<a href="https://discord.gg/6DvjyPAw2T">
<img src="https://img.shields.io/discord/1111649116020285532?style=for-the-badge&logo=discord&logoColor=EAF7CC&label=Discord&labelColor=0D1202&color=A7DC22" alt="Discord">
</a>
<a href="https://github.com/Zan1456/Firkaextension/blob/main/LICENSE">
<img src="https://img.shields.io/github/license/Zan1456/Firkaextension?style=for-the-badge&logo=discord&logoColor=EAF7CC&label=Discord&labelColor=0D1202&color=A7DC22" alt="License">
<a href="https://github.com/QwIT-Development/firka-extension/blob/main/LICENSE">
<img src="https://img.shields.io/github/license/QwIT-Development/firka-extension?style=for-the-badge&logo=discord&logoColor=EAF7CC&label=Discord&labelColor=0D1202&color=A7DC22" alt="License">
</a>
</p>
<p align="center">
<a href="https://chromewebstore.google.com/detail/firxa/emafoaifbfppcccgfmpcoheonhjnpldj?hl=hu">
<img src="https://github.com/QwIT-Development/firka-extension/blob/main/images/chrome.png?raw=true" alt="Elérhető a Chrome Web Store-on" width="200">
</a>
<a href="https://addons.mozilla.org/hu/firefox/addon/firxa/">
<img src="https://github.com/QwIT-Development/firka-extension/blob/main/images/firefox.png?raw=true" alt="Elérhető a Firefox add-ons oldalon" width="200">
</a>
</p>
@@ -34,13 +43,7 @@
## 🚀 Telepítés
1. Töltsd le a legfrissebb verziót a [Releases](https://github.com/Zan1456/Firkaextension/releases) oldalról
2. Csomagold ki a letöltött fájlt
3. Chrome böngészőben navigálj a `chrome://extensions` oldalra
4. Kapcsold be a "Fejlesztői mód"-ot a jobb felső sarokban
5. Kattints a "Kicsomagolt bővítmény betöltése" gombra
6. Válaszd ki a kicsomagolt mappát
7. Kész! A bővítmény automatikusan működésbe lép, amikor megnyitod az e-KRÉTA oldalt
1. Töltsd le a legfrissebb verziót a fenti gombok segítségével a böngésződnek megfelelően.
## ⚙️ Beállítások
@@ -61,12 +64,13 @@ A bővítmény jelenleg az alábbi e-KRÉTA oldalakat támogatja:
- Hiányzások
- Házi feladatok
- Jegyek
- Intézménykereső
## 👥 Csapat
- **[Zan1456](https://github.com/Zan1456)** - Vezető Fejlesztő
- **[BalazsManus](https://github.com/BalazsManus)** - Fejlesztő
- **[Xou](https://github.com/Xou)** - Designer
- **[BalazsManus](https://github.com/olajcsere)** - Fejlesztő
- **[Xou](https://yoursit.ee/xou)** - Designer
## 🤝 Közreműködés
@@ -80,7 +84,7 @@ A bővítmény jelenleg az alábbi e-KRÉTA oldalakat támogatja:
## 📝 Licensz
A projekt [GNU General Public License v3.0](LICENSE) alatt jelent meg. További információért lásd a LICENSE fájlt.
A projekt [GNU Affero General Public License v3.0](LICENSE) alatt jelent meg. További információért lásd a LICENSE fájlt.
## 💬 Kapcsolat

View File

@@ -1,520 +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;
grid-template-areas:
"school user"
"nav nav";
padding: 1rem;
gap: 0.5rem;
}
grid-template-columns:1fr auto auto;
grid-template-areas:"school toggle user"
"nav nav nav";
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;
}
.kreta-nav {
padding: 0 clamp(0.5rem, 3vw, 1.5rem);
position: sticky;
top: 0;
z-index: 100;
overflow-x: auto;
-webkit-overflow-scrolling: touch;
scrollbar-width: none;
-ms-overflow-style: none;
display: flex;
justify-content: center;
.school-details {
font-size:12px;
}
@media (max-width: 768px) {
.kreta-nav {
grid-area: nav;
padding: 0;
margin-top: 0.5rem;
}
}.user-profile {
position:relative;
justify-self:flex-end;
}
.nav-links {
display: flex;
gap: clamp(0.5rem, 2vw, 1rem);
padding: 0.25rem;
justify-content: center;
}
@media (max-width: 768px) {
.nav-links {
justify-content: flex-start;
width: 100%;
gap: 0.25rem;
}
}
.nav-links a {
color: var(--text-secondary);
text-decoration: none;
padding: clamp(0.5rem, 1.5vw, 1rem) 0.5rem;
font-weight: 500;
white-space: nowrap;
transition: all 0.2s ease;
display: flex;
align-items: center;
gap: 0.5rem;
border-radius: 8px;
}
@media (max-width: 768px) {
.nav-links a {
padding: 0.5rem;
font-size: 13px;
}
.nav-links a .material-icons-round {
font-size: 20px;
}
}
.nav-links a:hover {
color: var(--text-primary);
background-color: var(--card-card);
}
.nav-links a.active {
color: var(--accent-accent);
}
.user-profile {
position: relative;
justify-self: flex-end;
}
@media (max-width: 768px) {
@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-name {
display: block;
color: var(--text-primary);
font-size: 16px;
font-weight: 500;
}
.user-time {
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(--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;
}
.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 {
color:var(--text-secondary);
font-size:14px;
font-weight:500;
}
.absences-container {
display: flex;
flex-direction: column;
gap: 16px;
background:var(--card-card);
border-radius:16px;
overflow:hidden;
box-shadow:0px 1px var(--shadow-blur) 0px var(--accent-shadow);
}
.absence-group {
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);
.absences-table {
width:100%;
border-collapse:collapse;
}
.absence-date {
padding: 16px;
color: var(--text-primary);
font-weight: 600;
display: flex;
align-items: center;
gap: 8px;
.table-header {
background:var(--accent-15);
border-bottom:1px solid var(--accent-30);
}
.absence-count {
margin-left: auto;
background: var(--accent-accent);
color: var(--button-secondaryFill);
padding: 4px 8px;
border-radius: 12px;
font-size: 14px;
.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;
}
.absence-list {
padding: 16px;
display: flex;
flex-direction: column;
gap: 12px;
.table-row {
border-bottom:1px solid var(--accent-15);
transition:background-color 0.2s ease;
}
.absence-item {
display: grid;
grid-template-columns: auto 1fr auto;
align-items: center;
gap: 16px;
padding: 12px;
background: var(--accent-15);
border-radius: 12px;
transition: transform 0.2s ease;
.table-row:hover {
background:var(--accent-10);
}
.absence-item:hover {
transform: translateX(4px);
.table-row:last-child {
border-bottom:none;
}
.absence-time {
display: flex;
align-items: center;
gap: 4px;
color: var(--text-secondary);
font-size: 14px;
.table-cell {
padding:16px;
color:var(--text-primary);
vertical-align:middle;
}
.absence-details {
display: flex;
flex-direction: column;
gap: 4px;
.date-cell {
font-weight:600;
color:var(--accent-accent);
}
.lesson-cell {
text-align:center;
font-weight:500;
}
.subject-cell {
font-weight:600;
}
.topic-cell {
color:var(--text-secondary);
font-size:14px;
max-width:200px;
overflow:hidden;
text-overflow:ellipsis;
white-space:nowrap;
}
.status-cell {
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;
}
.status-badge.justified {
background:var(--grades-4-bg);
color:var(--grades-4);
}
.status-badge.unjustified {
background:var(--grades-1-bg);
color:var(--grades-1);
}
.status-badge.pending {
background:var(--grades-3-bg);
color:var(--grades-3);
}
@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);
}
}@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);
}
opacity:0;
transform:translateY(-10px);
}
to {
opacity:1;
transform:translateY(0);
}
}@keyframes spin {
to {
opacity: 1;
transform: translateY(0);
}
transform:rotate(360deg);
}
@keyframes spin {
to { transform: rotate(360deg); }
}
::-webkit-scrollbar {
width: clamp(4px, 1vw, 8px);
height: clamp(4px, 1vw, 8px);
}
::-webkit-scrollbar-track {
background: var(--background);
}
::-webkit-scrollbar-thumb {
background: var(--text-secondary);
border-radius: 4px;
}
::-webkit-scrollbar-thumb:hover {
background: var(--text-primary);
}

File diff suppressed because it is too large Load Diff

View File

@@ -14,6 +14,10 @@ body {
font-size: 16px;
}
h2 {
background-color: #00000000 !important;
}
.kreta-container {
min-height: 100vh;
display: flex;
@@ -35,42 +39,194 @@ body {
gap: 20px;
}
.card {
.widget-card {
background: var(--card-card);
padding: 20px;
padding-top: 5px !important;
border-radius: 24px;
overflow: hidden;
animation: fadeIn 0.5s ease forwards;
box-shadow: 0px 1px var(--shadow-blur) 0px var(--accent-shadow);
box-shadow: 0px 1px var(--shadow-blur, 2px) 0px var(--accent-shadow);
display: flex;
flex-direction: column;
height: 100%;
border: none;
min-height: 400px;
}
.widget-header {
padding: 20px 20px 0 20px;
background: var(--card-card) !important;
}
.widget-card-title {
font-size: 18px;
font-weight: 600;
color: var(--text-primary);
margin: 0;
padding-bottom: 16px;
}
.widget-content {
flex: 1;
padding: 0 20px;
background: var(--card-card);
display: flex;
flex-direction: column;
justify-content: flex-start;
}
.widget-footer {
padding: 0px 20px 20px 20px;
background: var(--card-card);
}
.widget-link {
margin: 0;
padding: 0;
}
.card h2 {
font-size: 16px;
font-size: 18px;
font-weight: 600;
color: var(--text-primary);
background-color: var(--card-card);
margin: 0;
padding: 20px 0 16px 0;
}
.card:last-child {
grid-column: 1 / -1;
}
.grade-item, .absence-item, .note-item, .exam-item, .news-item {
border-radius: 6px;
.widget-item {
border-radius: 12px;
transition: transform 0.2s ease, box-shadow 0.2s ease;
border: 1px solid var(--card-card);
border: none;
background: var(--card-card);
display: flex;
flex-direction: column;
margin-bottom: 12px;
padding: 12px;
padding: 8px;
position: relative;
min-height: 80px;
}
.widget-row {
display: flex;
align-items: flex-start;
justify-content: space-between;
width: 100%;
gap: 12px;
min-height: 40px;
}
.widget-row.grade-row {
align-items: center;
justify-content: flex-start;
}
.widget-details {
flex: 1;
display: flex;
flex-direction: column;
gap: 6px;
min-width: 0;
}
.widget-details.grade-details {
flex: 1;
margin-right: auto;
}
.widget-title {
color: var(--text-primary);
font-weight: 600;
font-size: 16px;
line-height: 1.3;
word-wrap: break-word;
overflow-wrap: break-word;
hyphens: auto;
max-width: 100%;
}
.widget-subtitle {
color: var(--text-secondary);
font-weight: 500;
font-size: 14px;
line-height: 1.2;
word-wrap: break-word;
overflow-wrap: break-word;
}
.widget-content {
color: var(--text-secondary);
font-size: 14px;
line-height: 1.4;
margin-top: 4px;
}
.widget-date {
color: var(--text-secondary);
font-size: 14px;
font-weight: 500;
white-space: nowrap;
text-align: right;
align-self: center;
}
.grade-type-with-date {
display: flex;
justify-content: space-between;
align-items: center;
width: 100%;
gap: 8px;
}
.grade-type-with-date .grade-type {
flex: 1;
min-width: 0;
}
.note-author {
color: var(--text-tertiary);
font-size: 12px;
font-weight: 400;
margin-top: 4px;
word-wrap: break-word;
overflow-wrap: break-word;
}
.grade-date {
color: var(--text-secondary);
font-size: 13px;
font-weight: 400;
white-space: nowrap;
text-align: right;
}
.widget-author {
color: var(--text-tertiary);
font-size: 12px;
font-weight: 400;
word-wrap: break-word;
overflow-wrap: break-word;
max-width: 100%;
}
.news-author {
display: flex;
flex-direction: column;
align-items: flex-end;
gap: 4px;
text-align: right;
word-wrap: break-word;
overflow-wrap: break-word;
hyphens: auto;
}
.widget-empty {
color: var(--text-secondary);
font-style: italic;
text-align: center;
padding: 20px;
}
.grade {
width: 32px;
@@ -84,16 +240,32 @@ body {
color: var(--text-primary);
font-size: 22px;
}
.subject-name, .absence-type, .note-title, .exam-subject {
color: var(--text-primary);
font-weight: 600;
.news-title {
font-size: 16px;
font-weight: 600;
margin-bottom: 8px;
word-wrap: break-word;
overflow-wrap: break-word;
hyphens: auto;
line-height: 1.4;
}
.grade-type, .absence-date, .note-date, .exam-date {
color: var(--text-secondary);
font-weight: 500;
.news-content {
font-size: 14px;
line-height: 1.4;
color: var(--text-secondary);
word-wrap: break-word;
overflow-wrap: break-word;
hyphens: auto;
}
.exam-type {
font-size: 12px;
font-weight: 500;
letter-spacing: 0.5px;
}
.more-link {
margin-top: auto;
display: inline-flex;
@@ -120,6 +292,7 @@ body {
.grade-3 {color: var(--grades-3); background-color: var(--grades-background-3);}
.grade-4 {color: var(--grades-4); background-color: var(--grades-background-4);}
.grade-5 {color: var(--grades-5); background-color: var(--grades-background-5);}
.grade-Sz {color: var(--grades-3); background-color: var(--grades-background-3);}
@keyframes fadeIn {
from {
@@ -179,15 +352,17 @@ body {
width: 20px;
height: 20px;
}
.subject-name, .absence-type, .note-title, .exam-subject {
color: var(--text-primary);
font-weight: 600;
.news-title {
font-size: 16px;
font-weight: 600;
margin-bottom: 8px;
}
.grade-type, .absence-date, .note-date, .exam-date {
color: var(--text-secondary);
font-weight: 500;
.news-content {
font-size: 14px;
line-height: 1.4;
color: var(--text-secondary);
}
.more-link {
margin-top: auto;
@@ -211,22 +386,12 @@ body {
font-size: 0.875rem;
}
.grade-row {
.exam-info {
display: flex;
align-items: center;
justify-content: space-between;
width: 100%;
}
.grade-details {
flex: 1;
margin-right: 10px;
}
.grade-date, .exam-date {
gap: 8px;
margin-top: 4px;
color: var(--text-secondary);
font-size: 14px;
white-space: nowrap;
}
.exam-info {

View File

@@ -1,446 +1,583 @@
const utils = {
shortenSchoolName(name, maxLength = 50) {
if (!name || name.length <= maxLength) return name || '';
const [code, fullName] = name.split(' - ');
if (fullName) {
const maxFullNameLength = maxLength - code.length - 3;
if (fullName.length > maxFullNameLength) {
return `${code} - ${fullName.substring(0, maxFullNameLength)}...`;
}
}
return `${name.substring(0, maxLength - 3)}...`;
},
const DashboardUtils = {
formatGradeValue(value) {
return value?.trim() || '';
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;
const hungarianMonths = [
'január', 'február', 'március', 'április', 'május', 'június',
'július', 'augusztus', 'szeptember', 'október', 'november', 'december'
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",
];
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",
];
return `${hungarianMonths[month - 1]} ${day}.`;
}
return `${LanguageManager.t(monthKeys[month - 1])} ${day}.`;
},
};
class DashboardDataExtractor {
class DashboardDataManager {
constructor() {
this.data = {
this.dashboardData = {
grades: [],
absences: [],
notes: [],
upcomingExams: [],
news: []
news: [],
};
}
extractGrades() {
const gradeRows = document.querySelectorAll('#legutobbiErtekelesek tr:not(:first-child)');
this.data.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;
extractGradeData() {
const gradeRows = document.querySelectorAll(
"#legutobbiErtekelesek tr:not(:first-child)",
);
const [fullSubject, date] = gradeInfo.split('\n').map(str => str.trim());
const { subject, type } = this.parseSubjectInfo(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;
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 dateMatch = fullSubject.match(datePattern);
if (dateMatch) {
const subjectPart = fullSubject.substring(0, dateMatch.index).trim();
const datePart = dateMatch[0].trim();
return {
value: utils.formatGradeValue(gradeValue),
subject,
date: utils.parseDate(date),
type: type || 'Értékelés'
subject: subjectPart,
type: "",
dateInSubject: datePart,
};
}).filter(Boolean);
}
}
parseSubjectInfo(fullSubject) {
const months = ['január', 'február', 'március', 'április', 'május', 'június',
'július', 'augusztus', 'szeptember', 'október', 'november', 'december'];
const monthPattern = new RegExp(months.join('|'), 'i');
const monthMatch = fullSubject.match(monthPattern);
if (!monthMatch) return { subject: fullSubject, type: '' };
const monthIndex = fullSubject.lastIndexOf(monthMatch[0]);
return {
subject: fullSubject.substring(0, monthIndex).trim(),
type: fullSubject.substring(monthIndex).trim()
};
}
extractAbsences() {
const absenceRows = document.querySelectorAll('#legutobbiMulasztasok tr:not(:first-child)');
this.data.absences = Array.from(absenceRows).map(row => {
const spans = row.querySelectorAll('span');
if (spans.length < 4) return null;
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"),
];
const fallbackMonthPattern = new RegExp(months.join("|"), "i");
const monthMatch = fullSubject.match(fallbackMonthPattern);
if (monthMatch) {
const monthIndex = fullSubject.lastIndexOf(monthMatch[0]);
return {
date: spans[0]?.textContent?.trim() || '',
day: spans[2]?.textContent?.trim() || '',
type: spans[1]?.textContent?.trim() || '',
count: spans[3]?.textContent?.trim() || ''
subject: fullSubject.substring(0, monthIndex).trim(),
type: fullSubject.substring(monthIndex).trim(),
};
}).filter(Boolean);
}
return { subject: fullSubject, type: "" };
}
extractNotes() {
const noteRows = document.querySelectorAll('#legutobbiFeljegyzesek tr:not(:first-child)');
this.data.notes = Array.from(noteRows).map(row => {
const spans = row.querySelectorAll('span');
if (spans.length < 3) return null;
extractAbsenceData() {
const absenceRows = document.querySelectorAll(
"#legutobbiMulasztasok tr:not(:first-child)",
);
return {
title: spans[0]?.textContent?.trim() || '',
author: spans[1]?.textContent?.trim() || '',
date: spans[2]?.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);
}
extractExams() {
const examRows = document.querySelectorAll('#legutobbiBejelentettSzamonkeres tr:not(:first-child)');
this.data.upcomingExams = Array.from(examRows).map(row => {
const spans = row.querySelectorAll('span');
if (spans.length < 4) return null;
extractNoteData() {
const noteRows = document.querySelectorAll(
"#legutobbiFeljegyzesek 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.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);
}
extractNews() {
const newsContainer = document.querySelector('.faliujsag-lista, #faliujsagLista');
if (!newsContainer) return;
const newsItems = newsContainer.querySelectorAll('.nb-item, .news-item');
this.data.news = Array.from(newsItems).map(item => {
const titleElement = item.querySelector('.subject h4, .news-title');
const contentElement = item.querySelector('.content, .news-content');
const dateElement = item.querySelector('.nb-date, .news-date');
let dateStr = '';
if (dateElement) {
const yearElement = dateElement.querySelector('.year');
const monthElement = dateElement.querySelector('.month');
const dayElement = dateElement.querySelector('.day');
if (yearElement && monthElement && dayElement) {
dateStr = `${yearElement.textContent} ${monthElement.textContent} ${dayElement.textContent}`;
} else {
dateStr = dateElement.textContent;
}
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;
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",
headers: {
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 authorElement = item.querySelector('.auth-name span, .news-author');
return {
title: titleElement?.textContent?.trim() || '',
date: dateStr.trim(),
content: contentElement?.textContent?.trim() || '',
author: authorElement?.textContent?.trim() || ''
};
}).filter(news => news.title || news.content);
const data = await response.json();
if (!data.FaliujsagElemek || !Array.isArray(data.FaliujsagElemek)) {
return;
}
data.FaliujsagElemek.forEach((item, index) => {
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+)\)\//);
if (match) {
const timestamp = parseInt(match[1]);
const date = new Date(timestamp);
formattedDate = date.toLocaleDateString("hu-HU");
}
}
if (!formattedDate) {
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();
const newsItem = {
title: item.EsemenyCime || `Hír ${index + 1}`,
content: cleanContent || "Nincs elérhető tartalom",
date: formattedDate,
author: `${item.Nev || "Ismeretlen"} (${item.Munkakor || "Ismeretlen"})`,
};
this.dashboardData.news.push(newsItem);
});
} catch (error) {
console.error("❌ Error fetching news from API:", error);
}
}
extractAll() {
this.extractGrades();
this.extractAbsences();
this.extractNotes();
this.extractExams();
this.extractNews();
return this.data;
async extractAllData() {
this.extractGradeData();
this.extractAbsenceData();
this.extractNoteData();
this.extractExamData();
await this.extractNewsData();
return this.dashboardData;
}
}
class DashboardUI {
class DashboardRenderer {
constructor(data) {
this.data = {
...data,
schoolInfo: {
name: cookies.getCookie(COOKIE_KEYS.SCHOOL_NAME) || DEFAULT_VALUES.SCHOOL,
id: cookies.getCookie(COOKIE_KEYS.SCHOOL_CODE) || ''
name:
cookieManager.get(COOKIE_KEYS.SCHOOL_NAME) || DEFAULT_VALUES.SCHOOL,
id: cookieManager.get(COOKIE_KEYS.SCHOOL_CODE) || "",
},
userData: {
name: cookies.getCookie(COOKIE_KEYS.USER_NAME) || DEFAULT_VALUES.USER,
time: document.querySelector('.usermenu_timer')?.textContent?.trim() || DEFAULT_VALUES.TIMER
}
name: cookieManager.get(COOKIE_KEYS.USER_NAME) || DEFAULT_VALUES.USER,
time:
document.querySelector(".usermenu_timer")?.textContent?.trim() ||
DEFAULT_VALUES.TIMER,
},
};
this.schoolNameFull = `${this.data.schoolInfo.id} - ${this.data.schoolInfo.name}`;
this.shortenedSchoolName = utils.shortenSchoolName(this.schoolNameFull);
this.shortenedSchoolName = helper.shortenSchoolName(this.schoolNameFull);
}
static generateHeaderHTML(data, schoolNameFull, shortenedSchoolName) {
return `
<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">
Firka
</p>
<div class="school-details" title="${schoolNameFull}">
${shortenedSchoolName}
</div>
</div>
<nav class="kreta-nav">
<div class="nav-links">
<a href="/Intezmeny/Faliujsag" data-page="dashboard" class="nav-item active">
<img src="${chrome.runtime.getURL('icons/dashboard-active.svg')}" alt="Kezdőlap">
Kezdőlap
</a>
<a href="/TanuloErtekeles/Osztalyzatok" data-page="grades" class="nav-item">
<img src="${chrome.runtime.getURL('icons/grades-inactive.svg')}" alt="Jegyek">
Jegyek
</a>
<a href="/Orarend/InformaciokOrarend" data-page="timetable" class="nav-item">
<img src="${chrome.runtime.getURL('icons/timetable-inactive.svg')}" alt="Órarend">
Órarend
</a>
<a href="/Hianyzas/Hianyzasok" data-page="absences" class="nav-item">
<img src="${chrome.runtime.getURL('icons/absences-inactive.svg')}" alt="Mulasztások">
Mulasztások
</a>
<a href="/Tanulo/TanuloHaziFeladat" data-page="other" class="nav-item">
<img src="${chrome.runtime.getURL('icons/others.svg')}" alt="Egyéb">
Egyéb
</a>
</div>
</nav>
<div class="user-profile">
<button class="user-dropdown-btn">
<div class="user-info">
<span class="user-name">${data.userData.name}</span>
<span class="nav-logout-timer" id="logoutTimer">${data.userData.time}</span>
</div>
</button>
<div class="user-dropdown">
<a href="/Adminisztracio/Profil" data-page="profile" class="dropdown-item">
<img src="${chrome.runtime.getURL('icons/profile.svg')}" alt="Profil">
Profil
</a>
<a href="#" class="dropdown-item" id="settingsBtn">
<img src="${chrome.runtime.getURL('icons/settings.svg')}" alt="Beállítások">
Beállítások
</a>
<a href="/Home/Logout" data-page="logout" class="dropdown-item">
<img src="${chrome.runtime.getURL('icons/logout.svg')}" alt="Kijelentkezés">
Kijelentkezés
</a>
</div>
</div>
</header>
`;
}
generateMainContentHTML() {
generateMainContent() {
return `
<main class="kreta-main">
<div class="grid-container">
${this.generateGradeCard()}
${this.generateAbsenceCard()}
${this.generateNoteCard()}
${this.generateExamCard()}
${this.generateNewsCard()}
${this.createGradeCard()}
${this.createAbsenceCard()}
${this.createNoteCard()}
${this.createExamCard()}
${this.createNewsCard()}
</div>
</main>
`;
}
generateNewsCard() {
const newsItems = this.data.news.map(news => `
<div class="news-item">
<div class="news-header">
<div class="news-date">${news.date}</div>
${news.author ? `<div class="news-author">${news.author}</div>` : ''}
</div>
<div class="news-details">
<h3 class="news-title">${news.title}</h3>
<div class="news-content">${news.content}</div>
</div>
</div>
`).join('');
return this.generateCard('Hírek', newsItems || 'Jelenleg ez egy nem támogatott funkció', '/Intezmeny/Faliujsag', 'Összes hír');
}
generateGradeCard() {
const gradeItems = this.data.grades.map(grade => `
<div class="grade-item">
<div class="grade-row">
<div class="grade grade-${grade.value}">${grade.value}</div>
<div class="grade-details">
<div class="subject-name">${grade.subject}</div>
<div class="grade-type">${grade.type}</div>
createNewsCard() {
const newsItems = this.data.news
.map(
(news) => `
<div class="widget-item news-item">
<div class="widget-row">
<div class="widget-details news-details">
<div class="widget-title news-title">${news.title}</div>
<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>` : ""}
</div>
${grade.date ? `<div class="grade-date">${grade.date}</div>` : ''}
</div>
</div>
`).join('');
`,
)
.join("");
return this.generateCard('Értékeléseid', gradeItems, '/TanuloErtekeles/Osztalyzatok', 'Összes jegyed');
return this.createCard(
LanguageManager.t("dashboard.news"),
newsItems || LanguageManager.t("dashboard.not_supported"),
"/Intezmeny/Faliujsag",
LanguageManager.t("dashboard.all_news"),
);
}
generateAbsenceCard() {
const absenceItems = this.data.absences.map(absence => `
<div class="absence-item">
<div class="absence-details">
<div class="absence-type">${absence.type}</div>
<div class="absence-date">${absence.date}</div>
createGradeCard() {
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>
<div class="widget-details grade-details">
<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>` : ""}
</div>
</div>
</div>
</div>
`).join('');
`,
)
.join("");
return this.generateCard('Mulasztások', absenceItems, '/Hianyzas/Hianyzasok', 'Összes mulasztás');
return this.createCard(
LanguageManager.t("dashboard.grades"),
gradeItems,
"/TanuloErtekeles/Osztalyzatok",
LanguageManager.t("dashboard.all_grades"),
);
}
generateNoteCard() {
const noteItems = this.data.notes.map(note => `
<div class="note-item">
<div class="note-details">
<div class="note-title">${note.title}</div>
<div class="note-date">${note.date}</div>
createAbsenceCard() {
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>` : ""}
</div>
</div>
`).join('');
`,
)
.join("");
return this.generateCard('Feljegyzések', noteItems, '/TanuloErtekeles/InformaciokFeljegyzesek', 'Összes üzeneted');
return this.createCard(
LanguageManager.t("dashboard.absences"),
absenceItems,
"/Hianyzas/Hianyzasok",
LanguageManager.t("dashboard.all_absences"),
);
}
generateExamCard() {
const examItems = this.data.upcomingExams.map(exam => `
<div class="exam-item">
<div class="exam-details">
<div class="exam-subject">${exam.subject}</div>
<div class="exam-date">${utils.formatHungarianDate(exam.date)}</div>
createNoteCard() {
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>` : ""}
</div>
</div>
`).join('');
`,
)
.join("");
return this.generateCard('Bejelentett dolgozatok', examItems, '/Tanulo/TanuloBejelentettSzamonkeresek', 'Összes dolgozat');
return this.createCard(
LanguageManager.t("dashboard.notes"),
noteItems,
"/TanuloErtekeles/InformaciokFeljegyzesek",
LanguageManager.t("dashboard.all_messages"),
);
}
generateCard(title, content, linkHref, linkText) {
createExamCard() {
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>
<div class="widget-date exam-date">${DashboardUtils.formatHungarianDate(exam.date)}</div>
</div>
</div>
`,
)
.join("");
return this.createCard(
LanguageManager.t("dashboard.exams"),
examItems,
"/Tanulo/TanuloBejelentettSzamonkeresek",
LanguageManager.t("dashboard.all_exams"),
);
}
createCard(title, content, linkHref, linkText) {
return `
<div class="card">
<h2>${title}</h2>
<div class="card-content">
${content || `Jelenleg ez egy nem támogatott funkció`}
<a href="${linkHref}" class="more-link">
<div class="widget-card card">
<div class="widget-header">
<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>`}
</div>
<div class="widget-footer">
<a href="${linkHref}" class="widget-link more-link">
${linkText}
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="17" viewBox="0 0 16 17" fill="none">
<path d="M11.2997 5.19947L5.64282 5.19947M11.2997 5.19947L11.2997 10.8563M11.2997 5.19947L4.70001 11.7991" stroke="var(--accent-accent)" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
</svg>
</svg>
</a>
</div>
</div>
`;
}
render() {
document.body.innerHTML = `
<div class="kreta-container">
${DashboardUI.generateHeaderHTML(this.data, this.schoolNameFull, this.shortenedSchoolName)}
${this.generateMainContentHTML()}
</div>
`;
setupUserDropdown();
setupLogoutTimer();
}
}
function setupLogoutTimer() {
const timerElement = document.querySelector('.nav-logout-timer');
if (!timerElement) return;
const timeString = timerElement.textContent;
const startTime = parseInt(timeString?.match(/\d+/)?.[0] || "45");
let timeLeft = startTime * 60;
const updateTimer = () => {
const minutes = Math.floor(timeLeft / 60);
const seconds = timeLeft % 60;
timerElement.textContent = `${minutes}:${seconds.toString().padStart(2, '0')}`;
document.body.innerHTML = '';
if (timeLeft <= 0) {
window.location.href = '/Home/Logout';
const kretaContainer = document.createElement('div');
kretaContainer.className = 'kreta-container';
const headerDiv = document.createElement('div');
const parser = new DOMParser();
const headerDoc = parser.parseFromString(createTemplate.header(), 'text/html');
const headerContent = headerDoc.body;
while (headerContent.firstChild) {
headerDiv.appendChild(headerContent.firstChild);
}
timeLeft--;
};
updateTimer();
setInterval(updateTimer, 1000);
}
class FontLoader {
static loadFonts() {
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/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);
});
kretaContainer.appendChild(headerDiv);
const mainContentDiv = document.createElement('div');
const parser2 = new DOMParser();
const mainDoc = parser2.parseFromString(this.generateMainContent(), 'text/html');
const mainContent = mainDoc.body;
while (mainContent.firstChild) {
mainContentDiv.appendChild(mainContent.firstChild);
}
kretaContainer.appendChild(mainContentDiv);
document.body.appendChild(kretaContainer);
setupUserDropdown();
setupMobileNavigation();
}
}
class DashboardApp {
class DashboardApplication {
constructor() {
this.initialize();
this.init();
}
async initialize() {
if (!window.location.href.includes('/Intezmeny/Faliujsag')) return;
async init() {
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 (!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",
);
if (newsContainer) {
const possibleSelectors = [
".nb-item",
".news-item",
".faliujsag-item",
".list-group-item",
"li",
'div[class*="item"]',
'div[class*="news"]',
];
for (const selector of possibleSelectors) {
const items = newsContainer.querySelectorAll(selector);
if (items.length > 0) {
newsItemsFound = true;
break;
}
}
if (!newsItemsFound) {
if (
newsContainer.children.length > 0 ||
newsContainer.textContent.trim().length > 0
) {
newsItemsFound = true;
}
}
}
if (!newsItemsFound) {
attempts++;
await new Promise((resolve) => setTimeout(resolve, 100));
}
}
try {
const dataExtractor = new DashboardDataExtractor();
const dashboardData = dataExtractor.extractAll();
FontLoader.loadFonts();
const ui = new DashboardUI(dashboardData);
ui.render();
const dataManager = new DashboardDataManager();
const dashboardData = await dataManager.extractAllData();
const renderer = new DashboardRenderer(dashboardData);
renderer.render();
} catch (error) {
console.error('Error initializing dashboard:', error);
console.error("Error initializing dashboard:", error);
}
}
}
new DashboardApp();
new DashboardApplication();

BIN
fonts/Icons.woff2 Normal file

Binary file not shown.

View File

@@ -1,202 +1,57 @@
:root {
--primary: #050B15;
--secondary: #3F444F;
--tertiary: #1C469A;
--icon: #0A2456;
--accent: #3673EE;
--bg: #DAE4F7;
--card: #EDF3FF;
--cardsec: #FBFCFF;
--error: #E32D2D;
--error-bg: rgba(227, 45, 45, 0.05);
}
:root[data-theme="dark"] {
--primary: #EBF1FD;
--secondary: #CFD8E9;
--tertiary: #AEC8FC;
--icon: #BAD1FF;
--accent: #3673ed;
--bg: #070A0E;
--card: #0F131B;
--cardsec: #131822;
--error: #FF4444;
--error-bg: rgba(255, 68, 68, 0.1);
}
* {
box-sizing: border-box;
margin: 0;
padding: 0;
}
body {
margin: 0;
padding: 0;
color: var(--primary);
background-color: var(--bg) !important;
font-family: "Montserrat", serif !important;
min-height: 100vh;
font-size: 16px;
display: flex;
align-items: center;
justify-content: center;
}
.forgot-container {
width: 100%;
max-width: 500px;
padding: 20px;
margin: 0 auto;
}
.forgot-header {
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;
color: var(--secondary);
font-size: 14px;
margin-bottom: 8px;
}
.form-control {
width: 100%;
padding: 12px 16px;
border: 2px solid transparent;
border-radius: 12px;
font-size: 16px;
font-family: "Montserrat", serif;
background: var(--cardsec);
color: var(--primary);
transition: all 0.2s ease;
}
.form-control:focus {
outline: none;
border-color: var(--accent);
}
.form-control::placeholder {
color: var(--secondary);
}
.form-actions {
margin-top: 24px;
display: flex;
justify-content: space-between;
align-items: center;
}
.help-link {
color: var(--accent);
text-decoration: none;
font-size: 14px;
transition: color 0.2s ease;
}
.help-link:hover {
color: var(--tertiary);
}
.btn-submit {
padding: 12px 24px;
background: var(--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;
}
.btn-submit:hover {
background: var(--tertiary);
}
.btn-submit:disabled {
opacity: 0.7;
cursor: not-allowed;
}
.error-message {
color: var(--error);
font-size: 14px;
margin-top: 4px;
display: none;
}
.error-message.show {
display: block;
animation: fadeIn 0.2s ease;
}
.g-recaptcha {
margin-top: 24px;
display: flex;
justify-content: center;
}
@keyframes fadeIn {
from { opacity: 0; transform: translateY(-4px); }
to { opacity: 1; transform: translateY(0); }
}
@media (max-width: 600px) {
.forgot-container {
padding: 16px;
}
.forgot-card {
padding: 20px;
}
.form-actions {
flex-direction: column;
gap: 16px;
align-items: stretch;
}
.btn-submit {
width: 100%;
}
}
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 {
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%;
}
.maintenance-logo {
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;
}
.maintenance-message {
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;
}
.maintenance-cactus {
position:fixed;
bottom:0px;
right:20px;
width:120px;
height:120px;
opacity:1;
z-index:1000;
}

View File

@@ -1,152 +1,290 @@
(() => {
const transformForgotPasswordPage = () => {
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);
}
});
document.body.innerHTML = `
<div class="forgot-container">
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Montserrat:ital,wght@0,100..900;1,100..900&display=swap" rel="stylesheet">
<link href="https://fonts.googleapis.com/icon?family=Material+Icons+Round" rel="stylesheet">
// reCAPTCHA functionality removed for security compliance
const loadDependencies = async () => {
// reCAPTCHA functionality removed for security compliance
// Extension now works without external script dependencies
};
const createPageStructure = () => {
// Biztonságos DOM létrehozás innerHTML helyett
document.body.innerHTML = '';
// Biztonságos HTML parsing DOMParser használatával
const parser = new DOMParser();
const doc = parser.parseFromString(`
<div class="forgot-container">
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Montserrat:ital,wght@0,100..900;1,100..900&display=swap" rel="stylesheet">
<link href="https://fonts.googleapis.com/icon?family=Material+Icons+Round" rel="stylesheet">
<style>
.g-recaptcha {
margin-top: 5px;
display: flex;
justify-content: center;
}
</style>
<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>
<div class="forgot-card">
<h1 class="forgot-title">Elfelejtett jelszó</h1>
<form id="forgotForm" novalidate>
<div class="form-group">
<label class="form-label" for="username">OM azonosítód</label>
<input type="text" id="username" name="username" class="form-control"
placeholder="Add meg az OM azonosítód" required>
<div class="error-message">Kérjük, add meg az OM azonosítód.</div>
</div>
<div class="form-group">
<label class="form-label" for="email">E-mail cím</label>
<input type="email" id="email" name="email" class="form-control"
placeholder="Add meg az e-mail címed" required>
<div class="error-message">Kérjük, add meg az e-mail címed.</div>
</div>
<div class="g-recaptcha" data-sitekey="6LcmPB8dAAAAACJPQBj7WfpBoBsEfyibZeIG5Vbl"></div>
<div class="form-actions">
<a href="/Adminisztracio/Login" class="help-link">
Vissza a bejelentkezéshez
</a>
<button type="submit" class="btn-submit">
Jelszó visszaállítása
</button>
</div>
</form>
</div>
<h1 class="forgot-title" data-i18n="forgotpassword.title">Elfelejtett jelszó</h1>
<form id="forgotForm" novalidate>
<div class="form-group">
<label class="form-label" for="BejelentkezesiNev" data-i18n="forgotpassword.om_id_label">OM azonosító</label>
<input type="text" id="BejelentkezesiNev" name="BejelentkezesiNev" class="form-control"
data-i18n-attr="placeholder" data-i18n="forgotpassword.om_id_placeholder"
placeholder="Adja meg az OM azonosítóját" required>
<div class="error-message" data-i18n="forgotpassword.om_id_required">Az OM azonosító megadása kötelező</div>
</div>
<div class="form-group">
<label class="form-label" for="EmailCim" data-i18n="forgotpassword.email_label">E-mail cím</label>
<input type="email" id="EmailCim" name="EmailCim" class="form-control"
data-i18n-attr="placeholder" data-i18n="forgotpassword.email_placeholder"
placeholder="Adja meg az e-mail címét" required>
<div class="error-message" data-i18n="forgotpassword.email_required">Az e-mail cím megadása kötelező</div>
</div>
<!-- reCAPTCHA container removed for security compliance -->
<div class="form-actions">
<a href="/Adminisztracio/Login" class="help-link" data-i18n="forgotpassword.back_to_login">
Vissza a bejelentkezéshez
</a>
<button type="submit" class="btn-submit" data-i18n="forgotpassword.reset_button">
Jelszó visszaállítása
</button>
</div>
</form>
</div>
`;
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');
</div>
`, 'text/html');
const tempDiv = doc.body;
// Biztonságos DOM hozzáadás
while (tempDiv.firstChild) {
document.body.appendChild(tempDiv.firstChild);
}
};
const transformForgotPasswordPage = async () => {
await loadDependencies();
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);
}
return isValid;
});
createPageStructure();
let attempts = 0;
const maxAttempts = 50;
const waitForLanguageManager = () => {
return new Promise((resolve) => {
const checkLanguageManager = () => {
attempts++;
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");
resolve();
}
};
checkLanguageManager();
});
};
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;
await waitForLanguageManager();
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");
if (attr) {
element.setAttribute(attr, translation);
} else {
element.textContent = translation;
}
}
});
if (!isValid) {
return;
}
// reCAPTCHA rendering removed for security compliance
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);
setTimeout(() => {
if (messageDiv.parentNode) {
messageDiv.remove();
}
const submitButton = form.querySelector('.btn-submit');
submitButton.disabled = true;
try {
const formData = new FormData(form);
const response = await fetch('/Adminisztracio/ElfelejtettJelszo/LinkKuldes', {
method: 'POST',
}, 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;
}
});
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;
}
// reCAPTCHA validation removed for security compliance
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);
// reCAPTCHA data removed for security compliance
const response = await fetch(
"/Adminisztracio/ElfelejtettJelszo/LinkKuldes",
{
method: "POST",
body: formData,
headers: {
'X-Requested-With': 'XMLHttpRequest'
}
});
const result = await response.json();
if (result.Success) {
window.location.href = '/Adminisztracio/Login';
} else {
alert(result.Message || 'Hiba történt a jelszó visszaállítása során. (Kérlek használd az eredeti kréta oldalt erre)');
grecaptcha.reset();
}
} catch (error) {
//alert('Hiba történt a jelszó visszaállítása során.');
grecaptcha.reset();
} finally {
submitButton.disabled = false;
"X-Requested-With": "XMLHttpRequest",
},
},
);
if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`);
}
};
if (window.location.href.includes('/Adminisztracio/ElfelejtettJelszo')) {
transformForgotPasswordPage();
const result = await response.json();
if (result.Success) {
showMessage(LanguageManager.t("forgotpassword.success_message"));
form.reset();
// reCAPTCHA reset removed
setTimeout(() => {
window.location.href = "/Adminisztracio/Login";
}, 3000);
} else {
showMessage(
result.Message || LanguageManager.t("forgotpassword.error_message"),
true,
);
// reCAPTCHA reset removed
}
} catch (error) {
console.error("Password reset error:", error);
showMessage(LanguageManager.t("forgotpassword.error_message"), true);
// reCAPTCHA reset removed
} finally {
submitButton.disabled = false;
submitButton.textContent = originalText;
}
})();
};
if (window.location.href.includes("/Adminisztracio/ElfelejtettJelszo")) {
transformForgotPasswordPage().catch(console.error);
}
})();

185
global/language.js Normal file
View File

@@ -0,0 +1,185 @@
(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 {
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 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,51 +1,57 @@
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: 'Inter', 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-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-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-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;
}

View File

@@ -1,65 +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');
if (maintenanceContent && maintenanceContent.textContent.includes('frissítés alatt')) {
const body = document.body;
const mainLogo = chrome.runtime.getURL('images/firka_logo_128.png');
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');
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 = 'Karbantartás';
const messageDiv = document.createElement('div');
messageDiv.className = 'maintenance-message';
const paragraph1 = document.createElement('p');
paragraph1.textContent = 'A KRÉTA rendszer jelenleg frissítés alatt van, hamarosan újra elérhetővé válik.';
const paragraph2 = document.createElement('p');
paragraph2.textContent = 'Köszönjük türelmüket és megértésüket!';
const footer = document.createElement('div');
footer.className = 'maintenance-footer';
footer.textContent = 'KRÉTA Csapat';
messageDiv.appendChild(paragraph1);
messageDiv.appendChild(paragraph2);
container.appendChild(logo);
container.appendChild(title);
container.appendChild(messageDiv);
container.appendChild(footer);
body.appendChild(container);
}
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 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 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();
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,257 +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) {
.kreta-header {
grid-template-columns: minmax(250px, 350px) 1fr minmax(180px, 250px);
}
to {
opacity:1;
transform:translateY(0);
}
@media (max-width: 768px) {
}@media (max-width:1200px) {
.kreta-header {
grid-template-columns: 1fr auto;
grid-template-areas:
"school user"
"nav nav";
padding: 1rem;
gap: 0.5rem;
grid-template-columns:minmax(250px,350px) 1fr minmax(180px,250px);
}
}/* Hamburger menu styles */
.nav-toggle {
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);
}
.nav-toggle svg {
width:24px;
height:24px;
fill:var(--text-primary);
}
@media (max-width:768px) {
.kreta-header {
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;
}
}@media (max-width:480px) {
.kreta-header {
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;
}
}@media (max-width:360px) {
.kreta-header {
padding:0.5rem;
}
.school-info {
grid-area: school;
max-width: none;
display: flex;
align-items: center;
gap: 0.5rem;
}
.logo-text {
margin: 0;
font-size: 20px;
font-size:14px;
}
.school-details {
font-size: 12px;
font-size:9px;
max-width:120px;
}
.kreta-nav {
grid-area: nav;
padding: 0;
margin-top: 0.5rem;
overflow-x: auto;
-webkit-overflow-scrolling: touch;
scrollbar-width: none;
-ms-overflow-style: none;
.user-info {
max-width:80px;
}
.kreta-nav::-webkit-scrollbar {
display: none;
}
.nav-links {
justify-content: flex-start;
width: 100%;
gap: 0.25rem;
}
.nav-item {
padding: 0.5rem;
font-size: 13px;
}
.user-profile {
grid-area: user;
}
.user-name {
font-size: 14px;
font-size:11px;
}
.nav-logout-timer {
font-size: 12px;
}
font-size:9px;
}
}@keyframes slideDown {
from {
opacity:0;
transform:translateY(-10px);
}
to {
opacity:1;
transform:translateY(0);
}
}

View File

@@ -1,103 +1,177 @@
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: 'Iskola',
USER: 'Felhasználó',
TIMER: '45:00'
SCHOOL: LanguageManager.t("navigation.school_default"),
USER: LanguageManager.t("navigation.user_default"),
TIMER: "45:00",
};
const cookies = {
getCookie(name) {
const value = `; ${document.cookie}`;
const parts = value.split(`; ${name}=`);
return parts.length === 2 ? parts.pop().split(';').shift() : null;
}
};
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: cookies.getCookie(COOKIE_KEYS.SCHOOL_NAME) || DEFAULT_VALUES.SCHOOL,
schoolId: cookies.getCookie(COOKIE_KEYS.SCHOOL_CODE) || '',
name: cookies.getCookie(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");
document.addEventListener('DOMContentLoaded', () => {
updateHeaderInfo();
setupUserDropdown();
setupSettingsButton();
if (!navToggle || !nav) {
return;
}
const isFirefox = navigator.userAgent.toLowerCase().indexOf('firefox') > -1;
if (isFirefox) {
let isNavOpen = false;
navToggle.addEventListener("click", (e) => {
e.preventDefault();
e.stopPropagation();
if (isNavOpen) {
nav.style.display = "none";
nav.classList.remove("show");
isNavOpen = false;
} else {
nav.style.display = "flex";
nav.classList.add("show");
isNavOpen = true;
}
});
navToggle.addEventListener("touchend", (e) => {
e.preventDefault();
e.stopPropagation();
if (isNavOpen) {
nav.style.display = "none";
nav.classList.remove("show");
isNavOpen = false;
} else {
nav.style.display = "flex";
nav.classList.add("show");
isNavOpen = true;
}
});
document.addEventListener("click", (e) => {
if (!nav.contains(e.target) && !navToggle.contains(e.target) && isNavOpen) {
nav.style.display = "none";
nav.classList.remove("show");
isNavOpen = false;
}
});
const navItems = document.querySelectorAll(".nav-item");
navItems.forEach((item) => {
item.addEventListener("click", () => {
nav.style.display = "none";
nav.classList.remove("show");
isNavOpen = false;
});
});
} else {
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();
});

View File

@@ -1,160 +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);
}
::-webkit-scrollbar-track {
background:var(--background);
}
::-webkit-scrollbar-thumb {
background:var(--text-secondary);
border-radius:4px;
}
::-webkit-scrollbar-thumb:hover {
background:var(--text-primary);
}

View File

@@ -1,127 +1,202 @@
(() => {
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`;
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(() => {});
} catch (error) {
console.error("Error setting theme:", 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;
}
@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);
}
}
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 });
}
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;
if (message.action === "getTheme") {
const currentTheme =
document.documentElement.getAttribute("data-theme") || "light-green";
sendResponse({ theme: currentTheme });
}
function setTheme(theme) {
try {
const actualTheme = theme === 'default' ? 'light-blue' : theme;
document.documentElement.setAttribute('data-theme', actualTheme);
setCookie('themePreference', actualTheme);
localStorage.setItem('themePreference', actualTheme);
chrome.runtime.sendMessage({
action: 'themeChanged',
theme: actualTheme
}).catch(() => {
console.log('Extension context not available for theme sync');
});
console.log('Theme set to:', actualTheme);
} catch (error) {
console.error('Error setting theme:', error);
}
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);
}
function initializeTheme() {
const cookieTheme = getCookie('themePreference');
const localStorageTheme = localStorage.getItem('themePreference');
const theme = cookieTheme || localStorageTheme || 'light-blue';
setTheme(theme);
if (cookieTheme !== localStorageTheme) {
if (cookieTheme) {
localStorage.setItem('themePreference', cookieTheme);
} else if (localStorageTheme) {
setCookie('themePreference', localStorageTheme);
}
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', () => {
initializeTheme();
});
initializeTheme();
} else {
initializeTheme();
}
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-blue';
sendResponse({ theme: currentTheme });
}
return true;
if (document.readyState === "loading") {
document.addEventListener("DOMContentLoaded", () => {
observer.observe(document.documentElement, {
attributes: true,
attributeFilter: ["data-theme"],
});
observer.observe(document.head, {
childList: true,
subtree: true,
});
});
const observer = new MutationObserver((mutations) => {
const currentTheme = document.documentElement.getAttribute('data-theme');
const savedTheme = getCookie('themePreference') || localStorage.getItem('themePreference');
if ((!currentTheme && savedTheme) || (currentTheme !== savedTheme && savedTheme)) {
setTheme(savedTheme);
}
} 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']
});
});
} else {
observer.observe(document.documentElement, {
attributes: true,
attributeFilter: ['data-theme']
});
}
})();
observer.observe(document.head, {
childList: true,
subtree: true,
});
}
})();

File diff suppressed because one or more lines are too long

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -1,28 +1,3 @@
@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;
}
* {
box-sizing: border-box;
margin: 0;
@@ -67,10 +42,10 @@ body {
@media (max-width: 768px) {
.kreta-header {
grid-template-columns: 1fr auto;
grid-template-columns: 1fr auto auto;
grid-template-areas:
"school user"
"nav nav";
"school toggle user"
"nav nav nav";
padding: 1rem;
gap: 0.5rem;
}
@@ -135,77 +110,6 @@ body {
}
}
.kreta-nav {
padding: 0 clamp(0.5rem, 3vw, 1.5rem);
position: sticky;
top: 0;
z-index: 100;
overflow-x: auto;
-webkit-overflow-scrolling: touch;
scrollbar-width: none;
-ms-overflow-style: none;
display: flex;
justify-content: center;
}
@media (max-width: 768px) {
.kreta-nav {
grid-area: nav;
padding: 0;
margin-top: 0.5rem;
}
}
.nav-links {
display: flex;
gap: clamp(0.5rem, 2vw, 1rem);
padding: 0.25rem;
justify-content: center;
}
@media (max-width: 768px) {
.nav-links {
justify-content: flex-start;
width: 100%;
gap: 0.25rem;
}
}
.nav-links a {
color: var(--text-secondary);
text-decoration: none;
padding: clamp(0.5rem, 1.5vw, 1rem) 0.5rem;
font-weight: 500;
white-space: nowrap;
transition: all 0.2s ease;
display: flex;
align-items: center;
gap: 0.5rem;
border-radius: 8px;
}
@media (max-width: 768px) {
.nav-links a {
padding: 0.5rem;
font-size: 13px;
}
.nav-links a .material-icons-round {
font-size: 20px;
}
}
.nav-links a:hover {
color: var(--text-primary);
background-color: var(--card-card);
}
.nav-links a.active {
color: var(--accent-accent);
}
.user-profile {
position: relative;
justify-self: flex-end;
@@ -235,31 +139,22 @@ body {
gap: 0.25rem;
}
.user-name {
font-weight: 600;
font-size: 14px;
}
.nav-logout-timer {
font-size: 12px;
color: var(--text-secondary);
}
.user-dropdown {
position: absolute;
top: 100%;
right: 0;
margin-top: 0.5rem;
background: var(--card-card);
border-radius: 12px;
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
min-width: 200px;
box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1);
width: 200px;
display: none;
z-index: 1000;
overflow: hidden;
}
.user-dropdown.show {
display: block;
animation: dropdownShow 0.2s ease;
}
.dropdown-item {
@@ -289,13 +184,13 @@ body {
.filter-card {
background: var(--card-card);
border-radius: 24px;
padding: 1.5rem;
margin-bottom: 1.5rem;
box-shadow: 0px 1px 3px 0px var(--accent-shadow);
padding: 20px;
margin-bottom: 24px;
box-shadow: 0px 1px var(--shadow-blur) 0px var(--accent-shadow);
}
.filter-header {
margin-bottom: 1rem;
margin-bottom: 16px;
}
.filter-header h2 {
@@ -305,45 +200,144 @@ body {
background-color: var(--card-card);
}
/* Checkbox oszlop stílusai */
.checkbox-header {
width: 50px;
text-align: center;
font-size: 16px;
}
.checkbox-cell {
width: 50px;
text-align: center;
padding: 8px !important;
}
.homework-checkbox {
width: 20px;
height: 20px;
cursor: pointer;
appearance: none;
border: 2px solid var(--accent-30);
border-radius: 4px;
background-color: var(--card-card);
position: relative;
transition: all 0.2s ease;
display: flex;
align-items: center;
justify-content: center;
}
.homework-checkbox:hover {
border-color: var(--accent);
background-color: var(--accent-15);
transform: scale(1.05);
}
.homework-checkbox:checked {
background-color: var(--accent);
border-color: var(--accent);
}
.homework-checkbox:checked::after {
content: '✓';
color: white;
font-size: 14px;
font-weight: bold;
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
}
.homework-checkbox:focus {
outline: 2px solid var(--accent);
outline-offset: 2px;
}
.homework-checkbox:active {
transform: scale(0.95);
}
/* Megjelölt házi feladatok stílusai */
.table-row.user-completed {
opacity: 0.6;
background-color: var(--accent-15) !important;
}
.table-row.user-completed .table-cell {
color: var(--text-secondary);
}
.table-row.user-completed .status-badge.completed {
background-color: var(--success);
color: white;
}
/* Mobil nézet checkbox stílusai */
@media (max-width: 768px) {
.checkbox-header {
width: 40px;
font-size: 14px;
}
.checkbox-cell {
width: 40px;
padding: 6px !important;
}
.homework-checkbox {
width: 18px;
height: 18px;
}
.homework-checkbox:checked::after {
font-size: 12px;
}
.table-row.user-completed {
opacity: 0.7;
}
}
.filter-content {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(250px, 1fr));
gap: 1rem;
width: 100%;
grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
gap: 16px;
}
.filter-group {
display: flex;
flex-direction: column;
gap: 0.5rem;
gap: 8px;
}
.filter-group label {
display: flex;
align-items: center;
gap: 0.5rem;
font-size: 14px;
gap: 8px;
color: var(--text-secondary);
font-size: 14px;
}
.filter-group select,
.filter-group input {
padding: 0.75rem;
border-radius: 12px;
border: 1px solid var(--accent-15);
background-color: var(--background);
padding: 10px;
border: none;
border-radius: 8px;
background: var(--button-secondaryFill);
color: var(--text-primary);
font-family: inherit;
font-size: 14px;
width: 100%;
transition: border-color 0.2s ease, box-shadow 0.2s ease;
transition: all 0.2s ease;
}
.filter-group select:focus,
.filter-group input:focus {
outline: none;
border-color: var(--accent-accent);
box-shadow: 0 0 0 2px var(--accent-15);
box-shadow: 0 0 0 2px var(--accent-accent);
}
.filter-actions {
@@ -377,136 +371,226 @@ body {
opacity: 0.9;
}
.homework-list {
.stats-overview {
display: grid;
grid-template-columns: 1fr;
gap: 1rem;
grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
gap: 16px;
margin-bottom: 24px;
}
.homework-date-group {
margin-bottom: 2rem;
.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;
}
.date-header {
display: flex;
align-items: center;
gap: 0.5rem;
margin-bottom: 0.5rem;
padding-bottom: 0.5rem;
.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;
box-shadow: 0px 1px var(--shadow-blur) 0px var(--accent-shadow);
}
.homework-table {
width: 100%;
border-collapse: collapse;
}
.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 {
padding: 16px;
display: flex;
flex-direction: column;
gap: 12px;
}
.date-header h3 {
font-size: 16px;
font-weight: 600;
color: var(--text-primary);
margin: 0;
}
.homework-item {
background: var(--card-card);
display: flex;
flex-direction: column;
gap: 8px;
padding: 12px;
margin: 0 16px 12px 16px;
background: var(--accent-15);
border-radius: 12px;
padding: 1rem;
margin-bottom: 0.5rem;
box-shadow: 0px 1px 2px 0px var(--accent-shadow);
transition: transform 0.2s ease;
}
.homework-item:hover {
transform: translateY(-2px);
transform: translateX(4px);
}
.homework-item.due-tomorrow {
border-left: 4px solid var(--accent-accent);
background-color: var(--accent-5);
background: var(--accent-accent);
color: white;
}
.homework-header {
.homework-item.due-tomorrow .homework-subject,
.homework-item.due-tomorrow .homework-content,
.homework-item.due-tomorrow .homework-teacher {
color: white;
}
.homework-details {
display: flex;
justify-content: space-between;
margin-bottom: 0.5rem;
flex-direction: column;
gap: 4px;
}
.homework-subject {
font-weight: 600;
font-size: 16px;
color: var(--text-primary);
}
.homework-deadline {
font-size: 14px;
color: var(--text-secondary);
}
.homework-deadline.urgent {
color: var(--accent-accent);
font-weight: 500;
margin-bottom: 4px;
}
.homework-content {
margin-bottom: 0.5rem;
color: var(--text-primary);
font-size: 14px;
}
.homework-footer {
display: flex;
justify-content: space-between;
align-items: center;
font-size: 12px;
color: var(--text-secondary);
margin-bottom: 8px;
line-height: 1.4;
word-wrap: break-word;
overflow-wrap: break-word;
white-space: pre-wrap;
}
.homework-teacher {
color: var(--text-secondary);
font-size: 12px;
font-style: italic;
}
.loading-overlay {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
background-color: rgba(0, 0, 0, 0.7);
display: flex;
justify-content: center;
align-items: center;
z-index: 9999;
}
.loading-container {
background-color: var(--background);
padding: 2rem;
border-radius: 16px;
text-align: center;
max-width: 90%;
width: 300px;
}
.loading-logo {
width: 80px;
margin-bottom: 1rem;
}
.loading-text {
font-size: 18px;
font-weight: 600;
margin-bottom: 0.5rem;
color: var(--text-primary);
}
.loading-text2 {
font-size: 14px;
color: var(--text-secondary);
}
.empty-state {
text-align: center;
padding: 2rem;
color: var(--text-secondary);
display: none;
background: var(--card-card);
border-radius: 24px;
box-shadow: 0px 1px var(--shadow-blur) 0px var(--accent-shadow);
}
.empty-state p {
@@ -524,4 +608,146 @@ 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 {
from {
opacity: 0;
transform: translateY(-10px);
}
to {
opacity: 1;
transform: translateY(0);
}
}
@keyframes dropdownShow {
from {
opacity: 0;
transform: translateY(-10px);
}
to {
opacity: 1;
transform: translateY(0);
}
}
@keyframes spin {
to { transform: rotate(360deg); }
}
::-webkit-scrollbar {
width: clamp(4px, 1vw, 8px);
height: clamp(4px, 1vw, 8px);
}
::-webkit-scrollbar-track {
background: var(--background);
}
::-webkit-scrollbar-thumb {
background: var(--text-secondary);
border-radius: 4px;
}
::-webkit-scrollbar-thumb:hover {
background: var(--text-primary);
}

File diff suppressed because it is too large Load Diff

356
i18n/en.json Normal file
View File

@@ -0,0 +1,356 @@
{
"loading": {
"text": "Loading...",
"subtext": "Please wait!"
},
"settings": {
"title": "Settings",
"theme": "Theme",
"language": "Language",
"themes": {
"light_blue": "Light Blue",
"light_green": "Light Green",
"dark_blue": "Dark Blue",
"dark_green": "Dark Green",
"dark_red": "Dark Red",
"dark_purple": "Dark Purple",
"dark_orange": "Dark Orange",
"dark_pink": "Dark Pink",
"dark_yellow": "Dark Yellow",
"dark_cyan": "Dark Cyan",
"dark_lime": "Dark Lime",
"dark_indigo": "Dark Indigo"
},
"languages": {
"hu": "Magyar",
"en": "English"
},
"about": {
"title": "About",
"description": "Firka is an open-source project that creates a custom user interface for the KRÉTA system.",
"github": "GitHub"
},
"support": {
"title": "Support",
"description": "If you like our work and would like to support the development, you can do so in the following way:",
"kofi": "Ko-Fi"
}
},
"navigation": {
"dashboard": "Home",
"timetable": "Timetable",
"grades": "Grades",
"homework": "Homework",
"absences": "Absences",
"other": "Other",
"messages": "Messages",
"profile": "Profile",
"settings": "Settings",
"logout": "Logout",
"nav_toggle": "Open navigation"
},
"dashboard": {
"welcome": "Welcome",
"recent_grades": "Recent grades",
"upcoming_lessons": "Upcoming lessons",
"homework_due": "Homework due",
"news": "News",
"grades": "Your grades",
"absences": "Absences",
"notes": "Notes",
"exams": "Announced tests",
"all_news": "All news",
"all_grades": "All your grades",
"all_absences": "All absences",
"all_messages": "All your messages",
"all_exams": "All tests",
"not_supported": "There is currently no data to show",
"evaluation": "Evaluation"
},
"grades": {
"title": "Grades",
"subject": "Subject",
"grade": "Grade",
"date": "Date",
"teacher": "Teacher",
"average": "Average",
"chart_title": "Grades",
"semester_evaluations": "Semester evaluations",
"year_end_evaluations": "End of year tickets",
"semester_average": "Semester average",
"no_grades": "No grades",
"september": "September",
"october": "October",
"november": "November",
"december": "December",
"january_1": "January I",
"january_2": "January II",
"february": "February",
"march": "March",
"april": "April",
"may": "May",
"june_1": "June I",
"june_2": "June II"
},
"timetable": {
"title": "Timetable",
"lesson": "Lesson",
"time": "Time",
"subject": "Subject",
"teacher": "Teacher",
"classroom": "Classroom",
"homework_indicator": "Homework",
"test_indicator": "Test",
"teacher_label": "Teacher:",
"substitute_teacher_label": "Substitute teacher:",
"classroom_label": "Classroom:",
"time_label": "Time:",
"status_label": "Status:",
"substitution": "Substitution",
"cancelled": "Cancelled",
"has_homework": "Has homework",
"no_lessons_this_week": "No lessons this week or timeout occurred",
"monday": "Monday",
"tuesday": "Tuesday",
"wednesday": "Wednesday",
"thursday": "Thursday",
"friday": "Friday",
"found_current_week": "Found current week",
"open_homework": "Open homework"
},
"homework": {
"title": "Homework",
"due_date": "Due date",
"subject": "Subject",
"description": "Description",
"filter_title": "Filter",
"all_subjects": "All subjects",
"all_teachers": "All teachers",
"all_deadlines": "All deadlines",
"tomorrow_deadline": "Tomorrow's deadline",
"this_week": "This week",
"next_week": "Next week",
"no_homework": "No homework to display.",
"no_filtered_homework": "No homework matching the filter criteria.",
"teacher": "Teacher",
"no_matching_homework": "No homework matching the filter criteria.",
"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",
"date": "Date",
"lesson": "Lesson",
"type": "Type",
"justified": "Justified",
"unjustified": "Unjustified",
"filter_title": "Filter",
"all_subjects": "All subjects",
"all_types": "All types",
"pending": "Pending justification",
"subject": "Subject",
"justification": "Justification",
"hours": "hours",
"page_transform_error": "An error occurred while transforming the page",
"time_period": "Time period",
"all_periods": "All periods",
"current_month": "Current month",
"last_month": "Last month",
"current_semester": "Current semester",
"last_30_days": "Last 30 days",
"total_absences": "Total absences",
"topic": "Topic",
"status": "Status"
},
"profile": {
"title": "Profile",
"name": "Name",
"class": "Class",
"school": "School",
"student_id": "Student ID",
"settings_title": "Profile settings",
"tab_settings": "Settings",
"tab_password": "Change password",
"tab_security": "Security settings",
"tab_contacts": "Contact information",
"two_factor_description": "To use two-factor authentication, install a time-based one-time password (TOTP) application:",
"android": "Android",
"iphone": "iPhone",
"enable_2fa": "Enable two-factor authentication",
"security_key": "Security key:",
"verification_code_label": "Verification code",
"verification_code_help": "Enter the 6-digit code shown in your authenticator app.",
"verification_code_placeholder": "123456",
"verify_and_activate": "Verify and activate",
"backup_codes_description": "You can use the following backup codes to log in if you don't have access to your authenticator app. Each code can only be used once.",
"email_label": "Email address",
"email_help": "Email address is required for password recovery.",
"phone_label": "Phone number",
"phone_help": "Phone number is optional.",
"phone_placeholder": "+1 xxx xxx xxxx",
"current_password": "Current password",
"new_password": "New password",
"new_password_help": "Password must be at least 8 characters long.",
"confirm_password": "Confirm new password",
"change_password": "Change password",
"show_tips": "Show tips",
"show_tips_help": "Toggle display of tips on/off.",
"email_required": "Email address is required!",
"email_invalid": "Please enter a valid email address!",
"phone_invalid": "Please enter a valid phone number!",
"contacts_saved": "Contact information saved successfully!",
"contacts_save_error": "An error occurred while saving. Please try again later.",
"settings_saved": "Settings saved successfully! Please log in again for changes to take effect.",
"settings_save_error": "An error occurred while saving. Please try again later.",
"password_fields_required": "Please fill in all fields!",
"passwords_not_match": "New passwords do not match!",
"password_too_short": "New password must be at least 8 characters long!",
"password_changed": "Password changed successfully!",
"password_change_error": "An error occurred while changing password. Please try again later."
},
"login": {
"title": "Login",
"username": "Username",
"password": "Password",
"login_button": "Login",
"forgot_password": "Forgot password",
"two_factor_title": "Two-factor authentication",
"verification_code": "Verification code",
"username_placeholder": "Username",
"password_placeholder": "Password",
"username_required": "Please enter your username.",
"password_required": "Please enter your password.",
"help_login": "Can't log in?",
"help_link": "Help",
"system_message": "System message",
"privacy_policy": "Privacy policy",
"kreta_id": "KRÉTA ID",
"system_notification": "System notification"
},
"forgot_password": {
"title": "Forgot password",
"om_id": "OM ID",
"email": "Email address",
"om_id_placeholder": "Enter your OM ID",
"email_placeholder": "Enter your email address",
"om_id_required": "Please enter your OM ID.",
"email_required": "Please enter your email address."
},
"two_factor": {
"title": "Two-factor authentication",
"code_placeholder": "One-time password",
"code_required": "Please enter the one-time password.",
"verify_button": "Verify code",
"verifying": "Verifying...",
"trust_device": "Trust this device"
},
"logout": {
"title": "Logout",
"message": "Are you sure you want to logout?",
"confirm": "Yes",
"cancel": "Cancel",
"success": "Successfully logged out!",
"continue": "Continue"
},
"common": {
"save": "Save",
"cancel": "Cancel",
"close": "Close",
"loading": "Loading...",
"error": "Error",
"success": "Success",
"warning": "Warning",
"info": "Information",
"yes": "Yes",
"no": "No",
"continue": "Continue",
"back": "Back",
"next": "Next",
"previous": "Previous",
"all": "All",
"none": "None",
"filter": "Filter",
"search": "Search",
"select": "Select",
"required": "Required",
"optional": "Optional",
"api_error": "API error",
"api_load_error": "API load error",
"monday": "Monday",
"tuesday": "Tuesday",
"wednesday": "Wednesday",
"thursday": "Thursday",
"friday": "Friday",
"saturday": "Saturday",
"sunday": "Sunday",
"today": "Today",
"tomorrow": "Tomorrow"
},
"months": {
"january": "January",
"february": "February",
"march": "March",
"april": "April",
"may": "May",
"june": "June",
"july": "July",
"august": "August",
"september": "September",
"october": "October",
"november": "November",
"december": "December"
},
"search": {
"title": "Choose school",
"select_institution": "Please select an institution to continue!"
},
"roleselect": {
"student_book": "Student Book",
"student_description": "View grades, absences, timetable and other information.",
"dkt_title": "Digital Collaboration Space (DKT)",
"dkt_description": "Classroom communication and assignments.",
"logout_title": "Logout",
"logout_description": "Log out of the system",
"role_change_error": "An error occurred while changing roles."
},
"maintenance": {
"title": "Maintenance",
"message1": "The KRÉTA system is currently being updated and will be available again soon.",
"message2": "Thank you for your patience and understanding!",
"team": "KRÉTA Team"
},
"about": {
"title": "About",
"description": "Firka is an open source project that creates a custom user interface for the KRÉTA system.",
"support_title": "Support",
"support_description": "If you like our work and want to support development, you can do so in the following way:",
"version": "v1.1.0"
},
"app": {
"title": "Firka - KRÉTA",
"settings_title": "Firka - Settings"
},
"forgotpassword": {
"title": "Forgot Password",
"om_id_label": "OM ID",
"om_id_placeholder": "Enter your OM ID",
"om_id_required": "OM ID is required",
"email_label": "Email address",
"email_placeholder": "Enter your email address",
"email_required": "Email address is required",
"back_to_login": "Back to login",
"reset_button": "Reset password",
"error_message": "An error occurred during password reset",
"success_message": "Password reset link sent to your email address",
"invalid_data": "Invalid data",
"invalid_email": "Invalid email address format",
"recaptcha_required": "Please complete the reCAPTCHA"
}
}

356
i18n/hu.json Normal file
View File

@@ -0,0 +1,356 @@
{
"loading": {
"text": "Betöltés alatt...",
"subtext": "Kis türelmet!"
},
"settings": {
"title": "Beállítások",
"theme": "Téma",
"language": "Nyelv",
"themes": {
"light_blue": "Világos Kék",
"light_green": "Világos Zöld",
"dark_blue": "Sötét Kék",
"dark_green": "Sötét Zöld",
"dark_red": "Sötét Piros",
"dark_purple": "Sötét Lila",
"dark_orange": "Sötét Narancs",
"dark_pink": "Sötét Rózsaszín",
"dark_yellow": "Sötét Sárga",
"dark_cyan": "Sötét Cián",
"dark_lime": "Sötét Lime",
"dark_indigo": "Sötét Indigó"
},
"languages": {
"hu": "Magyar",
"en": "English"
},
"about": {
"title": "Névjegy",
"description": "A Firka egy nyílt forráskódú projekt, amely a KRÉTA rendszerhez készít saját felhasználói felületet.",
"github": "GitHub"
},
"support": {
"title": "Támogatás",
"description": "Ha tetszik a munkánk és szeretnéd támogatni a fejlesztést, az alábbi módon teheted meg:",
"kofi": "Ko-Fi"
}
},
"navigation": {
"dashboard": "Kezdőlap",
"timetable": "Órarend",
"grades": "Jegyek",
"homework": "Házi feladatok",
"absences": "Mulasztások",
"other": "Egyéb",
"messages": "Üzenetek",
"profile": "Profil",
"settings": "Beállítások",
"logout": "Kijelentkezés",
"nav_toggle": "Navigáció megnyitása"
},
"dashboard": {
"welcome": "Üdvözöljük",
"recent_grades": "Legutóbbi jegyek",
"upcoming_lessons": "Következő órák",
"homework_due": "Esedékes házi feladatok",
"news": "Hírek",
"grades": "Értékeléseid",
"absences": "Mulasztások",
"notes": "Feljegyzések",
"exams": "Bejelentett dolgozatok",
"all_news": "Összes hír",
"all_grades": "Összes jegyed",
"all_absences": "Összes mulasztás",
"all_messages": "Összes üzeneted",
"all_exams": "Összes dolgozat",
"not_supported": "Jelenleg nincsen adat amivel fel lehetne tölteni",
"evaluation": "Értékelés"
},
"grades": {
"title": "Jegyek",
"subject": "Tantárgy",
"grade": "Jegy",
"date": "Dátum",
"teacher": "Tanár",
"average": "Átlag",
"chart_title": "Jegyek",
"semester_evaluations": "Félévi értékelések",
"year_end_evaluations": "Év végi értékelések",
"semester_average": "Félévi átlag",
"no_grades": "Nincsenek jegyek",
"september": "Szeptember",
"october": "Oktober",
"november": "November",
"december": "December",
"january_1": "JanuarI",
"january_2": "JanuarII",
"february": "Februar",
"march": "Marcius",
"april": "Aprilis",
"may": "Majus",
"june_1": "JuniusI",
"june_2": "JuniusII"
},
"timetable": {
"title": "Órarend",
"lesson": "Óra",
"time": "Idő",
"subject": "Tantárgy",
"teacher": "Tanár",
"classroom": "Terem",
"homework_indicator": "Házi feladat",
"test_indicator": "Számonkérés",
"teacher_label": "Tanár:",
"substitute_teacher_label": "Helyettesítő tanár:",
"classroom_label": "Terem:",
"time_label": "Időpont:",
"status_label": "Állapot:",
"substitution": "Helyettesítés",
"cancelled": "Elmarad",
"has_homework": "Van házi feladat",
"no_lessons_this_week": "Nincsenek órák ezen a héten vagy időtúllépés történt",
"monday": "Hétfő",
"tuesday": "Kedd",
"wednesday": "Szerda",
"thursday": "Csütörtök",
"friday": "Péntek",
"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ő",
"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": "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": "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",
"date": "Dátum",
"lesson": "Óra",
"type": "Típus",
"justified": "Igazolt",
"unjustified": "Igazolatlan",
"filter_title": "Szűrés",
"all_subjects": "Minden tantárgy",
"all_types": "Mindegy",
"pending": "Igazolásra vár",
"subject": "Tantárgy",
"justification": "Igazolás",
"hours": "óra",
"page_transform_error": "Hiba történt az oldal átalakítása során",
"time_period": "Időszak",
"all_periods": "Összes időszak",
"current_month": "Aktuális hónap",
"last_month": "Előző hónap",
"current_semester": "Aktuális félév",
"last_30_days": "Utolsó 30 nap",
"total_absences": "Összes hiányzás",
"topic": "Téma",
"status": "Állapot"
},
"profile": {
"title": "Profil",
"name": "Név",
"class": "Osztály",
"school": "Iskola",
"student_id": "Diák azonosító",
"settings_title": "Profil beállítások",
"tab_settings": "Beállítások",
"tab_password": "Jelszó módosítása",
"tab_security": "Biztonsági beállítások",
"tab_contacts": "Elérhetőségek",
"two_factor_description": "A kétfaktoros hitelesítés használatához telepítsen egy időalapú, egyszer használatos jelszó (TOTP) alkalmazást:",
"android": "Android",
"iphone": "iPhone",
"enable_2fa": "Kétfaktoros azonosítás bekapcsolása",
"security_key": "Biztonsági kulcs:",
"verification_code_label": "Ellenőrző kód",
"verification_code_help": "Adja meg a hitelesítő alkalmazásban megjelenő 6 számjegyű kódot.",
"verification_code_placeholder": "123456",
"verify_and_activate": "Ellenőrzés és aktiválás",
"backup_codes_description": "Az alábbi biztonsági kódokat használhatja bejelentkezéshez, ha nem fér hozzá a hitelesítő alkalmazásához. Minden kód csak egyszer használható.",
"email_label": "E-mail cím",
"email_help": "Az e-mail cím megadása a jelszó emlékeztető miatt szükséges.",
"phone_label": "Telefonszám",
"phone_help": "A telefonszám megadása nem kötelező.",
"phone_placeholder": "+36 xx xxx xxxx",
"current_password": "Jelenlegi jelszó",
"new_password": "Új jelszó",
"new_password_help": "A jelszónak legalább 8 karakter hosszúnak kell lennie.",
"confirm_password": "Új jelszó megerősítése",
"change_password": "Jelszó módosítása",
"show_tips": "Tippek megjelenítése",
"show_tips_help": "A tippek megjelenítésének ki/be kapcsolása.",
"email_required": "Az e-mail cím megadása kötelező!",
"email_invalid": "Kérjük, adjon meg egy érvényes e-mail címet!",
"phone_invalid": "Kérjük, adjon meg egy érvényes telefonszámot!",
"contacts_saved": "Elérhetőségek sikeresen mentve!",
"contacts_save_error": "Hiba történt a mentés során. Kérjük, próbálja újra később.",
"settings_saved": "Beállítások sikeresen mentve! A változtatások érvényesítéséhez jelentkezzen be újra.",
"settings_save_error": "Hiba történt a mentés során. Kérjük, próbálja újra később.",
"password_fields_required": "Kérjük, töltse ki az összes mezőt!",
"passwords_not_match": "Az új jelszavak nem egyeznek!",
"password_too_short": "Az új jelszónak legalább 8 karakter hosszúnak kell lennie!",
"password_changed": "Jelszó sikeresen módosítva!",
"password_change_error": "Hiba történt a jelszó módosítása során. Kérjük, próbálja újra később."
},
"login": {
"title": "Bejelentkezés",
"username": "Felhasználónév",
"password": "Jelszó",
"login_button": "Bejelentkezés",
"forgot_password": "Elfelejtett jelszó",
"two_factor_title": "Kétfaktoros hitelesítés",
"verification_code": "Ellenőrző kód",
"username_placeholder": "Felhasználónév",
"password_placeholder": "Jelszó",
"username_required": "Kérjük, add meg a felhasználóneved.",
"password_required": "Kérjük, add meg a jelszavad.",
"help_login": "Nem tudsz bejelentkezni?",
"help_link": "Segítség",
"system_message": "Rendszerüzenet",
"privacy_policy": "Adatvédelmi szabályzat",
"kreta_id": "KRÉTA azonosító",
"system_notification": "Rendszerértesítés"
},
"forgot_password": {
"title": "Elfelejtett jelszó",
"om_id": "OM azonosítód",
"email": "E-mail cím",
"om_id_placeholder": "Add meg az OM azonosítód",
"email_placeholder": "Add meg az e-mail címed",
"om_id_required": "Kérjük, add meg az OM azonosítód.",
"email_required": "Kérjük, add meg az e-mail címed."
},
"two_factor": {
"title": "Kétfaktoros azonosítás",
"code_placeholder": "Egyszeri jelszó",
"code_required": "Kérjük, add meg az egyszeri jelszót.",
"verify_button": "Kód ellenőrzése",
"verifying": "Ellenőrzés...",
"trust_device": "Eszköz megbízhatónak jelölése"
},
"logout": {
"title": "Kijelentkezés",
"message": "Biztosan ki szeretne jelentkezni?",
"confirm": "Igen",
"cancel": "Mégse",
"success": "Sikeres kijelentkezés!",
"continue": "Tovább"
},
"common": {
"save": "Mentés",
"cancel": "Mégse",
"close": "Bezárás",
"loading": "Betöltés...",
"error": "Hiba",
"success": "Sikeres",
"warning": "Figyelmeztetés",
"info": "Információ",
"yes": "Igen",
"no": "Nem",
"continue": "Tovább",
"back": "Vissza",
"next": "Következő",
"previous": "Előző",
"all": "Összes",
"none": "Nincs",
"filter": "Szűrés",
"search": "Keresés",
"select": "Válassz",
"required": "Kötelező",
"optional": "Opcionális",
"api_error": "API hiba",
"api_load_error": "API betöltési hiba",
"monday": "hétfő",
"tuesday": "kedd",
"wednesday": "szerda",
"thursday": "csütörtök",
"friday": "péntek",
"saturday": "szombat",
"sunday": "vasárnap",
"today": "Ma",
"tomorrow": "Holnap"
},
"months": {
"january": "január",
"february": "február",
"march": "március",
"april": "április",
"may": "május",
"june": "június",
"july": "július",
"august": "augusztus",
"september": "szeptember",
"october": "október",
"november": "november",
"december": "december"
},
"search": {
"title": "Válassz iskolát",
"select_institution": "Kérjük, válasszon egy intézményt a folytatáshoz!"
},
"roleselect": {
"student_book": "Ellenőrzőkönyv",
"student_description": "Jegyek, hiányzások, órarended és egyéb információk megtekintése.",
"dkt_title": "Digitális Kollaborációs Tér (DKT)",
"dkt_description": "Osztálytermi kommunikáció és feladatok.",
"logout_title": "Kijelentkezés",
"logout_description": "Kilépés a rendszerből",
"role_change_error": "Hiba történt a szerepkör váltása közben."
},
"maintenance": {
"title": "Karbantartás",
"message1": "A KRÉTA rendszer jelenleg frissítés alatt van, hamarosan újra elérhetővé válik.",
"message2": "Köszönjük türelmüket és megértésüket!",
"team": "KRÉTA Csapat"
},
"about": {
"title": "Névjegy",
"description": "A Firka egy nyílt forráskódú projekt, amely a KRÉTA rendszerhez készít saját felhasználói felületet.",
"support_title": "Támogatás",
"support_description": "Ha tetszik a munkánk és szeretnéd támogatni a fejlesztést, az alábbi módon teheted meg:",
"version": "v1.1.0"
},
"app": {
"title": "Firka - KRÉTA",
"settings_title": "Firxa - Beállítások"
},
"forgotpassword": {
"title": "Elfelejtett jelszó",
"om_id_label": "OM azonosító",
"om_id_placeholder": "Adja meg az OM azonosítóját",
"om_id_required": "Az OM azonosító megadása kötelező",
"email_label": "E-mail cím",
"email_placeholder": "Adja meg az e-mail címét",
"email_required": "Az e-mail cím megadása kötelező",
"back_to_login": "Vissza a bejelentkezéshez",
"reset_button": "Jelszó visszaállítása",
"error_message": "Hiba történt a jelszó visszaállítása során",
"success_message": "A jelszó visszaállítási link elküldve az e-mail címére",
"invalid_data": "Hibás adatok",
"invalid_email": "Érvénytelen e-mail cím formátum",
"recaptcha_required": "Kérjük, töltse ki a reCAPTCHA-t"
}
}

View File

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="128" height="128" viewBox="0 0 24 24"><path fill="none" stroke="#A7DC22" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M15 19h4m0 0v-4m0 4l-4-4M9 5H5m0 0v4m0-4l4 4m6-4h4m0 0v4m0-4l-4 4M9 19H5m0 0v-4m0 4l4-4"/></svg>

After

Width:  |  Height:  |  Size: 283 B

1
icons/BadgeCheck.svg Normal file
View File

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="128" height="128" viewBox="0 0 24 24"><g fill="none"><path fill-rule="evenodd" clip-rule="evenodd" d="M10.054 2.344a3 3 0 0 1 3.892 0l1.271 1.084a1 1 0 0 0 .57.236l1.665.133a3 3 0 0 1 2.751 2.751l.133 1.666a1 1 0 0 0 .236.569l1.084 1.271a3 3 0 0 1 0 3.892l-1.084 1.271a1 1 0 0 0-.236.57l-.133 1.665a3 3 0 0 1-2.751 2.751l-1.666.133a1 1 0 0 0-.569.236l-1.271 1.084a3 3 0 0 1-3.892 0l-1.271-1.084a1 1 0 0 0-.57-.236l-1.665-.133a3 3 0 0 1-2.751-2.751l-.133-1.666a1 1 0 0 0-.236-.569l-1.084-1.271a3 3 0 0 1 0-3.892l1.084-1.271a1 1 0 0 0 .236-.57l.133-1.665a3 3 0 0 1 2.751-2.751l1.666-.133a1 1 0 0 0 .569-.236l1.271-1.084zm5.653 8.363a1 1 0 0 0-1.414-1.414L11 12.586l-1.293-1.293a1 1 0 0 0-1.414 1.414l2 2a1 1 0 0 0 1.414 0l4-4z" fill="#A7DC22"/></g></svg>

After

Width:  |  Height:  |  Size: 799 B

1
icons/Calendar.svg Normal file
View File

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="128" height="128" viewBox="0 0 24 24"><g fill="none"><path fill="#A7DC22" d="M4 7v2h16V7a2 2 0 0 0-2-2H6a2 2 0 0 0-2 2"/><path stroke="#A7DC22" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M16 5h2a2 2 0 0 1 2 2v2H4V7a2 2 0 0 1 2-2h2m8 0V3m0 2H8m0-2v2M4 9.5V19a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V9.5"/></g></svg>

After

Width:  |  Height:  |  Size: 376 B

View File

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="128" height="128" viewBox="0 0 24 24"><path fill="#A7DC22" fill-rule="evenodd" d="M12 21a9 9 0 1 0 0-18a9 9 0 0 0 0 18m1.707-11.293a1 1 0 0 0-1.414-1.414l-3 3a1 1 0 0 0 0 1.414l3 3a1 1 0 0 0 1.414-1.414L11.414 12z" clip-rule="evenodd"/></svg>

After

Width:  |  Height:  |  Size: 289 B

View File

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="128" height="128" viewBox="0 0 24 24"><path fill="#A7DC22" fill-rule="evenodd" d="M12 21a9 9 0 1 0 0-18a9 9 0 0 0 0 18M10.293 9.707a1 1 0 1 1 1.414-1.414l3 3a1 1 0 0 1 0 1.414l-3 3a1 1 0 0 1-1.414-1.414L12.586 12z" clip-rule="evenodd"/></svg>

After

Width:  |  Height:  |  Size: 289 B

1
icons/CloseCircle.svg Normal file
View File

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="128" height="128" viewBox="0 0 24 24"><g fill="none"><path fill-rule="evenodd" clip-rule="evenodd" d="M2 12C2 6.477 6.477 2 12 2s10 4.477 10 10s-4.477 10-10 10S2 17.523 2 12zm8.207-3.207a1 1 0 0 0-1.414 1.414L10.586 12l-1.793 1.793a1 1 0 1 0 1.414 1.414L12 13.414l1.793 1.793a1 1 0 0 0 1.414-1.414L13.414 12l1.793-1.793a1 1 0 0 0-1.414-1.414L12 10.586l-1.793-1.793z" fill="#A7DC22"/></g></svg>

After

Width:  |  Height:  |  Size: 440 B

1
icons/Subject.svg Normal file
View File

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="128" height="128" viewBox="0 0 24 24"><g fill="none"><path fill-rule="evenodd" clip-rule="evenodd" d="M11.514 3.126a1 1 0 0 1 .972 0l9 5A1 1 0 0 1 22 9v7a1 1 0 1 1-2 0v-5.3l-1 .555v.004l-6.067 3.016a2 2 0 0 1-1.848-.035L2.357 9.479a1 1 0 0 0-.284-.103a1 1 0 0 1 .441-1.25l9-5zM5 13.199V17a1 1 0 0 0 .553.894l6 3a1 1 0 0 0 .894 0l6-3A1 1 0 0 0 19 17v-3.256l-6.083 2.844a2 2 0 0 1-1.805-.056L5 13.2z" fill="#A7DC22"/></g></svg>

After

Width:  |  Height:  |  Size: 472 B

1
icons/assigment.svg Normal file
View File

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="128" height="128" viewBox="0 0 24 24"><g fill="none"><path stroke="#FFA046" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M14 8H9m2 4H9"/><path fill="#FFA046" d="M3 16h8c0 1.333.8 4 4 4a3 3 0 0 0 3-3V4h1a2 2 0 0 1 2 2v2a2 2 0 0 1-2 2h-1v7a3 3 0 0 1-3 3H5a2 2 0 0 1-2-2z"/><path stroke="#FFA046" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M15 20c-3.2 0-4-2.667-4-4H3v2a2 2 0 0 0 2 2zm0 0a3 3 0 0 0 3-3v-7m0-6H7a2 2 0 0 0-2 2v9.5M18 4h1a2 2 0 0 1 2 2v2a2 2 0 0 1-2 2h-1m0-6v6"/></g></svg>

After

Width:  |  Height:  |  Size: 578 B

1
icons/homework.svg Normal file
View File

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="128" height="128" viewBox="0 0 24 24"><g fill="none"><path fill-rule="evenodd" clip-rule="evenodd" d="M15.586 3a2 2 0 0 1 2.828 0L21 5.586a2 2 0 0 1 0 2.828L19.414 10L14 4.586L15.586 3zm-3 3l-9 9A2 2 0 0 0 3 16.414V19a2 2 0 0 0 2 2h2.586A2 2 0 0 0 9 20.414l9-9L12.586 6z" fill="#A7DC22"/></g></svg>

After

Width:  |  Height:  |  Size: 345 B

1
icons/messages.svg Normal file
View File

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" viewBox="0 0 32 32"><g fill="none"><path fill-rule="evenodd" clip-rule="evenodd" d="M6 21a3 3 0 0 1-3-3v-3h5a2 2 0 0 0 2 2h4a2 2 0 0 0 2-2h5v3a3 3 0 0 1-3 3H6zm15-8h-5a2 2 0 0 0-2 2h-4a2 2 0 0 0-2-2H3V6a3 3 0 0 1 3-3h12a3 3 0 0 1 3 3v7z" fill="#A7DC22"/></g></svg>

After

Width:  |  Height:  |  Size: 327 B

BIN
images/cactus.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 42 KiB

BIN
images/chrome.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 21 KiB

BIN
images/firefox.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 45 KiB

View File

@@ -1,385 +1,313 @@
@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;
}
: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,54 +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 || ''
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('KRÉTA azonosító: ', '');
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>KRÉTA azonosító: ${schoolInfo.omCode}</div>` : ''}
${schoolInfo.kretaId ? `<div>${schoolInfo.kretaId}</div>` : ""}
${schoolInfo.omCode ? `<div>${LanguageManager.t("login.kreta_id")}: ${schoolInfo.omCode}</div>` : ""}
</div>
</div>
@@ -61,141 +66,138 @@ async function transformLoginPage() {
<div class="form-group">
<input class="form-control" type="text" id="UserName" name="UserName"
placeholder="Felhasználónév" maxlength="256" autocomplete="username" required>
<div class="error-message">Kérjük, add meg a felhasználóneved.</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="Jelszó" maxlength="256" autocomplete="current-password" required>
<button type="button" class="show-password" aria-label="Jelszó mutatása">
<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">Kérjük, add meg a jelszavad.</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">Bejelentkezés</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">Elfelejtettem a jelszavam</a>
<a href="https://tudasbazis.ekreta.hu/pages/viewpage.action?pageId=2425086" target="_blank" class="help-link">Nem tudsz bejelentkezni?</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>Rendszerértesítés</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">Adatkezelési tájékoztató</a>
target="_blank" class="privacy-link">${LanguageManager.t("login.privacy_policy")}</a>
</footer>
</div>
`;
document.body.innerHTML = newHTML;
// Biztonságos DOM létrehozás innerHTML helyett
document.body.innerHTML = '';
// Biztonságos HTML parsing DOMParser használatával
const parser = new DOMParser();
const doc = parser.parseFromString(newHTML, 'text/html');
const tempDiv = doc.body;
while (tempDiv.firstChild) {
document.body.appendChild(tempDiv.firstChild);
}
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');
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`);
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', () => {
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;
}
});
if (!isValid) {
return;
}
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) => {
});
}
}

261
login/twofactor.css Normal file
View File

@@ -0,0 +1,261 @@
:root {
--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;
}
:root[data-theme="dark-blue"] {
--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;
}
* {
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;
}
.login-container {
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);
}
.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;
}
.logo-text {
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;
}
.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;
}
.twofactor-form {
width:100%;
}
.form-group {
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;
}
.form-control:focus {
outline:none;
border-color:var(--accent-accent) !important;
}
.form-control::placeholder {
color:var(--text-secondary) !important;
}
.password-group {
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;
}
.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));
}
.show-password:hover .icon-eye {
opacity:1;
}
.form-check {
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;
}
.form-check-input:checked {
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;
}
.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;
}
.btn-kreta:hover {
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;
}
.btn-link:hover {
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;
}
.login-footer {
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;
}
.privacy-link:hover {
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;
}
.error-message.show {
display:block;
}
.form-control.error {
border:1px solid var(--error-accent) !important;
}
header,main > .container-fluid,footer {
display:none !important;
}
@media (max-width:576px) {
.login-container {
width:100%;
padding:16px;
}
.login-card {
padding:16px;
}
}

188
login/twofactor.js Normal file
View File

@@ -0,0 +1,188 @@
async function transformTwoFactorPage() {
try {
if (document.readyState !== "complete") {
await new Promise((resolve) => {
window.addEventListener("load", resolve);
});
}
if (typeof loadingScreen !== "undefined") {
loadingScreen.show();
}
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",
};
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">
Firka
</p>
<h1 class="twofactor-title">${LanguageManager.t("twofactor.title")}</h1>
</div>
<form class="twofactor-form" action="${formData.action}" method="post" id="twoFactorForm">
<input type="hidden" id="ClientId" name="ClientId" value="${formData.clientId}">
<input type="hidden" id="RememberLogin" name="RememberLogin" value="${formData.rememberLogin}">
<input type="hidden" id="ReturnUrl" name="ReturnUrl" value="${formData.returnUrl}">
<input type="hidden" id="IsRecoveryCode" name="IsRecoveryCode" value="${formData.isRecoveryCode}">
<input name="__RequestVerificationToken" type="hidden" value="${formData.requestToken}">
<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">
</button>
<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")}
</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>
</div>
<div class="d-flex justify-content-center mt-3">
<span class="subtext">
${LanguageManager.t("twofactor.no_access")}
<button type="submit" class="btn-link" formaction="/account/loginwithrecoverycode">
${LanguageManager.t("twofactor.recovery_code")}
</button>
</span>
</div>
</form>
</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>
</footer>
</div>
`;
document.body.innerHTML = '';
const parser = new DOMParser();
const doc = parser.parseFromString(newHTML, 'text/html');
const tempDiv = doc.body;
while (tempDiv.firstChild) {
document.body.appendChild(tempDiv.firstChild);
}
applyTheme();
setupEventListeners();
if (typeof loadingScreen !== "undefined") {
loadingScreen.hide();
}
} catch (error) {
if (typeof loadingScreen !== "undefined") {
loadingScreen.hide();
}
}
}
function applyTheme() {
try {
if (typeof getCookie === "function") {
const theme = getCookie("theme") || "light-blue";
document.documentElement.setAttribute("data-theme", theme);
}
} catch (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");
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`,
);
});
}
formInputs.forEach((input) => {
input.addEventListener("input", () => {
validateInput(input);
});
input.addEventListener("blur", () => {
validateInput(input, true);
});
});
if (twoFactorForm) {
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");
} else {
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]");
let isValid = true;
inputs.forEach((input) => {
if (!validateInput(input, true)) {
isValid = false;
}
});
if (isValid) {
const submitButton = form.querySelector(".btn-kreta");
if (submitButton) {
submitButton.disabled = true;
submitButton.innerHTML = '';
const spinnerSpan = document.createElement('span');
spinnerSpan.className = 'spinner';
const textSpan = document.createElement('span');
textSpan.className = 'btn-text';
textSpan.textContent = LanguageManager.t('twofactor.verifying');
submitButton.appendChild(spinnerSpan);
submitButton.appendChild(textSpan);
}
form.submit();
}
}
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,42 +1,17 @@
(() => {
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 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 = getCookie('themePreference') || localStorage.getItem('themePreference') || 'light-blue';
const instituteCode = getCookie('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>
@@ -59,38 +34,38 @@
</footer>
</div>
`;
// Replace body content
document.body.innerHTML = newHTML;
// Start countdown timer
const timerElement = document.getElementById('automaticRedirectTimer');
document.body.innerHTML = '';
const parser = new DOMParser();
const doc = parser.parseFromString(newHTML, 'text/html');
const tempDiv = doc.body;
while (tempDiv.firstChild) {
document.body.appendChild(tempDiv.firstChild);
}
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

@@ -1,7 +1,7 @@
{
"manifest_version": 3,
"name": "Firxa",
"version": "1.1.0",
"version": "1.3.1",
"description": "KRÉTA webes verziójának újraírása",
"icons": {
"128": "images/firka_logo_128.png"
@@ -12,107 +12,209 @@
"128": "images/firka_logo_128.png"
}
},
"web_accessible_resources": [{
"resources": [
"settings/*",
"images/*",
"fonts/*.woff2",
"icons/*.svg",
"grades/chart.js"
],
"matches": ["https://*.e-kreta.hu/*"]
}],
"browser_specific_settings": {
"gecko": {
"id": "firxa@zan1456.hu",
"strict_min_version": "109.0",
"data_collection_permissions": {
"required": ["none"]
}
}
},
"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/*"
"https://idp.e-kreta.hu/Account/Login*",
"https://idp.e-kreta.hu/Account/Logout*",
"https://idp.e-kreta.hu/Account/LoginWithTwoFactor*",
"https://*.e-kreta.hu/Hianyzas/Hianyzasok*",
"https://*.e-kreta.hu/Adminisztracio/BelepesKezelo*",
"https://*.e-kreta.hu/Intezmeny/Faliujsag*",
"https://*.e-kreta.hu/TanuloErtekeles/Osztalyzatok*",
"https://*.e-kreta.hu/Orarend/InformaciokOrarend*",
"https://*.e-kreta.hu/Adminisztracio/Profil*",
"https://*.e-kreta.hu/Tanulo/TanuloHaziFeladat*",
"https://*.e-kreta.hu/Adminisztracio/ElfelejtettJelszo*",
"https://intezmenykereso.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"
],
"js": ["global/maintenance.js", "global/theme.js", "global/navigation.js"],
"css": ["global/theme.css", "global/navigation.css"],
"run_at": "document_start"
},
{
"matches": [
"https://*.e-kreta.hu/*"
"https://idp.e-kreta.hu/Account/Login*"
],
"css": ["global/maintenance.css"],
"run_at": "document_end"
"js": [
"login/login.js"
],
"css": [
"login/login.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"
],
"run_at": "document_start"
},
{
"matches": [
"https://*.e-kreta.hu/Hianyzas/Hianyzasok*"
],
"js": ["absences/absences.js"],
"css": ["absences/absences.css"],
"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"
"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_end"
},
{
"matches": [
"https://*.e-kreta.hu/Adminisztracio/ElfelejtettJelszo*"
"js": [
"roleselect/roleselect.js"
],
"js": ["forgotpassword/forgotpassword.js"],
"css": ["forgotpassword/forgotpassword.css"],
"run_at": "document_end"
"css": [
"roleselect/roleselect.css"
],
"run_at": "document_start"
},
{
"matches": [
"https://*.e-kreta.hu/Intezmeny/Faliujsag*"
],
"js": ["dashboard/dashboard.js"],
"css": ["dashboard/dashboard.css"],
"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"
],
"run_at": "document_end"
}
]

View File

@@ -1,487 +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;
}
.nav-links {
display: flex;
gap: clamp(0.5rem, 2vw, 1rem);
padding: 0.25rem;
justify-content: center;
}
.nav-links a {
color: var(--text-secondary);
text-decoration: none;
padding: clamp(0.5rem, 1.5vw, 1rem) 0.5rem;
font-weight: 500;
white-space: nowrap;
transition: all 0.2s ease;
display: flex;
align-items: center;
gap: 0.5rem;
border-radius: 8px;
}
.nav-links a:hover {
color: var(--text-primary);
background-color: var(--card-card);
}
.nav-links a.active {
color: 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(--card-card);
background:var(--card-card);
}
.user-info {
text-align: right;
text-align:right;
}
.user-name {
display: block;
color: var(--text-primary);
font-size: 16px;
font-weight: 500;
}
.user-time {
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: 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;
grid-template-areas:
"school user"
"nav nav";
padding: 1rem;
gap: 0.5rem;
}
.school-info {
grid-area: school;
}
.nav-links {
grid-area: nav;
margin-top: 0.5rem;
justify-content: flex-start;
}
.user-profile {
grid-area: user;
}
.app-grid {
grid-template-columns: 1fr;
}
.profile-tabs {
padding: 1rem;
}
.tab-content {
padding: 1rem;
}
grid-template-columns:1fr auto auto;
grid-template-areas:"school toggle user"
"nav nav nav";
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,36 +1,6 @@
(() => {
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 shortenSchoolName(name) {
if (!name) return '';
const maxLength = 30;
if (name.length <= maxLength) return name;
const parts = name.split(' - ');
if (parts.length === 2) {
const [code, fullName] = parts;
return `${code} - ${fullName.substring(0, maxLength - code.length - 5)}...`;
}
return name.substring(0, maxLength - 3) + '...';
}
function createSecurityTab() {
return `
function createSecurityTab() {
return `
<div class="security-content">
<div class="setup-steps">
<div class="step-card">
@@ -125,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>
@@ -145,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>
@@ -168,10 +138,10 @@
</div>
</div>
`;
}
function createSettingsTab() {
return `
}
function createSettingsTab() {
return `
<div class="settings-form">
<div class="form-group">
<label class="form-label">
@@ -185,253 +155,214 @@
</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 = getCookie('userEmail') || '';
phoneInput.value = getCookie('userPhone') || '';
saveButton?.addEventListener('click', async () => {
const email = emailInput.value.trim();
const phone = phoneInput.value.trim();
if (!email) {
alert('Az e-mail cím megadása kötelező!');
return;
}
if (email && !isValidEmail(email)) {
alert('Kérjük, adjon meg egy érvényes e-mail címet!');
return;
}
if (phone && !isValidPhone(phone)) {
alert('Kérjük, adjon meg egy érvényes telefonszámot!');
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('Elérhetőségek sikeresen mentve!');
} else {
throw new Error('Hiba történt a mentés során.');
}
} catch (error) {
console.error('Error saving contacts:', error);
alert('Hiba történt a mentés során. Kérjük, próbálja újra később.');
}
});
}
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('Beállítások sikeresen mentve! A változtatások érvényesítéséhez jelentkezzen be újra.');
} else {
throw new Error('Hiba történt a mentés során.');
}
} catch (error) {
console.error('Error saving settings:', error);
alert('Hiba történt a mentés során. Kérjük, próbálja újra később.');
}
});
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('Kérjük, töltse ki az összes mezőt!');
return;
}
if (newPassword !== confirmPassword) {
alert('Az új jelszavak nem egyeznek!');
return;
}
if (newPassword.length < 8) {
alert('Az új jelszónak legalább 8 karakter hosszúnak kell lennie!');
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('Jelszó sikeresen módosítva!');
document.getElementById('currentPassword').value = '';
document.getElementById('newPassword').value = '';
document.getElementById('confirmPassword').value = '';
} else {
throw new Error('Hiba történt a jelszó módosítása során.');
}
} catch (error) {
console.error('Error changing password:', error);
alert('Hiba történt a jelszó módosítása során. Kérjük, próbálja újra később.');
}
});
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) {
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) {
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) {
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(data) {
const schoolNameFull = `${data.schoolInfo.id} - ${data.schoolInfo.name}`;
const shortenedSchoolName = shortenSchoolName(schoolNameFull);
return `
}
function createProfileHTML() {
return `
<div class="kreta-container">
<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">
Firka
</p>
<div class="school-details" title="${schoolNameFull}">
${shortenedSchoolName}
</div>
</div>
<nav class="kreta-nav">
<div class="nav-links">
<a href="/Intezmeny/Faliujsag">
<span class="material-icons-round">calendar_today</span>
Kezdőlap
</a>
<a href="/TanuloErtekeles/Osztalyzatok">
<span class="material-icons-round">bookmark_border</span>
Jegyek
</a>
<a href="/Orarend/InformaciokOrarend">
<span class="material-icons-round">home</span>
Órarend
</a>
<a href="/Hianyzas/Hianyzasok">
<span class="material-icons-round">schedule</span>
Hiányok
</a>
</div>
</nav>
<div class="user-profile">
<button class="user-dropdown-btn">
<div class="user-info">
<span class="user-name">${data.userData.name}</span>
<span class="user-time" id="logoutTimer">${data.userData.time}</span>
</div>
</button>
<div class="user-dropdown">
<a href="/Adminisztracio/Profil" class="dropdown-item">
<span class="material-icons-round">person</span>
Profil
</a>
<a href="#" class="dropdown-item" id="settingsBtn">
<span class="material-icons-round">settings</span>
Beállítások
</a>
<a href="/Home/Logout" class="dropdown-item">
<span class="material-icons-round">logout</span>
Kijelentkezés
</a>
</div>
</div>
</header>
${createTemplate.header()}
<main class="kreta-main">
<div class="card">
@@ -464,43 +395,23 @@
</main>
</div>
`;
}
async function init() {
if (window.location.pathname.includes('/Adminisztracio/Profil')) {
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/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);
});
const userData = {
schoolInfo: {
name: getCookie('schoolName') || 'Iskola',
id: getCookie('schoolCode') || ''
},
userData: {
name: getCookie('userName') || 'Felhasználó',
time: document.querySelector('.usermenu_timer')?.textContent?.trim() || '45:00',
email: getCookie('userEmail') || ''
}
};
document.body.innerHTML = createProfileHTML(userData);
setupEventListeners();
setupContactForm();
}
async function init() {
if (window.location.pathname.includes("/Adminisztracio/Profil")) {
document.body.innerHTML = '';
const parser = new DOMParser();
const doc = parser.parseFromString(createProfileHTML(), 'text/html');
const tempDiv = doc.body;
while (tempDiv.firstChild) {
document.body.appendChild(tempDiv.firstChild);
}
setupUserDropdown();
setupMobileNavigation();
setupEventListeners();
setupContactForm();
}
init();
})();
}
init();
})();

View File

@@ -1,380 +1,275 @@
@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;
}
* {
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,24 +1,17 @@
(() => {
const setCookie = (name, value, days = 365) => {
const date = new Date();
date.setTime(date.getTime() + (days * 24 * 60 * 60 * 1000));
document.cookie = `${name}=${value}; expires=${date.toUTCString()}; path=/; domain=.e-kreta.hu`;
};
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();
@@ -27,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('Hiba történt a szerepkör váltása közben.');
console.error("Error changing role:", error);
alert(LanguageManager.t("roleselect.role_change_error"));
}
};
@@ -50,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">
@@ -70,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">
Ellenőrzőkönyv
<div class="role-description">Jegyek, hiányzások, órarended és egyéb információk megtekintése.</div>
${LanguageManager.t("roleselect.student_book")}
<div class="role-description">${LanguageManager.t("roleselect.student_description")}</div>
</div>
</div>
</div>
@@ -82,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">
Digitális Kollaborációs Tér (DKT)
<div class="role-description">Osztálytermi kommunikáció és feladatok.</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">
Kijelentkezés
<div class="role-description">Kilépés a rendszerből</div>
${LanguageManager.t("roleselect.logout_title")}
<div class="role-description">${LanguageManager.t("roleselect.logout_description")}</div>
</div>
</div>
</div>
@@ -107,77 +103,77 @@
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() || 'Felhasználónév';
const userNameEl = document.querySelector(".UserName");
const userName =
userNameEl?.textContent.trim() || LanguageManager.t("common.username");
if (schoolCode && fullSchoolName) {
setCookie('schoolCode', schoolCode);
setCookie('schoolName', fullSchoolName);
setCookie('schoolSubdomain', schoolSubdomain);
cookieManager.set("schoolCode", schoolCode);
cookieManager.set("schoolName", fullSchoolName);
cookieManager.set("schoolSubdomain", schoolSubdomain);
}
if (userName) {
setCookie('userName', userName);
cookieManager.set("userName", userName);
}
document.body.innerHTML = '';
const parser = new DOMParser();
const doc = parser.parseFromString(createHTML(
schoolCode,
fullSchoolName,
userName,
), 'text/html');
const tempDiv = doc.body;
while (tempDiv.firstChild) {
document.body.appendChild(tempDiv.firstChild);
}
document.body.innerHTML = createHTML(schoolCode, fullSchoolName, userName);
const links = [
{ rel: 'preconnect', href: 'https://fonts.googleapis.com' },
{ rel: 'preconnect', href: 'https://fonts.gstatic.com', crossorigin: true },
{ href: 'https://fonts.googleapis.com/css2?family=Montserrat:ital,wght@0,100..900;1,100..900&family=Figtree:wght@300..900&display=swap', rel: 'stylesheet' }
];
links.forEach(link => {
const linkElement = document.createElement('link');
Object.entries(link).forEach(([key, value]) => linkElement[key] = value);
document.head.appendChild(linkElement);
});
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();
}
})();
})();

194
search/search.css Normal file
View File

@@ -0,0 +1,194 @@
header,footer,.page-title,.card-kreta {
display:none !important;
}
* {
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;
}
/* 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%);
}
/* 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);
}
.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;
}
.logo {
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;
}
/* 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);
}
/* Form styling */
form {
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;
}
.form-control:focus {
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;
}
/* 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;
}
.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;
}
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;
}
.dropdown-item.active {
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;
}
.btn-kreta:hover {
background-color:var(--accent-secondary) !important;
transform:translateY(-1px) !important;
}
.btn-kreta:active {
transform:translateY(1px) !important;
}
.btn-kreta:disabled {
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%;
}
.privacy-link {
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;
}
/* Responsive adjustments */
@media (max-width:576px) {
.firka-search-wrapper {
width:95%;
}
.search-title {
font-size:20px;
}
.btn-kreta {
padding:10px 20px !important;
font-size:14px !important;
}
}

144
search/search.js Normal file
View File

@@ -0,0 +1,144 @@
function initializeTransformation() {
const form = document.querySelector("form");
const autocomplete = document.querySelector(".autocomplete");
if (form && autocomplete) {
applyFirkaStyling();
} else {
setTimeout(initializeTransformation, 500);
}
}
document.addEventListener("DOMContentLoaded", () => {
setTimeout(initializeTransformation, 1000);
});
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") {
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 logoText = document.createElement('p');
logoText.className = 'logo-text';
const logoImg = document.createElement('img');
logoImg.src = chrome.runtime.getURL('images/firka_logo.png');
logoImg.alt = 'Firka';
logoImg.className = 'logo';
logoText.appendChild(logoImg);
logoText.appendChild(document.createTextNode('Firka'));
const searchTitle = document.createElement('h1');
searchTitle.className = 'search-title';
searchTitle.textContent = 'Válassz iskolát';
firkaHeader.appendChild(logoText);
firkaHeader.appendChild(searchTitle);
const formContainer = document.createElement("div");
formContainer.className = "firka-form-container";
const firkaFooter = document.createElement("div");
firkaFooter.className = "firka-footer";
const privacyLink = document.createElement('a');
privacyLink.href = 'https://tudasbazis.ekreta.hu/pages/viewpage.action?pageId=4064926';
privacyLink.target = '_blank';
privacyLink.className = 'privacy-link';
privacyLink.textContent = 'Adatkezelési tájékoztató';
firkaFooter.appendChild(privacyLink);
const existingWrapper = document.querySelector(".firka-search-wrapper");
if (existingWrapper) {
existingWrapper.remove();
}
searchWrapper.appendChild(firkaHeader);
if (originalForm) {
formContainer.appendChild(originalForm);
searchWrapper.appendChild(formContainer);
}
searchWrapper.appendChild(firkaFooter);
document.body.appendChild(searchWrapper);
setupAutocompleteListeners();
if (redirectButton) {
redirectButton.addEventListener("click", function (event) {
if (!instituteCodeInput.value) {
event.preventDefault();
alert(LanguageManager.t("search.select_institution"));
}
});
}
observeAutocompleteValue(instituteCodeInput, redirectButton);
} catch (error) {
}
}
function setupAutocompleteListeners() {
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");
if (dropdown) {
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;
}
});
});
}
});
observer.observe(document.body, {
childList: true,
subtree: true,
});
}
}
function observeAutocompleteValue(valueInput, button) {
if (!valueInput || !button) return;
const observer = new MutationObserver((mutations) => {
button.disabled = !valueInput.value;
});
observer.observe(valueInput, {
attributes: true,
attributeFilter: ["value"],
});
const checkInterval = setInterval(() => {
if (valueInput.value) {
button.disabled = false;
clearInterval(checkInterval);
}
}, 500);
}

View File

@@ -1,276 +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 {
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 {
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 {
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;
}
.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;
}
.language-option:hover {
background:var(--card-hover);
border-color:var(--accent-accent);
}
.language-option.active {
background:var(--accent-accent);
border-color:var(--accent-accent);
color:white;
}
.language-name {
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

@@ -3,7 +3,9 @@
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Firxa Beállítások</title>
<title>Firxa - Beállítások</title>
<link rel="icon" type="image/png" href="../images/firka_logo_128.png">
<link rel="shortcut icon" type="image/png" href="../images/firka_logo_128.png">
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Montserrat:ital,wght@0,100..900;1,100..900&display=swap" rel="stylesheet">
@@ -15,18 +17,18 @@
<div class="popup-container">
<header class="popup-header">
<p class="logo-text">
<img src="https://i.imgur.com/WugwlzI.png" alt="Firka" class="logo">
<img src="../images/firka_logo.png" alt="Firka" class="logo">
Firxa
</p>
</header>
<div class="settings-card">
<h2>Beállítások</h2>
<h2 data-i18n="settings.title">Beállítások</h2>
<div class="settings-group">
<div class="setting-section">
<div class="setting-header">
<span class="material-icons-round">palette</span>
Téma
<span data-i18n="settings.theme">Téma</span>
</div>
<div class="theme-grid">
<button class="theme-option" data-theme="default">
@@ -36,7 +38,7 @@
<div class="preview-card"></div>
</div>
</div>
<span class="theme-name">Világos Kék</span>
<span class="theme-name" data-i18n="settings.themes.light_blue">Világos Kék</span>
</button>
<button class="theme-option" data-theme="light-green">
<div class="theme-preview light-green">
@@ -45,7 +47,7 @@
<div class="preview-card"></div>
</div>
</div>
<span class="theme-name">Világos Zöld</span>
<span class="theme-name" data-i18n="settings.themes.light_green">Világos Zöld</span>
</button>
<button class="theme-option" data-theme="dark-blue">
<div class="theme-preview dark-blue">
@@ -54,7 +56,7 @@
<div class="preview-card"></div>
</div>
</div>
<span class="theme-name">Sötét Kék</span>
<span class="theme-name" data-i18n="settings.themes.dark_blue">Sötét Kék</span>
</button>
<button class="theme-option" data-theme="dark-green">
<div class="theme-preview dark-green">
@@ -63,7 +65,22 @@
<div class="preview-card"></div>
</div>
</div>
<span class="theme-name">Sötét Zöld</span>
<span class="theme-name" data-i18n="settings.themes.dark_green">Sötét Zöld</span>
</button>
</div>
</div>
<div class="setting-section">
<div class="setting-header">
<span class="material-icons-round">language</span>
<span data-i18n="settings.language">Nyelv</span>
</div>
<div class="language-grid">
<button class="language-option" data-language="hu">
<span class="language-name" data-i18n="settings.languages.hu">Magyar</span>
</button>
<button class="language-option" data-language="en">
<span class="language-name" data-i18n="settings.languages.en">English</span>
</button>
</div>
</div>
@@ -71,24 +88,24 @@
</div>
<div class="about-card">
<h2>Névjegy</h2>
<h2 data-i18n="settings.about.title">Névjegy</h2>
<div class="about-content">
<p>A Firka egy nyílt forráskódú projekt, amely a KRÉTA rendszerhez készít saját felhasználói felületet.</p>
<p data-i18n="settings.about.description">A Firka egy nyílt forráskódú projekt, amely a KRÉTA rendszerhez készít saját felhasználói felületet.</p>
<a href="https://github.com/QwIT-Development/" target="_blank" class="github-link">
<span class="material-icons-round">code</span>
GitHub
<span data-i18n="settings.about.github">GitHub</span>
</a>
</div>
</div>
<div class="support-card">
<h2>Támogatás</h2>
<h2 data-i18n="settings.support.title">Támogatás</h2>
<div class="support-content">
<p>Ha tetszik a munkánk és szeretnéd támogatni a fejlesztést, az alábbi módon teheted meg:</p>
<p data-i18n="settings.support.description">Ha tetszik a munkánk és szeretnéd támogatni a fejlesztést, az alábbi módon teheted meg:</p>
<div class="support-buttons">
<a href="https://ko-fi.com/zan1456" target="_blank" class="support-button">
<span class="material-icons-round">coffee</span>
Ko-Fi
<span data-i18n="settings.support.kofi">Ko-Fi</span>
</a>
</div>
</div>
@@ -98,6 +115,8 @@
<div class="version-info" id="version">v1.1.0</div>
</footer>
</div>
<script src="index.js"></script>
<script src="../tools/cookieManager.js"></script>
<script src="../global/language.js"></script>
<script src="index.js"></script>
</body>
</html>

View File

@@ -1,141 +1,250 @@
document.addEventListener('DOMContentLoaded', async () => {
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 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`;
}
async function getCurrentTheme() {
try {
const [tab] = await chrome.tabs.query({ active: true, currentWindow: true });
const response = await chrome.tabs.sendMessage(tab.id, { action: 'getTheme' });
return response.theme;
} catch (error) {
console.error('Error getting current theme:', error);
return 'default';
}
}
function updateThemeButtons(currentTheme) {
document.querySelectorAll('.theme-option').forEach(button => {
const theme = button.dataset.theme;
button.classList.toggle('active', theme === currentTheme);
/*if (theme === 'light-blue' || theme === 'dark-blue' || theme === 'default') {
button.classList.add('disabled');
button.setAttribute('disabled', 'true');
}*/
});
}
function isThemeDisabled(theme) {
return theme === 'default' || theme === 'dark-blue';
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`;
}
function getCurrentTheme() {
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();
}
function getCurrentLanguage() {
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);
});
}
async function applyLanguage(language) {
setCookie("languagePreference", language);
localStorage.setItem("languagePreference", language);
updateLanguageButtons(language);
const tabs = await chrome.tabs.query({});
tabs.forEach((tab) => {
chrome.tabs
.sendMessage(tab.id, {
action: "changeLanguage",
language: language,
})
.catch(() => {});
});
}
async function applyTheme(theme) {
if (isThemeDisabled(theme)) {
alert('Ez a téma jelenleg nem elérhető.');
return;
}
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(() => {
console.log('Tab not ready for theme change:', tab.id);
});
});
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('Ez a téma jelenleg nem elérhető.');
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);
});
});
let initialTheme = localStorage.getItem('themePreference') ||
getCookie('themePreference') ||
await getCurrentTheme() ||
'light-green';
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();
document.getElementById('version').textContent = `v${manifest.version}`;
themeButtons.forEach(button => {
button.addEventListener('mouseover', () => {
if (!button.hasAttribute('disabled')) {
button.style.transform = 'translateY(-2px)';
}
});
button.addEventListener('mouseout', () => {
button.style.transform = 'translateY(0)';
});
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 = `
position: fixed;
top: 20px;
right: 20px;
background: var(--accent-accent);
color: white;
padding: 12px 20px;
border-radius: 8px;
font-family: 'Montserrat', sans-serif;
font-weight: 500;
z-index: 10000;
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 = `
@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;
}
});
});
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)";
});
});
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

25
tools/cookieManager.js Normal file
View File

@@ -0,0 +1,25 @@
const cookieManager = {
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`;
},
};

122
tools/createTemplate.js Normal file
View File

@@ -0,0 +1,122 @@
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") || "",
},
};
const schoolNameFull = `${data.schoolInfo.id} - ${data.schoolInfo.name}`;
const shortenedSchoolName = helper.shortenSchoolName(schoolNameFull);
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">
Firka
</p>
<div class="school-details" title="${schoolNameFull}">
${shortenedSchoolName}
</div>
</div>
<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>
</button>
<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>
<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>
<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>
</div>
</nav>
<div class="user-profile">
<button class="user-dropdown-btn">
<div class="user-info">
<span class="user-name">${data.userData.name}</span>
<span class="nav-logout-timer" id="logoutTimer">${data.userData.time}</span>
</div>
</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")}
</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")}
</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")}
</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")}
</a>
</div>
</div>
</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--;
}
};
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");
});
});

40
tools/helper.js Normal file
View File

@@ -0,0 +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));
}
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;
},
};

53
tools/loadingScreen.css Normal file
View File

@@ -0,0 +1,53 @@
.modalBckgroundMain {
display:none !important;
}
body:not(.loaded) {
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;
}
.loading-content {
display:flex;
flex-direction:column;
align-items:center;
gap:1rem;
}
.loading-logo {
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;
}
.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%;
}

71
tools/loadingScreen.js Normal file
View File

@@ -0,0 +1,71 @@
const loadingScreen = {
show() {
document.body.classList.remove("loaded");
const existingLoadingScreen = document.querySelector(".loading-screen");
if (existingLoadingScreen) return;
const loadingScreen = document.createElement("div");
loadingScreen.className = "loading-screen";
const loadingContent = document.createElement('div');
loadingContent.className = 'loading-content';
const loadingLogo = document.createElement('img');
loadingLogo.src = chrome.runtime.getURL("images/loading.gif");
loadingLogo.alt = 'Firka';
loadingLogo.className = 'loading-logo';
const loadingText = document.createElement('div');
loadingText.className = 'loading-text';
loadingText.setAttribute('data-i18n', 'loading.text');
loadingText.textContent = 'Betöltés alatt...';
const loadingText2 = document.createElement('div');
loadingText2.className = 'loading-text2';
loadingText2.setAttribute('data-i18n', 'loading.subtext');
loadingText2.textContent = 'Kis türelmet!';
loadingContent.appendChild(loadingLogo);
loadingContent.appendChild(loadingText);
loadingContent.appendChild(loadingText2);
loadingScreen.appendChild(loadingContent);
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";
const removeLoadingScreen = () => {
if (loadingScreen && loadingScreen.parentNode) {
loadingScreen.remove();
}
};
loadingScreen.addEventListener("transitionend", removeLoadingScreen, {
once: true,
});
setTimeout(removeLoadingScreen, 500);
}
},
};
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();
}
});