diff --git a/administrace/data/katalog-26032301.xml b/administrace/data/katalog-26032301.xml
new file mode 100644
index 0000000..f976550
--- /dev/null
+++ b/administrace/data/katalog-26032301.xml
@@ -0,0 +1,44 @@
+
+
+
+
+ 2/15/300
+ 100
+ m3
+
+
+ 2/15/400
+ 110
+ m3
+
+
+ 2/15/500
+ 120
+ m3
+
+
+
+
+ 2/14/400
+ 200
+ m3
+
+
+ 2/14/500
+ 210
+ m3
+
+
+
+
+ 20/20/200
+ 300
+ m3
+
+
+ 25/25/200
+ 310
+ m3
+
+
+
diff --git a/administrace/index.html b/administrace/index.html
index 1fcc4ab..dbd5e3d 100644
--- a/administrace/index.html
+++ b/administrace/index.html
@@ -1 +1,66 @@
-HELLO WORLD
\ No newline at end of file
+
+
+
+
+
+
diff --git a/administrace/katalog.js b/administrace/katalog.js
new file mode 100644
index 0000000..5af236d
--- /dev/null
+++ b/administrace/katalog.js
@@ -0,0 +1,392 @@
+
+function katalogToXML(katalog) {
+ let xml = '
';
+
+ Object.entries(katalog).forEach(([kategorie, produkty]) => {
+ xml += ``;
+
+ Object.entries(produkty).forEach(([nazev, data]) => {
+ xml += ``;
+ Object.entries(data).forEach(([key, value]) => {
+ xml += `<${key}>${value}${key}>`;
+ });
+ xml += ``;
+ });
+
+ xml += ``;
+ });
+
+ xml += '';
+ return xml;
+}
+
+
+function xmlToKatalog(xmlString) {
+ const parser = new DOMParser();
+ const xmlDoc = parser.parseFromString(xmlString, "application/xml");
+ const katalog = {};
+
+ xmlDoc.querySelectorAll('kategorie').forEach(kat => {
+ const kNazev = kat.getAttribute('nazev');
+ katalog[kNazev] = {};
+
+ kat.querySelectorAll('produkt').forEach(prod => {
+ const pNazev = prod.getAttribute('nazev');
+ const data = {};
+
+ prod.childNodes.forEach(node => {
+ if(node.nodeType === 1) { // ELEMENT_NODE
+ const key = node.nodeName;
+ let value = node.textContent;
+ // pokus převést čísla
+ if(!isNaN(value)) value = Number(value);
+ data[key] = value;
+ }
+ });
+
+ katalog[kNazev][pNazev] = data;
+ });
+ });
+
+ return katalog;
+}
+
+function uuidv4() {
+ return "10000000-1000-4000-8000-100000000000".replace(/[018]/g, c =>
+ (+c ^ crypto.getRandomValues(new Uint8Array(1))[0] & 15 >> +c / 4).toString(16)
+ );
+}
+
+// Vypocita ceny do katalogu na zaklade zadane ceny bez DPH
+// Ceny se zaokrouhluji na koruny nahoru
+// Vsechny rozmery v katalogu jsou v cm
+function vypocitejCenu(uuid) {
+ let nazev = document.getElementById("nazev-"+uuid).value
+ // Prehodi pripadnou desetinnou carku na desetinnou tecku
+ let zakladniCenaBezDPH = document.getElementById("cena-"+uuid).value.replace(/,/,'.')
+ let mj = document.getElementById("mj-"+uuid).value
+ // Rozbije rozmery na jednotlive hodnoty, prevede na cisla, seradi vzestupne
+ let rozmery = document.getElementById("rozmery-"+uuid).value.split('/').map(Number).sort((x, y) => x - y)
+
+ let cena = {
+ "bezDPH": zakladniCenaBezDPH,
+ "sDPH": zakladniCenaBezDPH * 1.21,
+ "ks": 0
+ }
+ console.log(mj)
+
+ if (mj == "ks") {
+ cena.ks = cena.sDPH
+ }
+ // MJ = m
+ // cena je s DPH za m
+ // pouzije se pouze nejvetsi z rozmeru
+ else if (mj == "m") {
+ cena.ks = cena.sDPH/(100/rozmery.pop())
+ }
+ // MJ = m2
+ // cena je s DPH za m2
+ // zahazuje se nejmensi ze tri rozmeru
+ // vypocet je cena/(10000/(r1*r2))
+ else if (mj == "m2") {
+ cena.ks = cena.sDPH/(10000/(rozmery.pop()*rozmery.pop()))
+ }
+ // MJ = m3
+ // cena je s DPH za m3
+ // vypocet je cena/(1000000/(r1*r2*r3))
+ else if (mj == "m3") {
+ cena.ks = cena.sDPH/(1000000/(rozmery.pop()*rozmery.pop()*rozmery.pop()))
+ }
+
+ cena.bezDPH = Math.ceil(cena.bezDPH)
+ cena.sDPH= Math.ceil(cena.sDPH)
+ cena.ks = Math.ceil(cena.ks)
+ document.getElementById("cenadph-"+uuid).value = cena.sDPH
+ document.getElementById("cenaks-"+uuid).value = cena.ks
+ return cena
+}
+
+function zapniNaElementSortableJS(el) {
+ new Sortable(el, {
+ group: 'nested',
+ animation: 150,
+ fallbackOnBody: true,
+ filter: ".ignore-elements",
+ onMove: function (evt) {
+ const dragged = evt.dragged; // element, který se táhne
+ const target = evt.to; // element, kam by měl být vložen
+ const isPolozka = dragged.classList.contains('polozka'); // např. kategorie mají class 'category'
+ const targetIsKatalog = target.classList.contains('katalog'); // produkty mají class 'item'
+ // Pokud se snažíme vložit kategorii do produktu, zablokuj
+ if (! isPolozka && ! targetIsKatalog) {
+ return false; // zakáže přesun
+ }
+ return true; // jinak povolit
+ },
+ swapThreshold: 0.65
+ });
+}
+
+// Rucne vyrobit polozku
+document.addEventListener("click", function(event) {
+ if (event.target.classList.contains("pridat-polozku")) {
+ let kategorie = event.target.closest(".kategorie");
+ let seznam = kategorie.querySelector(".polozky");
+ let nova = vyrobPolozku("Nova polozka", 100, "m3", "10/10/100");
+ seznam.appendChild(nova);
+ }
+// Rucne vyrobit kategorii
+ if (event.target.classList.contains("pridat-kategorii")) {
+ //let katalog = event.target.closest(".katalog");
+ let katalog = document.getElementById("katalog")
+ let nova = vyrobKategorii("Nova Kategorie");
+ katalog.appendChild(nova)
+ //event.target.before(nova)
+ }
+ if (event.target.classList.contains("vymaz-kat")) {
+ let potvrzeni = confirm("Opravdu vymazat?")
+ if(potvrzeni) {
+ event.target.closest(".kategorie").remove()
+ }
+ }
+ if (event.target.classList.contains("vymaz")) {
+ let potvrzeni = confirm("Opravdu vymazat?")
+ if(potvrzeni) {
+ event.target.closest(".polozka").remove()
+ }
+ }
+ if(event.target.classList.contains("ulozit-katalog")) {
+ // tady se bude implementovat ulozeni katalogu do XML
+ console.log("FF")
+ console.log(document.getElementById("katalog"))
+ }
+});
+
+
+function vyrobPolozku(nazev, cena, mj, rozmery) {
+
+ let uuid = uuidv4()
+ let btnDel = document.createElement("button");
+ btnDel.className = "vymaz"
+ btnDel.textContent = "✗"
+
+ let nova = document.createElement("div");
+ nova.className = "list-group-item nested-2 polozka";
+ nova.id = uuid
+ nova.appendChild(btnDel)
+
+ let nazevPolozky = document.createElement("input")
+ nazevPolozky.setAttribute("type", "text")
+ nazevPolozky.value = nazev
+ nazevPolozky.id = "nazev-" + uuid
+
+ let rozmeryPolozky = document.createElement("input")
+ rozmeryPolozky.setAttribute("type", "text")
+ rozmeryPolozky.value = rozmery
+ rozmeryPolozky.id = "rozmery-" + uuid
+ rozmeryPolozky.setAttribute("onChange", "vypocitejCenu(this.parentElement.id)")
+
+ let cenaPolozky = document.createElement("input")
+ cenaPolozky.setAttribute("type", "text")
+ cenaPolozky.setAttribute("onChange", "vypocitejCenu(this.parentElement.id)")
+ cenaPolozky.value = cena
+ cenaPolozky.id = "cena-" + uuid
+
+ let cenaPolozkySDPH = document.createElement("input")
+ cenaPolozkySDPH.setAttribute("type", "text")
+ cenaPolozkySDPH.id = "cenadph-" + uuid
+ let cenaPolozkyKs = document.createElement("input")
+ cenaPolozkyKs.setAttribute("type", "text")
+ cenaPolozkyKs.id = "cenaks-" + uuid
+
+ let mjPolozky = document.createElement("select")
+ mjPolozky.id = "mj-" + uuid
+ mjPolozky.setAttribute("onChange", "vypocitejCenu(this.parentElement.id)")
+ let mjMoznosti = [{"klic": "m", "hodnota": "m"}, {"klic": "m2","hodnota": "m²"},{"klic": "m3","hodnota": "m³"},{"klic": "ks","hodnota": "ks"}]
+ mjMoznosti.forEach((x, index, array) => {
+ var option = document.createElement("option");
+ option.value = x.klic
+ option.text = x.hodnota
+ mjPolozky.appendChild(option);
+ });
+
+ nova.appendChild(document.createTextNode(" Nazev "));
+ nova.appendChild(nazevPolozky)
+ nova.appendChild(document.createTextNode(" Rozmery "));
+ nova.appendChild(rozmeryPolozky)
+ nova.appendChild(document.createTextNode(" MJ "));
+ nova.appendChild(mjPolozky)
+ nova.appendChild(document.createTextNode(" Cena bez DPH "));
+ nova.appendChild(cenaPolozky)
+ nova.appendChild(document.createTextNode(" Cena s DPH "));
+ nova.appendChild(cenaPolozkySDPH)
+ nova.appendChild(document.createTextNode(" Cena s DPH/ks "));
+ nova.appendChild(cenaPolozkyKs)
+
+ return nova
+}
+
+function vyrobKategorii(nazev) {
+ let uuid = uuidv4()
+ let kategorie = document.createElement("div")
+ kategorie.className = "list-group-item nested-1 kategorie"
+ let nazevKategorie = document.createElement("input")
+ nazevKategorie.setAttribute("type", "text")
+ nazevKategorie.value = nazev
+ nazevKategorie.id = "nazev-" + uuid
+ //kategorie.textContent = nazev
+ kategorie.appendChild(nazevKategorie)
+ let katProdCont = document.createElement("div")
+ katProdCont.className = "list-group nested-sortable polozky"
+ kategorie.appendChild(katProdCont)
+
+ let pridavatko = document.createElement("button");
+ pridavatko.className = "pridat-polozku"
+ pridavatko.textContent = "Pridat Polozku"
+ let btnDel = document.createElement("button");
+ btnDel.className = "vymaz-kat"
+ btnDel.textContent = "Odebrat Kategorii"
+
+ kategorie.appendChild(btnDel)
+ kategorie.appendChild(pridavatko)
+
+ zapniNaElementSortableJS(katProdCont)
+
+ return kategorie
+}
+
+function vyrobKatalog() {
+ let kat = document.createElement("div")
+ kat.className = "list-group nested-sortable katalog"
+ kat.id = "katalog"
+ zapniNaElementSortableJS(kat)
+ return kat
+}
+
+
+
+// Vygenerovat ze vzorovych dat
+// Tady se nepredpoklada dopocitani ceny s DPH a za kus
+// Cena s DPH a za kus bude ulozena v datech predem vyrobeneho katalogu
+let kata = vyrobKatalog()
+function naplnitKatalog() {
+ let potvrzeni = confirm("Nacist vybrany katalog?\r !! Neulozene zmeny budou ztraceny !!")
+ if(! potvrzeni) {
+ return
+ }
+ document.getElementById("katalog").innerHTML=""
+ let katalog = {
+ "Prkna": {
+ "Prkna 2/15/300 JCH": {
+ "rozmery": "2/15/300",
+ "cena": 100,
+ "mj": "m3"
+ },
+ "Prkna 2/15/400": {
+ "rozmery": "2/15/400",
+ "cena": 110,
+ "mj": "m3"
+ },
+ "Prkna 2/15/500": {
+ "rozmery": "2/15/500",
+ "cena": 120,
+ "mj": "m3"
+ }
+ },
+ "Palubky": {
+ "palubky 2/14/400": {
+ "rozmery": "2/14/400",
+ "cena": 200,
+ "mj": "m3"
+ },
+ "palubky 2/14/500": {
+ "rozmery": "2/14/500",
+ "cena": 210,
+ "mj": "m3"
+ }
+ },
+ "Hranoly": {
+ "hranol 20/20/200": {
+ "rozmery": "20/20/200",
+ "cena": 300,
+ "mj": "m3"
+ },
+ "hranol 25/25/200": {
+ "rozmery": "25/25/200",
+ "cena": 310,
+ "mj": "m3"
+ }
+ }
+ }
+ Object.entries(katalog).forEach(([kategorie, produkty]) => {
+ let kat = vyrobKategorii(kategorie)
+ katProdCont = kat.getElementsByClassName("polozky")[0]
+ Object.entries(produkty).forEach(([nazev, data]) => {
+ let prod = vyrobPolozku(nazev, data.cena, data.mj, data.rozmery)
+ katProdCont.appendChild(prod)
+ });
+ kata.appendChild(kat)
+ });
+
+ return kata
+}
+
+document.getElementById("telo").appendChild(kata)
+
+// let pridavatko = document.createElement("button");
+// pridavatko.className = "pridat-kategorii"
+// pridavatko.textContent = "Pridat Kategorii"
+// document.getElementById("katalog").appendChild(pridavatko)
+
+//document.getElementById("telo").appendChild(ukladatko)
+
+ // console.log(katalogToXML(katalog))
+//
+// XML='
100m3110m3120m3200m3210m3300m3310m3'
+//
+// console.log(xmlToKatalog(XML))
+
+
+
+// Tohle je GPT funkcionalita pro management souboru
+/*
+ const select = document.getElementById('fileSelect');
+ const output = document.getElementById('output');
+ const button = document.getElementById('loadBtn');
+
+ // načtení seznamu souborů
+ async function loadFileList() {
+ const res = await fetch('/api/files');
+ const files = await res.json();
+
+ // filtr jen XML (klidně to nech na backendu)
+ const xmlFiles = files.filter(f => f.name.endsWith('.xml'));
+
+ xmlFiles.forEach(file => {
+ const option = document.createElement('option');
+ option.value = file.name;
+ option.textContent = file.name;
+ select.appendChild(option);
+ });
+ }
+
+ // načtení konkrétního souboru
+ async function loadSelectedFile() {
+ const fileName = select.value;
+
+ if (!fileName) {
+ alert('Nevybral jsi soubor');
+ return;
+ }
+
+ const res = await fetch(`/api/file?name=${encodeURIComponent(fileName)}`);
+ const data = await res.text(); // XML → text
+
+ output.textContent = data;
+ }
+
+ // eventy
+ button.addEventListener('click', loadSelectedFile);
+
+ // init
+ loadFileList();*/
diff --git a/debug.php b/debug.php
deleted file mode 100644
index 7e335a6..0000000
--- a/debug.php
+++ /dev/null
@@ -1,3 +0,0 @@
-
-
-
-
Dodávka krovů
-
Naším cílem je zajistit, aby se Vaše sny mohly uskutečnit. Neváhejte nás tedy kontaktovat a my zajistíme, aby Vám sousedi Váš projekt záviděli!
Využijte formulář níže, zanechte nám na sebe kontakt. My se ozveme.
-
-
@@ -178,9 +168,6 @@ if($_POST["sendMail"]) {
$m->sendMail();
echo "Email Odeslán.";
}
-
-
-
}
?>
@@ -196,4 +183,4 @@ if($_POST["sendMail"]) {
-