Add/remove items from stores ++
|
@ -1 +1,2 @@
|
|||
webdata/connection.php
|
||||
temp/
|
|
@ -1,7 +1,55 @@
|
|||
:root {
|
||||
--bg-accent: #19A6A0;
|
||||
--wsTop: constant(safe-area-inset-top);
|
||||
--wsTop: env(safe-area-inset-top);
|
||||
--wsBottom: constant(safe-area-inset-bottom);
|
||||
--wsBottom: env(safe-area-inset-bottom);
|
||||
}
|
||||
|
||||
html {
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
body {
|
||||
height: 100%;
|
||||
|
||||
padding-bottom: var(--wsTop);
|
||||
/* padding-bottom: 50px; */
|
||||
|
||||
background-repeat: no-repeat;
|
||||
background-attachment: fixed;
|
||||
background-color: var(--bg-accent);
|
||||
|
||||
background-image: -o-linear-gradient(to bottom left, #eee 0%, var(--bg-accent) 100%);
|
||||
background-image: -webkit-linear-gradient(to bottom left, #eee 0%, var(--bg-accent) 100%);
|
||||
background-image: linear-gradient(to bottom left, #eee 0%, var(--bg-accent) 100%);
|
||||
}
|
||||
|
||||
.navbar {
|
||||
padding-top: var(--wsTop);
|
||||
margin-bottom: 5px;
|
||||
}
|
||||
|
||||
.card {
|
||||
margin: 5px 2px;
|
||||
margin: 5px 10px;
|
||||
}
|
||||
|
||||
#home .card {
|
||||
min-height: 250px;
|
||||
}
|
||||
|
||||
.iconWrapper {
|
||||
float: right;
|
||||
margin-top: -30px;
|
||||
margin-right: 10px;
|
||||
}
|
||||
.iconWrapper img {
|
||||
margin-left: 10px;
|
||||
}
|
||||
.iconWrapper img, .iconBtn {
|
||||
cursor: pointer;
|
||||
height: 20px;
|
||||
width: 20px;
|
||||
}
|
||||
|
||||
.card-columns .card {
|
||||
|
@ -30,18 +78,10 @@ span.price {
|
|||
.addItemForm input {
|
||||
transition: width 0.5s;
|
||||
}
|
||||
.addItemForm input:not([type="submit"]):focus {
|
||||
.addItemForm input:not([type="submit"],[type="image"]):focus {
|
||||
width: 40%;
|
||||
}
|
||||
|
||||
/*.addItemForm input {
|
||||
width: 60%;
|
||||
.addItemForm input[type="image"] {
|
||||
padding-left: 5px;
|
||||
padding-right: 5px;
|
||||
}
|
||||
|
||||
.addItemForm input[type='number'] {
|
||||
width: 20%;
|
||||
}
|
||||
|
||||
.addItemForm input[type='submit'] {
|
||||
width: 20%;
|
||||
}*/
|
||||
|
|
|
@ -0,0 +1,3 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-dash" viewBox="0 0 16 16">
|
||||
<path d="M4 8a.5.5 0 0 1 .5-.5h7a.5.5 0 0 1 0 1h-7A.5.5 0 0 1 4 8z"/>
|
||||
</svg>
|
After Width: | Height: | Size: 203 B |
Before Width: | Height: | Size: 578 B After Width: | Height: | Size: 578 B |
Before Width: | Height: | Size: 336 B After Width: | Height: | Size: 336 B |
|
@ -0,0 +1,3 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-plus" viewBox="0 0 16 16">
|
||||
<path d="M8 4a.5.5 0 0 1 .5.5v3h3a.5.5 0 0 1 0 1h-3v3a.5.5 0 0 1-1 0v-3h-3a.5.5 0 0 1 0-1h3v-3A.5.5 0 0 1 8 4z"/>
|
||||
</svg>
|
After Width: | Height: | Size: 247 B |
|
@ -0,0 +1,4 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-x-circle" viewBox="0 0 16 16">
|
||||
<path d="M8 15A7 7 0 1 1 8 1a7 7 0 0 1 0 14zm0 1A8 8 0 1 0 8 0a8 8 0 0 0 0 16z"/>
|
||||
<path d="M4.646 4.646a.5.5 0 0 1 .708 0L8 7.293l2.646-2.647a.5.5 0 0 1 .708.708L8.707 8l2.647 2.646a.5.5 0 0 1-.708.708L8 8.707l-2.646 2.647a.5.5 0 0 1-.708-.708L7.293 8 4.646 5.354a.5.5 0 0 1 0-.708z"/>
|
||||
</svg>
|
After Width: | Height: | Size: 423 B |
40
index.php
|
@ -12,37 +12,35 @@
|
|||
<script src="/js/jquery-3.5.1.min.js"></script>
|
||||
<script src="/js/bootstrap.min.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<body id="home">
|
||||
|
||||
<?php include 'webdata/navbar.php'; ?>
|
||||
|
||||
<h1 class="headline text-center">Grocery Assist</h1>
|
||||
<div class="container" style="padding-top: 5px;">
|
||||
<div class="container-sm" style="padding-top: 5px;">
|
||||
|
||||
<div class="card-group" style="text-align: center;">
|
||||
<div class="row row-cols-1 row-cols-sm-2 row-cols-md-3" style="margin: auto; max-width: 900px;"> <!-- .row-cols-lg-4 -->
|
||||
<!--<div class="row row-cols-1 row-cols-sm-2" style="margin: auto; max-width: 900px;"> <!-- .row-cols-lg-4 -->
|
||||
|
||||
<a href='/plan'>
|
||||
<div class="col mb-4" style='min-width: 100px; min-height: 200px;'>
|
||||
<div class="card h-100" style="margin: auto;">
|
||||
<img src="#" class="card-img-top" alt="Plan">
|
||||
<div class="card-body">
|
||||
<h5 class="card-title">Plan shopping</h5>
|
||||
<p class="card-text"></p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</a>
|
||||
|
||||
<div class="col mb-4" style='min-width: 100px; min-height: 200px;'>
|
||||
<div class="card h-100" style="margin: auto;">
|
||||
<img src="#" class="card-img-top" alt="Plan"></a>
|
||||
<div class="card h-100" style="">
|
||||
<a href='/plan'>
|
||||
<img src="#" class="card-img-top" alt="Plan">
|
||||
<div class="card-body">
|
||||
<h5 class="card-title">Review</h5>
|
||||
<h5 class="card-title">Plan shopping</h5>
|
||||
<p class="card-text"></p>
|
||||
</div>
|
||||
</div>
|
||||
</a>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
<div class="card h-100" style="">
|
||||
<img src="#" class="card-img-top" alt="Plan"></a>
|
||||
<div class="card-body">
|
||||
<h5 class="card-title">Review</h5>
|
||||
<p class="card-text"></p>
|
||||
</div>
|
||||
</div>
|
||||
<!-- </div> -->
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
|
190
plan/do.php
|
@ -9,34 +9,84 @@ header("Content-Type: application/json");
|
|||
$data = [];
|
||||
$returns = [];
|
||||
|
||||
if(!empty($_GET)){
|
||||
$data = $_GET;
|
||||
}
|
||||
elseif(!empty($_POST)){
|
||||
$data = $_POST;
|
||||
}
|
||||
|
||||
|
||||
foreach([$_GET, $_POST] as $request){
|
||||
if(!empty($request)){
|
||||
foreach($request as $key => $value){
|
||||
if(($data[$key] = filter($value)) === false){
|
||||
print_r($value);
|
||||
echo "Failed to sanitize: `".$key."`: ".$value." \t-\t type: ".gettype($value)."\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(!empty($data) && isset($user_id)){
|
||||
if(isset($data['plan'])){
|
||||
$sql = "SELECT * FROM plan_store WHERE `user_id` = '$user_id'";
|
||||
$result = $db->query($sql);
|
||||
|
||||
while($stores = $result->fetch_assoc()){
|
||||
|
||||
if($result2 = $db->query("SELECT * FROM plan_store_item WHERE `plan_store_id` = '$stores[plan_store_id]'")){
|
||||
|
||||
$stores['items'] = [];
|
||||
if($result2->num_rows > 0){
|
||||
$stores['items'] = $result2->fetch_all(MYSQLI_ASSOC);
|
||||
}
|
||||
if($data['plan'] == 'saveStore'){
|
||||
|
||||
if($data['storeName'] == ""){
|
||||
returns("Missing store-name value", 1);
|
||||
}
|
||||
|
||||
if( initStore($data['storeName']) ){
|
||||
returns();
|
||||
}
|
||||
else {
|
||||
returns($db->error,1);
|
||||
}
|
||||
}
|
||||
|
||||
$returns[] = $stores;
|
||||
else if($data['plan'] == 'addItem'){
|
||||
|
||||
|
||||
if(($temp = checkArgs(array("storeID"=>@$data['storeID'], "name"=>@$data['name'], "price"=>@$data['price']))) !== true){
|
||||
returns("Missing a value: $temp", 1);
|
||||
}
|
||||
|
||||
if( addItem($data['storeID'], $data['name'], $data['price']) ){
|
||||
returns();
|
||||
}
|
||||
else {
|
||||
returns($db->error,1);
|
||||
}
|
||||
}
|
||||
|
||||
else if($data['plan'] == "remItem"){
|
||||
|
||||
if(($temp = checkArgs(array("storeID"=>@$data['storeID'], "position"=>@$data['position'], "price"=>@$data['price']))) !== true){
|
||||
returns("Missing a value: $temp", 1);
|
||||
}
|
||||
|
||||
if( remItem($data['storeID'], $data['position'], $data['price']) ){
|
||||
returns();
|
||||
}
|
||||
else {
|
||||
$error = $db->error;
|
||||
if($error == ""){ $error = "No rows deleted"; }
|
||||
returns($error,1);
|
||||
}
|
||||
}
|
||||
|
||||
else {
|
||||
$sql = "SELECT * FROM plan_store WHERE `user_id` = '$user_id'";
|
||||
$result = $db->query($sql);
|
||||
|
||||
while($stores = $result->fetch_assoc()){
|
||||
|
||||
if($result2 = $db->query("SELECT * FROM plan_store_item WHERE `plan_store_id` = '$stores[plan_store_id]'")){
|
||||
|
||||
$stores['items'] = [];
|
||||
if($result2->num_rows > 0){
|
||||
$stores['items'] = $result2->fetch_all(MYSQLI_ASSOC);
|
||||
}
|
||||
}
|
||||
else {
|
||||
returns($db->error,1);
|
||||
}
|
||||
|
||||
$returns[] = $stores;
|
||||
}
|
||||
}
|
||||
|
||||
returns($returns);
|
||||
|
@ -46,8 +96,11 @@ else {
|
|||
returns("Nothing to do", 404);
|
||||
}
|
||||
|
||||
function returns($content, $code = 0){
|
||||
if($code != 0){
|
||||
returns("Fatal error!\n\nInput data:\n".print_r($data, true), 400);
|
||||
|
||||
|
||||
function returns($content = 'Success', $code = 0){
|
||||
if($code != 0 || $content == 'Success'){
|
||||
$returns['status'] = $code;
|
||||
$returns['message'] = $content;
|
||||
}
|
||||
|
@ -58,4 +111,99 @@ function returns($content, $code = 0){
|
|||
echo json_encode($returns);
|
||||
die();
|
||||
}
|
||||
|
||||
|
||||
function filter($data){
|
||||
global $db;
|
||||
|
||||
if(gettype($data) !== "array"){
|
||||
$data = trim(htmlentities(strip_tags($data)));
|
||||
|
||||
return $db->real_escape_string($data);
|
||||
}
|
||||
else if(gettype($data) == "array"){
|
||||
foreach($data as $key => $value){
|
||||
$data[$key] = filter($value);
|
||||
}
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// class Store {
|
||||
// private $storeID;
|
||||
// private $storeName;
|
||||
// private $items = [];
|
||||
|
||||
// function __construct($existing = false){
|
||||
// if($existing){
|
||||
// $sql = "INSERT INTO "
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
function checkArgs($args){
|
||||
foreach($args as $key => $arg){
|
||||
if($arg == ""){
|
||||
return $key;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
function initStore($storeName){
|
||||
global $db, $user_id;
|
||||
|
||||
// CHECK IF STORE EXISTS
|
||||
$storeCheckSql = "SELECT count(0) FROM plan_store WHERE `user_id` = '$user_id' AND `name` = '$storeName';";
|
||||
if($storeCheckRes = $db->query($storeCheckSql)){
|
||||
$matchingStores = $storeCheckRes->fetch_row()[0];
|
||||
|
||||
if($matchingStores == 1){
|
||||
$sql = "UPDATE plan_store SET null WHERE `user_id` = '$user_id' AND `name` = '$storeName';";
|
||||
}
|
||||
else if($matchingStores == 0){
|
||||
$sql = "INSERT INTO plan_store (user_id, `name`) VALUES ($user_id, '$storeName');";
|
||||
}
|
||||
else {
|
||||
return false;
|
||||
}
|
||||
|
||||
if( $db->query($sql) !== false){
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
function addItem($storeID, $name, $price){
|
||||
global $db, $user_id;
|
||||
|
||||
$insertItemSQL = "INSERT INTO plan_store_item (`plan_store_id`, `name`, `price`) VALUES ((SELECT plan_store_id FROM plan_store WHERE `user_id` = '$user_id' AND `plan_store_id` = '$storeID'), '$name', $price);";
|
||||
if($db->query($insertItemSQL)){
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
function remItem($storeID, $pos, $price){
|
||||
global $db, $user_id;
|
||||
|
||||
$verifyUserOwnershipSQL = "SELECT `plan_store_id` FROM plan_store WHERE `user_id` = '$user_id' AND `plan_store_id` = '$storeID'";
|
||||
$findRowSql = "SELECT `plan_item_id` FROM plan_store_item WHERE `plan_store_id` = ($verifyUserOwnershipSQL) LIMIT $pos, 1";
|
||||
$removeItemsql = "DELETE FROM plan_store_item WHERE `plan_item_id` = ($findRowSql) AND `price` = '$price';";
|
||||
if($db->query($removeItemsql)){
|
||||
if(mysqli_affected_rows($db) > 0){
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
|
||||
?>
|
|
@ -10,43 +10,28 @@
|
|||
<link rel="stylesheet" href="/css/index.css" type="text/css" />
|
||||
|
||||
<script src="/js/jquery-3.5.1.min.js"></script>
|
||||
<script src="//unpkg.com/@popperjs/core@2"></script>
|
||||
<script src="/js/bootstrap.min.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<body id='plan'>
|
||||
<?php include '../webdata/navbar.php'; ?>
|
||||
<h1 class="headline text-center">Grocery Assist</h1>
|
||||
<div class="container" style="padding-top: 5px; text-align: center;">
|
||||
|
||||
<div class="card-columns" id="stores" style="text-align: center;">
|
||||
<div class="" style="margin: auto; max-width: 900px;">
|
||||
|
||||
<?php
|
||||
for ($i=0; $i < 0; $i++) {
|
||||
?>
|
||||
<div class="card store" id="store<?=$i+1;?>" style="width: 18rem;">
|
||||
<div class='card-header'>Store <?=$i+1;?></div>
|
||||
<div class="card-body">
|
||||
<ul class="list-group list-group-flush">
|
||||
<?php for ($j=0; $j < random_int(1,10); $j++) {
|
||||
echo "<li class='list-group-item'><span>Item ".($j+1)."</span><span class='price'>".random_int(9,200).",-</span></li>";
|
||||
} ?>
|
||||
</ul>
|
||||
</div>
|
||||
<div class='card-footer subtotal'>Subtotal: <span class='price'>-,-</span></div>
|
||||
</div>
|
||||
<?php
|
||||
}
|
||||
?>
|
||||
|
||||
|
||||
</div>
|
||||
<hr>
|
||||
<h5>Please enable javascript for this page to work</h5>
|
||||
<hr>
|
||||
</div>
|
||||
|
||||
<button id="addStore">Add store</button>
|
||||
<br>
|
||||
<button id="addStore">Add store</button><br><br>
|
||||
<button id="refreshAll">Refresh all</button>
|
||||
|
||||
</div>
|
||||
|
||||
<script src='plan.js'></script>
|
||||
|
||||
</body>
|
||||
|
||||
</html>
|
226
plan/plan.js
|
@ -1,29 +1,36 @@
|
|||
/*jshint sub:true, esversion: 6, -W083 */
|
||||
|
||||
class Store {
|
||||
constructor(title) {
|
||||
constructor(title, storeID) {
|
||||
this.items = [];
|
||||
|
||||
title = title || "Store "+($(".store").length+1);
|
||||
let storeNum = $(".store").length+1;
|
||||
this.title = title || "Store "+storeNum;
|
||||
this.storeID = storeID || null;
|
||||
|
||||
|
||||
let html = "";
|
||||
html += "<div class='card store' style='width: 20rem;'>";
|
||||
html += " <div class='card-header'>"+title+"</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'>";
|
||||
html += " <input type='number' class='form-control newItemPrice' value='0' min='0'>";
|
||||
html += " <div class='input-group-append'>";
|
||||
html += " <input type='submit' class='form-control addItem' value='+'>";
|
||||
html += " </div>";
|
||||
html += " </form>";
|
||||
html += " </div>";
|
||||
html += " <div class='card-footer subtotal'>Subtotal: <span class='price'>-,-</span></div>";
|
||||
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");
|
||||
|
@ -32,36 +39,97 @@ class Store {
|
|||
this.selector.find(".addItemForm").on('submit', function(ev){
|
||||
ev.preventDefault();
|
||||
|
||||
if( that.addItem($(this).find('.newItemName').val(), $(this).find('.newItemPrice').val()) !== false){
|
||||
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').on('click keyup', ev => {
|
||||
if(ev.type == 'click' || ev.keyCode == 13){
|
||||
// $(ev.target).tooltip('hide').css('background-color','red');
|
||||
alert("Coming soon");
|
||||
}
|
||||
});
|
||||
|
||||
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(); });
|
||||
}
|
||||
|
||||
addItem(text, price){
|
||||
if(text.length > 0){
|
||||
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+",- <button class='remItem'>-</button></span></li>");
|
||||
this.selector.find(".emptyList").hide();
|
||||
|
||||
this.verify();
|
||||
return true;
|
||||
}
|
||||
catch(e){
|
||||
alert("Something failed. Try again.");
|
||||
console.error(e, e.stack);
|
||||
}
|
||||
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;
|
||||
}
|
||||
remItem(pos){
|
||||
|
||||
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'><img class='iconBtn' src='/icon/dash.svg' alt='-' style='height: 16px; width: 16px;' /></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);
|
||||
// remove from database here?
|
||||
|
||||
$(this.selector).find(".remItem").unbind().each((key, val) => {
|
||||
if(key == pos){
|
||||
|
@ -70,6 +138,7 @@ class Store {
|
|||
});
|
||||
|
||||
this.verify();
|
||||
return true;
|
||||
}
|
||||
verify(){
|
||||
// UPDATE TOTAL PRICE
|
||||
|
@ -78,7 +147,7 @@ class Store {
|
|||
total += item.price;
|
||||
});
|
||||
|
||||
$(this.selector).find(".subtotal .price").html(total+",-");
|
||||
$(this.selector).find(".subtotal .price").html(total.toFixed(2)+" kr");
|
||||
|
||||
// SHOW if-empty MESSAGE
|
||||
if(this.selector.find("li").length <= 1){
|
||||
|
@ -88,9 +157,38 @@ class Store {
|
|||
// BIND remove-buttons
|
||||
$(this.selector).find(".remItem").unbind().each((key, val) => {
|
||||
let that = this;
|
||||
$(val).click(function(){ that.remItem(key); });
|
||||
$(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();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
@ -100,22 +198,50 @@ $("#addStore").click(ev => {
|
|||
stores.push(new Store());
|
||||
});
|
||||
|
||||
// ADD STORE
|
||||
$("#refreshAll").click(ev => {
|
||||
stores = [];
|
||||
getStores();
|
||||
});
|
||||
|
||||
// $(document).on('ready', function(){
|
||||
$(".store").each((_1, store) => {
|
||||
// console.log(key, value);
|
||||
let totalPrice = 0;
|
||||
$(store).find("li span.price").each((_2,item) => {
|
||||
// GET STORES
|
||||
function getStores(){
|
||||
$("#stores").html("");
|
||||
|
||||
let priceStr = item.innerHTML;
|
||||
try {
|
||||
totalPrice += Number(priceStr.substr(0, priceStr.length-2));
|
||||
$.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);
|
||||
}
|
||||
catch(e){
|
||||
console.error("Failed find the number in '"+priceStr+"': "+e);
|
||||
}
|
||||
});
|
||||
$(store).find(".subtotal .price").html(totalPrice+",-");
|
||||
});
|
||||
// });
|
||||
}
|
||||
})
|
||||
.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);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,24 @@
|
|||
<?php $activePage = $_SERVER['REQUEST_URI']; if($activePage == "/index.php"){ $activePage = "/"; } ?><nav class="navbar navbar-expand-sm navbar-light bg-light" style="z-index: 2;">
|
||||
<div class="container-fluid" style="max-width: 900px;">
|
||||
<a class="navbar-brand" href="/"><img src='#' style="height: 24px;" alt='Groceries' /></a>
|
||||
<button class="navbar-toggler" type="button" data-bs-toggle="collapse"
|
||||
data-bs-target="#navbarSupportedContent" aria-controls="navbarSupportedContent" aria-expanded="false"
|
||||
aria-label="Toggle navigation">
|
||||
<span class="navbar-toggler-icon"></span>
|
||||
</button>
|
||||
<div class="collapse navbar-collapse" id="navbarSupportedContent">
|
||||
<ul class="navbar-nav me-auto mb-2 mb-sm-0">
|
||||
<?php
|
||||
$links["Home"] = "/";
|
||||
$links["Plan"] = "/plan/";
|
||||
$links["Review"] = "/review/";
|
||||
foreach($links as $title => $href){
|
||||
echo '<li class="nav-item">';
|
||||
echo '<a class="nav-link'.($activePage == $href?" active\" aria-current=\"page":"").'" href="'.$href.'">'.$title.'</a>';
|
||||
echo "</li>\n";
|
||||
}
|
||||
?>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</nav>
|