360 lines
11 KiB
JavaScript
360 lines
11 KiB
JavaScript
/*jshint sub:true, esversion: 6, -W083 */
|
||
|
||
class Store {
|
||
constructor(title, storeID) {
|
||
this.items = [];
|
||
|
||
let storeNum = $(".store").length+1;
|
||
this.title = title || "Store "+storeNum;
|
||
this.storeID = storeID || null;
|
||
|
||
|
||
let html = "";
|
||
html += "<div class='card store' style='width: 25rem; max-width: 90vw;'>";
|
||
html += " <div class='card-header'>"+this.title+"</div>";
|
||
html += " <div class='iconWrapper'>";
|
||
html += " <img src='../icon/pencil-square.svg' class='editStoreName' alt='edit name' data-toggle='tooltip' title='Edit store name' tabindex=0 role='button' />";
|
||
html += " <img src='../icon/x-circle.svg' class='removeStore' alt='remove store' data-toggle='tooltip' title='Remove store' tabindex=0 role='button' />";
|
||
html += " </div>";
|
||
html += " <div class='card-body'>";
|
||
html += " <ul class='list-group list-group-flush'>";
|
||
html += " <li class='list-group-item emptyList'>No items added</li>";
|
||
html += " </ul>";
|
||
html += " <hr>";
|
||
html += " <form action='#!' class='form-row input-group input-group-sm addItemForm'>";
|
||
html += " <input type='text' class='form-control newItemName' placeholder='New Item Name' data-toggle='tooltip' title='New Item Name' aria-label='New Item Name'>";
|
||
html += " <input type='number' class='form-control newItemPrice' value='0' min='0' step='.01' data-toggle='tooltip' title='Price' aria-label='Price'>";
|
||
html += " <div class='input-group-append'>";
|
||
html += " <input type='image' class='form-control addItem' src='../icon/plus.svg' alt='+'>";
|
||
html += " </div>";
|
||
html += " </form>";
|
||
// html += " <button class='save'>Save</button>";
|
||
html += " </div>";
|
||
html += " <div class='card-footer subtotal'>Subtotal: <span class='price'>0.00 kr</span></div>";
|
||
html += "</div>";
|
||
|
||
this.selector = $(html).appendTo("#stores");
|
||
|
||
let that = this;
|
||
this.selector.find(".addItemForm").on('submit', function(ev){
|
||
ev.preventDefault();
|
||
|
||
that.addItem($(this).find('.newItemName').val(), $(this).find('.newItemPrice').val())
|
||
.done(json => {
|
||
$(this).find('.newItemPrice').val(0);
|
||
$(this).find('.newItemName').val("").focus();
|
||
});
|
||
});
|
||
|
||
|
||
this.selector.find('.editStoreName').one('click keyup', ev => { this.editNameFn(ev); });
|
||
|
||
this.selector.find('.removeStore').on('click keyup', ev => {
|
||
if(ev.type == 'click' || ev.keyCode == 13){
|
||
if(confirm("Are you sure you want to remove this store?")){ this.removeStore(); }
|
||
}
|
||
});
|
||
|
||
$(function () {
|
||
$('[data-toggle="tooltip"]').tooltip();
|
||
});
|
||
|
||
|
||
/** DEV **/
|
||
// this.selector.find('.save').click(ev => { this.save(); });
|
||
}
|
||
|
||
editNameFn(ev){
|
||
if(ev.type == 'click' || ev.keyCode == 13){
|
||
|
||
$(ev.target).parent().hide();
|
||
|
||
let headerElem = $(ev.target).parent().parent().find(".card-header");
|
||
let orgHtml = headerElem.html();
|
||
|
||
headerElem.html("<span style='display: none;'>"+orgHtml+"</span><form action='#' class='changeNameForm'><input type='text' class='newName' value='"+orgHtml+"'><input type='image' src='../icon/pencil-square.svg'></form>");
|
||
headerElem.find(".changeNameForm").on('submit keyup', ev2 => {
|
||
if(ev2.type == "submit"){
|
||
|
||
ev2.preventDefault();
|
||
|
||
let newName = $(ev2.target).find(".newName").val();
|
||
|
||
let that = this;
|
||
this.rename(newName).done(json => {
|
||
|
||
// success
|
||
headerElem.html(newName);
|
||
that.selector.find('.iconWrapper').show();
|
||
that.selector.find('.editStoreName').one('click keyup', ev3 => { this.editNameFn(ev3); });
|
||
});
|
||
}
|
||
|
||
});
|
||
|
||
headerElem.find(".newName").on('keyup', ev3 => { this.resetEditNameFn(ev3); });
|
||
// $("body").one('click', ev3 => { this.resetEditNameFn(ev3); });
|
||
}
|
||
}
|
||
|
||
resetEditNameFn(ev){
|
||
if(
|
||
(ev.type=="keyup" && ev.keyCode === 27) ||
|
||
ev.type != "keyup"
|
||
){
|
||
// cancel
|
||
let orgHtml = this.selector.find('.card-header span').html();
|
||
this.selector.find('.card-header').html(orgHtml);
|
||
|
||
this.selector.find('.iconWrapper').show();
|
||
this.selector.find('.editStoreName').one('click keyup', ev3 => { this.editNameFn(ev3); });
|
||
|
||
}
|
||
}
|
||
|
||
addItem(text, price){
|
||
if(text.length > 0){
|
||
|
||
if(this.storeID === null){
|
||
this.getStoreID().done(json => { this.addItem(text, price); });
|
||
|
||
return;
|
||
}
|
||
|
||
let that = this;
|
||
return $.ajax({
|
||
method: "POST",
|
||
url: "do.php",
|
||
data: { plan: 'addItem', storeID: this.storeID, name: text, price: price },
|
||
dataType: 'JSON'
|
||
})
|
||
.done(json => {
|
||
if(handleJsonErrors(json)){
|
||
return false;
|
||
}
|
||
|
||
// console.log("addItem return:", json);
|
||
return that.addItemHtml(text, price);
|
||
})
|
||
.fail(handleAjaxErrors);
|
||
|
||
}
|
||
|
||
return false;
|
||
}
|
||
|
||
addItemHtml(text, price){
|
||
try {
|
||
price = Number(price);
|
||
this.items.push({ text: text, price: price });
|
||
this.selector.find("ul").append("<li class='list-group-item'><span>"+text+"</span><span class='price'>"+price.toFixed(2)+" kr <button class='remItem' data-price='"+price+"' data-toggle='tooltip' title='Remove item' style='background: url(../icon/dash.svg); height: 20px; width: 20px;'></button></span></li>");
|
||
this.selector.find(".emptyList").hide();
|
||
this.verify();
|
||
return true;
|
||
}
|
||
catch(e){
|
||
alert("Something failed. Try again.");
|
||
console.error(e, e.stack);
|
||
}
|
||
return false;
|
||
}
|
||
remItem(pos, price){
|
||
let that = this;
|
||
|
||
return $.ajax({
|
||
method: "POST",
|
||
url: "do.php",
|
||
data: { plan: 'remItem', storeID: this.storeID, position: pos, price: price },
|
||
dataType: 'JSON'
|
||
})
|
||
.done(json => {
|
||
if(handleJsonErrors(json)){
|
||
return false;
|
||
}
|
||
|
||
// console.log("remItem return:", json);
|
||
return that.remItemHtml(pos);
|
||
})
|
||
.fail(handleAjaxErrors);
|
||
|
||
}
|
||
remItemHtml(pos){
|
||
this.items.splice(pos,1);
|
||
|
||
$(this.selector).find(".remItem").unbind().each((key, val) => {
|
||
if(key == pos){
|
||
$(val).parent().parent().remove();
|
||
}
|
||
});
|
||
|
||
this.verify();
|
||
return true;
|
||
}
|
||
verify(){
|
||
// UPDATE TOTAL PRICE
|
||
let total = 0;
|
||
this.items.forEach(item => {
|
||
total += item.price;
|
||
});
|
||
|
||
$(this.selector).find(".subtotal .price").html(total.toFixed(2)+" kr");
|
||
|
||
// SHOW if-empty MESSAGE
|
||
if(this.selector.find("li").length <= 1){
|
||
this.selector.find(".emptyList").show();
|
||
}
|
||
|
||
// BIND remove-buttons
|
||
$(this.selector).find(".remItem").unbind().each((key, val) => {
|
||
let that = this;
|
||
$(val).click(function(){
|
||
that.remItem(key, $(this).attr("data-price"));
|
||
try {
|
||
$(this).tooltip('dispose');
|
||
}
|
||
catch(ignore){}
|
||
});
|
||
});
|
||
}
|
||
|
||
// save(){
|
||
// $.ajax({
|
||
// method: "POST",
|
||
// url: "do.php",
|
||
// data: { plan: 'saveStore', storeName: this.title, items: this.items },
|
||
// dataType: 'JSON'
|
||
// })
|
||
// .done(json => {
|
||
// // json = JSON.parse(body);
|
||
|
||
// if(handleJsonErrors(json)){
|
||
// return;
|
||
// }
|
||
|
||
// // console.log(json);
|
||
// })
|
||
// .fail(handleAjaxErrors);
|
||
// }
|
||
|
||
removeStore(){
|
||
this.selector.remove();
|
||
if(this.storeID != null){
|
||
$.ajax({
|
||
method: "POST",
|
||
url: "do.php",
|
||
data: { plan: 'deleteStore', storeID: this.storeID, storeName: this.title, itemsLength: this.items.length },
|
||
dataType: 'JSON'
|
||
})
|
||
.done(json => {
|
||
if(handleJsonErrors(json)){
|
||
return;
|
||
}
|
||
|
||
console.log("Delete store response:",json);
|
||
})
|
||
.fail(handleAjaxErrors);
|
||
}
|
||
}
|
||
|
||
getStoreID(){
|
||
|
||
let that = this;
|
||
|
||
return $.ajax({
|
||
method: "POST",
|
||
url: "do.php",
|
||
data: { plan: 'saveStore', storeName: this.title },
|
||
dataType: 'JSON'
|
||
})
|
||
.done(json => {
|
||
if(handleJsonErrors(json)){
|
||
return false;
|
||
}
|
||
|
||
console.log("getStore:", json);
|
||
that.storeID = json['data'];
|
||
return that.storeID;
|
||
})
|
||
.fail(handleAjaxErrors);
|
||
}
|
||
|
||
rename(newName){
|
||
|
||
if(this.storeID !== null){
|
||
|
||
return $.ajax({
|
||
method: "POST",
|
||
url: "do.php",
|
||
data: { plan: 'renameStore', storeID: this.storeID, newName: newName },
|
||
dataType: 'JSON'
|
||
})
|
||
.done(json => {
|
||
if(handleJsonErrors(json)){
|
||
return false;
|
||
}
|
||
|
||
return true;
|
||
})
|
||
.fail(handleAjaxErrors);
|
||
}
|
||
|
||
//TODO:
|
||
console.log("No store-id");
|
||
}
|
||
}
|
||
|
||
|
||
var stores = [];
|
||
|
||
$("#addStore").click(ev => {
|
||
stores.push(new Store());
|
||
});
|
||
|
||
$("#refreshAll").click(ev => {
|
||
$(".tooltip").remove();
|
||
stores = [];
|
||
getStores();
|
||
});
|
||
|
||
// GET STORES
|
||
function getStores(){
|
||
$("#stores").html("");
|
||
|
||
$.getJSON('do.php', { plan: '' })
|
||
.done(json => {
|
||
if(handleJsonErrors(json)){
|
||
return;
|
||
}
|
||
|
||
// console.log(json);
|
||
for(const store in json.data){
|
||
storeID = stores.length;
|
||
|
||
stores.push(new Store(json.data[store].name, json.data[store].plan_store_id));
|
||
for(const item in json.data[store].items){
|
||
stores[storeID].addItemHtml(json.data[store].items[item].name, json.data[store].items[item].price);
|
||
}
|
||
}
|
||
})
|
||
.fail(handleAjaxErrors);
|
||
}
|
||
getStores();
|
||
|
||
|
||
|
||
function handleJsonErrors(json){
|
||
if(typeof json.status != "undefined" && json.status != 0){
|
||
alert(json.message);
|
||
return true;
|
||
}
|
||
|
||
return false;
|
||
}
|
||
function handleAjaxErrors(jqxhr, textStatus, error){
|
||
if(textStatus === "parsererror" && jqxhr.responseText != ""){
|
||
alert("An error occured:\n"+jqxhr.responseText);
|
||
}
|
||
else {
|
||
alert("An error occured:\n"+error);
|
||
}
|
||
} |