496 lines
17 KiB
JavaScript
496 lines
17 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 += " <div class='draggable' style='width: 100%; height: 10px; border-width: 1px;'></div> <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='form-control form-floating'>";
|
|
html += " <input type='text' id='newItemName0' class='form-control newItemName' placeholder='New Item Name' aria-label='New Item Name'>";
|
|
html += " <label for='newItemName0'>New Item Name</label>";
|
|
html += " </div>";
|
|
html += " <div class='form-control form-floating'>";
|
|
html += " <input type='number' id='newItemPrice0' class='form-control newItemPrice' value='0' min='0' step='.01' aria-label='Price'>";
|
|
html += " <label for='newItemPrice0'>Price</label>";
|
|
html += " </div>";
|
|
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");
|
|
|
|
this.selector.find(".addItemForm").on('submit', ev => {
|
|
ev.preventDefault();
|
|
|
|
this.addItem($(ev.target).find('.newItemName').val(), $(ev.target).find('.newItemPrice').val()).done(json => {
|
|
this.selector.find('.newItemPrice').val(0);
|
|
this.selector.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 $.ajax();
|
|
}
|
|
|
|
let that = this;
|
|
return ajaxReq({ plan: 'addItem', storeID: this.storeID, name: text, price: price })
|
|
.done(json => {
|
|
return that.addItemHtml(text, price, json['data']);
|
|
});
|
|
|
|
}
|
|
}
|
|
|
|
addItemHtml(text, price, itemID, amount){
|
|
amount = amount || 1;
|
|
try {
|
|
price = Number(price);
|
|
this.items.push({ text: text, price: price, itemID: itemID, amount: amount });
|
|
|
|
let html = "\n";
|
|
html += "<li class='list-group-item draggable' id='item_"+itemID+"' data-itemID='"+itemID+"' draggable='true'>";
|
|
html += " <span style='float: left;'>"+text+"</span>";
|
|
|
|
/*
|
|
html += " <br><span class='' style='float: left; padding: 0 10px;'>";
|
|
html += " <div class='input-group'>";
|
|
html += " <button class='btn btn-outline-danger itemAmountDown' type='button'>-</button>";
|
|
html += " <input class='form-control itemAmount' type='number' value='"+amount+"' min='0' max='99' aria-label='Amount of item' style='-webkit-appearance: none; -moz-appearance: textfield; width: 29px; padding: 0 5px;' >";
|
|
html += " <span class='input-group-text' style='padding-left: 3px; font-family: var(--bs-font-monospace);font-size: 12px;text-align: right;'>x"+price.toFixed(2)+" kr</span>";
|
|
html += " <button class='btn btn-outline-success itemAmountUp' type='button'>+</button>";
|
|
html += " </div>";
|
|
html += " </span>";
|
|
*/
|
|
html += " <span class='price'>"+price.toFixed(2)+" kr ";
|
|
html += "<img src='../icon/dash-circle.svg' alt='Remove item' class='remItem' data-itemID='"+itemID+"' data-price='"+price+"' style='height: 20px; width: 20px; cursor: pointer;'></span>";
|
|
html += "</li>";
|
|
|
|
this.selector.find("ul").append(html);
|
|
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, itemID, price){
|
|
let that = this;
|
|
|
|
return ajaxReq({ plan: 'remItem', storeID: this.storeID, itemID: itemID, price: price })
|
|
.done(json => {
|
|
// console.log("remItem return:", json);
|
|
return that.remItemHtml(itemID);
|
|
});
|
|
|
|
}
|
|
remItemHtml(itemID){
|
|
// this.items.splice(pos,1);
|
|
|
|
for(let i = 0; i < this.items.length; i++){
|
|
if(this.items[i].itemID === itemID){
|
|
this.items.splice(i,1);
|
|
break;
|
|
}
|
|
}
|
|
this.selector.find('#item_'+itemID).remove();
|
|
|
|
// $(this.selector).find(".remItem").unbind().each((key, val) => {
|
|
// if(key+1 == pos){
|
|
// $(val).parent().parent().remove();
|
|
// }
|
|
// });
|
|
|
|
this.verify();
|
|
return true;
|
|
}
|
|
|
|
setItemAmount(pos, amount){
|
|
this.items[pos].amount = amount;
|
|
|
|
this.verify();
|
|
|
|
return true;
|
|
|
|
// return ajaxReq({ plan: 'remItem', storeID: this.storeID, position: pos, price: price });
|
|
}
|
|
|
|
setItemPosition(itemID, afterID){
|
|
afterID = afterID || 0;
|
|
if(itemID !== afterID){
|
|
return ajaxReq({ plan: 'moveItem', storeID: this.storeID, itemID: itemID, afterID: afterID });
|
|
}
|
|
return false;
|
|
}
|
|
|
|
verify(){
|
|
// UPDATE TOTAL PRICE
|
|
let total = 0;
|
|
this.items.forEach(item => {
|
|
total += item.price*item.amount;
|
|
// console.log("verify - item: "+item.price+"*"+item.amount);
|
|
});
|
|
$(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 add/remove item amount
|
|
this.selector.find('.itemAmountDown').each((key, val) => {
|
|
let that = this;
|
|
$(val).unbind().click(function(){
|
|
let newValue = Number($(this).parent().find('.itemAmount').val())-1;
|
|
if(newValue > 0){
|
|
$(this).parent().find('.itemAmount').val(newValue);
|
|
// UPDATE VALUE
|
|
that.setItemAmount(key+1, newValue);
|
|
}
|
|
});
|
|
});
|
|
this.selector.find('.itemAmountUp').each((key, val) => {
|
|
let that = this;
|
|
$(val).unbind().click(function(){
|
|
let newValue = Number($(this).parent().find('.itemAmount').val())+1;
|
|
if(newValue < 100){
|
|
$(this).parent().find('.itemAmount').val(newValue);
|
|
// UPDATE VALUE
|
|
that.setItemAmount(key+1, newValue);
|
|
}
|
|
});
|
|
});
|
|
this.selector.find('.itemAmount').each((key, val) => {
|
|
$(val).unbind().on('change', function(){
|
|
let newValue = Number( console.log($(this).val()) );
|
|
// UPDATE VALUE
|
|
that.setItemAmount(key+1, newValue);
|
|
});
|
|
});
|
|
|
|
// DRAGGABLE
|
|
let draggingObj = null, dragPos = null;
|
|
this.selector.find('.draggable').unbind().on('dragstart dragover dragenter dragleave dragend', ev => {
|
|
// this.selector.find('.draggable').hammer().bind('swipe', ev => {
|
|
if(ev.type === 'dragover' || ev.type === 'dragenter'){
|
|
ev.preventDefault();
|
|
// console.log(ev);
|
|
$(ev.currentTarget).addClass('drag-over');
|
|
dragPos = ev.currentTarget;
|
|
}
|
|
else if(ev.type === 'dragstart'){
|
|
// console.log('drag start');
|
|
draggingObj = $(ev.target);
|
|
draggingObj.css('opacity', 0.2);
|
|
}
|
|
else if(ev.type === 'dragleave'){
|
|
$('.drag-over').removeClass('drag-over');
|
|
}
|
|
else if(ev.type === 'dragend'){
|
|
// console.log(draggingObj);
|
|
if(draggingObj === null){
|
|
console.warn('no object to move');
|
|
return;
|
|
}
|
|
|
|
// console.log("move object", draggingObj, "to", dragPos);
|
|
|
|
draggingObj.css('opacity', 1);
|
|
|
|
if( this.setItemPosition(draggingObj.attr('data-itemID'), $(dragPos).attr('data-itemID')) !== false){
|
|
|
|
if($(dragPos).attr('data-itemID') == null){
|
|
draggingObj.detach().insertAfter('.emptyList');
|
|
}
|
|
else {
|
|
draggingObj.detach().insertAfter(dragPos);
|
|
}
|
|
draggingObj = null;
|
|
}
|
|
|
|
$('.drag-over').removeClass('drag-over');
|
|
}
|
|
});
|
|
|
|
// BIND remove-buttons
|
|
$(this.selector).find(".remItem").unbind().each((key, val) => {
|
|
let that = this;
|
|
$(val).click(function(){
|
|
if($(this).hasClass("confirm")){
|
|
|
|
that.remItem(key+1, $(this).attr('data-itemID'), $(this).attr("data-price"));
|
|
try {
|
|
$(this).tooltip('dispose');
|
|
}
|
|
catch(ignore){}
|
|
}
|
|
else {
|
|
$(".confirm").removeClass("confirm");
|
|
|
|
$(this).addClass("confirm");
|
|
let newThat = this;
|
|
setTimeout(function(){ $(newThat).removeClass("confirm"); }, 5000);
|
|
|
|
}
|
|
});
|
|
});
|
|
}
|
|
|
|
// STORE MANIPULATION
|
|
removeStore(){
|
|
this.selector.remove();
|
|
if(this.storeID != null){
|
|
ajaxReq({ plan: 'deleteStore', storeID: this.storeID, storeName: this.title, itemsLength: this.items.length })
|
|
.done(json => {
|
|
console.log("Delete store response:",json);
|
|
});
|
|
}
|
|
}
|
|
|
|
getStoreID(){
|
|
let that = this;
|
|
|
|
return ajaxReq({ plan: 'saveStore', storeName: this.title })
|
|
.done(json => {
|
|
console.log("getStore:", json);
|
|
that.storeID = json['data'];
|
|
return that.storeID;
|
|
});
|
|
}
|
|
|
|
rename(newName){
|
|
this.title = newName;
|
|
|
|
if(this.storeID !== null){
|
|
return ajaxReq({ plan: 'renameStore', storeID: this.storeID, newName: newName });
|
|
}
|
|
|
|
// Return blank ajax as a false
|
|
return $.ajax();
|
|
}
|
|
}
|
|
|
|
var stores = [];
|
|
$("#stores").html("");
|
|
|
|
$("#addStore").click(ev => {
|
|
stores.push(new Store());
|
|
});
|
|
|
|
$("#refreshAll").click(ev => {
|
|
$(".tooltip").remove();
|
|
getStores(spaceID);
|
|
});
|
|
|
|
$("body").on('click', function(ev){
|
|
if( $(".price").find( ev.target ).length === 0){
|
|
$(".confirm").removeClass("confirm");
|
|
}
|
|
});
|
|
|
|
let spaceID = 0;
|
|
function getSpaces(){
|
|
return ajaxReq({plan: 'spaces'}).done(json => {
|
|
let optionsHtml = "";
|
|
|
|
console.log(json);
|
|
|
|
let spaceNum = 1;
|
|
for(const spaceI in json.data.spaces){
|
|
const space = json.data.spaces[spaceI];
|
|
if(spaceID === 0){
|
|
spaceID = space['space_id'];
|
|
}
|
|
let spaceName = space['space_name'] || "Space "+spaceNum;
|
|
optionsHtml += "<option value='"+space['space_id']+"'>"+spaceName+"</option>\n";
|
|
spaceNum++;
|
|
}
|
|
|
|
let spaceSelectElem = $("#spaceSelect");
|
|
spaceSelectElem
|
|
.html(optionsHtml)
|
|
.on('change', ev => {
|
|
spaceID = $(ev.target).val();
|
|
getStores(spaceID);
|
|
});
|
|
|
|
if(typeof json.data.lastSpace !== "undefined"){
|
|
spaceID = Number(json.data.lastSpace);
|
|
spaceSelectElem.val(spaceID);
|
|
}
|
|
});
|
|
|
|
|
|
}
|
|
getSpaces().done(() => { getStores(spaceID); });
|
|
|
|
// GET STORES
|
|
function getStores(spaceID){
|
|
spaceID = spaceID || 0;
|
|
|
|
$("#stores").html("");
|
|
stores = [];
|
|
|
|
let options = { plan: '' };
|
|
if(spaceID !== 0){
|
|
options = { plan: '', space: spaceID }
|
|
}
|
|
|
|
$.getJSON('do.php', options)
|
|
.done(json => {
|
|
if(handleJsonErrors(json)){
|
|
return;
|
|
}
|
|
|
|
// console.log(json);
|
|
for(const store in json.data){
|
|
let 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,
|
|
json.data[store].items[item].plan_item_id,
|
|
json.data[store].items[item].amount);
|
|
}
|
|
}
|
|
})
|
|
.fail(handleAjaxErrors);
|
|
}
|
|
|
|
|
|
function ajaxReq( data ){
|
|
if(typeof spaceID !== "undefined" && spaceID != 0){
|
|
data.space = spaceID;
|
|
}
|
|
return $.ajax({
|
|
method: "POST",
|
|
url: "do.php",
|
|
data: data,
|
|
dataType: 'JSON'
|
|
})
|
|
.done(json => {
|
|
if(handleJsonErrors(json)){
|
|
return false;
|
|
}
|
|
|
|
return true;
|
|
})
|
|
.fail(handleAjaxErrors);
|
|
}
|
|
|
|
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);
|
|
}
|
|
} |