Merge pull request 'chore: Update branch' (#1) from 3002833/Backend:main into main
Reviewed-on: #1main
commit
9d9e111e04
|
@ -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";
|
||||
});
|
||||
|
|
|
@ -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();
|
||||
});
|
||||
|
|
|
@ -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();
|
||||
}
|
|
@ -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>
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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!
|
||||
|
|
|
@ -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>
|
||||
|
|
Loading…
Reference in New Issue