/*jshint sub:true, esversion: 6, -W083 */
class Store {
constructor(title, storeID, state) {
this.items = [];
this.state = state || 'planning'; // states: planning/shopping/closed
let storeNum = $(".store").length+1;
this.title = title || "Store "+storeNum;
this.storeID = storeID || null;
let html = "";
html += "
";
html += " ";
html += "
";
html += " ";
html += "
";
html += "
";
html += "
";
// html += "
";
html += "
";
html += "
";
html += "
";
html += "
";
html += " - No items added
";
html += "
";
html += "
";
html += "
";
html += " ";
html += " ";
html += "
";
html += " ";
html += "
";
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();
});
});
/** CHANGE STATE **/
this.selector.find('.iconWrapper .page-item').on('click', ev=>{
this.selector.find('.page-item.active').removeClass('active');
$(ev.currentTarget).addClass('active');
if($(ev.currentTarget).hasClass('planningState')){
this.setState('planning');
}
else if($(ev.currentTarget).hasClass('shoppingState')){
this.setState('shopping');
}
else if($(ev.currentTarget).hasClass('closedState')){
this.setState('closed');
}
});
this.selector.find('.editStoreName').one('click', ev => { this.editNameFn(ev); });
this.selector.find('.removeStore').on('click', ev => {
if(confirm("Are you sure you want to remove this store?")){ this.removeStore(); }
});
$(function () {
$('[data-toggle="tooltip"]').tooltip();
});
}
setState(state, animTime){
animTime = animTime || 200;
let prevState = this.state;
if(state === "planning"){
this.state = "planning";
this.selector.find('.itemAmountButtons').slideDown(animTime);
this.selector.find('.itemAmountText').slideUp(animTime);
this.selector.find('.addItemFormWrapper').slideDown(animTime);
}
if(state !== "planning"){
this.selector.find('.itemAmountButtons').slideUp(animTime);
this.selector.find('.itemAmountText:not(.oneItem)').slideDown(animTime);
this.selector.find('.addItemFormWrapper').slideUp(animTime);
}
if(state === "shopping"){
this.state = "shopping";
}
if(state !== "shopping"){
}
if(state === "closed"){
this.state = "closed";
this.selector.find('.remItem').hide();
}
if(state !== "closed"){
this.selector.find('.remItem').show();
}
if(prevState !== state){
ajaxReq({ plan: 'setState', storeID: this.storeID, state: this.state });
}
}
editNameFn(ev){
if(ev.type === 'click'){
this.selector.find('.iconWrapper').hide();
// $(ev.target).parent().hide();
let headerElem = $(ev.target).parent().parent().find(".card-header");
let orgHtml = headerElem.html();
headerElem.html(""+orgHtml+"");
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); });
headerElem.find('input').first().focus();
// $("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 += "";
html += " "+text+"";
html += " "+(price*amount).toFixed(2)+"";
html += "
";
html += " ";
html += " "; // "+(this.state !== "planning"?"style='display: none;'":'')+"
html += " ";
html += " ";
if(price !== 0) {
html += " x" + price.toFixed(2) + "";
}
html += " ";
html += "
";
html += " "; // "+(this.state !== "shopping"?"style='display: none;'":'')+"
html += " Amount: "+amount+"x " + price.toFixed(2) + "";
html += "
";
html += " ";
html += "";
this.selector.find("ul.storeItems").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;
if(this.state === "planning"){
return ajaxReq({ plan: 'remItem', storeID: this.storeID, itemID: itemID, price: price })
.done(json => {
// console.log("remItem return:", json);
return that.remItemHtml(itemID);
});
}
}
remItemHtml(itemID){
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.verify();
return true;
}
setItemAmount(itemID, amount){
// console.log(itemID, amount, this.items);
this.items.forEach((item, key) => {
if(item.itemID === itemID){
this.items[key].amount = amount;
this.selector.find('#item_'+itemID+" .priceWrapper .price").html(Number(amount*this.items[key].price).toFixed(2));
}
});
if(typeof this.itemAmountDelay === "undefined"){
this.itemAmountDelay = {};
}
if(typeof this.itemAmountDelay[itemID] !== "undefined"){ clearTimeout(this.itemAmountDelay[itemID]); }
this.itemAmountDelay[itemID] = setTimeout(() => {
return ajaxReq({ plan: 'updateItemAmount', storeID: this.storeID, itemID: itemID, newAmount: amount })
.done(()=>{ this.verify(); });
}, 500);
}
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));
// SHOW if-empty MESSAGE
if(this.selector.find("li").length <= 1){
this.selector.find(".emptyList").show();
}
// BIND add/remove item amount
let that = this;
this.selector.find('.itemAmountBtn').off().on('click change', function(e){
let itemid = $(this).parent().parent().parent().attr('data-itemid');
let amountElem = $(this).parent().find('.itemAmount');
let newValue = Number(amountElem.val());
if($(this).html() === "-"){
newValue--;
}
else if($(this).html() === "+"){
newValue++;
}
if(newValue > 0 && newValue < 100){
amountElem.val(newValue);
that.setItemAmount(itemid, newValue);
let textAmountElem = $(this).parent().parent().find('.itemAmountText');
textAmountElem.find('.itemAmount').html(newValue);
if(newValue === 1){
textAmountElem.addClass('oneItem');
}
else {
textAmountElem.removeClass('oneItem');
}
}
});
// 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").each((key, val) => {
let that = this;
$(val).off().on('click', function(){
// console.log("remItem", $(this).hasClass("confirm"), $(this));
if($(this).hasClass("confirm")){
that.remItem(key+1, $(this).attr('data-itemid'), $(this).attr("data-price"));
try {
$(this).tooltip('dispose');
}
catch(ignore){}
}
else {
// console.log("remItem addClass");
$(".confirm").removeClass("confirm");
setTimeout(() => { $(this).addClass("confirm"); }, 10);
let newThat = this;
setTimeout(function(){ $(newThat).removeClass("confirm"); }, 5000);
}
});
});
$(this.selector).find(".ariaButton").off('keydown').on('keydown', function(e){
if(e.code === "Space" || e.code === "Enter"){
e.preventDefault();
$(this).trigger('click');
}
});
// Update the total-price
updateTotalPrice();
}
// 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 totalPrice = 0;
function updateTotalPrice(){
totalPrice = 0;
for(const storeKey in stores){
const store = stores[storeKey];
for(const itemKey in store.items){
totalPrice += store.items[itemKey].amount*store.items[itemKey].price;
}
}
$("#totalPrice").html(totalPrice);
}
let spaceID = 0;
function getSpaces(){
$("#stores").html("Loading...");
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 += "\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;
}
$("#stores").html("");
// console.log(json);
for(const store in json.data){
let storeKey = stores.length;
stores.push(new Store(json.data[store].name, json.data[store].plan_store_id, json.data[store].state));
for(const item in json.data[store].items){
stores[storeKey].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);
}
stores[storeKey].setState(json.data[store].state, 1);
}
updateTotalPrice();
})
.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){
if(json.message === "Not logged in"){
location.href = '../login.php';
}
else {
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);
}
}