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}`; }); 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();*/