290 lines
9.8 KiB
JavaScript
290 lines
9.8 KiB
JavaScript
"use strict";
|
|
|
|
const app = document.getElementById("appContent");
|
|
let userdata;
|
|
load();
|
|
const emptyPages = {
|
|
"title": {"type": "title"},
|
|
"blank": {"type": "blank"},
|
|
"report": {
|
|
"type": "report",
|
|
"days": [ [], [], [], [], [], ],
|
|
},
|
|
|
|
};
|
|
let templates;
|
|
|
|
// const templates = {
|
|
// "blank": (await fetchTemplate("blank"))
|
|
// };
|
|
// let blank = fetchTemplate("blank").then(b=>{blank=b});
|
|
// let blank = fetchTemplate("blank")
|
|
async function init() {
|
|
if (typeof templates === "undefined") {
|
|
templates = {
|
|
"title": await fetchTemplate("title"),
|
|
"blank": await fetchTemplate("blank"),
|
|
"report": await fetchTemplate("report"),
|
|
"report_input": await fetchTemplate("report_input"),
|
|
};
|
|
}
|
|
userdata.pages = userdata.pages || [];
|
|
[...app.children].forEach(child => app.removeChild(child))
|
|
|
|
userdata.pages.forEach((e,i) => {
|
|
pageNew(e.type);
|
|
populate(i+1);
|
|
})
|
|
}
|
|
|
|
function pageAdd(template) {
|
|
pageNew(template);
|
|
userdata.pages.push(emptyPages[template]);
|
|
populate(app.children.length);
|
|
save();
|
|
}
|
|
|
|
function pageNew(template) {
|
|
const node = templates[template].content.cloneNode(true);
|
|
node.children[0].id = `Page-${app.children.length+1}`;
|
|
app.appendChild(node);
|
|
fixPageCount();
|
|
}
|
|
|
|
function populate(pnum) {
|
|
if (pnum > 0 && pnum <= app.children.length && pnum <= userdata.pages.length) {
|
|
const node = app.children[pnum-1];
|
|
const data = userdata.pages[pnum-1];
|
|
node.querySelectorAll(".logo").forEach(i=>i.src = userdata.meta.logo);
|
|
if (node.classList.contains(data.type)) {
|
|
switch (data.type) {
|
|
case "report":
|
|
let startDate = data.start;
|
|
if (typeof startDate === "undefined") {
|
|
const dates = (pnum > 1) && app.children[pnum-2].getElementsByClassName("date") || [];
|
|
startDate = dates.length > 1 && dates[1].textContent.split(".").reverse().map(Number) || undefined;
|
|
if (typeof startDate === "undefined") {
|
|
startDate = userdata.meta.start || [0,0,0];
|
|
} else {
|
|
startDate[1] -= 1;
|
|
startDate[2] += 3;
|
|
}
|
|
}
|
|
let endDate = data.end;
|
|
if (typeof endDate === "undefined") {
|
|
endDate = [...startDate];
|
|
endDate[2] += 4;
|
|
}
|
|
const date = node.querySelectorAll(".date");
|
|
date[0].textContent = getDate(startDate);
|
|
date[1].textContent = getDate(endDate);
|
|
|
|
let week = node.querySelector(".week").querySelectorAll(".day");
|
|
let weekh = null;
|
|
for (const i in [...week]) {
|
|
let day = week[i].querySelectorAll(".day-line");
|
|
for (const j in [...day]) {
|
|
if (data.days.length > i && data.days[i].length > j && data.days[i][j].length === 2) {
|
|
day[j].querySelectorAll("div")[0].textContent = data.days[i][j][0];
|
|
day[j].querySelectorAll("div")[1].textContent = data.days[i][j][1];
|
|
}
|
|
}
|
|
const st = [...week[i].querySelectorAll(".sh")].reduce(
|
|
(total,e) => {
|
|
return total + Number(e.textContent)
|
|
},
|
|
0
|
|
) || null;
|
|
week[i].querySelector(".subtotal").textContent = st;
|
|
weekh += st;
|
|
}
|
|
node.querySelector(".total").textContent = weekh;
|
|
|
|
case "blank":
|
|
node.querySelector(".pnum").textContent = pnum;
|
|
break;
|
|
case "title":
|
|
let tdate = node.querySelectorAll(".tdate");
|
|
tdate[0].textContent = getDate(userdata.meta.start);
|
|
tdate[1].textContent = getDate(userdata.meta.end);
|
|
node.querySelector(".name").textContent = `${userdata.meta.lastName}, ${userdata.meta.firstName}`;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
function getTotal(day) {
|
|
let st = [...day.querySelectorAll(".sh")].reduce(
|
|
(total,e) => {
|
|
return total + Number(e.textContent)},
|
|
0
|
|
);
|
|
st = st || null;
|
|
day.querySelector(".subtotal").textContent = st;
|
|
return st;
|
|
|
|
}
|
|
|
|
function getDate(date) {
|
|
let d = date && new Date(...date) || new Date();
|
|
return `${String(d.getDate()).padStart(2, "0")}.${String(d.getMonth()+1).padStart(2, "0")}.${d.getFullYear()}`
|
|
}
|
|
|
|
function fixPageCount() {
|
|
const pc = document.getElementsByClassName("pcount");
|
|
for (let i=0; i < pc.length; i++) {
|
|
pc[i].textContent = app.children.length;
|
|
}
|
|
}
|
|
|
|
async function fetchTemplate(tname) {
|
|
let template = document.createElement("template");
|
|
template.innerHTML = await ( await fetch(`assets/templates/${tname}.html`)).text();
|
|
return template.content.getElementById(tname);
|
|
}
|
|
|
|
function load() {
|
|
userdata = JSON.parse(localStorage.getItem("userdata")) ||
|
|
{ "meta": {
|
|
"firstName": "",
|
|
"lastName": "",
|
|
"start": null,
|
|
"end": null,
|
|
"logo": ""
|
|
},
|
|
"pages": [],
|
|
};
|
|
}
|
|
|
|
function save() {
|
|
localStorage.setItem("userdata", JSON.stringify(userdata))
|
|
}
|
|
|
|
function hideOverlay() {
|
|
document.getElementById("overlay").style.display = "none";
|
|
document.getElementById("import").style.display = "none";
|
|
}
|
|
|
|
function ignoreData(event) {
|
|
event.preventDefault();
|
|
event.stopPropagation();
|
|
}
|
|
|
|
function showImport(event) {
|
|
document.getElementById("overlay").style.display = "block";
|
|
document.getElementById("import").style.display = "block";
|
|
}
|
|
|
|
function importData(event) {
|
|
event.preventDefault();
|
|
|
|
if (event.dataTransfer.items) {
|
|
[...event.dataTransfer.items].forEach(f => {
|
|
if (f.kind == "file") {
|
|
f.getAsFile().text().then(t => {
|
|
userdata = JSON.parse(t);
|
|
init();
|
|
})
|
|
}
|
|
})
|
|
} else {
|
|
[...event.dataTransfer.files].forEach(f => {
|
|
if (f.kind == "file") {
|
|
f.text().then(t => {
|
|
userdata = JSON.parse(t);
|
|
init();
|
|
})
|
|
}
|
|
})
|
|
}
|
|
document.getElementById("overlay").style.display = "none";
|
|
document.getElementById("import").style.display = "none";
|
|
}
|
|
|
|
function exportData() {
|
|
const e = document.createElement('a');
|
|
e.setAttribute('href', 'data:text/plain;charset=utf-8,' + encodeURIComponent(JSON.stringify(userdata)));
|
|
e.setAttribute('download', "Berichtsheft.json");
|
|
e.click();
|
|
}
|
|
|
|
function getIndex(n, e) {
|
|
// Find index of element (or object containing) e in nodelist n)
|
|
for (const i in n) {
|
|
if (n[i].contains(e)) {
|
|
return i;
|
|
}
|
|
}
|
|
return null;
|
|
};
|
|
function editDate(e, target) {
|
|
const page = getIndex(app.children, e);
|
|
const input = document.createElement("input");
|
|
let data = target === "meta" && userdata["meta"] || userdata["pages"][page];
|
|
input.value = getDate(data[target[1]]);
|
|
input.classList = e.classList;
|
|
input.pattern = "[0-9]{2}.[0-9]{2}.[0-9]{4}";
|
|
input.onblur = () => {
|
|
data[target[1]] = input.value.split(".").reverse().map(Number);
|
|
e.style.display = "block";
|
|
input.remove();
|
|
populate(Number(page)+1);
|
|
save();
|
|
};
|
|
e.style.display = "none";
|
|
e.insertAdjacentElement("afterend", input);
|
|
input.focus();
|
|
}
|
|
|
|
function editDayOpen(e) {
|
|
let page = getIndex(app.children, e);
|
|
let day = (page !== null && getIndex(app.children[page].querySelectorAll(".day"), e))
|
|
|
|
if (day !== null && userdata["pages"][page] !== "undefined" && userdata["pages"][page][day] !== "undefined") {
|
|
const node = templates["report_input"].content.cloneNode(true).children[0];
|
|
const data = userdata["pages"][page]["days"][day];
|
|
for (const li in [...node.querySelectorAll(".day-line")]) {
|
|
if (data.length <= li || data[li].length !== 2) {
|
|
data[li] = ["", ""];
|
|
}
|
|
const inputs = node.querySelectorAll(".day-line")[li].querySelectorAll("input");
|
|
[...inputs].forEach((input,i) => {
|
|
input.value = data[li][i];
|
|
input.onblur = () => {editDayClose(node, e, page, day)};
|
|
if (i === 1) {
|
|
input.onchange = () => {
|
|
node.querySelector(".subtotal").textContent = [...node.querySelectorAll(".sh")].reduce(
|
|
(total,e) => {
|
|
return total + Number(e.value)
|
|
}, 0) || null;
|
|
};
|
|
}
|
|
});
|
|
}
|
|
e.style.display = "none";
|
|
e.insertAdjacentElement("afterend", node);
|
|
node.querySelector("input").focus();
|
|
}
|
|
}
|
|
|
|
function editDayClose(node, onode, page, day) {
|
|
const inputs = node.querySelectorAll("input");
|
|
setTimeout(() => {
|
|
if (![...inputs].some(i=>{return document.activeElement === i})) {
|
|
for (const li in node.querySelectorAll(".day-line")) {
|
|
const data = userdata["pages"][page]["days"][day];
|
|
if (data.length > li && data[li].length === 2) {
|
|
const inputs = node.querySelectorAll(".day-line")[li].querySelectorAll("input");
|
|
[...inputs].forEach((input,i) => {
|
|
data[li][i] = input.value;
|
|
})
|
|
}
|
|
}
|
|
node.remove();
|
|
onode.style.display = "flex";
|
|
populate(Number(page)+1);
|
|
save();
|
|
}
|
|
}, 10);
|
|
}
|