tickets/templates/party.html
Julius f2c235f8c7
All checks were successful
continuous-integration/drone/push Build is passing
Fix CRLF problems
It replaces a \r\n with \n now, and a \r with \n to also support
macOS line endings
2022-06-28 16:37:10 +02:00

258 lines
9.1 KiB
HTML

{% extends "base.html" %}
{% block content %}
<div class="columns">
<div class="column col-md-12 col-mx-auto col-6">
<h1>{{name}}</h1>
<h2>Modus</h2>
<div class="form-group">
<label class="form-radio form-inline">
<input type="radio" name="mode" value="false" checked=""><i class="form-icon"></i> Toevoegen
</label>
<label class="form-radio form-inline">
<input type="radio" name="mode" value="true"><i class="form-icon"></i> Controleren
</label>
</div>
<h2>Camera</h2>
<div>
<p><select id="videoSource"></select><button class="btn btn-primary" id="start_scan_btn">Start
Scannen</button> </p>
<h4><span id="last-scanned">Nog geen gescand</span></h4>
<h3><span id="scan-status">Nog geen gescand</span></h3>
<div class="columns">
<video autoplay playsinline controls="false" class="column col-12"></video>
</div>
</div>
<div class="columns">
<div class="column col-md-12 col-6">
<h2>Handmatig Toevoegen</h2>
<form id="student_number_wrapper">
<p><label for="student_number">Leerlingnummer:</label></p>
<input type="text" id="student_number" name="student_number" placeholder="Leerlingnummer">
<button class="btn btn-primary" id="add_student">"Scan"</button>
</form>
</div>
<div class="column col-md-12 col-6">
<h2>Extra opties</h2>
<p><a href="/party/{{id}}/lijst">Bekijk een tabel in je browser</a></p>
<p><a href="/party/{{id}}/export">Exporteer als CSV</a></p>
<p><label for="file-selector">Importeer CSV:</label><input type="file" id="file-selector"
accept=".csv" /></p>
<p><button id="file-selector-button">Importeer</button> <span id="import-result"></span></p>
</div>
</div>
</div>
</div>
<input type="hidden" id="party_id" value="{{id}}">
<script src="//unpkg.com/javascript-barcode-reader"></script>
<script>
function set_colour(state) {
if (state == "OK") {
document.body.classList.add("bg-success");
setTimeout(function () {
document.body.classList.remove("bg-success");
}, 1000);
} else if (state == "WARN") {
document.body.classList.add("bg-warning");
setTimeout(function () {
document.body.classList.remove("bg-warning");
}, 1000);
} else if ("ERR") {
document.body.classList.add("bg-error");
setTimeout(function () {
document.body.classList.remove("bg-error");
}, 1000);
}
}
function set_scan_status(status) {
document.getElementById("scan-status").innerHTML = status;
}
function set_state(data) {
let code = data.code;
let state = data.state;
let check = document.querySelector('input[name="mode"]:checked').value === "true";
document.getElementById("last-scanned").innerText = code;
if (state === "NotFound") {
// leerlingnummer niet gevonden op de gastenlijst
// alert("Leerlingnummer niet gevonden");
set_scan_status("Heeft (waarschijnlijk) niet betaald");
set_colour("ERR");
} else if (state === "Found") {
// leerlingnummer is gevonden en mag naar binnen
// alert("Leerlingnummer gevonden");
set_scan_status("Mag naar binnen");
set_colour("OK");
} else if (state === "Added") {
// leerlingummer is toegevoegd aan de gastenlijst
// alert("Leerlingnummer toegevoegd");
set_scan_status("Toegevoegd");
set_colour("OK");
} else if (state === "AlreadyScanned") {
// leerlingnummer is al gescand, bij check==false is er al betaald, bij check==true is de leerling al binnen
if (check) {
// alert("Leerlingnummer is al binnen");
set_scan_status("Al binnen");
set_colour("ERR");
} else {
// alert("Leerlingnummer is al betaald");
set_scan_status("Al betaald");
set_colour("WARN");
}
} else {
alert("Error");
}
}
function scan_ticket(code) {
let check = document.querySelector('input[name="mode"]:checked').value === "true";
let party_id = +document.getElementById("party_id").value;
fetch("/api/ticket", {
method: "POST",
headers: {
"Content-Type": "application/json"
},
body: JSON.stringify({
party: party_id,
code: code,
check: check,
})
}).then(function (response) {
return response.json();
}).then(function (data) {
console.log(data)
return data;
}).then(set_state);
}
function return_handler(e) {
e.preventDefault();
let code = document.getElementById("student_number").value;
console.log(code);
scan_ticket(code);
}
function button_click_handler() {
let code = document.getElementById("student_number").value;
scan_ticket(code);
}
document.getElementById("add_student").addEventListener("click", button_click_handler);
document.getElementById("student_number_wrapper").addEventListener("submit", return_handler);
document.getElementById("start_scan_btn").addEventListener('click', start_scanning);
const videoElement = document.querySelector("video");
const videoSelect = document.querySelector("select#videoSource");
function start_scanning() {
navigator.mediaDevices
.enumerateDevices()
.then(gotDevices)
.then(getStream)
.catch(handleError);
}
videoSelect.onchange = getStream;
function gotDevices(deviceInfos) {
for (let i = 0; i !== deviceInfos.length; ++i) {
const deviceInfo = deviceInfos[i];
const option = document.createElement("option");
option.value = deviceInfo.deviceId;
if (deviceInfo.kind === "videoinput") {
option.text = deviceInfo.label || "camera " + (videoSelect.length + 1);
videoSelect.appendChild(option);
} else {
console.log("Found another kind of device: ", deviceInfo);
}
}
}
function getStream() {
if (window.stream) {
window.stream.getTracks().forEach(function (track) {
track.stop();
});
}
const constraints = {
video: {
deviceId: { exact: videoSelect.value },
},
};
navigator.mediaDevices
.getUserMedia(constraints)
.then(gotStream)
.catch(handleError);
}
function gotStream(stream) {
window.stream = stream; // make stream available to console
videoElement.srcObject = stream;
setInterval(() => {
console.log("scanning now?")
const canvas = document.createElement("canvas");
canvas.width = videoElement.videoWidth;
canvas.height = videoElement.videoHeight;
canvas.getContext("2d").drawImage(videoElement, 0, 0);
do_scan(canvas);
}, 500);
}
function handleError(error) {
console.error("Error: ", error);
}
let last_scan = "";
function do_scan(imageData) {
javascriptBarcodeReader({
image: imageData,
barcode: 'codabar',
options: {
useAdaptiveThreshold: true,
}
})
.then(code => {
if (code.length == 6) {
if (last_scan === code) {
return;
}
last_scan = code;
scan_ticket(code);
}
})
.catch(err => {
console.log(err)
})
}
function upload_csv() {
let file = document.getElementById("file-selector").files[0];
if (file) {
const reader = new FileReader();
let num = 0;
reader.onload = (evt) => {
let result = evt.target.result;
result = result.replace("\r\n", "\n").replace("\r", "\n");
for (let line of result.split("\n")) {
for (let llnr of line.split(",")) {
if (llnr.length === 6 && !isNaN(llnr)) {
scan_ticket(llnr);
num += 1;
}
}
}
document.getElementById("import-result").innerHTML = `${num} leerlingen geïmporteerd!`
}
reader.readAsText(file);
}
}
document.getElementById("file-selector-button").addEventListener("click", upload_csv);
</script>
{% endblock %}