(Hopefully) fix position of store-buttons, [WIP] check items, some bugfixes

master
Eirik Th S 2021-06-13 01:57:04 +02:00
parent 5206d3f6f6
commit 8b1e62be80
5 changed files with 105 additions and 74 deletions

View File

@ -39,9 +39,9 @@ body {
}
.iconWrapper {
float: right;
margin-top: -30px;
margin-right: 10px;
/*float: right; */
/*margin-top: -35px;*/
/*margin-right: 10px;*/
}
.iconWrapper img {
margin-left: 10px;
@ -75,6 +75,7 @@ body {
#stores .card-header {
font-weight: bold;
height: 38px;
}
.priceWrapper {
@ -116,6 +117,10 @@ body.dollars span.price::after {
text-align: center;
}
.checkedItem span {
text-decoration: line-through;
}
.addItemForm div.form-control {
transition: width 0.5s;
}

View File

@ -98,6 +98,19 @@ if(!empty($data) && isset($user_id)){
}
}
else if($data['plan'] == "checkItem"){
if(($temp = checkArgs(array("storeID"=>@$data['storeID'], "itemID"=>@$data['itemID'], "checked"=>@$data['checked']))) !== true){
returns("Missing a value: $temp", 1);
}
if( checkItem($data['storeID'], $data['itemID'], $data['checked']) ){
returns();
}
else {
returns($db->error,1);
}
}
else if($data['plan'] == "remItem"){
if(($temp = checkArgs(array("storeID"=>@$data['storeID'], "itemID"=>@$data['itemID'], "price"=>@$data['price']))) !== true){
returns("Missing a value: $temp", 1);
@ -198,7 +211,7 @@ if(!empty($data) && isset($user_id)){
while($stores = $result->fetch_assoc()){
if($result2 = $db->query("SELECT `plan_item_id`, `name`, `price`, `amount` FROM plan_store_item WHERE `plan_store_id` = '$stores[plan_store_id]' ORDER BY pos")){
if($result2 = $db->query("SELECT `plan_item_id`, `name`, `price`, `amount`, `checked` FROM plan_store_item WHERE `plan_store_id` = '$stores[plan_store_id]' ORDER BY pos")){
$stores['items'] = [];
if($result2->num_rows > 0){
@ -371,13 +384,25 @@ function addItem($storeID, $name, $price){
return false;
}
function checkItem($storeID, $itemID, $checked){
global $db, $spaceID;
$verifyUserOwnershipSQL = "SELECT `plan_store_id` FROM plan_store WHERE `space_id` = '$spaceID' AND `plan_store_id` = '$storeID'";
$findRowSql = "SELECT `plan_item_id` FROM plan_store_item WHERE `plan_store_id` = ($verifyUserOwnershipSQL) AND `plan_item_id` = '$itemID'";
$checkItemSql = "UPDATE plan_store_item SET `checked` = ".($checked?1:0)." WHERE `plan_item_id` = ($findRowSql);";
if($db->query($checkItemSql)){
return true;
}
return false;
}
function remItem($storeID, $itemID, $price){
global $db, $spaceID;
$verifyUserOwnershipSQL = "SELECT `plan_store_id` FROM plan_store WHERE `space_id` = '$spaceID' AND `plan_store_id` = '$storeID'";
$findRowSql = "SELECT `plan_item_id` FROM plan_store_item WHERE `plan_store_id` = ($verifyUserOwnershipSQL) AND `plan_item_id` = '$itemID'";
$removeItemsql = "DELETE FROM plan_store_item WHERE `plan_item_id` = ($findRowSql) AND `price` = '$price';";
if($db->query($removeItemsql) && mysqli_affected_rows($db) > 0){
$removeItemSql = "DELETE FROM plan_store_item WHERE `plan_item_id` = ($findRowSql) AND `price` = '$price';";
if($db->query($removeItemSql) && mysqli_affected_rows($db) > 0){
return true;
}
return false;

View File

@ -33,32 +33,5 @@
<script src='plan.js'></script>
<!--<div style='width: 30rem; margin: auto; margin-bottom: 100px;'>
<form action='#!' class='form-row input-group input-group-sm addItemForm'>
<div class="form-control form-floating">
<input type='text' id='newItemName0' class='form-control newItemName' placeholder='New Item Name' aria-label='New Item Name'>
<label for="newItemName0">New Item Name</label>
</div>
<div class="form-control form-floating">
<input type='number' id='newItemPrice0' class='form-control newItemPrice' value='0' min='0' step='.01' aria-label='Price'>
<label for="newItemPrice0">Price</label>
</div>
<div class='input-group-append'>
<input type='image' class='form-control addItem' src='../icon/plus.svg' alt='+'>
</div>
</form>
</div>-->
</body>
</html>

View File

@ -2,7 +2,7 @@
class Store {
constructor(title, storeID, state) {
this.items = [];
this.itemsObj = {};
this.state = state || 'planning'; // states: planning/shopping/closed
let storeNum = $(".store").length+1;
@ -11,19 +11,19 @@ class Store {
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' style='float: left; margin-top: -35px; margin-left: 1px;'>";
html += " <div class='iconWrapper' style='position: absolute; top: 1px; left: 1px;'>";
html += " <nav aria-label='State changer'><ul class='pagination'>";
html += " <li class='page-item planningState "+(this.state === 'planning'?"active":"")+"'><span class='page-link'><img src='../icon/list-check.svg' class='ariaButton' alt='Planning state' title='Planning state' data-toggle='tooltip' tabindex=0 role='button' /></span></li>";
html += " <li class='page-item shoppingState "+(this.state === 'shopping'?"active":"")+"'><span class='page-link'><img src='../icon/basket2.svg' class='ariaButton' alt='Shopping state' title='Shopping state' data-toggle='tooltip' tabindex=0 role='button' /></span></li>";
html += " <li class='page-item closedState "+(this.state === 'closed'?"active":"")+"'><span class='page-link'><img src='../icon/check-all.svg' class='ariaButton' alt='Closed state' title='Closed state' data-toggle='tooltip' tabindex=0 role='button' /></span></li>";
html += " </ul></nav>";
html += " </div>";
html += " <div class='iconWrapper'>";
html += " <div class='iconWrapper' style='position: absolute; top: 6px; right: 6px;'>";
html += " <img src='../icon/pencil-square.svg' class='editStoreName ariaButton' alt='edit name' data-toggle='tooltip' title='Edit store name' tabindex=0 role='button' />";
// html += " <img src='../icon/filter-square.svg' class='sortItems ariaButton' alt='sort items' data-toggle='tooltip' title='Sort items by appearance in store' tabindex=0 role='button' />";
html += " <img src='../icon/x-circle.svg' class='removeStore ariaButton' alt='remove store' data-toggle='tooltip' title='Remove store' tabindex=0 role='button' />";
html += " </div>";
html += " <div class='card-header'>"+this.title+"</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 storeItems'>";
html += " <li class='list-group-item emptyList'>No items added</li>";
@ -98,14 +98,18 @@ class Store {
if(state === "planning"){
this.state = "planning";
this.selector.find('.itemAmountButtons').slideDown(animTime);
this.selector.find('.itemAmountText').slideUp(animTime);
this.selector.find('li:not(.checkedItem) .itemAmountButtons').slideDown(animTime);
this.selector.find('li:not(.checkedItem) .itemAmountText').slideUp(animTime);
this.selector.find('.checkedItem .itemAmountText').slideDown(animTime);
this.selector.find('.addItemFormWrapper').slideDown(animTime);
this.selector.find('.remItem').show();
}
if(state !== "planning"){
this.selector.find('.itemAmountButtons').slideUp(animTime);
this.selector.find('.itemAmountText:not(.oneItem)').slideDown(animTime);
this.selector.find('.addItemFormWrapper').slideUp(animTime);
this.selector.find('.remItem').hide();
}
if(state === "shopping"){
@ -117,10 +121,10 @@ class Store {
if(state === "closed"){
this.state = "closed";
this.selector.find('.remItem').hide();
}
if(state !== "closed"){
this.selector.find('.remItem').show();
}
if(prevState !== state){
@ -196,21 +200,23 @@ class Store {
}
}
addItemHtml(text, price, itemID, amount){
addItemHtml(text, price, itemID, amount, checked){
amount = amount || 1;
checked = Number(checked) || 0;
try {
price = Number(price);
this.items.push({ text: text, price: price, itemID: itemID, amount: amount });
this.itemsObj[itemID] = { text: text, price: price, itemID: itemID, amount: amount, checked: checked };
let html = "\n";
html += "<li class='list-group-item draggable' id='item_"+itemID+"' data-itemid='"+itemID+"' draggable='true'>";
html += "<li class='list-group-item draggable"+(checked?' checkedItem':'')+"' id='item_"+itemID+"' data-itemid='"+itemID+"' draggable='true'>";
html += " <span style='float: left;'>"+text+"</span>";
html += " <div class='priceWrapper'><span class='price'>"+(price*amount).toFixed(2)+"</span>";
html += "<img src='../icon/dash-circle.svg' alt='Remove item' class='remItem ariaButton' data-itemID='"+itemID+"' data-price='"+price+"' style='margin-right: 3px;' tabindex='0' role='button'></div>";
html += " <span class='itemAmountWrapper' style='float: left; padding: 0 10px;'>";
html += " <div class='input-group itemAmountButtons' >"; // "+(this.state !== "planning"?"style='display: none;'":'')+"
html += " <div class='input-group itemAmountButtons' "+(this.state !== "planning" || checked?"style='display: none;'":'')+">";
html += " <button class='btn btn-outline-danger itemAmountBtn' type='button'>-</button>";
html += " <input class='form-control itemAmount itemAmountBtn' type='number' value='"+amount+"' min='0' max='99' aria-label='Amount of item' >";
if(price !== 0) {
@ -218,7 +224,7 @@ class Store {
}
html += " <button class='btn btn-outline-success itemAmountBtn' type='button'>+</button>";
html += " </div>";
html += " <div class='itemAmountText "+(amount <= 1?"oneItem":"")+"' style='display: none;'>"; // "+(this.state !== "shopping"?"style='display: none;'":'')+"
html += " <div class='itemAmountText "+(amount <= 1?"oneItem":"")+"' "+(this.state !== "shopping" || !checked?"style='display: none;'":'')+">"; //
html += " Amount: <span class='itemAmount' style='padding-left: 10px;'>"+amount+"</span>x <span class='price'>" + price.toFixed(2) + "</span>";
html += " </div>";
html += " </span>";
@ -237,27 +243,38 @@ class Store {
return false;
}
remItem(pos, itemID, price){
checkItem(itemID){
let newChecked = true;
if(this.itemsObj[itemID].checked){
newChecked = false;
}
alert("Tries to "+(newChecked?"check":"uncheck")+" an item!");
}
remItem(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);
});
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;
}
// for(let i = 0; i < this.items.length; i++){
// if(this.items[i].itemID === itemID){
// this.items.splice(i,1);
// break;
// }
// }
if(delete this.itemsObj[itemID]){
this.selector.find('#item_'+itemID).remove();
}
this.selector.find('#item_'+itemID).remove();
this.verify();
return true;
@ -265,12 +282,15 @@ class Store {
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));
}
});
// 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));
// }
// });
this.itemsObj[itemID].amount = amount;
this.selector.find('#item_'+itemID+" .priceWrapper .price").html(Number(amount*this.itemsObj[itemID].price).toFixed(2));
if(typeof this.itemAmountDelay === "undefined"){
this.itemAmountDelay = {};
@ -295,14 +315,20 @@ class Store {
verify(){
// UPDATE TOTAL PRICE
let total = 0;
this.items.forEach(item => {
// this.items.forEach(item => {
// total += item.price*item.amount;
// console.log("verify - item:' "+item.price+"*"+item.amount);
// });
for(const itemId in this.itemsObj){
let item = this.itemsObj[itemId];
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){
if(this.selector.find(".storeItems li").length <= 1){
this.selector.find(".emptyList").show();
}
@ -387,7 +413,7 @@ class Store {
// console.log("remItem", $(this).hasClass("confirm"), $(this));
if($(this).hasClass("confirm")){
that.remItem(key+1, $(this).attr('data-itemid'), $(this).attr("data-price"));
that.remItem($(this).attr('data-itemid'), $(this).attr("data-price"));
try {
$(this).tooltip('dispose');
}
@ -419,9 +445,9 @@ class Store {
removeStore(){
this.selector.remove();
if(this.storeID != null){
ajaxReq({ plan: 'deleteStore', storeID: this.storeID, storeName: this.title, itemsLength: this.items.length })
ajaxReq({ plan: 'deleteStore', storeID: this.storeID, storeName: this.title, itemsLength: Object.keys(this.itemsObj).length })
.done(json => {
console.log("Delete store response:",json);
// console.log("Delete store response:",json);
});
}
}
@ -473,8 +499,8 @@ function updateTotalPrice(){
for(const storeKey in stores){
const store = stores[storeKey];
for(const itemKey in store.items){
totalPrice += store.items[itemKey].amount*store.items[itemKey].price;
for(const itemID in store.itemsObj){
totalPrice += store.itemsObj[itemID].amount*store.itemsObj[itemID].price;
}
}
$("#totalPrice").html(totalPrice);
@ -547,7 +573,8 @@ function getStores(spaceID){
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);
json.data[store].items[item].amount,
json.data[store].items[item].checked);
}
stores[storeKey].setState(json.data[store].state, 1);
}

View File

@ -53,6 +53,7 @@ CREATE OR REPLACE TABLE plan_store_item (
`name` varchar(200) NOT NULL,
`price` decimal(8,2) NOT NULL,
`amount` tinyint(3) unsigned DEFAULT 1,
`checked` BOOLEAN default 0,
PRIMARY KEY (plan_item_id),
CONSTRAINT plan_store_item_FK FOREIGN KEY (plan_store_id) REFERENCES `plan_store`(`plan_store_id`)
) DEFAULT CHARSET=latin1 COLLATE=latin1_general_ci;