feat: Add sus (translations missing)
This commit is contained in:
		@@ -22,6 +22,8 @@
 | 
			
		||||
  "source-code": "Quellcode",
 | 
			
		||||
  "give-feedback": "Feedback geben",
 | 
			
		||||
  "feedback": "Feedback",
 | 
			
		||||
  "sus-title": "Bewerte den Rechner",
 | 
			
		||||
  "submit": "Absenden",
 | 
			
		||||
  "failed-base-area": "Die Mindestgrundfläche des Käfigs muss {{ MINIMUM_BASE_AREA }}m² (also z.B. 100x50cm) betragen.",
 | 
			
		||||
  "failed-overall-area": "Die Gesamtfläche im Käfig ist zu klein.",
 | 
			
		||||
  "failed-fall-height": "Die mögliche Fallhöhe darf nicht mehr als {{ maximum_fall_height }}cm betragen.",
 | 
			
		||||
 
 | 
			
		||||
@@ -22,6 +22,8 @@
 | 
			
		||||
  "source-code": "Source Code",
 | 
			
		||||
  "give-feedback": "Give Feedback",
 | 
			
		||||
  "feedback": "Feedback",
 | 
			
		||||
  "sus-title": "Rate the calculator",
 | 
			
		||||
  "submit": "Submit",
 | 
			
		||||
  "failed-base-area": "The base area of the cage must not be below {{ MINIMUM_BASE_AREA }}m².",
 | 
			
		||||
  "failed-overall-area": "The overall area in the cage is to small.",
 | 
			
		||||
  "failed-fall-height": "The possible fall height between floors must not be above {{ maximum_fall_height }}cm.",
 | 
			
		||||
 
 | 
			
		||||
@@ -261,7 +261,8 @@
 | 
			
		||||
                    <li class="footer-link"><a href="https://codeberg.org/moanos/rettenrechner" data-i18n="source-code">Quellcode</a>
 | 
			
		||||
                    </li>
 | 
			
		||||
                    <li class="footer-link">
 | 
			
		||||
                        <a class="js-modal-trigger is-text is-link" data-target="modal-feedback" data-i18n="give-feedback">
 | 
			
		||||
                        <a class="js-modal-trigger is-text is-link" data-target="modal-feedback"
 | 
			
		||||
                           data-i18n="give-feedback">
 | 
			
		||||
                            Feedback geben
 | 
			
		||||
                        </a>
 | 
			
		||||
                    </li>
 | 
			
		||||
@@ -280,16 +281,32 @@
 | 
			
		||||
            <button class="delete" aria-label="close"></button>
 | 
			
		||||
        </header>
 | 
			
		||||
        <div class="modal-card-body">
 | 
			
		||||
            <div class="section">
 | 
			
		||||
                <p>
 | 
			
		||||
                    Wir freuen uns sehr, wenn du uns Feedback zu unserem Rattenrechner gibst!
 | 
			
		||||
                    Der einfachste Weg das zu tun ist per E-Mail an <a
 | 
			
		||||
                        href="mailto:webmaster@vdrd.de">webmaster@vdrd.de</a>.
 | 
			
		||||
                </p>
 | 
			
		||||
                <p>
 | 
			
		||||
                Der Code dieser Website ist <a href="https://codeberg.org/moanos/rettenrechner">öffentlich einsehbar.</a>
 | 
			
		||||
                Gerne kannst du auch direkt dort <a href="https://codeberg.org/moanos/rettenrechner/issues">einen Issue</a> eröffnen!
 | 
			
		||||
                    Der Code dieser Website ist <a href="https://codeberg.org/moanos/rettenrechner">öffentlich
 | 
			
		||||
                    einsehbar.</a>
 | 
			
		||||
                    Gerne kannst du auch direkt dort <a href="https://codeberg.org/moanos/rettenrechner/issues">einen
 | 
			
		||||
                    Issue</a> eröffnen!
 | 
			
		||||
                </p>
 | 
			
		||||
            </div>
 | 
			
		||||
            <div class="section">
 | 
			
		||||
                <h1 class="title" data-i18n="sus-title">Bewerte den Rechner</h1>
 | 
			
		||||
                <form id="sus-form">
 | 
			
		||||
                    <!--- Questions here --->
 | 
			
		||||
                        <div class="control" id="sus-control">
 | 
			
		||||
                            <button class="button is-primary" type="submit" data-i18n="submit">Absenden</button>
 | 
			
		||||
                        </div>
 | 
			
		||||
 | 
			
		||||
                </form>
 | 
			
		||||
                <div id="response-message" class="notification is-hidden"></div>
 | 
			
		||||
            </div>
 | 
			
		||||
 | 
			
		||||
        </div>
 | 
			
		||||
    </div>
 | 
			
		||||
 | 
			
		||||
</div>
 | 
			
		||||
 
 | 
			
		||||
@@ -30,7 +30,7 @@ document.addEventListener('DOMContentLoaded', () => {
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    // Add a click event on various child elements to close the parent modal
 | 
			
		||||
    (document.querySelectorAll('.modal-background, .modal-close, .delete, .button') || []).forEach(($close) => {
 | 
			
		||||
    (document.querySelectorAll('.modal-background, .modal-close, .delete') || []).forEach(($close) => {
 | 
			
		||||
        const $target = $close.closest('.modal');
 | 
			
		||||
 | 
			
		||||
        $close.addEventListener('click', () => {
 | 
			
		||||
 
 | 
			
		||||
@@ -8,6 +8,7 @@ import '@fortawesome/fontawesome-free/js/brands';
 | 
			
		||||
import './feedback.js';
 | 
			
		||||
import './main.scss';
 | 
			
		||||
import {send} from './telemetry';
 | 
			
		||||
import './sus.js';
 | 
			
		||||
 | 
			
		||||
/////////////////
 | 
			
		||||
// TRANSLATION //
 | 
			
		||||
 
 | 
			
		||||
@@ -148,3 +148,17 @@ Reused from Notfellchen
 | 
			
		||||
.tooltip:not(.top) .tooltiptext::before {
 | 
			
		||||
  top: auto;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
// SUS Slider
 | 
			
		||||
 | 
			
		||||
.sus-slider {
 | 
			
		||||
  width: 100%;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.slider-labels {
 | 
			
		||||
  display: flex;
 | 
			
		||||
  justify-content: space-between;
 | 
			
		||||
  font-size: 0.9rem;
 | 
			
		||||
  margin-top: 0.25rem;
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										107
									
								
								src/sus.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										107
									
								
								src/sus.js
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,107 @@
 | 
			
		||||
const scaleQuestions = [
 | 
			
		||||
    "sus-question-easy-to-use", // I thought CageCalc is easy to use
 | 
			
		||||
    "sus-question-like-to-use-frequently", // I would like to use CageCalc frequently
 | 
			
		||||
    "sus-question-unnecessarily-complex", // I find CageCalc unnecessarily complex
 | 
			
		||||
    "sus-question-need-support-of-technical-person", // I think that I need the support of a technical person to be able to use CageCalc
 | 
			
		||||
    "sus-question-well-integrated", // I found various functions in CageCalc were well integrated
 | 
			
		||||
    "sus-question-inconsistency", // I thought there was too much inconsistency in CageCalc
 | 
			
		||||
    "sus-question-learn-quickly", // I would imagine that most people would learn to use CageCalc very quickly
 | 
			
		||||
    "sus-question-cumbersome", // I found CageCalc very cumbersome to use
 | 
			
		||||
    "sus-question-confident", // I felt very confident using CageCalc
 | 
			
		||||
    "sus-question-need-to-learn" // I needed to learn a lot of things before I could get going with CageCalc
 | 
			
		||||
];
 | 
			
		||||
 | 
			
		||||
const freetextQuestions = [
 | 
			
		||||
    "question-whats-missing", // Welche Funktion fehlt dir?
 | 
			
		||||
    "question-pain-points", // Was muss aus deiner Sicht an XX geändert werden?
 | 
			
		||||
    "question-other-feedback" // Was willst du uns mitgeben?
 | 
			
		||||
]
 | 
			
		||||
 | 
			
		||||
function prepareQuestionnaire() {
 | 
			
		||||
    const form = document.getElementById("sus-form");
 | 
			
		||||
 | 
			
		||||
    scaleQuestions.forEach((key, index) => {
 | 
			
		||||
        const field = document.createElement("div");
 | 
			
		||||
        field.className = "field";
 | 
			
		||||
        field.id = key;
 | 
			
		||||
        field.innerHTML = `
 | 
			
		||||
          <label class="label" data-i18n="${key}"></label>
 | 
			
		||||
          <p class="control">
 | 
			
		||||
            <input class="sus-slider" type="range" min="1" max="5" step="1" name=${key} required>
 | 
			
		||||
            <div class="slider-labels">
 | 
			
		||||
              <span data-i18n="strongly-disagree">Strongly Disagree</span>
 | 
			
		||||
              <span data-i18n="disagree">Disagree</span>
 | 
			
		||||
              <span data-i18n="neutral">Neutral</span>
 | 
			
		||||
              <span data-i18n="agree">Agree</span>
 | 
			
		||||
              <span data-i18n="strongly-agree">Strongly Agree</span>
 | 
			
		||||
            </div>
 | 
			
		||||
          </p>
 | 
			
		||||
        `;
 | 
			
		||||
        form.insertBefore(field, form.querySelector('#sus-control'));
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    freetextQuestions.forEach((key, index) => {
 | 
			
		||||
        const field = document.createElement("div");
 | 
			
		||||
        field.classList.add("field");
 | 
			
		||||
        field.id = key;
 | 
			
		||||
        field.innerHTML = `
 | 
			
		||||
            <label class="label" data-i18n="${key}"></label>
 | 
			
		||||
            <p class="control">
 | 
			
		||||
                <input class="input" type="text" name=${key}/>
 | 
			
		||||
            </p>
 | 
			
		||||
                `
 | 
			
		||||
        form.insertBefore(field, form.querySelector('#sus-control'));
 | 
			
		||||
    })
 | 
			
		||||
    return form;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
window.addEventListener('DOMContentLoaded', () => {
 | 
			
		||||
    let form = prepareQuestionnaire();
 | 
			
		||||
    form.addEventListener("submit", async (e) => {
 | 
			
		||||
        e.preventDefault();
 | 
			
		||||
 | 
			
		||||
        const formData = new FormData(form);
 | 
			
		||||
        const jsonData = {};
 | 
			
		||||
 | 
			
		||||
        for (let [key, value] of formData.entries()) {
 | 
			
		||||
            console.log(key, value);
 | 
			
		||||
            if (key.startsWith("sws-question")) {
 | 
			
		||||
                jsonData[key] = parseInt(value, 10);
 | 
			
		||||
            } else {
 | 
			
		||||
                jsonData[key] = value;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        try {
 | 
			
		||||
            const response = await fetch("https://storandom.hyteck.de/submit", {
 | 
			
		||||
                method: "POST",
 | 
			
		||||
                headers: {
 | 
			
		||||
                    "Content-Type": "application/json"
 | 
			
		||||
                },
 | 
			
		||||
                body: JSON.stringify(jsonData)
 | 
			
		||||
            });
 | 
			
		||||
 | 
			
		||||
            const messageDiv = document.getElementById("response-message");
 | 
			
		||||
 | 
			
		||||
            if (response.ok) {
 | 
			
		||||
                messageDiv.className = "notification is-success";
 | 
			
		||||
                messageDiv.setAttribute("data-i18n", "submit-success");
 | 
			
		||||
                messageDiv.textContent = "Survey submitted successfully!";
 | 
			
		||||
            } else {
 | 
			
		||||
                messageDiv.className = "notification is-danger";
 | 
			
		||||
                messageDiv.setAttribute("data-i18n", "submit-error");
 | 
			
		||||
                messageDiv.textContent = "There was an error submitting the survey.";
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            messageDiv.classList.remove("is-hidden");
 | 
			
		||||
 | 
			
		||||
        } catch (error) {
 | 
			
		||||
            const messageDiv = document.getElementById("response-message");
 | 
			
		||||
            messageDiv.className = "notification is-danger";
 | 
			
		||||
            messageDiv.removeAttribute("data-i18n"); // For dynamic error message
 | 
			
		||||
            messageDiv.textContent = "Network error: " + error.message;
 | 
			
		||||
            messageDiv.classList.remove("is-hidden");
 | 
			
		||||
        }
 | 
			
		||||
    });
 | 
			
		||||
});
 | 
			
		||||
		Reference in New Issue
	
	Block a user