Add shop
parent
d4309871e3
commit
c35de6ff64
@ -0,0 +1,217 @@
|
||||
/*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
var shopitems = [];
|
||||
var shopitems_flattened = [];
|
||||
var samedaydeliveryfee = 10.0;
|
||||
|
||||
function loadShopPage( {resolve, reject}) {
|
||||
app.dialog.preloader("Opening the shop...");
|
||||
apirequest(SETTINGS.apis.shopitems, [], function (resp) {
|
||||
app.dialog.close();
|
||||
shopitems = resp.items;
|
||||
samedaydeliveryfee = resp.samedaydeliveryfee;
|
||||
for (var cat in shopitems) {
|
||||
for (var i in shopitems[cat]["items"]) {
|
||||
shopitems_flattened[i] = shopitems[cat]["items"][i];
|
||||
}
|
||||
}
|
||||
resolve({
|
||||
content: compiledPages.shop({
|
||||
items: shopitems
|
||||
})
|
||||
}, {});
|
||||
}, function (error) {
|
||||
app.dialog.close();
|
||||
app.dialog.alert("Couldn't open the shop right now. Try again later.", "Whoops!");
|
||||
reject();
|
||||
});
|
||||
}
|
||||
|
||||
$("body").on("card:opened", ".shop-item-card", function () {
|
||||
app.swiper.destroy("#swiper-" + $(this).data("sku"));
|
||||
app.swiper.create("#swiper-" + $(this).data("sku"), {
|
||||
pagination: {
|
||||
el: "#swiper-pagination-" + $(this).data("sku"),
|
||||
type: "bullets"
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
var shoppingcart = {};
|
||||
|
||||
if (inStorage("shoppingcart")) {
|
||||
shoppingcart = JSON.parse(getStorage("shoppingcart"));
|
||||
}
|
||||
|
||||
function addToCart(sku, qty) {
|
||||
if (typeof qty == 'undefined') {
|
||||
qty = 1;
|
||||
}
|
||||
if (shoppingcart[sku]) {
|
||||
shoppingcart[sku] += qty;
|
||||
} else {
|
||||
shoppingcart[sku] = qty;
|
||||
}
|
||||
app.toast.show({
|
||||
icon: "<i class='far fa-cart-plus fa-2x'></i>",
|
||||
text: "Added to cart!",
|
||||
position: "center",
|
||||
horizontalPosition: "center",
|
||||
closeTimeout: 2000,
|
||||
destroyOnClose: true
|
||||
});
|
||||
updateCart();
|
||||
}
|
||||
|
||||
function removeFromCart(sku, qty) {
|
||||
// If no qty set, delete them all
|
||||
if (typeof qty == "undefined") {
|
||||
qty = 99999;
|
||||
}
|
||||
if (shoppingcart[sku]) {
|
||||
shoppingcart[sku] -= qty;
|
||||
}
|
||||
if (shoppingcart[sku] <= 0) {
|
||||
delete shoppingcart[sku];
|
||||
}
|
||||
updateCart();
|
||||
}
|
||||
|
||||
function emptyShoppingCart() {
|
||||
shoppingcart = {};
|
||||
updateCart();
|
||||
}
|
||||
|
||||
function updateCart() {
|
||||
setStorage("shoppingcart", JSON.stringify(shoppingcart));
|
||||
var totalitems = 0;
|
||||
for (var sku in shoppingcart) {
|
||||
totalitems += shoppingcart[sku];
|
||||
}
|
||||
$("#shopping-cart-items-chip-label").text(totalitems + "");
|
||||
|
||||
var cartitems = [];
|
||||
for (var sku in shoppingcart) {
|
||||
var item = shopitems_flattened[sku];
|
||||
item.qty = shoppingcart[sku];
|
||||
item.linetotal = (item.qty * item.price).toFixed(2);
|
||||
cartitems.push(item);
|
||||
}
|
||||
|
||||
$("#shoppingCartContainer").html(compiledPages.shoppingcart_fragment({
|
||||
cartitems: cartitems
|
||||
}));
|
||||
}
|
||||
|
||||
function openShopCheckout() {
|
||||
// Check if order is mailable or not by checking each item for mailability
|
||||
// Also check if all items are still in stock (cart could have sat around a while)
|
||||
var ordermailable = true;
|
||||
var orderinstock = true;
|
||||
var ordertotal = 0.0;
|
||||
var outofstockitems = [];
|
||||
for (var sku in shoppingcart) {
|
||||
if (shopitems_flattened[sku].mailable != true) {
|
||||
ordermailable = false;
|
||||
}
|
||||
if (shopitems_flattened[sku].instock != true) {
|
||||
orderinstock = false;
|
||||
outofstockitems.push(shopitems_flattened[sku].name);
|
||||
}
|
||||
ordertotal += (shopitems_flattened[sku].price * shoppingcart[sku]);
|
||||
}
|
||||
|
||||
if (!orderinstock) {
|
||||
if (outofstockitems.length == 1) {
|
||||
app.dialog.alert("The following item is out of stock. Remove it from your cart to complete your order.<br><br>" + outofstockitems[0], "Out of Stock!");
|
||||
} else {
|
||||
app.dialog.alert("The following items in your cart are out of stock. Remove them from your cart to complete your order.<br><br>" + outofstockitems.join("<br>"), "Out of Stock!");
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (ordermailable) {
|
||||
app.dialog.create({
|
||||
title: 'Checkout',
|
||||
text: "Your order can be either mailed to you (1-5 days) or delivered same-day. Either way, it will be sent to your account's address. Your saved payment method will be charged for $" + ordertotal.toFixed(2) + " plus any delivery fee when your order ships.",
|
||||
buttons: [
|
||||
{
|
||||
text: 'Mail (free)'
|
||||
},
|
||||
{
|
||||
text: 'Same-day delivery ($' + samedaydeliveryfee.toFixed(2) + ')'
|
||||
},
|
||||
{
|
||||
text: 'Cancel Checkout',
|
||||
color: "red"
|
||||
}
|
||||
],
|
||||
verticalButtons: true,
|
||||
onClick: function (dialog, index) {
|
||||
switch (index) {
|
||||
case 0:
|
||||
placeOrder("mail", ordertotal);
|
||||
break;
|
||||
case 1:
|
||||
placeOrder("courier", ordertotal + samedaydeliveryfee);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}).open();
|
||||
} else {
|
||||
app.dialog.create({
|
||||
title: 'Checkout',
|
||||
text: "Your order will be delivered to your account's address. Your saved payment method will be charged for $" + (ordertotal + samedaydeliveryfee).toFixed(2) + " (including delivery fee) when your order ships.",
|
||||
buttons: [
|
||||
{
|
||||
text: 'Confirm Order'
|
||||
},
|
||||
{
|
||||
text: 'Cancel Checkout',
|
||||
color: "red"
|
||||
}
|
||||
],
|
||||
verticalButtons: true,
|
||||
onClick: function (dialog, index) {
|
||||
switch (index) {
|
||||
case 0:
|
||||
placeOrder("courier", ordertotal + samedaydeliveryfee);
|
||||
break;
|
||||
case 1:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}).open();
|
||||
}
|
||||
}
|
||||
|
||||
function placeOrder(deliverymethod, ordertotal) {
|
||||
app.dialog.preloader("Placing order...");
|
||||
apirequest(SETTINGS.apis.shopbuy, {
|
||||
cart: JSON.stringify(shoppingcart),
|
||||
shipmethod: deliverymethod,
|
||||
total: (ordertotal * 1.0).toFixed(2),
|
||||
accountnumber: getStorage("accountnumber"),
|
||||
accountkey: getStorage("accountkey")
|
||||
}, function (resp) {
|
||||
app.dialog.close();
|
||||
if (resp.status == "ERROR") {
|
||||
app.dialog.alert(resp.msg, "Error");
|
||||
return;
|
||||
} else {
|
||||
emptyShoppingCart();
|
||||
app.dialog.alert("Your order has been received.", "Order placed!");
|
||||
app.popup.close();
|
||||
return;
|
||||
}
|
||||
}, function (error) {
|
||||
app.dialog.close();
|
||||
app.dialog.alert("Your order might not have gone through due to a network error. If you don't get a confirmation email, try again.", "Whoops!");
|
||||
})
|
||||
console.log(deliverymethod);
|
||||
console.log(shoppingcart);
|
||||
}
|
@ -0,0 +1,117 @@
|
||||
<!-- This Source Code Form is subject to the terms of the Mozilla Public
|
||||
- License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
- file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
|
||||
|
||||
<div class="page" data-name="shop">
|
||||
|
||||
<div class="navbar">
|
||||
<div class="navbar-bg"></div>
|
||||
<div class="navbar-inner">
|
||||
<div class="left">
|
||||
<a class="link back hapticbtn" href="#">
|
||||
<i class="icon icon-back"></i>
|
||||
<span class="if-not-md">Back</span>
|
||||
</a>
|
||||
</div>
|
||||
<div class="title">Shop</div>
|
||||
<div class="right">
|
||||
<a href="#" class="link hapticbtn popup-open" data-popup="#shoppingCartPopup">
|
||||
<span class="chip"><span class="chip-label" id="shopping-cart-items-chip-label">0</span></span>
|
||||
<i class="far fa-shopping-cart"></i>
|
||||
<span>Cart</span>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<div class="page-content noselect">
|
||||
<div class="row justify-content-center margin-top">
|
||||
<div class="col-100 medium-90 xlarge-75">
|
||||
<div class="row justify-content-left">
|
||||
<div class="col-100 no-margin" id="addPaymentMethodNag" style="display: none;">
|
||||
<div class="card">
|
||||
<div class="card-content text-align-center padding-half">
|
||||
<i class="fad fa-exclamation-circle fa-2x text-color-orange"></i><br>
|
||||
You need an account with a linked credit card to use the shop. <span class="taptext">Tap</span><span class="clicktext">Click</span> the button to update your account.
|
||||
<a class="button hapticbtn button-fill margin" href="/account"><i class="fas fa-user-circle"></i> My Account</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{{#each items}}
|
||||
<div class="col-100">
|
||||
<div class="block-title no-margin-bottom margin-half-top">{{category_name}}</div>
|
||||
</div>
|
||||
{{#each items}}
|
||||
<div class="col-100 small-50 large-33 no-margin">
|
||||
<div class="card card-expandable card-expandable-animate-width margin-half hapticbtn shop-item-card" id="shop-item-card-{{sku}}" data-sku="{{sku}}">
|
||||
<div class="card-content card-content-padding">
|
||||
<div class="pointercursor card-close">
|
||||
<div class="pointercursor" style="max-width: calc(100% - 2.5em);">{{name}}<br />
|
||||
<small style="opacity: 0.7">
|
||||
{{#js_if "this.price == '0.00'"}}Free{{else}}${{price}}{{/js_if}}
|
||||
{{#if instock}}{{else}} · Out of Stock{{/if}}
|
||||
</small>
|
||||
</div>
|
||||
<a href="#" class="link card-opened-fade-in pointercursor"
|
||||
style="position: absolute; right: 2em; top: calc(var(--f7-navbar-height) * 1.5);">
|
||||
<i class="fas fa-times"></i>
|
||||
</a>
|
||||
</div>
|
||||
{{#js_if "this.images.length > 0"}}
|
||||
<div style="text-align: center;" class="card-opened-fade-out card-opened-display-none">
|
||||
<img src="{{js 'this.images[0]'}}" style="max-width: 100%; max-height: 200px;"/>
|
||||
</div>
|
||||
{{/js_if}}
|
||||
<div class="card-opened-fade-in card-closed-display-none">
|
||||
{{#if instock}}
|
||||
<div class="button button-fill margin-top card-close" onclick="addToCart('{{sku}}', 1)">
|
||||
<i class="far fa-cart-plus"></i> Add to Cart
|
||||
</div>
|
||||
{{else}}
|
||||
<div class="button button-fill margin-top color-gray color-theme-gray">
|
||||
Out of Stock
|
||||
</div>
|
||||
{{/if}}
|
||||
{{#js_if "this.images.length > 0"}}
|
||||
<div class="swiper-container shop-images-swiper" data-sku="{{sku}}" id="swiper-{{sku}}">
|
||||
<div class="swiper-wrapper">
|
||||
{{#each images}}
|
||||
<div class="swiper-slide" style="display: flex; justify-content: center; align-items: center;">
|
||||
<img src="{{this}}" style="max-height: 400px; max-width: 90%;"/>
|
||||
</div>
|
||||
{{/each}}
|
||||
</div>
|
||||
<div id="swiper-pagination-{{sku}}" class="swiper-pagination"></div>
|
||||
</div>
|
||||
<br />
|
||||
{{/js_if}}
|
||||
{{description}}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{{/each}}
|
||||
{{/each}}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="popup" id="shoppingCartPopup">
|
||||
<div class="navbar">
|
||||
<div class="navbar-bg"></div>
|
||||
<div class="navbar-inner">
|
||||
<div class="left">
|
||||
<a class="link popup-close" href="#">
|
||||
<i class="icon icon-back"></i>
|
||||
<span class="if-not-md">Close</span>
|
||||
</a>
|
||||
</div>
|
||||
<div class="title">Cart</div>
|
||||
</div>
|
||||
</div>
|
||||
<div id="shoppingCartContainer">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
@ -0,0 +1,37 @@
|
||||
{{#js_if "this.cartitems.length > 0"}}
|
||||
<div class="block">
|
||||
<div class="button button-fill" onclick="openShopCheckout()">
|
||||
<i class="far fa-cash-register"></i> Go to Checkout
|
||||
</div>
|
||||
</div>
|
||||
<div class="list media-list">
|
||||
<ul>
|
||||
{{#each cartitems}}
|
||||
<li>
|
||||
<div class="item-content">
|
||||
<div class="item-media popup-close" onclick="app.card.open('#shop-item-card-{{sku}}');">
|
||||
{{#js_if "this.images.length > 0"}}
|
||||
<img src="{{js 'this.images[0]'}}" style="width: 80px;" />
|
||||
{{else}}
|
||||
<div style="width: 80px; height: 60px;"></div>
|
||||
{{/js_if}}</div>
|
||||
<div class="item-inner">
|
||||
<div class="item-title-row">
|
||||
<div class="item-title">{{name}}</div>
|
||||
<div class="item-after">{{#js_if "this.linetotal == '0.00'"}}Free{{else}}${{linetotal}}{{/js_if}}</div>
|
||||
</div>
|
||||
<div class="item-subtitle">{{#js_if "this.linetotal == '0.00'"}}Free{{else}}${{price}}{{/js_if}} x {{qty}} <div class="button button-small button-outline display-inline-block" onclick='removeFromCart("{{sku}}")'><i class="fas fa-minus-circle"></i> Remove</div></div>
|
||||
<div class="item-text">{{description}}</div>
|
||||
</div>
|
||||
</div>
|
||||
</li>
|
||||
{{/each}}
|
||||
</ul>
|
||||
</div>
|
||||
{{else}}
|
||||
<div class="block text-align-center">
|
||||
<i class="far fa-shopping-cart fa-4x"></i>
|
||||
<br /><br />
|
||||
Your cart is empty!
|
||||
</div>
|
||||
{{/js_if}}
|
Loading…
Reference in New Issue