From 710550655d5c8aafcce91514412c1903dd20f087 Mon Sep 17 00:00:00 2001 From: u2 Date: Wed, 12 Feb 2025 12:07:41 +0100 Subject: [PATCH] init --- css/style.css | 226 ++++++++ data/class.json | 34 ++ data/criteria.json | 326 +++++++++++ data/students/_class_json_schema.json | 105 ++++ data/students/_validate_json.py | 37 ++ ..._programowanie_aplikacji_II_2024_2025.json | 198 +++++++ index.html | 196 +++++++ js/script.js | 518 ++++++++++++++++++ 8 files changed, 1640 insertions(+) create mode 100644 css/style.css create mode 100644 data/class.json create mode 100644 data/criteria.json create mode 100644 data/students/_class_json_schema.json create mode 100644 data/students/_validate_json.py create mode 100644 data/students/ckziu_class_4i_programowanie_aplikacji_II_2024_2025.json create mode 100644 index.html create mode 100644 js/script.js diff --git a/css/style.css b/css/style.css new file mode 100644 index 0000000..c0f7182 --- /dev/null +++ b/css/style.css @@ -0,0 +1,226 @@ +/* Podstawowe style dla zakładek */ +.tab { + display: none; +} + +.tab.active { + display: block; +} +header { + display: flex; + justify-content: space-between; + align-items: right; +} +.header-box { + display: flex; + justify-content: space-between; + align-items: center; + background-color: cornflowerblue; /* Kolor tła nagłówka */ + padding: 10px; /* Padding wewnętrzny dla lepszego wyglądu */ + color: white; /* Kolor tekstu */ +} +.up-button { + display: flex; +} + +.header-title { + margin-left: auto; /* Przesuwa tytuł na prawo */ +} + +/* Style dla przycisków kategorii */ +.category-buttons { + margin: 10px 0; + text-align: center; + background-color: #A9A9A9; + + +} + +.category-buttons button { + margin: 5px; + padding: 10px 15px; + font-size: 16px; + cursor: pointer; + background-color: lightgray; + border: 1px solid black; + border-radius: 4px; + transition: background-color 0.3s, color 0.3s, border 0.3s; + + +} + +.category-buttons button.active { + background-color: #4CAF50; + color: white; + border: 1px solid #4CAF50; +} + +.up-button { + margin: 10px 0; + text-align: left; +} + +.up-button button { + margin: 5px; + padding: 10px 15px; + font-size: 16px; + cursor: pointer; + background-color: #f2f2f2; + border: 1px solid #ccc; + border-radius: 4px; + transition: background-color 0.3s, color 0.3s, border 0.3s; +} + +.up-button button.active { + background-color: #4CAF50; + color: white; + border: 1px solid #4CAF50; +} + +.container { + display: flex; + flex-direction: column; /* Elementy jeden pod drugim */ + align-items: flex-start; /* Ustawia elementy po lewej stronie */ + margin-left: 20px; /* Możesz dostosować margines według potrzeb */ +} + +.select-role, +.select-class { + margin: 10px 0; /* Dostosuj odstęp między elementami */ +} + +/* Stylizacja tabeli */ +table { + width: 100%; + border-collapse: collapse; + margin-top: 20px; + background-color: whitesmoke; +} + +th, td { + border: 1px solid grey; + padding: 8px; + text-align: center; +} + +th { + background-color: whitesmoke; +} + +tr:nth-child(even) { + background-color: whitesmoke; +} + +/* Stylizacja kontenera klasy */ +.select-class { + text-align: center; +} + +.select-role { + text-align: center; +} + +.select-class select { + padding: 5px; + font-size: 16px; + border: 1px solid #ccc; + border-radius: 4px; +} + +.select-role select { + padding: 5px; + font-size: 16px; + border: 1px solid #ccc; + border-radius: 4px; +} + +/* Stylizacja nagłówków */ +h1, h2, h3 { + text-align: center; +} + +/* Dodatkowe style dla układu */ +body { + font-family: Arial, sans-serif; + margin: 20px; + background-color: #fafafa; +} + +/* Stylizacja stopki */ +footer.footer { + width: 100%; + padding: 20px 0; + background-color: #fafafa; + color: #555; +} + +.footer-container { + max-width: 1200px; + margin: 0 auto; + display: flex; + flex-direction: column; + align-items: stretch; +} + +.footer-left, .footer-right { + width: 100%; +} + +.footer-left { + text-align: left; +} + +.footer-right { + text-align: right; +} + +.footer-line { + border: none; + border-top: 2px solid #ddd; + margin: 20px 0; + width: 100%; +} + +/* Dodatkowe style dla estetyki */ +.footer-left p, +.footer-right p { + margin: 5px 0; + font-size: 14px; + color: #333; + + +} + +/* Stylizacja przycisków ogólna */ +button { + outline: none; +} + +button:hover { + opacity: 0.8; +} + +/* Stylizacja checkboxów */ +input[type="checkbox"] { + transform: scale(1.2); + cursor: pointer; +} +.sticky { + position: sticky; + top: 0; + background-color: white; /* lub inny kolor, aby tło było widoczne */ + z-index: 1000; /* zapewnia, że będzie na wierzchu */ + border-bottom: 1px solid #ccc; /* opcjonalnie, aby oddzielić od treści */ +} + +.dark-background { + background-color: #2e2e2e; /* Ciemnoszare tło */ + color: black; /* Jasny kolor tekstu dla lepszej czytelności */ + margin: 0; + padding: 0; + font-family: Arial, sans-serif; +} + +.lead { + background-color: #555; +} \ No newline at end of file diff --git a/data/class.json b/data/class.json new file mode 100644 index 0000000..b7447ae --- /dev/null +++ b/data/class.json @@ -0,0 +1,34 @@ +[ + { + "school": "CKZiU", + "city": "City", + "year": "202/202", + "semester": "Semestr 1", + "subject": "Programowanie Aplikacji Internetowych I", + "level": "Podstawowy", + "publisher": "Dokumentacja", + "class": "3", + "group": "i", + "profile": "Technik Informatyk", + "max_points": 55, + "teacher": "M. Pabi", + "file_path": "students/ckziu_class_3i_programowanie_aplikacji_2024_2025.json", + "student_count": 17 + }, + { + "school": "CKZiU", + "city": "City", + "year": "202/202", + "semester": "Semestr 1", + "subject": "Programowanie Aplikacji Internetowych II", + "level": "Podstawowy", + "publisher": "Dokumentacja", + "class": "4", + "group": "i", + "profile": "Technik Informatyk", + "max_points": 55, + "teacher": "M. Pabi", + "file_path": "students/ckziu_class_4i_programowanie_aplikacji_II_2024_2025.json", + "student_count": 18 + } +] diff --git a/data/criteria.json b/data/criteria.json new file mode 100644 index 0000000..5254de0 --- /dev/null +++ b/data/criteria.json @@ -0,0 +1,326 @@ +{ + "criteria": [ + { + "id": 1, + "name": "95-100% raz w semestrze" + }, + { + "id": 2, + "name": "brak godzin nieusprawiedliwionych w semestrze" + }, + { + "id": 3, + "name": "minimum 85% frekwencje w semestrze" + }, + { + "id": 4, + "name": "uczestnictwo w etapie szkolnym" + }, + { + "id": 5, + "name": "uczestnictwo w etapie rejonowym" + }, + { + "id": 6, + "name": "uczestnictwo w etapie wojewódzkim" + }, + { + "id": 7, + "name": "uczestnictwo w etapie ogólnopolskim" + }, + { + "id": 8, + "name": "wyróżnienie w etapie szkolnym" + }, + { + "id": 9, + "name": "wyróżnienie w etapie rejonowym" + }, + { + "id": 10, + "name": "wyróżnienie w etapie wojewódzkim" + }, + { + "id": 11, + "name": "wyróżnienie w etapie ogólnopolskim" + }, + { + "id": 12, + "name": "laureat, finalista ogólnopolski" + }, + { + "id": 13, + "name": "każdy udział w konkursach" + }, + { + "id": 14, + "name": "wyróżnienie w konkursie" + }, + { + "id": 15, + "name": "każdy udział w reprezentowaniu" + }, + { + "id": 16, + "name": "uzyskanie wyniku w rozgrywkach na szczeblu rejonowym w przedziale I-III miejsce" + }, + { + "id": 17, + "name": "uzyskanie wyniku w rozgrywkach na szczeblu wojewódzkim w przedziale I-III miejsce" + }, + { + "id": 18, + "name": "uzyskanie wyniku w rozgrywkach na szczeblu ogólnopolskim w przedziale I-III miejsce" + }, + { + "id": 19, + "name": "aktywny udział w organizowaniu imprez klasowych, szkolnych, uroczystości okolicznościowych ( każdorazowo)" + }, + { + "id": 20, + "name": "pełnienie funkcji w klasie i wywiązywanie się z obowiązków ( na koniec każdego semestru)" + }, + { + "id": 21, + "name": "reprezentowanie szkoły na zewnątrz ( udział w uroczystościach okolicznościowych, prezentacja szkoły) każdorazowo" + }, + { + "id": 22, + "name": "uczestnictwo w poczcie sztandarowym ( raz w semestrze)" + }, + { + "id": 23, + "name": "pomoc nauczycielowi/ pracownikowi szkoły (raz w semestrze)" + }, + { + "id": 24, + "name": "wolontariat ( raz w semestrze)" + }, + { + "id": 25, + "name": "udział w akcjach charytatywnych ( każdorazowo)" + }, + { + "id": 26, + "name": "rozwijanie własnych zainteresowań poza szkołą ( zajęcia sportowe, muzyczne, artystyczne, koła naukowe) na koniec roku szkolnego" + }, + { + "id": 27, + "name": "każdą godzinę lekcyjną nieusprawiedliwioną ( raz w miesiącu)" + }, + { + "id": 28, + "name": "każde nieusprawiedliwione spóźnienie na zajęcia szkolne ( raz w miesiącu)" + }, + { + "id": 29, + "name": "każde nieusprawiedliwione spóźnienie na zajęcia szkolne ( raz w miesiącu)" + },{ + "id": 30, + "name": "przeszkadzanie w prowadzeniu zajęć dydaktyczno-wychowawczych (każdorazowo)" + }, + { + "id": 31, + "name": "niewłaściwe stosunek do nauczycieli i pracowników szkoły (każdorazowo)" + }, + { + "id": 32, + "name": "udział w bójce (każdorazowo)" + }, + { + "id": 33, + "name": "używanie wulgarnego słownictwa (każdorazowo)" + },{ + "id": 34, + "name": "palenie papierosów, e-papierosów na terenie szkoły (każdorazowo)" + }, + { + "id": 35, + "name": "agresję słowną (każdorazowo)" + }, + { + "id": 36, + "name": "korzystanie na lekcji z telefonu komórkowego, smartfona, innych urządzeń informatycznych na lekcji (każdorazowo)" + }, + { + "id": 37, + "name": "brak odpowiedniego stroju na uroczystościach okolicznościowych, egzaminach(każdorazowo)" + }, + { + "id": 38, + "name": "kradzież; spożywanie, posiadanie lub bycie pod wpływem alkoholu na terenie szkoły; zażywanie, posiadanie lub rozprowadzanie narkotyków lub środków odurzających na terenie szkoły; psychiczne lub fizyczne znęcanie się nad rówieśnikami; (każdorazowo)" + }, + { + "id": 39, + "name": "W sytuacjach nieujętych w powyższych tabelach o przydziale punktów decyduje nauczyciel. (wpis w dzienniku wraz uzasadnieniem)" + }, + { + "id": 40, + "name": "Ocenę roczną stanowi średnia punktów z całego roku szkolnego" + } + + ], + "categories": [ + { + "id": "frekwencja", + "name": "Frekwencja", + "criteria_ids": [ + 1,2,3 + ] + }, + { + "id": "konkursy-olimpiady", + "name": "udział w konkursach, olimpiadach przedmiotowych ( każdorazowo)", + "criteria_ids": [ + 4, + 5, + 6, + 7, + 8, + 9, + 10, + 11, + 12 + ] + }, + { + "id": "konkursy-szkolne", + "name": "udział w konkursach szkolnych (każdorazowo)", + "criteria_ids": [ + 13, + 14 + ] + }, + { + "id": "reprezentowanie-szkoły", + "name": "reprezentowanie szkoły w zawodach sportowych indywidualnie i w zespole:", + "criteria_ids": [ + 15, + 16, + 17, + 18 + ] + }, + { + "id": "inne-dodatnie", + "name": "Inne dodatnie", + "criteria_ids": [ + 19, + 20, + 21, + 22, + 23, + 24, + 25, + 26 + ] + }, + { + "id": "inne-ujemne", + "name": "Inne ujemne", + "criteria_ids": [ + 27, + 28, + 29, + 30, + 31, + 32, + 33, + 34, + 35, + 36, + 37, + 38, + 39, + 40 + + ] + } + ], + "roles": { + "teacher": { + "name": "Teacher", + "criteria_ids": [ + 1, + 2, + 3, + 4, + 5, + 6, + 7, + 27, + 28, + 29, + 30, + 31, + 32, + 33, + 34, + 35, + 36, + 37, + 38, + 39, + 40 + + ] + }, + "homeroom_teacher": { + "name": "Homeroom Teacher", + "criteria_ids": [ + 1, + 2, + 3, + 4, + 5, + 6, + 7, + 8 + ] + }, + "principal": { + "name": "Principal", + "criteria_ids": [ + 8, + 9, + 10, + 11 + ] + }, + "student": { + "name": "Student", + "criteria_ids": [ + 12, + 13 + ] + }, + "patryk": { + "name": "patryk", + "criteria_ids": [ + 15, + 16 + ] + } + }, + "people": [ + { + "name": "M. Pabiszczak", + "roles": [ + "teacher", + "homeroom_teacher" + ] + }, + { + "name": "A. Nowak", + "roles": [ + "principal" + ] + }, + { + "name": "K. Kowalski", + "roles": [ + "teacher" + ] + } + ] +} diff --git a/data/students/_class_json_schema.json b/data/students/_class_json_schema.json new file mode 100644 index 0000000..d906e47 --- /dev/null +++ b/data/students/_class_json_schema.json @@ -0,0 +1,105 @@ +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "type": "object", + "properties": { + "header": { + "type": "object", + "properties": { + "school": { + "type": "string" + }, + "city": { + "type": "string" + }, + "year": { + "type": "string" + }, + "semester": { + "type": "string" + }, + "subject": { + "type": "string" + }, + "level": { + "type": "string" + }, + "publisher": { + "type": "string" + }, + "class": { + "type": "string" + }, + "group": { + "type": "string" + }, + "profile": { + "type": "string" + }, + "max_points": { + "type": "integer" + }, + "teacher": { + "type": "string" + } + }, + "required": [ + "school", + "city", + "year", + "semester", + "subject", + "class", + "group", + "profile", + "teacher" + ] + }, + "students": { + "type": "array", + "items": { + "type": "object", + "properties": { + "id": { + "type": "integer" + }, + "first_name": { + "type": "string" + }, + "last_name": { + "type": "string" + }, + "name": { + "type": "string" + }, + "grade": { + "type": [ + "string", + "null" + ] + }, + "points": { + "type": [ + "number", + "null" + ] + }, + "status": { + "type": "integer" + } + }, + "required": [ + "id", + "first_name", + "last_name", + "name", + "grade", + "status" + ] + } + } + }, + "required": [ + "header", + "students" + ] +} \ No newline at end of file diff --git a/data/students/_validate_json.py b/data/students/_validate_json.py new file mode 100644 index 0000000..47e21af --- /dev/null +++ b/data/students/_validate_json.py @@ -0,0 +1,37 @@ +import json +import sys +from jsonschema import validate, ValidationError + +def validate_json(schema_file, json_file): + try: + # Wczytaj schemat JSON + with open(schema_file, 'r') as f: + schema = json.load(f) + + # Wczytaj dane JSON + with open(json_file, 'r') as f: + data = json.load(f) + + # Sprawdź, czy dane JSON są zgodne ze schematem + validate(instance=data, schema=schema) + print("JSON jest zgodny z schematem") + + except ValidationError as e: + print("JSON nie jest zgodny z schematem:", e.message) + except json.JSONDecodeError as e: + print("Błąd wczytywania JSON:", e) + except FileNotFoundError as e: + print("Plik nie został znaleziony:", e) + except Exception as e: + print("Wystąpił błąd:", e) + +if __name__ == "__main__": + if len(sys.argv) != 3: + print("Użycie: python validate_json.py ") + sys.exit(1) + + schema_file = sys.argv[1] + json_file = sys.argv[2] + + validate_json(schema_file, json_file) + diff --git a/data/students/ckziu_class_4i_programowanie_aplikacji_II_2024_2025.json b/data/students/ckziu_class_4i_programowanie_aplikacji_II_2024_2025.json new file mode 100644 index 0000000..25d61c5 --- /dev/null +++ b/data/students/ckziu_class_4i_programowanie_aplikacji_II_2024_2025.json @@ -0,0 +1,198 @@ +{ + "header": { + "school": "CKZiU", + "city": "City", + "year": "202/202", + "semester": "Semestr 1", + "subject": "Programowanie Aplikacji Internetowych II", + "level": "Podstawowy", + "publisher": "Dokumentacja", + "class": "4", + "group": "i", + "profile": "Technik Informatyk", + "max_points": 55, + "teacher": "M. Pabi" + }, + "students": [ + { + "id": 1, + "first_name": "Aleksander", + "last_name": "Adam", + "name": "Adam A", + "grade": "Brak ocen", + "points": null, + "info": "", + "status": 1 + }, + { + "id": 2, + "first_name": "Bartosz", + "last_name": "Boh", + "name": "Boh B", + "grade": "Brak ocen", + "points": null, + "info": "Na prośbę rodzica proszę o zwolnienie ucznia z 9 lekcji", + "status": 1 + }, + { + "id": 3, + "first_name": "Jakub", + "last_name": "Gj", + "name": "Gj J", + "grade": "Brak ocen", + "points": null, + "info": "Na prośbę rodzica proszę o zwolnienie ucznia z 9 lekcji", + "status": 1 + }, + { + "id": 4, + "first_name": "Wiktor", + "last_name": "Kier", + "name": "Kier W", + "grade": "Brak ocen", + "points": null, + "info": "", + "status": 1 + }, + { + "id": 5, + "first_name": "Jakub", + "last_name": "Km", + "name": "Km J", + "grade": "Brak ocen", + "points": null, + "info": "", + "status": 1 + }, + { + "id": 6, + "first_name": "Fabian", + "last_name": "Kow", + "name": "Kow F", + "grade": "Brak ocen", + "points": null, + "info": "", + "status": 1 + }, + { + "id": 7, + "first_name": "Patryk", + "last_name": "Mac", + "name": "Mac P", + "grade": "Brak ocen", + "points": null, + "info": "", + "status": 1 + }, + { + "id": 8, + "first_name": "Marcel", + "last_name": "Mars", + "name": "Mars M", + "grade": "Brak ocen", + "points": null, + "info": "", + "status": 1 + }, + { + "id": 9, + "first_name": "Szymon", + "last_name": "Pt", + "name": "Pt S", + "grade": "Brak ocen", + "points": null, + "info": "", + "status": 1 + }, + { + "id": 10, + "first_name": "Dmytro", + "last_name": "Shev", + "name": "Shev D", + "grade": "Brak ocen", + "points": null, + "info": "", + "status": 1 + }, + { + "id": 11, + "first_name": "Anna", + "last_name": "Sik", + "name": "Sik A", + "grade": "Brak ocen", + "points": null, + "info": "", + "status": 1 + }, + { + "id": 12, + "first_name": "Szymon", + "last_name": "Spili", + "name": "Spili S", + "grade": "Brak ocen", + "points": null, + "info": "Na prośbę rodzica proszę o zwolnienie ucznia z 9 lekcji", + "status": 1 + }, + { + "id": 13, + "first_name": "Alan", + "last_name": "Stas", + "name": "Stas A", + "grade": "Brak ocen", + "points": null, + "info": "", + "status": 1 + }, + { + "id": 14, + "first_name": "Kamil", + "last_name": "Szy", + "name": "Szy K", + "grade": "Brak ocen", + "points": null, + "info": "", + "status": 1 + }, + { + "id": 15, + "first_name": "Jakub", + "last_name": "Toc", + "name": "Toc J", + "grade": "Brak ocen", + "points": null, + "info": "Na prośbę rodzica proszę o zwolnienie ucznia z 9 lekcji", + "status": 1 + }, + { + "id": 16, + "first_name": "Mateusz", + "last_name": "Wój", + "name": "Wój M", + "grade": "Brak ocen", + "points": null, + "info": "Na prośbę rodzica proszę o zwolnienie ucznia z 9 lekcji", + "status": 1 + }, + { + "id": 17, + "first_name": "Tomasz", + "last_name": "Zad", + "name": "Zad T", + "grade": "Brak ocen", + "points": null, + "info": "", + "status": 1 + }, + { + "id": 18, + "first_name": "Wiktor", + "last_name": "Zal", + "name": "Zal W", + "grade": "Brak ocen", + "points": null, + "info": "", + "status": 1 + } + ] +} \ No newline at end of file diff --git a/index.html b/index.html new file mode 100644 index 0000000..4723828 --- /dev/null +++ b/index.html @@ -0,0 +1,196 @@ + + + + + Ocena Zachowania + + + + + + + + +
+
+ + + +
+

Ocena Zachowania

+
+
+ + +
+ + +
+

Ustal punkty dla kryteriów

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
KryteriumPunkty
Frekwencja 95-100%
Brak godzin nieusprawiedliwionych
Minimum 85% frekwencja
Etap szkolny
Etap rejonowy
Etap wojewódzki
Etap ogólnopolski
Udział w konkursach
Wyróżnienie w konkursie
Reprezentacja indywidualna
Reprezentacja zespołowa
Udział w zawodach
Organizacja imprez
Funkcje w klasie
Uroczystości okolicznościowe
Udział w poczcie sztandarowej
Pomoc nauczycielowi
Wolontariat
+
+ + +
+

Kryteria oceny zachowania -

+ + +
+

Wybierz role:

+ +
+ +
+

Wybierz klasę:

+ +
+ +
+ + + + + +
+ + + + + + + + + + + + +
Imię i Nazwisko
+
+ + +
+

Statystyka dla wszystkich dni

+
+
+ + + +
+ + +
+ + + + + + diff --git a/js/script.js b/js/script.js new file mode 100644 index 0000000..46c1cb2 --- /dev/null +++ b/js/script.js @@ -0,0 +1,518 @@ +// Zmienne globalne +let currentCategory = 'frekwencja'; +let currentClass = ''; +let studentsData = []; +let currentDay = 0; +let currentRole = "teacher" +let currentRoleCriterias = [] +const baseDate = new Date(); + +function generateTable(category) { + const table = document.getElementById('student-table'); + const thead = table.querySelector('thead tr'); + const tbody = table.querySelector('tbody'); + + // Wyczyść istniejące nagłówki i wiersze + thead.innerHTML = ''; + tbody.innerHTML = ''; + + // Dodaj nagłówek 'Imię i Nazwisko' + const thName = document.createElement('th'); + thName.textContent = "Imię i Nazwisko"; + thead.appendChild(thName); + + // Pobierz kolumny dla wybranej kategorii + const categoryColumns = categories[category]; + + // Dodaj nagłówki dla kryteriów w kategorii + categoryColumns.forEach(column => { + const th = document.createElement('th'); + th.textContent = column.name; + thead.appendChild(th); + }); + + // Generuj wiersze dla uczniów + studentsData.forEach(student => { + const row = document.createElement('tr'); + + // Komórka z imieniem i nazwiskiem + const tdName = document.createElement('td'); + tdName.textContent = `${student.first_name} ${student.last_name}`; + row.appendChild(tdName); + + // Upewnij się, że 'behavior' jest zdefiniowany + if (!student.behavior) { + student.behavior = {}; + } + + // Komórki z checkboxami dla kryteriów + categoryColumns.forEach(column => { + const td = document.createElement('td'); + const checkbox = document.createElement('input'); + checkbox.type = 'checkbox'; + const studentId = `${student.first_name}-${student.last_name}`.replace(/ /g, '-'); + checkbox.id = `${column.id}-${studentId}`; + checkbox.onchange = calculateStats; + + // Ustawienie stanu checkboxa na podstawie zapisanych danych + checkbox.checked = student.behavior[`day${currentDay}`]?.[column.id] || false; + + td.appendChild(checkbox); + row.appendChild(td); + }); + + tbody.appendChild(row); + }); +} +// Funkcja do wczytywania pliku JSON +async function fetchJSONFile(filePath) { + try { + const response = await fetch(filePath); + if (!response.ok) { + throw new Error(`Błąd HTTP! Status: ${response.status}`); + } + return await response.json(); + } catch (error) { + console.error("Błąd podczas pobierania pliku JSON:", error); + return null; + } +} + +// Obiekt do przechowywania danych klas i uczniów +const classData = {}; + +// Funkcja do wczytania pliku class.json i danych uczniów +async function loadClasses() { + const classFilePath = '/data/class.json'; + const classes = await fetchJSONFile(classFilePath); + + if (classes) { + console.log('Załadowane klasy:', classes); + + const selectClass = document.getElementById("select-class-select"); + selectClass.innerHTML = ""; // Wyczyść istniejące opcje + + classes.forEach(classInfo => { + const option = document.createElement('option'); + option.value = classInfo.file_path; + option.textContent = `Klasa: ${classInfo.class}`; + selectClass.appendChild(option); + console.log("Dodano klasę ", classInfo.class, " do SELECT"); + }); + + // Dodaj nasłuchiwacz zdarzeń na zmianę wyboru klasy + selectClass.addEventListener('change', function() { + const selectedClassFile = this.value; + console.log(`Wybrano klasę: ${selectedClassFile}`); + loadStudents(selectedClassFile); + }); + + // Opcjonalnie, ustaw domyślnie pierwszą klasę i załaduj jej uczniów + if (classes.length > 0) { + selectClass.selectedIndex = 0; + const defaultClassFile = classes[0].file_path; + loadStudents(defaultClassFile); + } + } +} + +// Funkcja do wczytania danych uczniów dla wybranej klasy +async function loadStudents(classFilePath) { + if (!classFilePath) { + console.warn("Nie wybrano żadnej klasy."); + return; + } + + const studentsFilePath = `/data/${classFilePath}`; + const data = await fetchJSONFile(studentsFilePath); + + if (data && Array.isArray(data.students)) { + console.log(`Uczniowie załadowani z pliku ${classFilePath}:`, data); + studentsData = data.students; // Aktualizuj globalną tablicę uczniów + + // Inicjalizacja 'behavior' dla każdego ucznia, jeśli jest niezdefiniowany + studentsData.forEach(student => { + if (!student.behavior) { + student.behavior = {}; + } + }); + + currentClass = classFilePath; // Ustaw aktualną klasę + generateTable(currentCategory); // Regeneruj tabelę z aktualną kategorią + } else { + console.error("Błąd: Nie udało się załadować danych uczniów lub dane są niepoprawne."); + studentsData = []; // Jeśli nie udało się załadować danych, wyczyść tablicę uczniów + currentClass = ''; + generateTable(currentCategory); // Regeneruj pustą tabelę + } +} + +async function getCategoriesWithCriteria() { + const criteriaFilePath = '/data/criteria.json'; + const criteria = await fetchJSONFile(criteriaFilePath); + let categoriesWithCriteria = {} + + criteria.categories.forEach(category => { + let criteriaForCategory = [] + criteria.criteria.forEach(criteria => { + if(category.criteria_ids.includes(criteria.id)) { + //console.log(`!!! ${category.name} posiada ${criteria.name}`) + criteriaForCategory.push({name: criteria.name, id: criteria.id}) + } + }) + categoriesWithCriteria[category.id] = criteriaForCategory + }) + + return categoriesWithCriteria + + +} + +// Funkcja do wczytania pliku criteria.json +async function loadCriteria() { + const criteriaFilePath = '/data/criteria.json'; + const criteria = await fetchJSONFile(criteriaFilePath); + + console.log("Załadowane kryteria:", criteria); + + // + // LADOWANIE ROL + // + const roles = criteria.roles; + + const selectroleByid = document.getElementById("select-role"); + let selectroleHTML = ""; // Zainicjalizuj pusty string na HTML + currentRole = "teacher" + // Iteracja przez klucze obiektu roles + for (const [key, value] of Object.entries(roles)) { + if(key == "teacher") { + currentRoleCriterias = value.criteria_ids + } + selectroleHTML += ``; + } + + // Wstawienie HTML do elementu select + selectroleByid.innerHTML = selectroleHTML; + + // category-buttons-box + const categoriesCriteria = criteria.categories; + const categoryButtonsBox = document.getElementById("category-buttons-box"); + let categoryButtonHTML = "" + categoriesCriteria.forEach(category => { + const hasCriteria = category.criteria_ids.some(criteriaId => currentRoleCriterias.includes(criteriaId)); + + // Jeśli kategoria ma kryteria, dodajemy przycisk + if (hasCriteria) { + categoryButtonHTML += ``; + } + }); + + categoryButtonsBox.innerHTML = categoryButtonHTML; +} + +async function changeRole(role) { + const select = document.getElementById('select-role'); + const selectedValue = select.value; + + const criteriaFilePath = '/data/criteria.json'; + const criteria = await fetchJSONFile(criteriaFilePath); + + currentRole = selectedValue + currentRoleCriterias = criteria.roles[currentRole].criteria_ids + console.log("currentRole:", currentRole) + console.log("currentRoleCriterias:", currentRoleCriterias) + + // category-buttons-box + const categoriesCriteria = criteria.categories; + const categoryButtonsBox = document.getElementById("category-buttons-box"); + let categoryButtonHTML = "" + categoriesCriteria.forEach(category => { + const hasCriteria = category.criteria_ids.some(criteriaId => currentRoleCriterias.includes(criteriaId)); + + + // Jeśli kategoria ma kryteria, dodajemy przycisk + if (hasCriteria) { + categoryButtonHTML += ``; + } + }); + + categoryButtonsBox.innerHTML = categoryButtonHTML; + + generateTable(currentCategory) +} + +// Funkcja do przełączania głównych zakładek +function showTab(tabName) { + // Ukryj wszystkie główne taby + const tabs = document.querySelectorAll('.tab'); + tabs.forEach(tab => tab.classList.remove('active')); + + // Pokaż wybrany tab + const selectedTab = document.getElementById(tabName); + if (selectedTab) { + selectedTab.classList.add('active'); + } + + if (tabName === 'criteria') { + loadDayData(); + } else if (tabName === 'points') { + calculateStats(); + } +} + +// Funkcja do przełączania kategorii w tabeli uczniów +function showInnerTab(category) { + currentCategory = category; + // Generowanie tabeli na podstawie wybranej kategorii + generateTable(category); + + // Podkreślenie aktywnego przycisku + const buttons = document.querySelectorAll('.category-buttons button'); + buttons.forEach(button => button.classList.remove('active')); + const activeButton = document.querySelector(`.category-buttons button[data-category="${category}"]`); + if (activeButton) { + activeButton.classList.add('active'); + } +} + +// Funkcja, aby ustawić domyślną kategorię i zakładkę +document.addEventListener("DOMContentLoaded", function() { + // Domyślnie pokazujemy kategorię 'frekwencja' + + + // Ustawienie daty na dziś + document.getElementById('current-date').innerText = baseDate.toLocaleDateString(); + + // Uruchomienie wczytywania klas i kryteriów + loadClasses(); + loadCriteria(); + + showInnerTab('frekwencja'); +}); + +// Funkcja do zmiany dnia +function changeDay(direction) { + saveDayData(); + currentDay += direction; + const newDate = new Date(baseDate); + newDate.setDate(baseDate.getDate() + currentDay); + document.getElementById('current-date').innerText = newDate.toLocaleDateString(); + loadDayData(); +} + +// Funkcja do ładowania danych dnia +function loadDayData() { + studentsData.forEach(student => { + const studentId = `${student.first_name}-${student.last_name}`.replace(/ /g, '-'); + const behavior = student.behavior[`day${currentDay}`] || {}; + + // Pobierz kryteria dla aktualnej kategorii + const categoryColumns = categories[currentCategory]; + categoryColumns.forEach(column => { + const checkbox = document.getElementById(`${column.id}-${studentId}`); + if (checkbox) { + checkbox.checked = behavior[column.id] || false; + } + }); + }); + + calculateStats(); +} + +// Funkcja do zapisywania danych dnia +function saveDayData() { + studentsData.forEach(student => { + const studentId = `${student.first_name}-${student.last_name}`.replace(/ /g, '-'); + + // Upewnij się, że 'behavior' jest zdefiniowany + if (!student.behavior) { + student.behavior = {}; + } + + let behavior = student.behavior[`day${currentDay}`] || {}; + + const categoryColumns = categories[currentCategory]; + + categoryColumns.forEach(column => { + const checkbox = document.getElementById(`${column.id}-${studentId}`); + if (checkbox) { + behavior[column.id] = checkbox.checked; + } + }); + + student.behavior[`day${currentDay}`] = behavior; + }); +} + +// Funkcja do obliczania statystyk +function calculateStats() { + // Pobieranie punktów z zakładki "Ustal punkty" + const points = { + frekwencja: parseInt(document.getElementById('frekwencja-punkty').value) || 0, + brak_godzin: parseInt(document.getElementById('brak_godzin-punkty').value) || 0, + min_85: parseInt(document.getElementById('min_85-punkty').value) || 0, + etap_szkolny: parseInt(document.getElementById('etap_szkolny-punkty').value) || 5, + etap_rejonowy: parseInt(document.getElementById('etap_rejonowy-punkty').value) || 10, + etap_wojewodzki: parseInt(document.getElementById('etap_wojewodzki-punkty').value) || 15, + etap_ogolnopolski: parseInt(document.getElementById('etap_ogolnopolski-punkty').value) || 20, + udzial_konkurs: parseInt(document.getElementById('udzial_konkurs-punkty').value) || 5, + wyroznienie_konkurs: parseInt(document.getElementById('wyroznienie_konkurs-punkty').value) || 10, + reprezentacja_indywidualna: parseInt(document.getElementById('reprezentacja_indywidualna-punkty').value) || 5, + reprezentacja_zespolowa: parseInt(document.getElementById('reprezentacja_zespolowa-punkty').value) || 10, + udzial_zawody: parseInt(document.getElementById('udzial_zawody-punkty').value) || 15, + organizacja_imprez: parseInt(document.getElementById('organizacja_imprez-punkty').value) || 10, + funkcja_klasa: parseInt(document.getElementById('funkcja_klasa-punkty').value) || 10, + uroczystosci: parseInt(document.getElementById('uroczystosci-punkty').value) || 10, + poczta_sztandar: parseInt(document.getElementById('poczta_sztandar-punkty').value) || 20, + pomoc_nauczyciel: parseInt(document.getElementById('pomoc_nauczyciel-punkty').value) || 10, + wolontariat: parseInt(document.getElementById('wolontariat-punkty').value) || 10 + }; + + let stats = ''; + + studentsData.forEach(student => { + let totalPoints = 0; + + Object.keys(student.behavior).forEach(day => { + const behavior = student.behavior[day]; + + let dayPoints = 0; + for (const [criterion, value] of Object.entries(behavior)) { + if (value && points[criterion]) { + dayPoints += points[criterion]; + } + } + + totalPoints += dayPoints; + }); + + stats += `${student.first_name} ${student.last_name}: ${totalPoints} punktów (${getGrade(totalPoints)})\n`; + }); + + document.getElementById('stats-output').innerText = stats; +} + +// Funkcja do przypisywania ocen na podstawie punktów +function getGrade(points) { + if (points >= 250) return "Wzorowe"; + if (points >= 180) return "Bardzo dobre"; + if (points >= 100) return "Dobre"; + if (points >= 50) return "Poprawne"; + if (points >= 0) return "Nieodpowiednie"; + return "Naganne"; +} + +// Funkcja do generowania tabeli uczniów na podstawie wybranej kategorii +async function generateTable(category) { + const table = document.getElementById('student-table'); + const thead = table.querySelector('thead tr'); + const tbody = table.querySelector('tbody'); + + // Wyczyść istniejące nagłówki i wiersze + thead.innerHTML = ''; + tbody.innerHTML = ''; + + // Dodaj nagłówek 'Imię i Nazwisko' + const thName = document.createElement('th'); + thName.textContent = "Imię i Nazwisko"; + thead.appendChild(thName); + + // get role + console.log("currentRole", currentRole) + + // Pobierz kolumny dla wybranej kategorii + const categories = await getCategoriesWithCriteria() + console.log("łot:", categories) + const categoryColumns = categories[category]; + + // Dodaj nagłówki dla kryteriów w kategorii + categoryColumns.forEach(column => { + const th = document.createElement('th'); + if(currentRoleCriterias.includes(column.id)) { + th.textContent = column.name; + thead.appendChild(th); + } + + + }); + + // Generuj wiersze dla uczniów + studentsData.forEach(student => { + const row = document.createElement('tr'); + + // Komórka z imieniem i nazwiskiem + const tdName = document.createElement('td'); + tdName.textContent = `${student.first_name} ${student.last_name}`; + row.appendChild(tdName); + + // Upewnij się, że 'behavior' jest zdefiniowany + if (!student.behavior) { + student.behavior = {}; + } + + // Komórki z checkboxami dla kryteriów + categoryColumns.forEach(column => { + if(currentRoleCriterias.includes(column.id)) { + const td = document.createElement('td'); + const checkbox = document.createElement('input'); + checkbox.type = 'checkbox'; + const studentId = `${student.first_name}-${student.last_name}`.replace(/ /g, '-'); + checkbox.id = `${column.id}-${studentId}`; + checkbox.onchange = calculateStats; + + // Ustawienie stanu checkboxa na podstawie zapisanych danych + checkbox.checked = student.behavior[`day${currentDay}`]?.[column.id] || false; + + td.appendChild(checkbox); + row.appendChild(td); + } + }); + + tbody.appendChild(row); + }); +} +function showTab(tabName) { + // Ukryj wszystkie zakładki + const tabs = document.querySelectorAll('.tab'); + tabs.forEach(tab => tab.classList.remove('active')); + + // Pokaż wybraną zakładkę + const selectedTab = document.getElementById(tabName); + if (selectedTab) { + selectedTab.classList.add('active'); + } + + // Zmieniaj tytuł nagłówka w zależności od wybranej zakładki + const headerTitle = document.getElementById('header-title'); + const upButtonContainer = document.getElementById('up-button-container'); + const selectRoleContainer = document.getElementById('select-role-container'); + const selectClassContainer = document.getElementById('select-class-container'); + + switch (tabName) { + case 'criteria': + headerTitle.textContent = 'Ocena Zachowania'; + generateTable(currentCategory); // Generuj tabelę dla aktualnej kategorii + upButtonContainer.style.display = 'block'; // Pokaż przyciski + selectRoleContainer.style.display = 'block'; // Pokaż wybór roli + selectClassContainer.style.display = 'block'; // Pokaż wybór klasy + break; + case 'stats': + headerTitle.textContent = 'Statystyka'; + upButtonContainer.style.display = 'none'; // Ukryj przyciski + selectRoleContainer.style.display = 'none'; // Ukryj wybór roli + selectClassContainer.style.display = 'none'; // Ukryj wybór klasy + break; + case 'points': + headerTitle.textContent = 'Ustal punkty'; + upButtonContainer.style.display = 'none'; // Ukryj przyciski + selectRoleContainer.style.display = 'none'; // Ukryj wybór roli + selectClassContainer.style.display = 'none'; // Ukryj wybór klasy + break; + default: + headerTitle.textContent = 'Ocena Zachowania'; + upButtonContainer.style.display = 'none'; // Ukryj przyciski + selectRoleContainer.style.display = 'none'; // Ukryj wybór roli + selectClassContainer.style.display = 'none'; // Ukryj wybór klasy + } +} +