chore: Update branch #1

Merged
2021323 merged 3 commits from :main into main 2024-11-14 20:29:42 +01:00
7 changed files with 148 additions and 128 deletions

View File

@ -3,29 +3,35 @@ document
.addEventListener("submit", function (event) {
event.preventDefault();
const form = event.target;
const formData = new FormData(form);
const jsonData = {
ssid: formData.get("ssid"),
psid: formData.get("psid"),
level: formData.get("level"),
};
fetch("/api/employee/skill/prototype", {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify(jsonData),
})
.then((response) => {
if (response.ok) {
window.location.href = "/skills";
} else {
return response.json().then((error) => {
console.error("Error:", error);
});
}
const skillSelectors = form.querySelectorAll(".skill-selector");
skillSelectors.forEach((selector) => {
const formData = new FormData(selector);
const jsonData = {
ssid: formData.get("ssid"),
psid: formData.get("psid"),
level: formData.get("level"),
};
fetch("/api/employee/skill/prototype", {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify(jsonData),
})
.catch((error) => {
console.error("Error:", error);
});
.then((response) => {
if (!response.ok) {
return response.json().then((error) => {
console.error("Error:", error);
});
}
})
.catch((error) => {
console.error("Error:", error);
});
});
// Redirect to the skills page after all requests are sent
window.location.href = "/skills";
});

View File

@ -1,103 +1,76 @@
/***
* @fileoverview Star Rating Component - Initializes and manages an interactive star rating system
* with hover effects, click handling, and dynamic descriptions.
* @version 2.2.0
*/
document.addEventListener("DOMContentLoaded", function () {
const stars = document.querySelectorAll(".star");
const ratingInput = document.getElementById("level");
const descriptionElement = document.querySelector(".rating-description");
const initialValue = parseInt(ratingInput.value) || 0;
updateStars(initialValue);
function initializeStarRatingComponents() {
const starRatingContainers = document.querySelectorAll(
".star-rating-container"
);
starRatingContainers.forEach((container) => {
const stars = container.querySelectorAll(".star");
const ratingInput = container.querySelector("input[name='level']");
const descriptionElement = container.querySelector(".rating-description");
stars.forEach((star) => {
/**
* Handle click events on stars
* Updates the rating value and displays the corresponding description
*/
star.addEventListener("click", function () {
const value = parseInt(this.dataset.value);
ratingInput.value = value;
updateStars(value);
showDescription(this.dataset.description);
stars.forEach((star) => {
star.addEventListener("click", function () {
const value = parseInt(this.dataset.value);
ratingInput.value = value;
updateStars(container, value);
showDescription(descriptionElement, this.dataset.description);
});
star.addEventListener("mouseenter", function () {
const value = parseInt(this.dataset.value);
highlightStars(container, value);
showDescription(descriptionElement, this.dataset.description);
});
});
/**
* Handle mouseenter events on stars
* Temporarily highlights stars and shows description on hover
*/
star.addEventListener("mouseenter", function () {
const value = parseInt(this.dataset.value);
highlightStars(value);
showDescription(this.dataset.description);
});
});
/**
* Handle mouseleave events on the entire star rating container
* Resets the display to the current selected rating
*/
document
.querySelector(".star-rating")
.addEventListener("mouseleave", function () {
container.addEventListener("mouseleave", function () {
const currentValue = parseInt(ratingInput.value) || 0;
updateStars(currentValue);
updateStars(container, currentValue);
if (currentValue > 0) {
const selectedStar = document.querySelector(
const selectedStar = container.querySelector(
`.star[data-value="${currentValue}"]`
);
showDescription(selectedStar.dataset.description);
showDescription(descriptionElement, selectedStar.dataset.description);
} else {
hideDescription();
hideDescription(descriptionElement);
}
});
/**
* Updates the visual state of stars based on a value
* @param {number} value - The rating value to display (1-5)
*/
function updateStars(value) {
stars.forEach((star) => {
const starValue = parseInt(star.dataset.value);
if (starValue <= value) {
star.classList.add("active");
} else {
star.classList.remove("active");
}
});
}
/**
* Temporarily highlights stars up to a specific value
* Used for hover effects
* @param {number} value - The rating value to highlight (1-5)
*/
function highlightStars(value) {
stars.forEach((star) => {
const starValue = parseInt(star.dataset.value);
if (starValue <= value) {
star.classList.add("active");
} else {
star.classList.remove("active");
}
});
}
/**
* Displays a description for the current rating
* @param {string} description - The description text to display
*/
function showDescription(description) {
if (description) {
descriptionElement.textContent = description;
descriptionElement.classList.add("visible");
});
}
function updateStars(container, value) {
const stars = container.querySelectorAll(".star");
stars.forEach((star) => {
const starValue = parseInt(star.dataset.value);
if (starValue <= value) {
star.classList.add("active");
} else {
star.classList.remove("active");
}
}
});
}
/**
* Hides the rating description
*/
function hideDescription() {
descriptionElement.classList.remove("visible");
function highlightStars(container, value) {
const stars = container.querySelectorAll(".star");
stars.forEach((star) => {
const starValue = parseInt(star.dataset.value);
if (starValue <= value) {
star.classList.add("active");
} else {
star.classList.remove("active");
}
});
}
function showDescription(descriptionElement, description) {
if (description) {
descriptionElement.textContent = description;
descriptionElement.classList.add("visible");
}
}
function hideDescription(descriptionElement) {
descriptionElement.classList.remove("visible");
}
document.addEventListener("DOMContentLoaded", function () {
initializeStarRatingComponents();
});

View File

@ -0,0 +1,31 @@
function handleSecondarySkillSelection(selectElement) {
const skillCreator = document.querySelector("#skillCreator");
const newSkillSelector = selectElement.closest(".row").cloneNode(true);
const selectedOptions = Array.from(
document.querySelectorAll("#skillCreator select[name='ssid']")
).map((select) => select.value);
// Filter out already selected options
const secondarySkillSelect =
newSkillSelector.querySelector("#secondarySkill");
const options = Array.from(secondarySkillSelect.options);
options.forEach((option) => {
if (selectedOptions.includes(option.value)) {
option.remove();
}
});
// Check if there are any options left to select
if (secondarySkillSelect.options.length <= 1) {
return; // Exit if no options left
}
newSkillSelector.querySelector("#secondarySkill").value = "";
newSkillSelector.querySelector("#level").value = "1";
newSkillSelector.querySelector(".btn-default").disabled = true;
const skillSelectorList = document.querySelector("#skillSelectorList");
skillSelectorList.appendChild(newSkillSelector);
// Initialize star rating components for the new skill selector
initializeStarRatingComponents();
}

View File

@ -6,33 +6,39 @@
class="star"
data-value="1"
data-description="Beginner - Basic knowledge and limited experience"
><i class="fas fa-star"></i
></span>
>
<i class="fas fa-star"></i>
</span>
<span
class="star"
data-value="2"
data-description="Elementary - Can handle simple tasks with guidance"
><i class="fas fa-star"></i
></span>
>
<i class="fas fa-star"></i>
</span>
<span
class="star"
data-value="3"
data-description="Intermediate - Independent work on most tasks"
><i class="fas fa-star"></i
></span>
>
<i class="fas fa-star"></i>
</span>
<span
class="star"
data-value="4"
data-description="Advanced - Deep knowledge and extensive experience"
><i class="fas fa-star"></i
></span>
>
<i class="fas fa-star"></i>
</span>
<span
class="star"
data-value="5"
data-description="Expert - Master level with ability to teach others"
><i class="fas fa-star"></i
></span>
>
<i class="fas fa-star"></i>
</span>
</div>
<div class="rating-description"></div>
<input type="hidden" name="level" value="1" />
</div>
</html>

View File

@ -1,6 +1,6 @@
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<div th:fragment="skillCreator">
<div th:fragment="skillCreator" id="skillCreator">
<form th:object="${skillPrototype}" id="addSkillForm" class="project-card">
<div class="card-body">
<!-- Primary Skill Dropdown -->
@ -22,11 +22,13 @@
</select>
</div>
<!-- Secondary Skill Selector -->
<div
th:replace="~{/fragments/skills/_skillSelector :: skillSelector}"
></div>
<div id="skillSelectorList" class="skill-selector-list">
<div
th:replace="~{/fragments/skills/_skillSelector :: skillSelector}"
></div>
</div>
<!-- Submit Button -->
<button type="submit" class="btn-default">Speichern</button>
<button type="submit" class="btn-default">Add Skill</button>
</div>
</form>
</div>

View File

@ -10,6 +10,7 @@
name="ssid"
class="form-control"
th:field="*{ssid}"
onchange="handleSecondarySkillSelection(this)"
>
<option value="" disabled selected>
Bitte eine Fähigkeit auswählen!

View File

@ -25,5 +25,6 @@
<script src="/js/skills/fetchSecondarySkills.js"></script>
<script src="/js/skills/levelSelector.js"></script>
<script src="/js/skills/addSkill.js"></script>
<script src="/js/skills/skillSelector.js"></script>
</body>
</html>