rzodkiew chincheck

This commit is contained in:
Fabian Kowalski 2025-02-14 11:23:48 +01:00
parent ad598b986e
commit 7caeca7ab8
7 changed files with 371 additions and 209 deletions

View File

@ -7,7 +7,7 @@
"Zadanie domowe": 10,
"Aktywność": 3,
"Sprawdzian": 4,
"good_frekwencja": 4,
"good_frekwencja": 9,
"aktywnosc": 2,
"bad_frekwencja": 0,
"sprawdzian": 1
@ -46,5 +46,18 @@
"bad_frekwencja": 27
}
}
]
],
"Jan-Kowalski": {
"bad_frekwencja": 2,
"good_frekwencja": 11,
"dobra_frekwencja": 10,
"aktywnosc": 1,
"sprawdzian": 3
},
"Anna-Nowak": {
"good_frekwencja": 4
},
"Piotr-Wiśniewski": {
"dobra_frekwencja": 3
}
}

View File

@ -1,6 +1,19 @@
[
{ "nazwa": "good_frekwencja", "punkty": 10 },
{ "nazwa": "bad_frekwencja", "punkty": -10 },
{ "nazwa": "aktywnosc", "punkty": 5 },
{ "nazwa": "sprawdzian", "punkty": -200 }
{
"nazwa": "dobra_frekwencja",
"punkty": 111
},
{
"nazwa": "zla_frekwencja",
"punkty": -10
},
{
"nazwa": "aktywnosc",
"punkty": 5
},
{
"nazwa": "sprawdzian",
"punkty": -20
}
]

View File

@ -2,7 +2,6 @@ const express = require("express");
const fs = require("fs");
const path = require("path");
const cors = require("cors");
const app = express();
const PORT = 4000;
@ -22,7 +21,8 @@ app.get("/uczniowie", (req, res) => {
console.error("Błąd odczytu uczniów:", err);
return res.status(500).send("Błąd odczytu uczniów.");
}
res.json(JSON.parse(data));
const uczniowieData = JSON.parse(data);
res.json({ uczniowie: uczniowieData.uczniowie });
});
});
@ -42,16 +42,24 @@ app.get("/dane", (req, res) => {
fs.readFile(DANE_FILE, "utf8", (err, data) => {
if (err) {
console.error("Błąd odczytu danych:", err);
return res.status(500).send("Błąd odczytu danych.");
// Jeśli plik nie istnieje, utwórz go z domyślnymi danymi
const defaultData = {};
fs.writeFile(DANE_FILE, JSON.stringify(defaultData, null, 2), err => {
if (err) {
console.error("Błąd tworzenia pliku danych:", err);
return res.status(500).send("Błąd tworzenia pliku danych.");
}
res.json(defaultData); // Zwróć puste dane
});
} else {
res.json(JSON.parse(data));
}
res.json(JSON.parse(data));
});
});
// Endpoint do zapisywania danych uczniów
app.post("/dane", (req, res) => {
const newData = req.body;
fs.writeFile(DANE_FILE, JSON.stringify(newData, null, 2), err => {
if (err) {
console.error("Błąd zapisywania danych:", err);
@ -61,6 +69,85 @@ app.post("/dane", (req, res) => {
});
});
// Endpoint do dodawania nowego kryterium
app.post("/kryteria", (req, res) => {
const { nazwa, punkty } = req.body;
if (!nazwa || !punkty) {
return res.status(400).send("Brak wymaganych danych.");
}
fs.readFile(KRYTERIA_FILE, "utf8", (err, data) => {
if (err) {
console.error("Błąd odczytu kryteriów:", err);
return res.status(500).send("Błąd odczytu kryteriów.");
}
const kryteria = JSON.parse(data);
// Sprawdź, czy kryterium już istnieje
if (kryteria.some(k => k.nazwa === nazwa)) {
return res.status(400).send("Kryterium już istnieje.");
}
kryteria.push({ nazwa, punkty });
fs.writeFile(KRYTERIA_FILE, JSON.stringify(kryteria, null, 2), err => {
if (err) {
console.error("Błąd zapisywania kryteriów:", err);
return res.status(500).send("Błąd zapisywania kryteriów.");
}
res.send("Kryterium dodane pomyślnie.");
});
});
});
// Endpoint do edycji istniejącego kryterium
app.put("/kryteria/:nazwa", (req, res) => {
const { nazwa } = req.params;
const { nowaNazwa, punkty } = req.body;
if (!nowaNazwa || !punkty) {
return res.status(400).send("Brak wymaganych danych.");
}
fs.readFile(KRYTERIA_FILE, "utf8", (err, data) => {
if (err) {
console.error("Błąd odczytu kryteriów:", err);
return res.status(500).send("Błąd odczytu kryteriów.");
}
const kryteria = JSON.parse(data);
const index = kryteria.findIndex(k => k.nazwa === nazwa);
if (index === -1) {
return res.status(404).send("Kryterium nie istnieje.");
}
kryteria[index] = { nazwa: nowaNazwa, punkty };
fs.writeFile(KRYTERIA_FILE, JSON.stringify(kryteria, null, 2), err => {
if (err) {
console.error("Błąd zapisywania kryteriów:", err);
return res.status(500).send("Błąd zapisywania kryteriów.");
}
res.send("Kryterium zaktualizowane pomyślnie.");
});
});
});
// Endpoint do usuwania kryterium
app.delete("/kryteria/:nazwa", (req, res) => {
const { nazwa } = req.params;
fs.readFile(KRYTERIA_FILE, "utf8", (err, data) => {
if (err) {
console.error("Błąd odczytu kryteriów:", err);
return res.status(500).send("Błąd odczytu kryteriów.");
}
const kryteria = JSON.parse(data);
const index = kryteria.findIndex(k => k.nazwa === nazwa);
if (index === -1) {
return res.status(404).send("Kryterium nie istnieje.");
}
kryteria.splice(index, 1);
fs.writeFile(KRYTERIA_FILE, JSON.stringify(kryteria, null, 2), err => {
if (err) {
console.error("Błąd zapisywania kryteriów:", err);
return res.status(500).send("Błąd zapisywania kryteriów.");
}
res.send("Kryterium usunięte pomyślnie.");
});
});
});
// Uruchomienie serwera
app.listen(PORT, () => {
console.log(`Serwer API działa na http://localhost:${PORT}`);

View File

@ -1,12 +1,8 @@
{
"klasy": {
"1A": [
{ "imie": "Jan", "nazwisko": "Kowalski" },
{ "imie": "Anna", "nazwisko": "Nowak" }
],
"2B": [
{ "imie": "Piotr", "nazwisko": "Wiśniewski" },
{ "imie": "Maria", "nazwisko": "Kowalczyk" }
]
}
"uczniowie": [
{ "imie": "Jan", "nazwisko": "Kowalski", "klasa": "4i" },
{ "imie": "Anna", "nazwisko": "Nowak", "klasa": "3a" },
{ "imie": "Piotr", "nazwisko": "Wiśniewski", "klasa": "2b" },
{ "imie": "Maria", "nazwisko": "Kowalczyk", "klasa": "1c" }
]
}

View File

@ -9,27 +9,48 @@
<body>
<div class="container">
<h1>Zarządzanie Uczniami</h1>
<!-- Zakładki -->
<div class="tabs">
<button id="students-tab">Uczniowie</button>
<button id="stats-tab">Statystyka</button>
<button id="criteria-tab">Zarządzanie kryteriami</button>
</div>
<!-- Wybór klasy -->
<label for="class-select">Wybierz klasę:</label>
<select id="class-select" style="margin-bottom: 50px;"></select>
<!-- Lista uczniów -->
<div id="students-list"></div>
<!-- Statystyki -->
<div id="stats-content" style="display: none;"></div>
<!-- Zarządzanie kryteriami -->
<div id="criteria-content" style="display: none;">
<h2>Lista kryteriów</h2>
<div id="criteria-list"></div>
<h2>Dodaj nowe kryterium</h2>
<form id="add-criteria-form">
<label for="new-criteria-name">Nazwa:</label>
<input type="text" id="new-criteria-name" required>
<label for="new-criteria-points">Punkty:</label>
<input type="number" id="new-criteria-points" required>
<button type="submit">Dodaj</button>
</form>
<h2>Edytuj kryterium</h2>
<form id="edit-criteria-form">
<label for="edit-criteria-name">Wybierz kryterium:</label>
<select id="edit-criteria-name" required></select>
<label for="edit-criteria-new-name">Nowa nazwa:</label>
<input type="text" id="edit-criteria-new-name" required>
<label for="edit-criteria-points">Punkty:</label>
<input type="number" id="edit-criteria-points" required>
<button type="submit">Zapisz zmiany</button>
</form>
<h2>Usuń kryterium</h2>
<form id="delete-criteria-form">
<label for="delete-criteria-name">Wybierz kryterium:</label>
<select id="delete-criteria-name" required></select>
<button type="submit">Usuń</button>
</form>
</div>
<!-- Przycisk do zapisywania danych -->
<button id="save-button">Zapisz dane</button>
</div>
<script src="script.js"></script>
</body>
</html>

299
script.js
View File

@ -1,13 +1,20 @@
let uczniowie = {};
let kryteria = [];
let dane = {};
document.addEventListener("DOMContentLoaded", () => {
const classSelect = document.getElementById("class-select");
const studentsList = document.getElementById("students-list");
const saveButton = document.getElementById("save-button");
const statsTab = document.getElementById("stats-tab");
const statsContent = document.getElementById("stats-content");
const criteriaContent = document.getElementById("criteria-content");
const saveButton = document.getElementById("save-button");
const studentsTab = document.getElementById("students-tab");
const statsTab = document.getElementById("stats-tab");
const criteriaTab = document.getElementById("criteria-tab");
const addCriteriaForm = document.getElementById("add-criteria-form");
const editCriteriaForm = document.getElementById("edit-criteria-form");
const deleteCriteriaForm = document.getElementById("delete-criteria-form");
const criteriaListDiv = document.getElementById("criteria-list");
const editCriteriaNameSelect = document.getElementById("edit-criteria-name");
const deleteCriteriaNameSelect = document.getElementById("delete-criteria-name");
let uczniowie = [];
let kryteria = [];
let dane = {};
// Ładowanie danych z serwera
Promise.all([
@ -15,147 +22,79 @@ document.addEventListener("DOMContentLoaded", () => {
fetch("http://localhost:4000/kryteria").then(response => response.json()),
fetch("http://localhost:4000/dane").then(response => response.json())
])
.then(([uczniowieData, kryteriaData, daneData]) => {
uczniowie = uczniowieData.klasy;
kryteria = kryteriaData;
dane = daneData;
.then(([uczniowieData, kryteriaData, daneData]) => {
uczniowie = uczniowieData.uczniowie;
kryteria = kryteriaData;
dane = daneData;
populateClassSelect();
renderStats(); // Renderuj statystyki przy ładowaniu
})
.catch(error => console.error("Błąd ładowania danych:", error));
console.log("Uczniowie:", uczniowie);
console.log("Kryteria:", kryteria);
console.log("Dane:", dane);
// Wypełnij listę klas
function populateClassSelect() {
Object.keys(uczniowie).forEach(klasa => {
const option = document.createElement("option");
option.value = klasa;
option.textContent = klasa;
classSelect.appendChild(option);
});
// Wyświetl pierwszą klasę domyślnie
if (classSelect.options.length > 0) {
classSelect.value = classSelect.options[0].value;
renderStudents(classSelect.value);
}
}
// Aktualizuj listę uczniów po wyborze klasy
classSelect.addEventListener("change", () => {
const selectedClass = classSelect.value;
renderStudents(selectedClass);
renderStats(); // Aktualizuj statystyki po zmianie klasy
});
renderStudents();
renderStats();
renderCriteria();
})
.catch(error => console.error("Błąd ładowania danych:", error));
// Renderuj uczniów
function renderStudents(className) {
function renderStudents() {
studentsList.innerHTML = "";
const students = uczniowie[className];
students.forEach(student => {
const studentKey = `${className}-${student.imie}-${student.nazwisko}`;
uczniowie.forEach(student => {
const studentKey = `${student.imie}-${student.nazwisko}`;
const details = document.createElement("details");
const summary = document.createElement("summary");
summary.textContent = `${student.imie} ${student.nazwisko}`;
summary.textContent = `${student.imie} ${student.nazwisko} (${student.klasa})`;
details.appendChild(summary);
const criteriaList = document.createElement("div");
criteriaList.className = "criteria-list";
kryteria.forEach(criteria => {
const criteriaItem = document.createElement("div");
criteriaItem.className = "criteria-item";
const label = document.createElement("span");
label.textContent = criteria.nazwa;
const pointsInfo = document.createElement("span");
pointsInfo.className = "points-info";
pointsInfo.textContent = `(${criteria.punkty} pkt)`;
const input = document.createElement("input");
input.type = "number";
input.min = "0";
// Wyszukaj dane ucznia w pliku `dane.json`
const savedStudent = dane[className]?.find(s => s.uczen.imie === student.imie && s.uczen.nazwisko === student.nazwisko);
input.value = savedStudent?.uczen[criteria.nazwa] || 0;
const savedStudent = dane[studentKey];
input.value = savedStudent?.[criteria.nazwa] || 0;
input.addEventListener("input", () => {
if (!savedStudent) {
dane[className] = dane[className] || [];
dane[className].push({
uczen: {
imie: student.imie,
nazwisko: student.nazwisko
}
});
dane[studentKey] = {};
}
const currentStudent = dane[className].find(s => s.uczen.imie === student.imie && s.uczen.nazwisko === student.nazwisko);
currentStudent.uczen[criteria.nazwa] = parseInt(input.value) || 0;
renderStats(); // Aktualizuj statystyki po edycji danych
dane[studentKey][criteria.nazwa] = parseInt(input.value) || 0;
renderStats();
});
criteriaItem.appendChild(label);
criteriaItem.appendChild(pointsInfo);
criteriaItem.appendChild(input);
criteriaList.appendChild(criteriaItem);
});
details.appendChild(criteriaList);
studentsList.appendChild(details);
});
}
// Zapisz dane na zewnętrznym serwerze
saveButton.addEventListener("click", () => {
fetch("http://localhost:4000/dane", {
method: "POST",
headers: {
"Content-Type": "application/json"
},
body: JSON.stringify(dane)
})
.then(response => {
if (response.ok) {
alert("Dane zostały zapisane!");
} else {
alert("Wystąpił błąd podczas zapisywania danych.");
}
})
.catch(error => console.error("Błąd zapisywania danych:", error));
});
// Renderuj statystyki
function renderStats() {
statsContent.innerHTML = "";
const selectedClass = classSelect.value;
const students = uczniowie[selectedClass];
if (!students) return;
students.forEach(student => {
const savedStudent = dane[selectedClass]?.find(s => s.uczen.imie === student.imie && s.uczen.nazwisko === student.nazwisko);
uczniowie.forEach(student => {
const studentKey = `${student.imie}-${student.nazwisko}`;
const savedStudent = dane[studentKey];
let totalPoints = 0;
if (savedStudent) {
kryteria.forEach(criteria => {
const count = savedStudent.uczen[criteria.nazwa] || 0;
const count = savedStudent[criteria.nazwa] || 0;
totalPoints += count * criteria.punkty;
});
}
const studentDiv = document.createElement("div");
studentDiv.className = "stat-item";
const name = document.createElement("strong");
name.textContent = `${student.imie} ${student.nazwisko}`;
name.textContent = `${student.imie} ${student.nazwisko} (${student.klasa})`;
const points = document.createElement("span");
points.className = "points";
points.textContent = `${totalPoints} pkt`;
@ -164,22 +103,166 @@ document.addEventListener("DOMContentLoaded", () => {
} else if (totalPoints < 0) {
points.classList.add("negative");
}
studentDiv.appendChild(name);
studentDiv.appendChild(points);
statsContent.appendChild(studentDiv);
});
}
// Przełączanie między zakładkami
statsTab.addEventListener("click", () => {
studentsList.style.display = "none";
statsContent.style.display = "block";
});
// Renderuj listę kryteriów
function renderCriteria() {
criteriaListDiv.innerHTML = "";
editCriteriaNameSelect.innerHTML = "";
deleteCriteriaNameSelect.innerHTML = "";
const studentsTab = document.getElementById("students-tab");
if (!Array.isArray(kryteria) || kryteria.length === 0) {
console.warn("Brak kryteriów do wyświetlenia.");
const noCriteriaMessage = document.createElement("p");
noCriteriaMessage.textContent = "Brak dostępnych kryteriów.";
criteriaListDiv.appendChild(noCriteriaMessage);
return;
}
kryteria.forEach(criteria => {
// Wyświetl kryterium na liście
const criteriaDiv = document.createElement("div");
criteriaDiv.textContent = `${criteria.nazwa}: ${criteria.punkty} pkt`;
criteriaListDiv.appendChild(criteriaDiv);
// Dodaj opcję do edycji
const editOption = document.createElement("option");
editOption.value = criteria.nazwa;
editOption.textContent = criteria.nazwa;
editCriteriaNameSelect.appendChild(editOption);
// Dodaj opcję do usunięcia
const deleteOption = document.createElement("option");
deleteOption.value = criteria.nazwa;
deleteOption.textContent = criteria.nazwa;
deleteCriteriaNameSelect.appendChild(deleteOption);
});
}
// Przełączanie między zakładkami
studentsTab.addEventListener("click", () => {
studentsList.style.display = "block";
statsContent.style.display = "none";
criteriaContent.style.display = "none";
});
statsTab.addEventListener("click", () => {
studentsList.style.display = "none";
statsContent.style.display = "block";
criteriaContent.style.display = "none";
});
criteriaTab.addEventListener("click", () => {
studentsList.style.display = "none";
statsContent.style.display = "none";
criteriaContent.style.display = "block"; // Pokaż zakładkę "Zarządzanie kryteriami"
renderCriteria(); // Odśwież listę kryteriów
});
// Dodawanie nowego kryterium
addCriteriaForm.addEventListener("submit", event => {
event.preventDefault();
const nazwa = document.getElementById("new-criteria-name").value.trim();
const punkty = parseInt(document.getElementById("new-criteria-points").value);
if (!nazwa || isNaN(punkty)) {
alert("Wprowadź poprawne dane.");
return;
}
fetch("http://localhost:4000/kryteria", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ nazwa, punkty })
})
.then(response => {
if (!response.ok) throw new Error("Błąd dodawania kryterium.");
return response.text();
})
.then(() => {
alert("Kryterium dodane pomyślnie.");
return fetch("http://localhost:4000/kryteria").then(response => response.json());
})
.then(kryteriaData => {
kryteria = kryteriaData;
renderCriteria();
})
.catch(error => console.error(error));
});
// Edycja istniejącego kryterium
editCriteriaForm.addEventListener("submit", event => {
event.preventDefault();
const nazwa = editCriteriaNameSelect.value;
const nowaNazwa = document.getElementById("edit-criteria-new-name").value.trim();
const punkty = parseInt(document.getElementById("edit-criteria-points").value);
if (!nowaNazwa || isNaN(punkty)) {
alert("Wprowadź poprawne dane.");
return;
}
fetch(`http://localhost:4000/kryteria/${encodeURIComponent(nazwa)}`, {
method: "PUT",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ nowaNazwa, punkty })
})
.then(response => {
if (!response.ok) throw new Error("Błąd edycji kryterium.");
return response.text();
})
.then(() => {
alert("Kryterium zaktualizowane pomyślnie.");
return fetch("http://localhost:4000/kryteria").then(response => response.json());
})
.then(kryteriaData => {
kryteria = kryteriaData;
renderCriteria();
})
.catch(error => console.error(error));
});
// Usuwanie kryterium
deleteCriteriaForm.addEventListener("submit", event => {
event.preventDefault();
const nazwa = deleteCriteriaNameSelect.value;
fetch(`http://localhost:4000/kryteria/${encodeURIComponent(nazwa)}`, {
method: "DELETE"
})
.then(response => {
if (!response.ok) throw new Error("Błąd usuwania kryterium.");
return response.text();
})
.then(() => {
alert("Kryterium usunięte pomyślnie.");
return fetch("http://localhost:4000/kryteria").then(response => response.json());
})
.then(kryteriaData => {
kryteria = kryteriaData;
renderCriteria();
})
.catch(error => console.error(error));
});
// Zapisz dane na zewnętrznym serwerze
saveButton.addEventListener("click", () => {
fetch("http://localhost:4000/dane", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify(dane)
})
.then(response => {
if (response.ok) {
alert("Dane zostały zapisane!");
} else {
alert("Wystąpił błąd podczas zapisywania danych.");
}
})
.catch(error => console.error("Błąd zapisywania danych:", error));
});
});

View File

@ -25,7 +25,7 @@ label {
font-weight: bold;
}
select {
select, input {
width: 100%;
padding: 10px;
margin-top: 5px;
@ -69,75 +69,24 @@ button:hover {
background-color: #0056b3;
}
/* Zakładka Uczniowie */
details {
/* Lista kryteriów */
#criteria-list div {
margin: 10px 0;
padding: 10px;
border: 1px solid #ddd;
border-radius: 4px;
background-color: #f9f9f9;
}
/* Formularze */
form {
margin-top: 20px;
}
form label {
margin-top: 10px;
}
form input, form select {
margin-bottom: 10px;
padding: 10px;
border: 1px solid #ddd;
border-radius: 4px;
background-color: #f9f9f9;
}
summary {
font-weight: bold;
cursor: pointer;
outline: none;
}
.criteria-list {
margin-left: 20px;
}
.criteria-item {
display: flex;
align-items: center;
margin: 5px 0;
}
.criteria-item span {
margin-right: 10px;
font-weight: bold;
}
.criteria-item .points-info {
font-size: 12px;
color: #666;
margin-left: 10px;
}
.criteria-item input {
width: 50px;
margin-left: 10px;
padding: 5px;
border: 1px solid #ccc;
border-radius: 4px;
}
/* Zakładka Statystyka */
.stat-item {
margin-bottom: 15px;
padding: 10px;
border: 1px solid #ddd;
border-radius: 8px;
background-color: #f9f9f9;
display: flex;
justify-content: space-between;
align-items: center;
}
.stat-item strong {
font-size: 16px;
}
.stat-item .points {
font-weight: bold;
font-size: 18px;
}
.stat-item .points.positive {
color: green;
}
.stat-item .points.negative {
color: red;
}