This commit is contained in:
Turtle committed 2026-01-11 10:26:39 +01:00
1 parent 565c1b9911
commit 28490ce8b3
36 files changed
+587 -179

No files matched your search

+298
View File
@@ -0,0 +1,298 @@
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=0.5">
<link rel="stylesheet" href="../lib/basic.css">
<script src="../auth.js"></script>
<script src="../lib/basic.js"></script>
<script src="../other/skills.js"></script>
<script src="../other/skilltree.js"></script>
<script src="./uebersicht_overlay.js"></script>
<script src="https://cdn.jsdelivr.net/npm/qrcodejs/qrcode.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
<title>Kurs Anzeige</title>
</head>
<body>
<div class="header_bar_1">
<div>
<button onclick="location.href = './uebersicht.html?user=' + userData.name;" class="back">Meine
Kurse</button>
</div>
<div>
</div>
<div>
<button class="profile" onclick='showOverlay("miniProfile")'>
<overlay id="miniProfile" />
</button>
</div>
</div>
<div class="header_bar_1_placeholder"></div>
<div class="course-card">
<span style="font-weight: bold;" id="course-name"></span>
<span id="course-owner"></span>
<br>
<span>Bewertungen der Sessions</span>
<div id="course-surveys" style="height: 200px; overflow-y: scroll; scrollbar-width: none; ">
</div>
</div>
<script>
const evaluationResults = {};
const couchDB = new CouchDB();
setUserData(couchDB).then(
() => {
const params = getURLArgsMap();
const courseId = params["course"];
if (courseId) {
loadCourse(courseId);
}
}
)
async function loadCourse(courseId) {
const course = await couchDB.get("course:" + courseId);
if (course == undefined) {
alert("Kurs existiert nicht!");
return;
}
const results = course.result_history;
document.getElementById("course-name").innerHTML = course.title;
document.getElementById("course-owner").innerHTML = "Ersteller: " + course.owner;
const courseSurveys = document.getElementById("course-surveys");
courseSurveys.innerHTML = "";
results.forEach((result, idx) => {
evaluationResults[idx] = result;
const date = new Date(result.date);
const dateStr = `${date.getDate()}.${date.getMonth() + 1}.${date.getFullYear()}`;
courseSurveys.innerHTML += `<div class="session" onclick="evaluationClick(${idx})">${dateStr}</div>`;
});
}
function evaluationClick(idx) {
const result = evaluationResults[idx];
if (!result) return;
showEvaluationResult(result);
}
</script>
<style>
button.back {
font-size: 20px;
padding: 15px;
padding-left: 40px;
padding-right: 40px;
background-color: var(--accent_color_bg);
border: none;
border-radius: var(--border-radius);
cursor: pointer;
}
button.back:focus-visible {
outline: 2px var(--accent_color_fg_o);
outline-offset: 2px;
}
button.back:hover {
background: var(--accent_color_bg_o);
border-radius: var(--border-radius);
}
</style>
<style>
.xp-bar {
width: 100%;
height: 20px;
background-color: #dbdfdb;
border-radius: 10px;
overflow: hidden;
margin: 10px 0;
}
.xp-bar::-moz-progress-bar {
background-color: #31b335;
}
.xp-bar::-webkit-progress-value {
background: #31b335;
}
.main-container {
display: flex;
flex-direction: column;
gap: 20px;
padding: 1.5rem;
align-items: center;
height: calc(100vh - 75px);
}
button.survey {
font-size: 20px;
padding: 15px;
padding-left: 40px;
padding-right: 40px;
background-color: var(--accent_color_bg);
border: none;
border-radius: var(--border-radius);
cursor: pointer;
max-width: 30rem;
width: 100%;
}
button.survey:focus-visible {
outline: 2px var(--accent_color_fg_o);
outline-offset: 2px;
}
button.survey:hover {
background: var(--accent_color_bg_o);
border-radius: var(--border-radius);
}
.courses-container {
width: 100%;
}
.level-container {
width: 100%;
display: flex;
flex-direction: column;
align-items: center;
}
.level {
font-family: Minecraftia;
color: #7bd67e;
}
#courses-container {
width: 100%;
display: flex;
flex-direction: column;
align-items: center;
max-height: 60vh;
}
#courses-list {
width: 100%;
overflow-y: scroll;
scrollbar-width: none;
height: auto;
}
.course-card {
position: relative;
margin: 1rem;
min-height: 300px;
padding: 16px;
background: var(--accent_color_bg_o);
border-radius: 12px;
box-shadow: var(--def-shadow);
display: flex;
flex-direction: column;
gap: 10px;
}
.course-title {
margin: 0;
padding: 10px;
font-size: 25px;
font-weight: bold;
}
.course-description {
margin: 0;
font-size: 20px;
padding: 10px;
}
.course-actions {
display: flex;
gap: 10px;
margin-top: auto;
}
.action {
padding: 8px;
border: none;
border-radius: 8px;
cursor: pointer;
font-size: 20px;
}
.action.start {
position: absolute;
top: 16px;
right: 70px;
font-size: 20px;
border-radius: var(--border-radius);
background-color: var(--accent_color_bg);
}
.action.start:hover {
background: var(--accent_color_bg_o);
border-radius: var(--border-radius);
}
.action.delete {
position: absolute;
top: 16px;
right: 16px;
font-size: 20px;
padding-left: 12px;
padding-right: 12px;
max-height: 40px;
border-radius: var(--border-radius);
background-color: var(--accent_color_bg);
}
.action.delete:hover {
background: var(--accent_color_bg_o);
border-radius: var(--border-radius);
}
button.new {
display: block;
margin: 20px auto;
font-size: 30px;
font-weight: bold;
border: none;
width: 60px;
height: 60px;
background-color: var(--accent_color_bg);
cursor: pointer;
}
button.new:hover {
background-color: var(--accent_color_bg_o);
}
.session {
font-size: 20px;
padding: 15px;
margin: 5px;
background-color: var(--accent_color_bg);
border: none;
border-radius: var(--border-radius);
cursor: pointer;
width: 100%;
max-width: 30rem;
}
.session:hover {
background: var(--accent_color_bg_o);
border-radius: var(--border-radius);
}
</style>
</body>
</html>
+325
View File
@@ -0,0 +1,325 @@
<!doctype html>
<html>
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=0.7" />
<link rel="stylesheet" href="../lib/basic.css" />
<script src="../auth.js"></script>
<script src="../lib/basic.js"></script>
<script src="./uebersicht_overlay.js"></script>
<script src="../other/skills.js"></script>
<script src="../other/skilltree.js"></script>
<title>Übersicht</title>
</head>
<body>
<style>
.holder_div {
position: fixed;
bottom: 2%;
left: 2%;
width: 96%;
background-color: var(--accent_color_bg_o);
backdrop-filter: blur(10px);
border-radius: var(--border-radius);
padding: 10px;
box-shadow: var(--def-shadow);
border: 1px solid black;
}
.holder_div > div.action_div {
display: flex;
flex-direction: row;
height: min-content;
gap: 10px;
}
.holder_div > div.action_div button {
font-size: 20px;
padding: 15px;
padding-left: 40px;
padding-right: 40px;
background-color: var(--accent_color_bg);
border: none;
border-radius: var(--border-radius);
cursor: pointer;
max-width: 100%;
width: 100%;
overflow-x: hidden;
}
.holder_div > div.action_div button:focus-visible {
outline: 2px var(--accent_color_fg_o);
outline-offset: 2px;
}
.holder_div > div.action_div button:hover {
background: var(--accent_color_bg_o);
border-radius: var(--border-radius);
}
.level-container {
width: 100%;
display: flex;
flex-direction: column;
align-items: center;
}
.level {
font-family: Minecraftia;
color: darkgreen;
margin-bottom: 5px;
}
#courses-list {
margin-top: 30px;
padding: 0 2%;
padding-bottom: 200px;
}
.course-card {
position: relative;
margin-top: 1px;
margin-bottom: 1rem;
min-height: 300px;
padding: 16px;
background: var(--accent_color_bg_o);
border-radius: 12px;
box-shadow: var(--def-shadow);
display: flex;
flex-direction: column;
gap: 10px;
}
.course-card:hover {
background: #b9d5e1;
}
.course-title {
margin: 0;
padding: 10px;
font-size: 25px;
font-weight: bold;
}
.course-description {
margin: 0;
font-size: 20px;
padding: 10px;
}
.course-actions {
display: flex;
gap: 10px;
margin-top: auto;
}
.action {
padding: 8px;
border: none;
border-radius: 8px;
cursor: pointer;
font-size: 20px;
}
.action.start {
position: absolute;
top: 16px;
right: 70px;
font-size: 20px;
border-radius: var(--border-radius);
background-color: var(--accent_color_bg);
}
.action.start:hover {
background: var(--accent_color_bg_o);
border-radius: var(--border-radius);
}
.action.delete {
position: absolute;
top: 16px;
right: 16px;
font-size: 20px;
padding-left: 12px;
padding-right: 12px;
max-height: 40px;
border-radius: var(--border-radius);
background-color: var(--accent_color_bg);
}
.action.delete:hover {
background: var(--accent_color_bg_o);
border-radius: var(--border-radius);
}
</style>
<div class="header_bar_1">
<div style="font-weight: bold">Meine Kurse</div>
<div></div>
<div>
<button class="profile" onclick="showOverlay('miniProfile')">
<overlay id="miniProfile" />
</button>
</div>
</div>
<div class="header_bar_1_placeholder"></div>
<div id="courses-list"></div>
<div class="holder_div">
<div class="level_div">
<div id="level-display" class="level-container">
<div class="level">Level <span id="level-number">5</span></div>
<div class="mc-xp-bar"><div></div></div>
</div>
</div>
<hr style="background-color: black; color: black;">
<div class="action_div">
<button class="survey" onclick="participateInSurvey()">An Umfrage teilnehmen</button>
<button onclick="newCourse()">Kurs hinzufügen</button>
</div>
</div>
<!-- Overlays -->
<overlay id="survey">
<div style="text-align: center; padding: 15px; margin-right: 2rem">
<input id="survey-code" type="text" placeholder="Umfrage-Code" />
<br />
<button style="margin-top: 1rem" onclick="startSurvey()">Teilnehmen</button>
</div>
</overlay>
<overlay id="add-course">
<div style="text-align: center; padding: 15px; margin-right: 2rem">
<input id="survey-code" type="text" placeholder="Kursname" />
<br />
<button class="" style="margin-top: 1rem" onclick="addCourse()">Hinzufügen</button>
</div>
</overlay>
<script>
const couchDB = new CouchDB();
setUserData(couchDB).then((val) => {
if (!val) return;
setCourseView();
setLevelProgress(userData.xp);
setLevel(userData.level);
});
async function startSurvey() {
const code = getOverlay("survey").getElementsByTagName("INPUT")[0].value.trim();
console.log(code);
var course = await couchDB.get("course:" + code);
if (course != undefined) {
const users = await couchDB.get("users");
users[userData.name].courses ??= [];
if (!users[userData.name].courses.includes(code)) {
users[userData.name].courses.push(code);
}
await couchDB.set("users", users);
location.href = "./umfrage.html?user=" + userData.name + ",course=" + code;
} else {
alert("Umfrage nicht gefunden!");
}
}
async function setCourseView() {
const courseList = document.getElementById("courses-list");
courseList.innerHTML = "";
for (const courseId of userData.courses) {
const course = await couchDB.get("course:" + courseId);
const expire_date = new Date(course.expire_date);
const isExpired = expire_date < new Date();
const card = document.createElement("div");
card.className = "course-card";
card.addEventListener("click", (e) => {
if (e.target.closest("button")) return;
location.href =
"./kursAnzeige.html?user=" + userData.name + ",course=" + courseId;
});
const surveyUrl = (card.innerHTML = `
<div class="course-title">${course.title}</div>
<div class="course-description">
${course.description}
</div>
${isExpired ? '': `
<button class="action start" onclick='location.href = "./umfrage.html?user=${userData.name},course=${courseId.trim()}";'>
Umfrage Starten
</button>`
}
<button class="action delete" onclick="deleteCourse('${courseId}')">
🗑
</button>
`);
courseList.appendChild(card);
}
}
async function deleteCourse(courseId) {
const users = await couchDB.get("users");
users[userData.name].courses = users[userData.name].courses.filter(
(id) => id !== courseId,
);
await couchDB.set("users", users);
location.reload();
}
function participateInSurvey() {
showOverlay("survey");
}
function selectCourse(courseName) {
console.log("Course selected:", courseName);
showOverlay("course");
}
function newCourse() {
showOverlay("add-course");
}
async function addCourse() {
const courseName = getOverlay("add-course")
.getElementsByTagName("INPUT")[0]
.value.trim();
const course = await couchDB.get("course:" + courseName);
if (course == undefined) {
alert("Kurs existiert nicht!");
return;
}
const users = await couchDB.get("users");
users[userData.name].courses.push(courseName);
await couchDB.set("users", users);
setCourseView();
location.reload();
}
function setLevelProgress(xp) {
const max = userData.level + 1;
const percent = xp / max;
setXPBarPercent(percent*100);
}
function setLevel(level) {
document.getElementById("level-number").textContent = level;
}
function addCourseToList(courseName) {
const coursesList = document.getElementById("courses-list");
const courseDiv = document.createElement("div");
courseDiv.className = "course-item";
courseDiv.innerHTML = `
<span>${courseName}</span>
<button onclick="editCourse('${courseName}')">Edit</button>
`;
coursesList.appendChild(courseDiv);
}
</script>
</body>
<style>
@font-face {
font-family: Minecraftia;
src: url(data:font/truetype;base64,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gICAAQD/AAAABQAAAAACAAOAAAMABwALAA8AEwAAITUhFSU1MxUlETMZATUzFT0BIRUBAAEA/oCA/wCAgAEAgICAgICAAYD+gAGAgICAgIAABQAAAAACAAOAAAMABwALAA8AEwAAMTUhFT0BMxU1ETMRATUzFSU1IRUBAICA/wCA/oABAICAgICAgAGA/oABgICAgICAAAAABQAAAQACAAKAAAMABwALAA8AEwAAETUzFSE1MxUlNSEVJTUzFSE1MxWAAQCA/oABAP6AgAEAgAEAgICAgICAgICAgICAAAAAAQAAAIACgAMAAAsAACURITUhETMRIRUhEQEA/wABAIABAP8AgAEAgAEA/wCA/wAAAQAA/4AAgAEAAAMAABURMxGAgAGA/oAAAQAAAYACgAIAAAMAABE1IRUCgAGAgIAAAQAAAAAAgAEAAAMAADERMxGAAQD/AAAABQAAAAACgAOAAAMABwALAA8AEwAAMTUzFTURMxkBNTMVNREzGQE1MxWAgICAgICAgAEA/wABAICAgAEA/wABAICAAAAFAAAAAAKAA4AAAwAHAA8AFwAbAAAzNSEVATUzFQERMxEzFSMVIREjNTM1MxEBNSEVgAGA/wCA/oCAgIABgICAgP4AAYCAgAGAgID/AAKA/oCAgAGAgID9gAKAgIAAAAABAAAAAAKAA4AACwAAMTUhESM1MzUzESEVAQCAgIABAIACAICA/QCAAAAAAAYAAAAAAoADgAAHAAsADwATABcAGwAAMREzFSE1MxEBNTMVPQEhFQE1MxUFETMRATUhFYABgID+AIABAP4AgAGAgP4AAYABAICA/wABAICAgICAAQCAgIABAP8AAQCAgAAAAAAHAAAAAAKAA4AAAwAHAAsADwATABcAGwAAMzUhFSU1MxUhETMRATUhFQE1MxUFETMRATUhFYABgP4AgAGAgP6AAQD+AIABgID+AAGAgICAgIABAP8AAQCAgAEAgICAAQD/AAEAgIAAAAMAAAAAAoADgAADAAcAEwAAEzUzFT0BMxUTESERMxUhESM1IRGAgICA/gCAAYCAAQACAICAgICA/YABAAEAgAGAgPyAAAAAAAQAAAAAAoADgAADAAcACwATAAAzNSEVJTUzFSERMxEBESEVIRUhFYABgP4AgAGAgP2AAoD+AAGAgICAgIABgP6AAYABgICAgAAAAAAFAAAAAAKAA4AAAwAHAA8AEwAXAAAzNSEVNREzESERMxUhFSEZATUzFT0BIRWAAYCA/YCAAYD+gIABAICAgAEA/wACAICA/wACAICAgICAAAMAAAAAAoADgAADAAcADwAAIREzGQE1MxU1ESEVIxEhEQEAgIDLine truncated
}
</style>
</html>
+227
View File
@@ -0,0 +1,227 @@
//=> use showEvaluationResult(object result_data) -> void;
function showEvaluationResult(result_history_data) {
const couchDB = new CouchDB();
var elm = getId("evaluation_result");
if (elm == null) {
elm = document.createElement("overlay");
elm.setAttribute("id", "evaluation_result");
document.body.appendChild(elm);
}
elm.innerHTML = `
<div class="overlay_title">Ergebnisse</div>
<div class="overlay_content" style="display: inline-block; min-width: 90vw; padding: 5px;"></div>
`;
_updateEvaResContent(showOverlay("evaluation_result"), 0, result_history_data);
}
function _updateEvaResContent(elm, pos, data) {
const root = elm.querySelector(".overlay_content");
const question = data.questions[pos];
const result = data.result.map(arr => arr[pos]);
root.innerHTML = `
<span style="text-align: left; display: inline-block; width: 100%;">
${pos+1}. ${question.title}
</span><br>`;
const span = document.createElement("span");
span.style = `
width: 100%;
display: inline-block;
padding: 10px;
border-radius: var(--border-radius);
margin-top: 10px;
margin-bottom: 20px;
max-height: 60vh;
min-height: 60vh;
display: flex;
flex-direction: column;
justify-content: center;
background: rgba(255, 255, 255, 0.6);
`;
root.appendChild(span);
const span2 = document.createElement("span");
span2.style = `
width: 100%;
text-align: center;
display: flex;
font-size: 30px;
font-weight: bold;
align-items: middle;
justify-content: center;
flex-direction: row;
`;
const prevPage = document.createElement("label");
prevPage.innerHTML = "&nbsp;&lt;&nbsp;";
if (pos-1 >= 0) {
prevPage.addEventListener("click", () => _updateEvaResContent(elm, pos-1, data));
_setEvaResHover(prevPage);
} else {
prevPage.style.opacity = "0.4";
}
prevPage.style.marginTop = "3px";
span2.appendChild(prevPage);
for (var i = 0; i < data.questions.length; i++) {
const isSel = i == pos;
const div = document.createElement("div");
div.style = `
display: inline-block;
padding-left: 10px;
padding-right: 10px;
text-align: center;
`;
div.innerHTML = `
<label style="border-radius: 50%; display: inline-block; width: 15px; height: 15px; background: ${isSel ? "none": "black"}; border: 2px solid black;"></label>
`;
if (!isSel) {
const pos2 = i;
div.addEventListener("click", () => _updateEvaResContent(elm, pos2, data));
_setEvaResHover(div);
}
span2.appendChild(div);
}
const nextPage = document.createElement("label");
nextPage.innerHTML = "&nbsp;&gt;&nbsp;";
if (pos+1 < data.questions.length) {
nextPage.addEventListener("click", () => _updateEvaResContent(elm, pos+1, data));
_setEvaResHover(nextPage);
} else {
nextPage.style.opacity = "0.4";
}
nextPage.style.marginTop = "3px";
span2.appendChild(nextPage);
root.appendChild(span2);
if (question.type == "scala" || question.type == "emoji") {
const canvas = document.createElement("canvas");
canvas.style = `
width: 100%;
height: calc(100% - 6vh);
border-radius: var(--border-radius);
`;
const ctx = canvas.getContext("2d");
_drawEvaResChart(ctx, question, result);
span.appendChild(canvas);
} else {
let answers = "";
for (var i of result) {
const div = document.createElement("div");
div.style = `
padding: 10px;
background: rgba(255, 255, 255, 1);
margin-bottom: 10px;
border-radius: var(--border-radius);
`;
div.innerText += i;
answers += div.outerHTML;
}
span.innerHTML = `<div style="width: 100%; height: 100%; overflow-y: auto;">
${answers}
</div>`;
span.style.justifyContent = "top";
span.style.setProperty("justify-content", "start");
}
}
function _drawEvaResChart(ctx, question, result) {
const colors = [
'216, 22, 22',
'255, 178, 0',
'255, 236, 0',
'215, 255, 0',
'65, 255, 0'
];
if (question.type == "scala") {
let data = [0,0,0,0,0];
for (var i of result) {
if (i < 1) i = 1;
if (i > 5) i = 5;
data[i-1]++;
}
new Chart(ctx, {
type: 'bar',
data: {
labels: ['Sehr schlecht', 'Schlecht', 'Normal', 'Gut', 'Sehr gut'],
datasets: [{
label: "Anzahl der Stimmen",
data: data,
backgroundColor: [
'rgba(' + colors[0] + ', 0.2)',
'rgba(' + colors[1] + ', 0.2)',
'rgba(' + colors[2] + ', 0.2)',
'rgba(' + colors[3] + ', 0.2)',
'rgba(' + colors[4] + ', 0.2)'
],
borderColor: [
'rgba(' + colors[0] + ', 1)',
'rgba(' + colors[1] + ', 1)',
'rgba(' + colors[2] + ', 1)',
'rgba(' + colors[3] + ', 1)',
'rgba(' + colors[4] + ', 1)'
],
borderWidth: 2
}]
},
options: {
scales: { y: { beginAtZero: true } }
}
});
} else if (question.type == "emoji") {
let data = [0,0,0];
for (var i of result) {
if (i < 1) i = 1;
if (i > 3) i = 5;
data[i-1]++;
}
new Chart(ctx, {
type: 'bar',
data: {
labels: ['Schlecht', 'Ausgeglichen', 'Gut'],
datasets: [{
label: "Anzahl der Stimmen",
data: data,
backgroundColor: [
'rgba(' + colors[0] + ', 0.2)',
'rgba(' + colors[2] + ', 0.2)',
'rgba(' + colors[4] + ', 0.2)'
],
borderColor: [
'rgba(' + colors[0] + ', 1)',
'rgba(' + colors[2] + ', 1)',
'rgba(' + colors[4] + ', 1)'
],
borderWidth: 2
}]
},
options: {
scales: { y: { beginAtZero: true } }
}
});
}
}
function _setEvaResHover(elm) {
elm.addEventListener('mouseover', function() {
elm.style.opacity = '0.5';
});
elm.addEventListener('mouseout', function() {
elm.style.opacity = '1';
});
}
+321
View File
@@ -0,0 +1,321 @@
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=0.8">
<link rel="stylesheet" href="../lib/basic.css">
<script src="../auth.js"></script>
<script src="../lib/basic.js"></script>
<script src="../other/skills.js"></script>
<script src="../other/skilltree.js"></script>
<title>Umfrage</title>
</head>
<body>
<style>
.main-container {
position: fixed;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
height: 94%;
width: 94%;
max-width: 700px;
box-shadow: var(--def-shadow);
border-radius: var(--border-radius);
background-color: var(--accent_color_bg_o2);
text-align: center;
padding: 15px;
}
.bttn-close {
position: absolute;
top: 10px;
right: 10px;
width: 50px;
height: 50px;
font-size: 20px;
font-weight: bold;
border-radius: var(--border-radius);
border: 1px solid black;
background: var(--accent_color_bg);
}
.bttn-close:hover {
box-shadow: var(--reversed_def_shadow);
}
#content {
display: flex;
width: 100%;
flex-direction: column;
}
#content > div:first-child {
background-color: rgba(255, 255, 255, 0.7);
border-radius: var(--border-radius);
padding: 30px 10px;
/*min-height: 120px;*/
font-size: 22px;
font-weight: bold;
margin-bottom: 40px;
width: 100%;
}
#content > div:nth-child(2) {
display: inline-block;
min-height: 200px;
}
#content > div:nth-child(2) > textarea {
width: 100%;
resize: none;
border-radius: var(--border-radius);
border: none;
background-color: rgba(255, 255, 255, 0.7);
padding: 20px;
min-height: 200px;
font-size: 16px;
}
#content > div:nth-child(2) > input {
width: 50%;
margin-top: 50px;
}
#content > .weiter-btn {
position: absolute;
text-align: center;
bottom: 80px;
left: 50%;
font-size: 20px;
transform: translateX(-50%);
border-radius: var(--border-radius);
}
#content > div:last-child {
position: absolute;
width: 100%;
text-align: center;
bottom: 20px;
left: 0;
}
.weiter-btn {
display: inline-block;
min-width: 150px;
padding: 10px;
font-size: 18px;
text-align: center;
background-color: #007bff;
color: white;
border: none;
border-radius: var(--border-radius);
}
.weiter-btn:hover {
background-color: #0056b3;
}
.end-dialog {
position: absolute;
top: 50%;
left: 50%;
width: 100%;
transform: translate(-50%, -50%);
text-align: center;
}
</style>
<div class="main-container" id="container1">
<button class="bttn-close" onclick='close_page()'>X</button>
<div style="height: 60px;"></div>
<div id="content"></div>
</div>
<div class="main-container" id="container2" style="display: none;">
<div class="end-dialog">
<h2>Vielen Dank für deine Teilnahme!</h2><br>
<h3 id="level_up" style="display: none;">Level up!<br><br><br></h3>
<h3 id="xp_up" style="display: none;">+1 XP-Punkt<br><br><br></h3>
<button class="weiter-btn" onclick="onEndEvent(this)">
Zurück zur Hauptseite
</button>
</div>
</div>
<script>
const couchDB = new CouchDB();
var courseData = null;
async function setCourse() {
const args = getURLArgsMap();
const coursename = args.course;
if (!coursename) return false;
const kurs = await couchDB.get("course:" + coursename);
if (!kurs) return false;
courseData = kurs;
return true;
}
async function updateCourseAnswer(answer) {
const args = getURLArgsMap();
const coursename = args.course;
if (!coursename) return null;
const kurs = await couchDB.get("course:" + coursename);
if (!kurs) return null;
kurs.result.push(answer);
await couchDB.set("course:" + coursename, kurs);
return kurs;
}
function close_page() {
location.href = "./uebersicht.html?user=" + userData.name;
}
function createNavBar(pos) {
const div = document.createElement("div");
div.style = `
width: 100%;
text-align: center;
display: flex;
font-size: 30px;
font-weight: bold;
align-items: middle;
justify-content: center;
flex-direction: row;
`;
const prevPage = document.createElement("label");
prevPage.innerHTML = "&nbsp;&lt;&nbsp;";
if (pos-1 >= 0) {
prevPage.addEventListener("click", () => updateContent(pos, pos-1));
} else {
prevPage.style.opacity = "0.4";
}
prevPage.style.marginTop = "3px";
div.appendChild(prevPage);
for (var i = 0; i < courseData.questions.length; i++) {
const isSel = i == pos;
const divI = document.createElement("div");
divI.style = `
display: inline-block;
padding-left: 10px;
padding-right: 10px;
text-align: center;
`;
divI.innerHTML = `
<label style="border-radius: 50%; display: inline-block; width: 15px; height: 15px; background: ${isSel ? "none": "black"}; border: 2px solid black;"></label>
`;
if (!isSel) {
const pos2 = i;
divI.addEventListener("click", () => updateContent(pos, pos2));
}
div.appendChild(divI);
}
const nextPage = document.createElement("label");
nextPage.innerHTML = "&nbsp;&gt;&nbsp;";
if (pos+1 < courseData.questions.length) {
nextPage.addEventListener("click", () => updateContent(pos, pos+1));
} else {
nextPage.style.opacity = "0.4";
}
nextPage.style.marginTop = "3px";
div.appendChild(nextPage);
return div;
}
function setUmfrage(position = 0) {
const elm = getId("content");
const data = courseData.questions[position];
var input;
if (data.type == "scala") {
input = `Schlecht&nbsp;<input class="input" data="scala" type="range" min="1" max="5" autofocus>&nbsp;Gut`;
} else {
input = `<textarea class="input" data="text" placeholder="Text hier eingeben..." autofocus></textarea>`;
}
elm.innerHTML = `
<div>${data.title}</div>
<div>${input}</div>
<button class="weiter-btn" onclick="updateContent(${position}, ${position+1})">${
position == courseData.questions.length-1 ? "Umfrage beenden": "Weiter"
}</button>
`;
elm.appendChild(createNavBar(position));
}
var finalResult = null;
function updateContent(old_page, page) {
if (page < 0) page = 0;
const inp = getId("content").querySelector(".input");
const type = inp.getAttribute("data");
if (type == "scala") {
try {
finalResult[old_page] = parseInt(inp.value);
} catch(err) {
console.error(err);
}
} else {
finalResult[old_page] = inp.value;
}
if (page >= courseData.questions.length) {
getId("container1").style.display = "none";
getId("container2").style.display = "unset";
onFinishEva();
return;
}
setUmfrage(page);
getId("content").querySelector(".input").focus();
}
async function onFinishEva() {
await updateCourseAnswer(finalResult);
if (await levelUpXP(couchDB)) {
const e = getId("level_up");
if (e) e.style.display = "unset";
await playLevelSound();
} else {
const e = getId("xp_up");
if (e) e.style.display = "unset";
await playXPSound();
}
}
async function onEndEvent() {
location.href = "./uebersicht.html?user=" + userData.name;
}
(async () => {
await setUserData(couchDB);
if (!(await setCourse())) {
console.error("No course defined");
return;
}
if (!courseData.expire_date) {
console.error("courseData.expire_date is null");
return;
}
const expire_date = new Date(courseData.expire_date);
if (courseData.questions.length == 0 || expire_date < new Date()) {
onEndEvent();
return;
}
finalResult = [];
for (var i in courseData.questions) finalResult.push(null);
setUmfrage();
})();
</script>
</body>
</html>