Optimize SC & add Layered Icon Descriptors (images preloaded)
604
index.html
@@ -375,7 +375,8 @@
|
|||||||
</footer> -->
|
</footer> -->
|
||||||
<img id="connectStatus" style="bottom: 15px; right: 15px; position: fixed; width: 50px;">
|
<img id="connectStatus" style="bottom: 15px; right: 15px; position: fixed; width: 50px;">
|
||||||
</main>
|
</main>
|
||||||
<img id="actionStatus" src="static/ico/statusok.png" style="z-index: 2048;margin: 0px;position: fixed;top: 50%;left: 50%;transform: translate(-50%, -50%);width: 100px;height: 100px;display: none;">
|
<img id="actionStatus" src="static/ico/statusok.png"
|
||||||
|
style="z-index: 2048;margin: 0px;position: fixed;top: 50%;left: 50%;transform: translate(-50%, -50%);width: 100px;height: 100px;display: none;">
|
||||||
<script src="static/showdown.min.js"></script>
|
<script src="static/showdown.min.js"></script>
|
||||||
<script src="static/jquery.js"></script>
|
<script src="static/jquery.js"></script>
|
||||||
<script src="static/gun.js"></script>
|
<script src="static/gun.js"></script>
|
||||||
@@ -466,7 +467,7 @@
|
|||||||
// const PUBLIC_KEY = "~cppGiuA4UFUPGTDoC-4r2izVC3F7MfpaCmF3iZdESN4.vntmjgbAVUpF_zfinYY6EKVFuuTYxh5xOrL4KmtdTmc"
|
// const PUBLIC_KEY = "~cppGiuA4UFUPGTDoC-4r2izVC3F7MfpaCmF3iZdESN4.vntmjgbAVUpF_zfinYY6EKVFuuTYxh5xOrL4KmtdTmc"
|
||||||
var TABLE = GROUPID + ":telesec.tech.eus";
|
var TABLE = GROUPID + ":telesec.tech.eus";
|
||||||
const RELAYS = [
|
const RELAYS = [
|
||||||
"https://gun-es01.tech.eus/gun",
|
// "https://gun-es01.tech.eus/gun",
|
||||||
"https://gun-es02.tech.eus/gun",
|
"https://gun-es02.tech.eus/gun",
|
||||||
"https://gun-es03.tech.eus/gun",
|
"https://gun-es03.tech.eus/gun",
|
||||||
"https://gun-es04.tech.eus/gun",
|
"https://gun-es04.tech.eus/gun",
|
||||||
@@ -528,12 +529,12 @@
|
|||||||
});
|
});
|
||||||
peerListEl.innerHTML = list.innerHTML;
|
peerListEl.innerHTML = list.innerHTML;
|
||||||
peerCountEl.innerText = peerCount;
|
peerCountEl.innerText = peerCount;
|
||||||
if (peerCount < 2){
|
if (peerCount < 2) {
|
||||||
document.getElementById("connectStatus").src = "static/ico/connect_ko.svg"
|
document.getElementById("connectStatus").src = "static/ico/connect_ko.svg"
|
||||||
gun.opt({peers: RELAYS});
|
gun.opt({ peers: RELAYS });
|
||||||
} else {
|
} else {
|
||||||
document.getElementById("connectStatus").src = "static/ico/connect_ok.svg"
|
document.getElementById("connectStatus").src = "static/ico/connect_ok.svg"
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
getPeers();
|
getPeers();
|
||||||
@@ -2101,289 +2102,334 @@
|
|||||||
};
|
};
|
||||||
},
|
},
|
||||||
index: function () {
|
index: function () {
|
||||||
var tts = false;
|
function setLayeredImages(comanda, key) {
|
||||||
var sc_nobtn = ""
|
// Base paths for each layer type (adjust paths as needed)
|
||||||
if (urlParams.get("sc_nobtn") == "yes") {
|
const basePaths = {
|
||||||
sc_nobtn = "pointer-events: none; opacity: 0.5"
|
Selección: "static/ico/layered1/",
|
||||||
|
Café: "static/ico/layered1/",
|
||||||
|
Endulzante: "static/ico/layered1/",
|
||||||
|
Cafeina: "static/ico/layered1/",
|
||||||
|
Leche: "static/ico/layered1/",
|
||||||
|
};
|
||||||
|
|
||||||
|
// Map for Selección to filenames
|
||||||
|
const selectionMap = {
|
||||||
|
"ColaCao con leche": "Selección-ColaCao.png",
|
||||||
|
"Infusión": "Selección-Infusion.png",
|
||||||
|
"Café con leche": "Selección-CaféLeche.png",
|
||||||
|
"Solo Leche": "Selección-Leche.png",
|
||||||
|
"Solo café (sin leche)": "Selección-CaféSolo.png",
|
||||||
|
};
|
||||||
|
|
||||||
|
// Start div with relative positioning for layering
|
||||||
|
let html = `<div style="position: relative; width: 200px; height: 200px; background: white; display: inline-block;">`;
|
||||||
|
|
||||||
|
// Layer 1: Selección image
|
||||||
|
const selection = comanda["Selección"];
|
||||||
|
console.log(selection)
|
||||||
|
if (selectionMap[selection]) {
|
||||||
|
html += `<img id="img1-${key}" src="${basePaths.Selección + selectionMap[selection]}" style="position: absolute; top: 0; left: 0; width: 100%; height: 100%;">`;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Layer 2: Café
|
||||||
|
if (comanda.Café) {
|
||||||
|
html += `<img id="img2-${key}" src="${basePaths.Café}Café-${comanda.Café}.png" style="position: absolute; top: 0; left: 0; width: 100%; height: 100%;">`;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Layer 3: Endulzante
|
||||||
|
if (comanda.Endulzante) {
|
||||||
|
html += `<img id="img3-${key}" src="${basePaths.Endulzante}Azucar-${comanda.Endulzante}.png" style="position: absolute; top: 0; left: 0; width: 100%; height: 100%;">`;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Layer 4: Cafeina
|
||||||
|
if (comanda.Cafeina) {
|
||||||
|
html += `<img id="img4-${key}" src="${basePaths.Cafeina}Cafeina-${comanda.Cafeina}.png" style="position: absolute; top: 0; left: 0; width: 100%; height: 100%;">`;
|
||||||
|
}
|
||||||
|
// Layer 5: Leche
|
||||||
|
if (comanda.Leche) {
|
||||||
|
html += `<img id="img5-${key}" src="${basePaths.Leche}Leche-${comanda.Leche}.png" style="position: absolute; top: 0; left: 0; width: 100%; height: 100%;">`;
|
||||||
|
}
|
||||||
|
// Layer 6: Temperatura
|
||||||
|
if (comanda.Temperatura) {
|
||||||
|
html += `<img id="img6-${key}" src="${basePaths.Leche}Temperatura-${comanda.Temperatura}.png" style="position: absolute; top: 0; left: 0; width: 100%; height: 100%;">`;
|
||||||
|
}
|
||||||
|
// Layer 7: Tamaño
|
||||||
|
if (comanda.Tamaño) {
|
||||||
|
html += `<img id="img7-${key}" src="${basePaths.Leche}Tamaño-${comanda.Tamaño}.png" style="position: absolute; top: 0; left: 0; width: 100%; height: 100%;">`;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Close div
|
||||||
|
html += "</div>";
|
||||||
|
|
||||||
|
return html;
|
||||||
}
|
}
|
||||||
setTimeout(() => {tts = true; console.log("TTS Enabled"); toastr.info("Texto a voz disponible")}, 6500)
|
|
||||||
|
|
||||||
|
var tts = false;
|
||||||
|
var sc_nobtn = "";
|
||||||
|
if (urlParams.get("sc_nobtn") == "yes") {
|
||||||
|
sc_nobtn = "pointer-events: none; opacity: 0.5";
|
||||||
|
}
|
||||||
|
setTimeout(() => {
|
||||||
|
tts = true;
|
||||||
|
console.log("TTS Enabled");
|
||||||
|
toastr.info("Texto a voz disponible");
|
||||||
|
}, 6500);
|
||||||
|
|
||||||
const tablebody = safeuuid();
|
const tablebody = safeuuid();
|
||||||
var btn_new = safeuuid();
|
var btn_new = safeuuid();
|
||||||
var tts_check = safeuuid();
|
var tts_check = safeuuid();
|
||||||
container.innerHTML = `
|
container.innerHTML = `
|
||||||
<h1>SuperCafé</h1>
|
<h1>SuperCafé</h1>
|
||||||
<button id="${btn_new}" style="${sc_nobtn};">Nueva comanda</button>
|
<button id="${btn_new}" style="${sc_nobtn};">Nueva comanda</button>
|
||||||
<br>
|
<br>
|
||||||
<label>
|
<label>
|
||||||
<b>Habilitar avisos:</b>
|
<b>Habilitar avisos:</b>
|
||||||
<input type="checkbox" id="${tts_check}" style="height: 25px;width: 25px;">
|
<input type="checkbox" id="${tts_check}" style="height: 25px;width: 25px;">
|
||||||
</label>
|
</label>
|
||||||
|
<div id="scrolltable"><table>
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th>Zona</th>
|
||||||
|
<th>Persona</th>
|
||||||
|
<th style="${sc_nobtn};">Estado</th>
|
||||||
|
<th>Comanda</th>
|
||||||
|
<th>Precio</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody id="${tablebody}"></tbody>
|
||||||
|
</table></div>
|
||||||
|
`;
|
||||||
|
|
||||||
<div id="scrolltable"><table>
|
tableScroll("#scrolltable");
|
||||||
<thead>
|
|
||||||
<tr>
|
|
||||||
<th>Zona</th>
|
|
||||||
<th>Persona</th>
|
|
||||||
<th style="${sc_nobtn};">Estado</th>
|
|
||||||
<th>Comanda</th>
|
|
||||||
<th>Precio</th>
|
|
||||||
</tr>
|
|
||||||
</thead>
|
|
||||||
<tbody id="${tablebody}">
|
|
||||||
</tbody>
|
|
||||||
</table></div>
|
|
||||||
`;
|
|
||||||
|
|
||||||
tableScroll("#scrolltable") // id="scrolltable"
|
|
||||||
var tablebody_EL = document.getElementById(tablebody);
|
var tablebody_EL = document.getElementById(tablebody);
|
||||||
var rows2 = {};
|
var rows2 = {};
|
||||||
function render() {
|
var renderedRows = {};
|
||||||
function sorter(a, b) {
|
|
||||||
if (
|
|
||||||
SC_Personas[a.Persona].Region.toUpperCase() <
|
|
||||||
SC_Personas[b.Persona].Region.toUpperCase()
|
|
||||||
) {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
if (
|
|
||||||
SC_Personas[a.Persona].Region.toUpperCase() >
|
|
||||||
SC_Personas[b.Persona].Region.toUpperCase()
|
|
||||||
) {
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
var tablebody_EL = document.getElementById(tablebody);
|
|
||||||
tablebody_EL.innerHTML = "";
|
|
||||||
var DefaultPersona = {
|
|
||||||
Foto: "static/ico/user_generic.png",
|
|
||||||
Nombre: "Desconocido??",
|
|
||||||
Puntos: "1",
|
|
||||||
Region: "SIN AULA",
|
|
||||||
Roles: "Cafe_SiCaf",
|
|
||||||
SC_Anilla: "#000000",
|
|
||||||
markdown: "Fantasma",
|
|
||||||
_key: "135733281028030249",
|
|
||||||
};
|
|
||||||
Object.values(rows2)
|
|
||||||
.sort(sorter)
|
|
||||||
.forEach((data) => {
|
|
||||||
var btn_Pedido = safeuuid();
|
|
||||||
var btn_Preparacion = safeuuid();
|
|
||||||
var btn_Hecho = safeuuid();
|
|
||||||
var btn_Entregado = safeuuid();
|
|
||||||
var btn_Deuda = safeuuid();
|
|
||||||
var btn_Pagado = safeuuid();
|
|
||||||
var span_precio = safeuuid();
|
|
||||||
var persona = SC_Personas[data.Persona] || DefaultPersona;
|
|
||||||
var new_tr = document.createElement("tr");
|
|
||||||
var pcalc = SC_priceCalc(JSON.parse(data.Comanda));
|
|
||||||
var precio = pcalc[0]
|
|
||||||
var resumen = pcalc[1]
|
|
||||||
if (persona == DefaultPersona) {
|
|
||||||
data.Persona = "135733281028030249";
|
|
||||||
}
|
|
||||||
if (sc_nobtn != "") {new_tr.style.pointerEvents = "none"}
|
|
||||||
|
|
||||||
new_tr.innerHTML = `
|
|
||||||
<td>${persona.Region.toUpperCase() || "?"}<br><br>${data.Fecha}</td>
|
|
||||||
<td class="TextBorder" style="background-color: ${persona.SC_Anilla
|
|
||||||
}; text-align: center; font-size: 17px;"><img src="${persona.Foto ||
|
|
||||||
"static/ico/user_generic.png"
|
|
||||||
}" height="50"><br> ${persona.Nombre || ""
|
|
||||||
}<br> <span style="font-size: 25px;">${persona.Puntos || "0"
|
|
||||||
} pts.</span></td>
|
|
||||||
<td style="font-size: 17px; ${sc_nobtn};">
|
|
||||||
<button id="${btn_Pedido}" class="">Pedido</button>
|
|
||||||
<br><button id="${btn_Preparacion}" class="">En preparación</button>
|
|
||||||
<br><button id="${btn_Hecho}" class="">Listo</button>
|
|
||||||
<br><button id="${btn_Entregado}" class="">Entregado</button>
|
|
||||||
<br><button id="${btn_Deuda}" class="">Deuda</button>
|
|
||||||
<br><button id="${btn_Pagado}" class="">Pagado</button></td>
|
|
||||||
<td><pre style="font-size: 17px;">${SC_parse(JSON.parse(data.Comanda)) +
|
|
||||||
"<hr>" +
|
|
||||||
data.Notas
|
|
||||||
}</pre></td>
|
|
||||||
<td><pre>${resumen}</pre><span style="font-size: 20px;" id="${span_precio}"></span></td>
|
|
||||||
`;
|
|
||||||
tablebody_EL.append(new_tr);
|
|
||||||
if (data.Estado == "Pedido") {
|
|
||||||
document.getElementById(btn_Pedido).classList = "rojo";
|
|
||||||
}
|
|
||||||
if (data.Estado == "En preparación") {
|
|
||||||
document.getElementById(btn_Preparacion).classList = "rojo";
|
|
||||||
new_tr.style.backgroundColor = "#FFCCCB";
|
|
||||||
}
|
|
||||||
if (data.Estado == "Listo") {
|
|
||||||
new_tr.style.backgroundColor = "gold";
|
|
||||||
document.getElementById(btn_Hecho).classList = "rojo";
|
|
||||||
}
|
|
||||||
if (data.Estado == "Entregado") {
|
|
||||||
document.getElementById(btn_Entregado).classList = "rojo";
|
|
||||||
new_tr.style.backgroundColor = "lightgreen";
|
|
||||||
}
|
|
||||||
if (data.Estado == "Deuda") {
|
|
||||||
document.getElementById(btn_Deuda).classList = "rojo";
|
|
||||||
new_tr.style.backgroundColor = "hotpink";
|
|
||||||
}
|
|
||||||
new_tr.onclick = () => {
|
|
||||||
setUrlHash("supercafe," + data._key);
|
|
||||||
};
|
|
||||||
if (SC_Personas[data.Persona].Puntos >= 10) {
|
|
||||||
document.getElementById(span_precio).innerHTML =
|
|
||||||
"Gratis!<br> Usando puntos";
|
|
||||||
} else {
|
|
||||||
document.getElementById(span_precio).innerHTML = `Pagando ${precio}c`
|
|
||||||
}
|
|
||||||
// Acciónes
|
|
||||||
document.getElementById(btn_Pedido).onclick = () => {
|
|
||||||
window.event.cancelBubble = true;
|
|
||||||
window.event.stopPropagation();
|
|
||||||
data.Estado = "Pedido";
|
|
||||||
var enc = SEA.encrypt(data, SECRET, (encrypted) => {
|
|
||||||
betterGunPut(
|
|
||||||
gun.get(TABLE).get("supercafe").get(data._key),
|
|
||||||
encrypted
|
|
||||||
);
|
|
||||||
toastr.success("Guardado!");
|
|
||||||
});
|
|
||||||
};
|
|
||||||
document.getElementById(btn_Preparacion).onclick = () => {
|
|
||||||
window.event.cancelBubble = true;
|
|
||||||
window.event.stopPropagation();
|
|
||||||
data.Estado = "En preparación";
|
|
||||||
var enc = SEA.encrypt(data, SECRET, (encrypted) => {
|
|
||||||
betterGunPut(
|
|
||||||
gun.get(TABLE).get("supercafe").get(data._key),
|
|
||||||
encrypted
|
|
||||||
);
|
|
||||||
toastr.success("Guardado!");
|
|
||||||
});
|
|
||||||
};
|
|
||||||
document.getElementById(btn_Hecho).onclick = () => {
|
|
||||||
window.event.cancelBubble = true;
|
|
||||||
window.event.stopPropagation();
|
|
||||||
data.Estado = "Listo";
|
|
||||||
var enc = SEA.encrypt(data, SECRET, (encrypted) => {
|
|
||||||
betterGunPut(
|
|
||||||
gun.get(TABLE).get("supercafe").get(data._key),
|
|
||||||
encrypted
|
|
||||||
);
|
|
||||||
toastr.success("Guardado!");
|
|
||||||
});
|
|
||||||
};
|
|
||||||
document.getElementById(btn_Entregado).onclick = () => {
|
|
||||||
window.event.cancelBubble = true;
|
|
||||||
window.event.stopPropagation();
|
|
||||||
data.Estado = "Entregado";
|
|
||||||
var enc = SEA.encrypt(data, SECRET, (encrypted) => {
|
|
||||||
betterGunPut(
|
|
||||||
gun.get(TABLE).get("supercafe").get(data._key),
|
|
||||||
encrypted
|
|
||||||
);
|
|
||||||
toastr.success("Guardado!");
|
|
||||||
});
|
|
||||||
};
|
|
||||||
document.getElementById(btn_Deuda).onclick = () => {
|
|
||||||
window.event.cancelBubble = true;
|
|
||||||
window.event.stopPropagation();
|
|
||||||
data.Estado = "Deuda";
|
|
||||||
var enc = SEA.encrypt(data, SECRET, (encrypted) => {
|
|
||||||
betterGunPut(
|
|
||||||
gun.get(TABLE).get("supercafe").get(data._key),
|
|
||||||
encrypted
|
|
||||||
);
|
|
||||||
toastr.success("Guardado!");
|
|
||||||
});
|
|
||||||
};
|
|
||||||
document.getElementById(btn_Pagado).onclick = () => {
|
|
||||||
window.event.cancelBubble = true;
|
|
||||||
window.event.stopPropagation();
|
|
||||||
if (!confirm("¿Quieres marcar como pagado? - Se borrara la comanda y se actualizarán los puntos.")) {return}
|
|
||||||
data.Estado = "Pagado";
|
|
||||||
betterGunPut(
|
|
||||||
gun.get(TABLE).get("supercafe").get(data._key),
|
|
||||||
null
|
|
||||||
);
|
|
||||||
//setUrlHash("personas");
|
|
||||||
//setUrlHash("supercafe");
|
|
||||||
toastr.success("Guardado!");
|
|
||||||
if (SC_Personas[data.Persona].Puntos >= 10) {
|
|
||||||
SC_Personas[data.Persona].Puntos -= 10;
|
|
||||||
toastr.success(
|
|
||||||
"¡Comada gratis para " +
|
|
||||||
SC_Personas[data.Persona].Nombre +
|
|
||||||
"!"
|
|
||||||
);
|
|
||||||
toastr.success(
|
|
||||||
"¡Comada gratis para " +
|
|
||||||
SC_Personas[data.Persona].Nombre +
|
|
||||||
"!"
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
SC_Personas[data.Persona].Puntos += 1;
|
|
||||||
toastr.success("¡Comada DE PAGO!");
|
|
||||||
}
|
|
||||||
SEA.encrypt(
|
|
||||||
SC_Personas[data.Persona],
|
|
||||||
SECRET,
|
|
||||||
(encrypted) => {
|
|
||||||
betterGunPut(
|
|
||||||
gun.get(TABLE).get("personas").get(data.Persona),
|
|
||||||
encrypted
|
|
||||||
);
|
|
||||||
}
|
|
||||||
);
|
|
||||||
};
|
|
||||||
});
|
|
||||||
}
|
|
||||||
var old = {};
|
var old = {};
|
||||||
gun
|
var old2 = {};
|
||||||
.get(TABLE)
|
|
||||||
.get("supercafe")
|
var DefaultPersona = {
|
||||||
.map()
|
Foto: "static/ico/user_generic.png",
|
||||||
.on((data, key, _msg, _ev) => {
|
Nombre: "Desconocido??",
|
||||||
EVENTLISTENER = _ev;
|
Puntos: "1",
|
||||||
//alert("sc_map_on")
|
Region: "SIN AULA",
|
||||||
function add_row(data, key) {
|
Roles: "Cafe_SiCaf",
|
||||||
if (data != null) {
|
SC_Anilla: "#000000",
|
||||||
data["_key"] = key;
|
markdown: "Fantasma",
|
||||||
console.log(old[key], data.Estado)
|
_key: "135733281028030249",
|
||||||
if (old[key] == undefined) {
|
|
||||||
old[key] = "";
|
|
||||||
}
|
|
||||||
if (old[key] != data.Estado) {
|
|
||||||
console.log("SC:Updated:", data)
|
|
||||||
if (tts && document.getElementById(tts_check).checked) {
|
|
||||||
var msg = `Comanda de ${SC_Personas[data.Persona].Region}. - ${JSON.parse(data.Comanda)["Selección"]}. - ${SC_Personas[data.Persona].Nombre}. - ${data.Estado}`
|
|
||||||
console.log("TTS: " + msg)
|
|
||||||
let utterance = new SpeechSynthesisUtterance(msg);
|
|
||||||
utterance.rate = 0.9
|
|
||||||
// utterance.voice = speechSynthesis.getVoices()[7]
|
|
||||||
speechSynthesis.speak(utterance);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
rows2[key] = data;
|
|
||||||
old[key] = data.Estado;
|
|
||||||
} else {
|
|
||||||
// console.log("delete", key);
|
|
||||||
delete rows2[key];
|
|
||||||
delete old[key];
|
|
||||||
}
|
|
||||||
render();
|
|
||||||
}
|
|
||||||
if (typeof data == "string") {
|
|
||||||
SEA.decrypt(data, SECRET, (data) => {
|
|
||||||
add_row(data, key);
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
add_row(data, key);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
document.getElementById(btn_new).onclick = () => {
|
|
||||||
setUrlHash("supercafe," + safeuuid(""));
|
|
||||||
};
|
};
|
||||||
},
|
|
||||||
|
// Sorting: Fecha desc, then Region, then Nombre
|
||||||
|
function sortRows(a, b) {
|
||||||
|
const fechaA = new Date(a.Fecha);
|
||||||
|
const fechaB = new Date(b.Fecha);
|
||||||
|
if (fechaA < fechaB) return 1;
|
||||||
|
if (fechaA > fechaB) return -1;
|
||||||
|
|
||||||
|
const regionA = (SC_Personas[a.Persona]?.Region || "").toUpperCase();
|
||||||
|
const regionB = (SC_Personas[b.Persona]?.Region || "").toUpperCase();
|
||||||
|
if (regionA < regionB) return -1;
|
||||||
|
if (regionA > regionB) return 1;
|
||||||
|
|
||||||
|
const nombreA = (SC_Personas[a.Persona]?.Nombre || "").toUpperCase();
|
||||||
|
const nombreB = (SC_Personas[b.Persona]?.Nombre || "").toUpperCase();
|
||||||
|
if (nombreA < nombreB) return -1;
|
||||||
|
if (nombreA > nombreB) return 1;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
function createRow(data) {
|
||||||
|
var persona = SC_Personas[data.Persona] || DefaultPersona;
|
||||||
|
var pcalc = SC_priceCalc(JSON.parse(data.Comanda));
|
||||||
|
var precio = pcalc[0];
|
||||||
|
var resumen = pcalc[1];
|
||||||
|
|
||||||
|
var new_tr = document.createElement("tr");
|
||||||
|
new_tr.id = "row-" + data._key;
|
||||||
|
if (sc_nobtn != "") {
|
||||||
|
new_tr.style.pointerEvents = "none";
|
||||||
|
new_tr.style.opacity = "0.5";
|
||||||
|
}
|
||||||
|
const ESTADOS = ["Pedido", "En preparación", "Listo", "Entregado", "Deuda", "Pagado"];
|
||||||
|
|
||||||
|
function createEstadoButtons(currentEstado, key) {
|
||||||
|
return ESTADOS.map(estado => {
|
||||||
|
const active = estado === currentEstado ? 'disabled class="rojo"' : '';
|
||||||
|
return `<button ${active} data-key="${key}" data-estado="${estado}" style="margin:2px;">${estado}</button><br>`;
|
||||||
|
}).join(" ");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set color for estado buttons and row background (simplified to text here)
|
||||||
|
var estadoClass = "";
|
||||||
|
var bgColor = "";
|
||||||
|
switch (data.Estado) {
|
||||||
|
case "Pedido": estadoClass = "rojo"; break;
|
||||||
|
case "En preparación": estadoClass = "rojo"; bgColor = "#FFCCCB"; break;
|
||||||
|
case "Listo": estadoClass = "rojo"; bgColor = "gold"; break;
|
||||||
|
case "Entregado": estadoClass = "rojo"; bgColor = "lightgreen"; break;
|
||||||
|
case "Deuda": estadoClass = "rojo"; bgColor = "hotpink"; break;
|
||||||
|
case "Pagado": estadoClass = ""; break;
|
||||||
|
}
|
||||||
|
new_tr.style.backgroundColor = bgColor;
|
||||||
|
|
||||||
|
new_tr.innerHTML = `
|
||||||
|
<td>${persona.Region.toUpperCase() || "?"}<br><br>${data.Fecha}</td>
|
||||||
|
<td class="TextBorder" style="background-color: ${persona.SC_Anilla}; text-align: center; font-size: 17px;">
|
||||||
|
<img src="${persona.Foto}" height="50"><br>${persona.Nombre}<br>
|
||||||
|
<span style="font-size: 25px;">${persona.Puntos} pts.</span>
|
||||||
|
</td>
|
||||||
|
<td style="font-size: 17px;">
|
||||||
|
${createEstadoButtons(data.Estado, data._key)}
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
${setLayeredImages(JSON.parse(data.Comanda), data._key)}
|
||||||
|
<pre style="font-size: 17px; display: inline-block;">${SC_parse(JSON.parse(data.Comanda))}<hr>${data.Notas}</pre>
|
||||||
|
</td>
|
||||||
|
<td><pre>${resumen}</pre>${persona.Puntos >= 10 ? "<br><span style='font-size:20px;'>Gratis! Usando puntos</span>" : `<br><span style='font-size:20px;'>Pagando ${precio}c</span>`}</td>
|
||||||
|
`;
|
||||||
|
|
||||||
|
// Add click to set URL hash
|
||||||
|
new_tr.onclick = () => {
|
||||||
|
setUrlHash("supercafe," + data._key);
|
||||||
|
};
|
||||||
|
|
||||||
|
return new_tr;
|
||||||
|
}
|
||||||
|
|
||||||
|
function insertSortedRow(tr, data) {
|
||||||
|
// Insert `tr` into `tablebody_EL` sorted per sortRows
|
||||||
|
const rows = Array.from(tablebody_EL.children);
|
||||||
|
let inserted = false;
|
||||||
|
for (let i = 0; i < rows.length; i++) {
|
||||||
|
let key = rows[i].id.replace("row-", "");
|
||||||
|
if (!rows2[key]) continue;
|
||||||
|
if (sortRows(data, rows2[key]) < 0) {
|
||||||
|
tablebody_EL.insertBefore(tr, rows[i]);
|
||||||
|
inserted = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!inserted) {
|
||||||
|
tablebody_EL.appendChild(tr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function renderRow(data) {
|
||||||
|
// Create and insert sorted row
|
||||||
|
const tr = createRow(data);
|
||||||
|
insertSortedRow(tr, data);
|
||||||
|
renderedRows[data._key] = tr;
|
||||||
|
}
|
||||||
|
|
||||||
|
function updateRow(data) {
|
||||||
|
const tr = renderedRows[data._key];
|
||||||
|
if (!tr) return;
|
||||||
|
const ESTADOS = ["Pedido", "En preparación", "Listo", "Entregado", "Deuda", "Pagado"];
|
||||||
|
|
||||||
|
function createEstadoButtons(currentEstado, key) {
|
||||||
|
return ESTADOS.map(estado => {
|
||||||
|
const active = estado === currentEstado ? 'disabled class="rojo"' : '';
|
||||||
|
return `<button ${active} data-key="${key}" data-estado="${estado}" style="margin:2px;">${estado}</button><br>`;
|
||||||
|
}).join(" ");
|
||||||
|
}
|
||||||
|
|
||||||
|
var persona = SC_Personas[data.Persona] || DefaultPersona;
|
||||||
|
var pcalc = SC_priceCalc(JSON.parse(data.Comanda));
|
||||||
|
var precio = pcalc[0];
|
||||||
|
var resumen = pcalc[1];
|
||||||
|
|
||||||
|
tr.style.pointerEvents = sc_nobtn ? "none" : "";
|
||||||
|
tr.style.opacity = sc_nobtn ? "0.5" : "";
|
||||||
|
|
||||||
|
// Update background and estado
|
||||||
|
var bgColor = "";
|
||||||
|
switch (data.Estado) {
|
||||||
|
case "Pedido": tr.style.backgroundColor = ""; break;
|
||||||
|
case "En preparación": bgColor = "#FFCCCB"; break;
|
||||||
|
case "Listo": bgColor = "gold"; break;
|
||||||
|
case "Entregado": bgColor = "lightgreen"; break;
|
||||||
|
case "Deuda": bgColor = "hotpink"; break;
|
||||||
|
case "Pagado": bgColor = ""; break;
|
||||||
|
}
|
||||||
|
tr.style.backgroundColor = bgColor;
|
||||||
|
|
||||||
|
// Update cells
|
||||||
|
tr.cells[0].innerHTML = `<p style="white-space: nowrap;">${persona.Region.toUpperCase() || "?"}<br><br>${data.Fecha}</p>`;
|
||||||
|
tr.cells[1].innerHTML = `<img src="${persona.Foto}" height="50"><br>${persona.Nombre}<br><span style="font-size: 25px;">${persona.Puntos} pts.</span>`;
|
||||||
|
tr.cells[2].innerHTML = createEstadoButtons(data.Estado, data._key);
|
||||||
|
tr.cells[3].innerHTML = `
|
||||||
|
${setLayeredImages(JSON.parse(data.Comanda), data._key)}
|
||||||
|
<pre style="font-size: 17px; display: inline-block;">${SC_parse(JSON.parse(data.Comanda))}<hr>${data.Notas}</pre>`;
|
||||||
|
tr.cells[4].innerHTML = `<pre>${resumen}</pre>${persona.Puntos >= 10 ? "<br><span style='font-size:20px;'>Gratis! Usando puntos</span>" : `<br><span style='font-size:20px;'>Pagando ${precio}c</span>`}`;
|
||||||
|
|
||||||
|
// Reposition if necessary (in case sorting keys changed)
|
||||||
|
tablebody_EL.removeChild(tr);
|
||||||
|
insertSortedRow(tr, data);
|
||||||
|
}
|
||||||
|
|
||||||
|
function speakTTS(data) {
|
||||||
|
if (tts && document.getElementById(tts_check).checked) {
|
||||||
|
var persona = SC_Personas[data.Persona] || DefaultPersona;
|
||||||
|
var comanda = JSON.parse(data.Comanda);
|
||||||
|
var msg = `Comanda de ${persona.Region}. ${comanda["Selección"]}. ${persona.Nombre}. Estado: ${data.Estado}`;
|
||||||
|
var utterance = new SpeechSynthesisUtterance(msg);
|
||||||
|
utterance.rate = 0.9;
|
||||||
|
speechSynthesis.speak(utterance);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function add_row(data, key) {
|
||||||
|
if (data != null) {
|
||||||
|
data["_key"] = key;
|
||||||
|
|
||||||
|
if (old2[key] === undefined) old2[key] = "";
|
||||||
|
if (old[key] === undefined) old[key] = "";
|
||||||
|
|
||||||
|
var estadoChanged = old[key] !== data.Estado;
|
||||||
|
var comandaChanged = old2[key] !== data.Comanda;
|
||||||
|
|
||||||
|
rows2[key] = data;
|
||||||
|
|
||||||
|
if (!renderedRows[key]) {
|
||||||
|
renderRow(data);
|
||||||
|
} else if (estadoChanged || comandaChanged) {
|
||||||
|
updateRow(data);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (estadoChanged) {
|
||||||
|
speakTTS(data);
|
||||||
|
}
|
||||||
|
|
||||||
|
old[key] = data.Estado;
|
||||||
|
old2[key] = data.Comanda;
|
||||||
|
} else {
|
||||||
|
// Remove row
|
||||||
|
if (renderedRows[key]) {
|
||||||
|
renderedRows[key].remove();
|
||||||
|
delete renderedRows[key];
|
||||||
|
}
|
||||||
|
delete rows2[key];
|
||||||
|
delete old[key];
|
||||||
|
delete old2[key];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
gun.get(TABLE).get("supercafe").map().on((data, key, _msg, _ev) => {
|
||||||
|
if (typeof data === "string") {
|
||||||
|
SEA.decrypt(data, SECRET, (decData) => {
|
||||||
|
add_row(decData, key);
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
add_row(data, key);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
document.getElementById(btn_new).onclick = () => {
|
||||||
|
SC_newCommand();
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
},
|
},
|
||||||
notificaciones: {
|
notificaciones: {
|
||||||
navcss: "btn6",
|
navcss: "btn6",
|
||||||
@@ -2639,4 +2685,4 @@
|
|||||||
</script>
|
</script>
|
||||||
</body>
|
</body>
|
||||||
|
|
||||||
</html>
|
</html>
|
||||||
BIN
static/ico/layered1/Azucar-Az. Blanco.png
Normal file
|
After Width: | Height: | Size: 4.3 KiB |
BIN
static/ico/layered1/Azucar-Az. Moreno.png
Normal file
|
After Width: | Height: | Size: 5.5 KiB |
BIN
static/ico/layered1/Azucar-Edulcorante.png
Normal file
|
After Width: | Height: | Size: 11 KiB |
BIN
static/ico/layered1/Azucar-Sacarina.png
Normal file
|
After Width: | Height: | Size: 11 KiB |
BIN
static/ico/layered1/Azucar-Sin.png
Normal file
|
After Width: | Height: | Size: 11 KiB |
BIN
static/ico/layered1/Azucar-Stevia (Gotas).png
Normal file
|
After Width: | Height: | Size: 8.6 KiB |
BIN
static/ico/layered1/Azucar-Stevia (Pastillas).png
Normal file
|
After Width: | Height: | Size: 20 KiB |
BIN
static/ico/layered1/Background.png
Normal file
|
After Width: | Height: | Size: 246 B |
BIN
static/ico/layered1/Cafeina-Con.png
Normal file
|
After Width: | Height: | Size: 24 KiB |
BIN
static/ico/layered1/Cafeina-Sin.png
Normal file
|
After Width: | Height: | Size: 27 KiB |
BIN
static/ico/layered1/Leche-Agua.png
Normal file
|
After Width: | Height: | Size: 12 KiB |
BIN
static/ico/layered1/Leche-Sin lactosa.png
Normal file
|
After Width: | Height: | Size: 11 KiB |
BIN
static/ico/layered1/Leche-Vegetal.png
Normal file
|
After Width: | Height: | Size: 11 KiB |
BIN
static/ico/layered1/Leche-de Vaca.png
Normal file
|
After Width: | Height: | Size: 14 KiB |
BIN
static/ico/layered1/Selección-CafeSolo.png
Normal file
|
After Width: | Height: | Size: 45 KiB |
BIN
static/ico/layered1/Selección-CaféLeche.png
Normal file
|
After Width: | Height: | Size: 50 KiB |
BIN
static/ico/layered1/Selección-ColaCao.png
Normal file
|
After Width: | Height: | Size: 74 KiB |
BIN
static/ico/layered1/Selección-Infusion.png
Normal file
|
After Width: | Height: | Size: 18 KiB |
BIN
static/ico/layered1/Selección-Leche.png
Normal file
|
After Width: | Height: | Size: 16 KiB |
BIN
static/ico/layered1/Tamaño-Grande.png
Normal file
|
After Width: | Height: | Size: 7.2 KiB |
BIN
static/ico/layered1/Tamaño-Pequeño.png
Normal file
|
After Width: | Height: | Size: 4.3 KiB |
BIN
static/ico/layered1/Temperatura-Caliente.png
Normal file
|
After Width: | Height: | Size: 12 KiB |
BIN
static/ico/layered1/Temperatura-Frio.png
Normal file
|
After Width: | Height: | Size: 11 KiB |
BIN
static/ico/layered1/Temperatura-Templado.png
Normal file
|
After Width: | Height: | Size: 10 KiB |