From 78e06e511b4a985151369f320ddf3ee65e1a4cd4 Mon Sep 17 00:00:00 2001 From: Mark Moffat Date: Tue, 17 Mar 2020 16:56:04 +1030 Subject: [PATCH] Customer account page (#124) * Adding customer login & account page support * Added account link * Sorting orders on account page * Small UI fixes * Removed debugs * Added tests Co-authored-by: Mark Moffat --- lib/schemas/editCustomer.json | 3 + public/javascripts/admin.min.js | 2 +- public/javascripts/expressCart.js | 52 ++++++++ public/javascripts/expressCart.min.js | 2 +- public/stylesheets/admin.css | 2 - public/stylesheets/admin.min.css | 2 +- public/stylesheets/less/admin.less | 2 - routes/customer.js | 170 +++++++++++++++++++++--- routes/payments/adyen.js | 1 + routes/payments/authorizenet.js | 1 + routes/payments/blockonomics.js | 1 + routes/payments/instore.js | 1 + routes/payments/paypal.js | 1 + routes/payments/stripe.js | 1 + test/specs/customers.js | 44 +++++- views/layouts/layout.hbs | 13 ++ views/settings-menu.hbs | 4 +- views/themes/Cloth/customer-account.hbs | 129 ++++++++++++++++++ views/themes/Cloth/customer-login.hbs | 12 ++ 19 files changed, 411 insertions(+), 32 deletions(-) create mode 100644 views/themes/Cloth/customer-account.hbs create mode 100644 views/themes/Cloth/customer-login.hbs diff --git a/lib/schemas/editCustomer.json b/lib/schemas/editCustomer.json index 585b91e..18635db 100644 --- a/lib/schemas/editCustomer.json +++ b/lib/schemas/editCustomer.json @@ -2,6 +2,9 @@ "$id": "editCustomer", "type": "object", "properties": { + "company": { + "type": "string" + }, "email": { "type": "string", "format": "emailAddress" diff --git a/public/javascripts/admin.min.js b/public/javascripts/admin.min.js index e80ba1c..ad7bb17 100644 --- a/public/javascripts/admin.min.js +++ b/public/javascripts/admin.min.js @@ -1 +1 @@ -function globalSearch(){$("#global-search-results").empty(),$.ajax({type:"POST",url:"/admin/searchall",data:{searchValue:$("#global-search-value").val()}}).done(e=>{$("#global-search").html('');let t=!1;if(e.customers.forEach(e=>{t=!0;const a=`\n
  • \n
    \n
    Customer
    \n
    ${e.firstName} ${e.lastName}
    \n
    ${e.email}
    \n
    \n
  • `;$("#global-search-results").append(a)}),e.orders.forEach(e=>{t=!0;const a=`\n
  • \n
    \n
    Order
    \n
    ${e.orderFirstname} ${e.orderLastname}
    \n
    ${moment(e.orderDate).format("YYYY/MM/DD")}
    \n
    ${e.orderEmail}
    \n
    \n
  • `;$("#global-search-results").append(a)}),e.products.forEach(e=>{t=!0;const a=`
  • \n
    \n
    Product
    \n
    ${e.productTitle}
    \n
    ${$("#currencySymbol").val()}${numeral(e.productPrice).format("0.00")}
    \n
    \n
  • `;$("#global-search-results").append(a)}),!0===t)$("#global-search-results").removeClass("invisible");else{const e='
  • \n
    \n
    Nothing found
    \n
    \n
  • ';$("#global-search-results").append(e),$("#global-search-results").removeClass("invisible")}feather.replace()})}$(document).ready(function(){if($.ajaxSetup({headers:{"csrf-token":$('meta[name="csrfToken"]').attr("content")}}),$(document).on("click","#btnGenerateAPIkey",function(e){e.preventDefault(),$.ajax({method:"POST",url:"/admin/createApiKey"}).done(function(e){$("#apiKey").val(e.apiKey),showNotification(e.message,"success",!0)}).fail(function(e){showNotification(e.responseJSON.message,"danger")})}),$(document).on("click",".product_opt_remove",function(e){e.preventDefault();var t=$(this).closest("li").find(".opt-name").html();$.ajax({method:"POST",url:"/admin/product/removeoption",data:{productId:$("#productId").val(),optName:t}}).done(function(e){showNotification(e.message,"success",!0)}).fail(function(e){showNotification(e.responseJSON.message,"danger")})}),$(document).on("click","#product_opt_add",function(e){e.preventDefault();var t=$("#product_optName").val(),a=$("#product_optLabel").val(),o=$("#product_optType").val(),s=$("#product_optOptions").val(),i={};""!==$("#productOptions").val()&&'"{}"'!==$("#productOptions").val()&&(i=JSON.parse($("#productOptions").val()));var n='
  • ';n+='
    ',n+='
    '+t+"
    ",n+='
    '+a+"
    ",n+='
    '+o+"
    ",n+='
    '+s+"
    ",n+='
    ',n+='',n+="
  • ",$("#product_opt_wrapper").append(n),i[t]={optName:t,optLabel:a,optType:o,optOptions:$.grep(s.split(","),function(e){return 0===e||e})},$("#productOptions").val(JSON.stringify(i)),$("#product_optName").val(""),$("#product_optLabel").val(""),$("#product_optOptions").val("")}),$(document).on("click","#btnSettingsUpdate",function(e){$("#settingsForm").submit()}),$("#settingsForm").validator().on("submit",function(e){e.isDefaultPrevented()||(e.preventDefault(),$("#footerHtml_input").val($(".CodeMirror")[0].CodeMirror.getValue()),$("#googleAnalytics_input").val($(".CodeMirror")[1].CodeMirror.getValue()),$("#customCss_input").val($(".CodeMirror")[2].CodeMirror.getValue()),$.ajax({method:"POST",url:"/admin/settings/update",data:$("#settingsForm").serialize()}).done(function(e){showNotification(e.message,"success")}).fail(function(e){showNotification(e.responseJSON.message,"danger")}))}),$(document).on("click","#orderStatusUpdate",function(e){$.ajax({method:"POST",url:"/admin/order/statusupdate",data:{order_id:$("#order_id").val(),status:$("#orderStatus").val()}}).done(function(e){showNotification(e.message,"success",!0)}).fail(function(e){showNotification(e.responseJSON.message,"danger")})}),$("#userNewForm").validator().on("submit",function(e){e.isDefaultPrevented()||(e.preventDefault(),$.ajax({method:"POST",url:"/admin/user/insert",data:{usersName:$("#usersName").val(),userEmail:$("#userEmail").val(),userPassword:$("#userPassword").val()}}).done(function(e){showNotification(e.message,"success",!1,"/admin/user/edit/"+e.userId)}).fail(function(e){showNotification(e.responseJSON.message,"danger")}))}),$(".userDelete").on("click",function(){confirm("Are you sure you want to delete?")&&$.ajax({method:"POST",url:"/admin/user/delete",data:{userId:$(this).attr("data-id")}}).done(function(e){showNotification(e.message,"success",!0)}).fail(function(e){showNotification(e.responseJSON.message,"danger")})}),$("#userEditForm").validator().on("submit",function(e){e.isDefaultPrevented()||(e.preventDefault(),$.ajax({method:"POST",url:"/admin/user/update",data:{userId:$("#userId").val(),usersName:$("#usersName").val(),userEmail:$("#userEmail").val(),userPassword:$("#userPassword").val(),userAdmin:$("#userPassword").is(":checked")}}).done(function(e){showNotification(e.message,"success")}).fail(function(e){showNotification(e.responseJSON.message,"danger")}))}),$("#productNewForm").validator().on("submit",function(e){e.isDefaultPrevented()||(e.preventDefault(),""===$("#productPermalink").val()&&""!==$("#productTitle").val()&&$("#productPermalink").val(slugify($("#productTitle").val())),$.ajax({method:"POST",url:"/admin/product/insert",data:{productTitle:$("#productTitle").val(),productPrice:$("#productPrice").val(),productPublished:$("#productPublished").val(),productStock:$("#productStock").val(),productDescription:$("#productDescription").val(),productPermalink:$("#productPermalink").val(),productOptions:$("#productOptions").val(),productSubscription:$("#productSubscription").val(),productComment:$("#productComment").is(":checked"),productTags:$("#productTags").val()}}).done(function(e){showNotification(e.message,"success",!1,"/admin/product/edit/"+e.productId)}).fail(function(e){showNotification(e.responseJSON.message,"danger")}))}),$("#productEditForm").validator().on("submit",function(e){e.isDefaultPrevented()||(e.preventDefault(),""===$("#productPermalink").val()&&""!==$("#productTitle").val()&&$("#productPermalink").val(slugify($("#productTitle").val())),$.ajax({method:"POST",url:"/admin/product/update",data:{productId:$("#productId").val(),productTitle:$("#productTitle").val(),productPrice:$("#productPrice").val(),productPublished:$("#productPublished").val(),productStock:$("#productStock").val(),productDescription:$("#productDescription").val(),productPermalink:$("#productPermalink").val(),productOptions:$("#productOptions").val(),productSubscription:$("#productSubscription").val(),productComment:$("#productComment").is(":checked"),productTags:$("#productTags").val()}}).done(function(e){showNotification(e.message,"success",!0)}).fail(function(e){showNotification(e.responseJSON.message,"danger")}))}),$(".set-as-main-image").on("click",function(){$.ajax({method:"POST",url:"/admin/product/setasmainimage",data:{product_id:$("#productId").val(),productImage:$(this).attr("data-id")}}).done(function(e){showNotification(e.message,"success",!0)}).fail(function(e){showNotification(e.responseJSON.message,"danger")})}),$(".btn-delete-image").on("click",function(){confirm("Are you sure you want to delete this image?")&&$.ajax({method:"POST",url:"/admin/product/deleteimage",data:{product_id:$("#productId").val(),productImage:$(this).attr("data-id")}}).done(function(e){showNotification(e.message,"success",!0)}).fail(function(e){showNotification(e.responseJSON.message,"danger")})}),$(".btn-delete-product").on("click",function(){confirm("Are you sure you want to delete this product?")&&$.ajax({method:"POST",url:"/admin/product/delete",data:{productId:$(this).attr("data-id")}}).done(function(e){showNotification(e.message,"success",!0)}).fail(function(e){showNotification(e.responseJSON.message,"danger")})}),$(document).on("click","#validatePermalink",function(e){""!==$("#productPermalink").val()?$.ajax({method:"POST",url:"/admin/validatePermalink",data:{permalink:$("#productPermalink").val(),docId:$("#productId").val()}}).done(function(e){showNotification(e.message,"success")}).fail(function(e){showNotification(e.responseJSON.message,"danger")}):showNotification("Please enter a permalink to validate","danger")}),$(document).on("click","#btn_product_filter",function(e){""!==$("#product_filter").val()?window.location.href="/admin/products/filter/"+$("#product_filter").val():showNotification("Please enter a keyword to filter","danger")}),$(document).on("click","#btn_order_filter",function(e){""!==$("#order_filter").val()?window.location.href="/admin/orders/filter/"+$("#order_filter").val():showNotification("Please enter a keyword to filter","danger")}),$(document).on("click","#btn_customer_filter",function(e){""!==$("#customer_filter").val()?window.location.href="/admin/customers/filter/"+$("#customer_filter").val():showNotification("Please enter a keyword to filter","danger")}),$(document).on("click","#lookupCustomer",function(e){e.preventDefault(),$.ajax({method:"POST",url:"/admin/customer/lookup",data:{customerEmail:$("#customerEmail").val()}}).done(function(e){showNotification(e.message,"success"),$("#orderFirstName").val(e.customer.firstName),$("#orderLastName").val(e.customer.lastName),$("#orderAddress1").val(e.customer.address1),$("#orderAddress2").val(e.customer.address2),$("#orderCountry").val(e.customer.country),$("#orderState").val(e.customer.state),$("#orderPostcode").val(e.customer.postcode),$("#orderPhone").val(e.customer.phone)}).fail(function(e){showNotification(e.responseJSON.message,"danger")})}),$(document).on("click","#orderCreate",function(e){e.preventDefault(),0===$("#createOrderForm").validator("validate").has(".has-error").length&&$.ajax({method:"POST",url:"/admin/order/create",data:{orderStatus:$("#orderStatus").val(),email:$("#customerEmail").val(),firstName:$("#orderFirstName").val(),lastName:$("#orderLastName").val(),address1:$("#orderAddress1").val(),address2:$("#orderAddress2").val(),country:$("#orderCountry").val(),state:$("#orderState").val(),postcode:$("#orderPostcode").val(),phone:$("#orderPhone").val(),orderComment:$("#orderComment").val()}}).done(function(e){showNotification(e.message,"success"),window.location=`/admin/order/view/${e.orderId}`}).fail(function(e){showNotification(e.responseJSON.message,"danger")})}),$("#sendTestEmail").on("click",function(e){e.preventDefault(),$.ajax({method:"POST",url:"/admin/testEmail"}).done(function(e){showNotification(e,"success")}).fail(function(e){showNotification(e.responseJSON.message,"danger")})}),$(document).on("click",".orderFilterByStatus",function(e){e.preventDefault(),window.location="/admin/orders/bystatus/"+$("#orderStatusFilter").val()}),$('input[class="publishedState"]').change(function(){$.ajax({method:"POST",url:"/admin/product/publishedState",data:{id:this.id,state:this.checked}}).done(function(e){showNotification(e.message,"success")}).fail(function(e){showNotification(e.responseJSON.message,"danger")})}),$("#updateCustomer").validator().on("click",function(e){e.preventDefault(),0===$("#customer-form").validator("validate").has(".has-error").length&&$.ajax({method:"POST",url:"/admin/customer/update",data:{customerId:$("#customerId").val(),email:$("#email").val(),firstName:$("#firstName").val(),lastName:$("#lastName").val(),address1:$("#address1").val(),address2:$("#address2").val(),country:$("#country").val(),state:$("#state").val(),postcode:$("#postcode").val(),phone:$("#phone").val()}}).done(function(e){showNotification(e.message,"success")}).fail(function(e){showNotification(e.responseJSON.message,"danger")})}),$("#deleteCustomer").on("click",function(e){e.preventDefault(),$.ajax({method:"DELETE",url:"/admin/customer",data:{customerId:$("#customerId").val()}}).done(function(e){showNotification(e.message,"success",!1,"/admin/customers")}).fail(function(e){showNotification(e.responseJSON.message,"danger")})}),$("#footerHtml").length){var e=window.CodeMirror.fromTextArea(document.getElementById("footerHtml"),{mode:"xml",tabMode:"indent",theme:"flatly",lineNumbers:!0,htmlMode:!0,fixedGutter:!1});e.setValue(e.getValue())}if($("#googleAnalytics").length&&window.CodeMirror.fromTextArea(document.getElementById("googleAnalytics"),{mode:"xml",tabMode:"indent",theme:"flatly",lineNumbers:!0,htmlMode:!0,fixedGutter:!1}),$("#customCss").length){var t=window.CodeMirror.fromTextArea(document.getElementById("customCss"),{mode:"text/css",tabMode:"indent",theme:"flatly",lineNumbers:!0}),a=window.cssbeautify(t.getValue(),{indent:" ",autosemicolon:!0});t.setValue(a)}$(document).on("click","#btnPageUpdate",function(e){e.preventDefault(),$.ajax({method:"POST",url:"/admin/settings/page",data:{pageId:$("#pageId").val(),pageName:$("#pageName").val(),pageSlug:$("#pageSlug").val(),pageEnabled:$("#pageEnabled").is(":checked"),pageContent:$("#pageContent").val()}}).done(function(e){showNotification(e.message,"success",!0)}).fail(function(e){showNotification(e.responseJSON.message,"danger")})}),$(document).on("click","#btnPageDelete",function(e){e.preventDefault(),confirm("Are you sure?")&&$.ajax({method:"POST",url:"/admin/settings/page/delete",data:{pageId:$(this).attr("data-id")}}).done(function(e){showNotification(e.message,"success",!0)}).fail(function(e){showNotification(e.message,"danger",!0)})}),$("#discountNewForm").validator().on("submit",function(e){e.isDefaultPrevented()||(e.preventDefault(),$.ajax({method:"POST",url:"/admin/settings/discount/create",data:{code:$("#discountCode").val(),type:$("#discountType").val(),value:$("#discountValue").val(),start:$("#discountStart").val(),end:$("#discountEnd").val()}}).done(function(e){showNotification(e.message,"success",!1,"/admin/settings/discount/edit/"+e.discountId)}).fail(function(e){showNotification(e.responseJSON.message,"danger")}))}),$("#discountEditForm").validator().on("submit",function(e){e.isDefaultPrevented()||(e.preventDefault(),$.ajax({method:"POST",url:"/admin/settings/discount/update",data:{discountId:$("#discountId").val(),code:$("#discountCode").val(),type:$("#discountType").val(),value:$("#discountValue").val(),start:$("#discountStart").val(),end:$("#discountEnd").val()}}).done(function(e){showNotification(e.message,"success")}).fail(function(e){showNotification(e.responseJSON.message,"danger")}))}),$("#discountStart").datetimepicker({uiLibrary:"bootstrap4",footer:!0,modal:!0,format:"dd/mm/yyyy HH:MM",showOtherMonths:!0}),$("#discountEnd").datetimepicker({uiLibrary:"bootstrap4",footer:!0,modal:!0,format:"dd/mm/yyyy HH:MM"}),$(document).on("click","#btnDiscountDelete",function(e){e.preventDefault(),confirm("Are you sure?")&&$.ajax({method:"DELETE",url:"/admin/settings/discount/delete",data:{discountId:$(this).attr("data-id")}}).done(function(e){showNotification(e.message,"success",!0)}).fail(function(e){showNotification(e.message,"danger",!0)})}),$(document).on("click","#settings-menu-new",function(e){e.preventDefault(),$.ajax({method:"POST",url:"/admin/settings/menu/new",data:{navMenu:$("#newNavMenu").val(),navLink:$("#newNavLink").val()}}).done(function(e){showNotification(e.message,"success",!0)}).fail(function(e){showNotification(e.message,"danger",!0)})}),$(document).on("click","#settings-menu-update",function(e){e.preventDefault();var t=$(this).attr("data-id"),a=$("#menuId-"+t);$.ajax({method:"POST",url:"/admin/settings/menu/update",data:{navId:a.find(".navId").val(),navMenu:a.find(".navMenu").val(),navLink:a.find(".navLink").val()}}).done(function(e){showNotification(e.message,"success",!0)}).fail(function(e){showNotification(e.message,"danger",!0)})}),$(document).on("click",".settings-menu-delete",function(e){e.preventDefault(),confirm("Are you sure?")&&$.ajax({method:"POST",url:"/admin/settings/menu/delete",data:{menuId:$(this).attr("data-id")}}).done(function(e){showNotification(e.message,"success",!0)}).fail(function(e){showNotification(e.message,"danger",!0)})}),$("#draggable_list").length&&$("#draggable_list").sortable({update:function(){var e=[];$(".navId").each(function(t){e.push($($(".navId")[t]).val())}),$.ajax({data:{order:e},type:"POST",url:"/admin/settings/menu/saveOrder"}).done(function(){showNotification("Menu order saved","success",!0)}).fail(function(e){showNotification(e.responseJSON.message,"danger",!0)})}}),$(document).on("click","#uploadButton",function(e){e.preventDefault();var t=new FormData($("#uploadForm")[0]);t.append("productId",$("#productId").val()),$.ajax({method:"POST",url:"/admin/file/upload",processData:!1,contentType:!1,cache:!1,data:t}).done(function(e){showNotification(e.message,"success",!0)}).fail(function(e){showNotification(e.responseJSON.message,"danger")})}),$("#global-search-value").on("keyup",e=>{""===$("#global-search-value").val()&&($("#global-search-results").empty(),$("#global-search-results").addClass("invisible"));let t=3;/^\d*\.?\d*$/.test($("#global-search-value").val())&&(t=1),$("#global-search-value").val().length>t&&($("#global-search").html(''),globalSearch())}),$("#globalSearchModal").on("shown.bs.modal",function(){$("#global-search-value").focus()}),$("body").on("click",".gr-click",e=>{$("#global-search-value").val();const t=$(e.currentTarget).closest(".global-result").attr("data-url");t&&(window.location=t)})}); \ No newline at end of file +function globalSearch(){$("#global-search-results").empty(),$.ajax({type:"POST",url:"/admin/searchall",data:{searchValue:$("#global-search-value").val()}}).done(e=>{$("#global-search").html('');let t=!1;if(e.customers.forEach(e=>{t=!0;const a=`\n
  • \n
    \n
    Customer
    \n
    ${e.firstName} ${e.lastName}
    \n
    ${e.email}
    \n
    \n
  • `;$("#global-search-results").append(a)}),e.orders.forEach(e=>{t=!0;const a=`\n
  • \n
    \n
    Order
    \n
    ${e.orderFirstname} ${e.orderLastname}
    \n
    ${moment(e.orderDate).format("YYYY/MM/DD")}
    \n
    ${e.orderEmail}
    \n
    \n
  • `;$("#global-search-results").append(a)}),e.products.forEach(e=>{t=!0;const a=`
  • \n
    \n
    Product
    \n
    ${e.productTitle}
    \n
    ${$("#currencySymbol").val()}${numeral(e.productPrice).format("0.00")}
    \n
    \n
  • `;$("#global-search-results").append(a)}),!0===t)$("#global-search-results").removeClass("invisible");else{const e='
  • \n
    \n
    Nothing found
    \n
    \n
  • ';$("#global-search-results").append(e),$("#global-search-results").removeClass("invisible")}feather.replace()})}$(document).ready(function(){if($.ajaxSetup({headers:{"csrf-token":$('meta[name="csrfToken"]').attr("content")}}),$(document).on("click","#btnGenerateAPIkey",function(e){e.preventDefault(),$.ajax({method:"POST",url:"/admin/createApiKey"}).done(function(e){$("#apiKey").val(e.apiKey),showNotification(e.message,"success",!0)}).fail(function(e){showNotification(e.responseJSON.message,"danger")})}),$(document).on("click",".product_opt_remove",function(e){e.preventDefault();var t=$(this).closest("li").find(".opt-name").html();$.ajax({method:"POST",url:"/admin/product/removeoption",data:{productId:$("#productId").val(),optName:t}}).done(function(e){showNotification(e.message,"success",!0)}).fail(function(e){showNotification(e.responseJSON.message,"danger")})}),$(document).on("click","#product_opt_add",function(e){e.preventDefault();var t=$("#product_optName").val(),a=$("#product_optLabel").val(),o=$("#product_optType").val(),i=$("#product_optOptions").val(),s={};""!==$("#productOptions").val()&&'"{}"'!==$("#productOptions").val()&&(s=JSON.parse($("#productOptions").val()));var n='
  • ';n+='
    ',n+='
    '+t+"
    ",n+='
    '+a+"
    ",n+='
    '+o+"
    ",n+='
    '+i+"
    ",n+='
    ',n+='',n+="
  • ",$("#product_opt_wrapper").append(n),s[t]={optName:t,optLabel:a,optType:o,optOptions:$.grep(i.split(","),function(e){return 0===e||e})},$("#productOptions").val(JSON.stringify(s)),$("#product_optName").val(""),$("#product_optLabel").val(""),$("#product_optOptions").val("")}),$(document).on("click","#btnSettingsUpdate",function(e){$("#settingsForm").submit()}),$("#settingsForm").validator().on("submit",function(e){e.isDefaultPrevented()||(e.preventDefault(),$("#footerHtml_input").val($(".CodeMirror")[0].CodeMirror.getValue()),$("#googleAnalytics_input").val($(".CodeMirror")[1].CodeMirror.getValue()),$("#customCss_input").val($(".CodeMirror")[2].CodeMirror.getValue()),$.ajax({method:"POST",url:"/admin/settings/update",data:$("#settingsForm").serialize()}).done(function(e){showNotification(e.message,"success")}).fail(function(e){showNotification(e.responseJSON.message,"danger")}))}),$(document).on("click","#orderStatusUpdate",function(e){$.ajax({method:"POST",url:"/admin/order/statusupdate",data:{order_id:$("#order_id").val(),status:$("#orderStatus").val()}}).done(function(e){showNotification(e.message,"success",!0)}).fail(function(e){showNotification(e.responseJSON.message,"danger")})}),$(document).on("click","#btnUserAdd",function(e){$("#userNewForm").submit()}),$("#userNewForm").validator().on("submit",function(e){e.isDefaultPrevented()||(e.preventDefault(),$.ajax({method:"POST",url:"/admin/user/insert",data:{usersName:$("#usersName").val(),userEmail:$("#userEmail").val(),userPassword:$("#userPassword").val()}}).done(function(e){showNotification(e.message,"success",!1,"/admin/user/edit/"+e.userId)}).fail(function(e){showNotification(e.responseJSON.message,"danger")}))}),$(".userDelete").on("click",function(){confirm("Are you sure you want to delete?")&&$.ajax({method:"POST",url:"/admin/user/delete",data:{userId:$(this).attr("data-id")}}).done(function(e){showNotification(e.message,"success",!0)}).fail(function(e){showNotification(e.responseJSON.message,"danger")})}),$(document).on("click","#btnUserEdit",function(e){$("#userEditForm").submit()}),$("#userEditForm").validator().on("submit",function(e){e.isDefaultPrevented()||(e.preventDefault(),$.ajax({method:"POST",url:"/admin/user/update",data:{userId:$("#userId").val(),usersName:$("#usersName").val(),userEmail:$("#userEmail").val(),userPassword:$("#userPassword").val(),userAdmin:$("#userPassword").is(":checked")}}).done(function(e){showNotification(e.message,"success")}).fail(function(e){showNotification(e.responseJSON.message,"danger")}))}),$("#productNewForm").validator().on("submit",function(e){e.isDefaultPrevented()||(e.preventDefault(),""===$("#productPermalink").val()&&""!==$("#productTitle").val()&&$("#productPermalink").val(slugify($("#productTitle").val())),$.ajax({method:"POST",url:"/admin/product/insert",data:{productTitle:$("#productTitle").val(),productPrice:$("#productPrice").val(),productPublished:$("#productPublished").val(),productStock:$("#productStock").val(),productDescription:$("#productDescription").val(),productPermalink:$("#productPermalink").val(),productOptions:$("#productOptions").val(),productSubscription:$("#productSubscription").val(),productComment:$("#productComment").is(":checked"),productTags:$("#productTags").val()}}).done(function(e){showNotification(e.message,"success",!1,"/admin/product/edit/"+e.productId)}).fail(function(e){showNotification(e.responseJSON.message,"danger")}))}),$("#productEditForm").validator().on("submit",function(e){e.isDefaultPrevented()||(e.preventDefault(),""===$("#productPermalink").val()&&""!==$("#productTitle").val()&&$("#productPermalink").val(slugify($("#productTitle").val())),$.ajax({method:"POST",url:"/admin/product/update",data:{productId:$("#productId").val(),productTitle:$("#productTitle").val(),productPrice:$("#productPrice").val(),productPublished:$("#productPublished").val(),productStock:$("#productStock").val(),productDescription:$("#productDescription").val(),productPermalink:$("#productPermalink").val(),productOptions:$("#productOptions").val(),productSubscription:$("#productSubscription").val(),productComment:$("#productComment").is(":checked"),productTags:$("#productTags").val()}}).done(function(e){showNotification(e.message,"success",!0)}).fail(function(e){showNotification(e.responseJSON.message,"danger")}))}),$(".set-as-main-image").on("click",function(){$.ajax({method:"POST",url:"/admin/product/setasmainimage",data:{product_id:$("#productId").val(),productImage:$(this).attr("data-id")}}).done(function(e){showNotification(e.message,"success",!0)}).fail(function(e){showNotification(e.responseJSON.message,"danger")})}),$(".btn-delete-image").on("click",function(){confirm("Are you sure you want to delete this image?")&&$.ajax({method:"POST",url:"/admin/product/deleteimage",data:{product_id:$("#productId").val(),productImage:$(this).attr("data-id")}}).done(function(e){showNotification(e.message,"success",!0)}).fail(function(e){showNotification(e.responseJSON.message,"danger")})}),$(".btn-delete-product").on("click",function(){confirm("Are you sure you want to delete this product?")&&$.ajax({method:"POST",url:"/admin/product/delete",data:{productId:$(this).attr("data-id")}}).done(function(e){showNotification(e.message,"success",!0)}).fail(function(e){showNotification(e.responseJSON.message,"danger")})}),$(document).on("click","#validatePermalink",function(e){""!==$("#productPermalink").val()?$.ajax({method:"POST",url:"/admin/validatePermalink",data:{permalink:$("#productPermalink").val(),docId:$("#productId").val()}}).done(function(e){showNotification(e.message,"success")}).fail(function(e){showNotification(e.responseJSON.message,"danger")}):showNotification("Please enter a permalink to validate","danger")}),$(document).on("click","#btn_product_filter",function(e){""!==$("#product_filter").val()?window.location.href="/admin/products/filter/"+$("#product_filter").val():showNotification("Please enter a keyword to filter","danger")}),$(document).on("click","#btn_order_filter",function(e){""!==$("#order_filter").val()?window.location.href="/admin/orders/filter/"+$("#order_filter").val():showNotification("Please enter a keyword to filter","danger")}),$(document).on("click","#btn_customer_filter",function(e){""!==$("#customer_filter").val()?window.location.href="/admin/customers/filter/"+$("#customer_filter").val():showNotification("Please enter a keyword to filter","danger")}),$(document).on("click","#lookupCustomer",function(e){e.preventDefault(),$.ajax({method:"POST",url:"/admin/customer/lookup",data:{customerEmail:$("#customerEmail").val()}}).done(function(e){showNotification(e.message,"success"),$("#orderFirstName").val(e.customer.firstName),$("#orderLastName").val(e.customer.lastName),$("#orderAddress1").val(e.customer.address1),$("#orderAddress2").val(e.customer.address2),$("#orderCountry").val(e.customer.country),$("#orderState").val(e.customer.state),$("#orderPostcode").val(e.customer.postcode),$("#orderPhone").val(e.customer.phone)}).fail(function(e){showNotification(e.responseJSON.message,"danger")})}),$(document).on("click","#orderCreate",function(e){e.preventDefault(),0===$("#createOrderForm").validator("validate").has(".has-error").length&&$.ajax({method:"POST",url:"/admin/order/create",data:{orderStatus:$("#orderStatus").val(),email:$("#customerEmail").val(),firstName:$("#orderFirstName").val(),lastName:$("#orderLastName").val(),address1:$("#orderAddress1").val(),address2:$("#orderAddress2").val(),country:$("#orderCountry").val(),state:$("#orderState").val(),postcode:$("#orderPostcode").val(),phone:$("#orderPhone").val(),orderComment:$("#orderComment").val()}}).done(function(e){showNotification(e.message,"success"),window.location=`/admin/order/view/${e.orderId}`}).fail(function(e){showNotification(e.responseJSON.message,"danger")})}),$("#sendTestEmail").on("click",function(e){e.preventDefault(),$.ajax({method:"POST",url:"/admin/testEmail"}).done(function(e){showNotification(e,"success")}).fail(function(e){showNotification(e.responseJSON.message,"danger")})}),$(document).on("click",".orderFilterByStatus",function(e){e.preventDefault(),window.location="/admin/orders/bystatus/"+$("#orderStatusFilter").val()}),$('input[class="publishedState"]').change(function(){$.ajax({method:"POST",url:"/admin/product/publishedState",data:{id:this.id,state:this.checked}}).done(function(e){showNotification(e.message,"success")}).fail(function(e){showNotification(e.responseJSON.message,"danger")})}),$("#updateCustomer").validator().on("click",function(e){e.preventDefault(),0===$("#customer-form").validator("validate").has(".has-error").length&&$.ajax({method:"POST",url:"/admin/customer/update",data:{customerId:$("#customerId").val(),email:$("#email").val(),firstName:$("#firstName").val(),lastName:$("#lastName").val(),address1:$("#address1").val(),address2:$("#address2").val(),country:$("#country").val(),state:$("#state").val(),postcode:$("#postcode").val(),phone:$("#phone").val()}}).done(function(e){showNotification(e.message,"success")}).fail(function(e){showNotification(e.responseJSON.message,"danger")})}),$("#deleteCustomer").on("click",function(e){e.preventDefault(),$.ajax({method:"DELETE",url:"/admin/customer",data:{customerId:$("#customerId").val()}}).done(function(e){showNotification(e.message,"success",!1,"/admin/customers")}).fail(function(e){showNotification(e.responseJSON.message,"danger")})}),$("#footerHtml").length){var e=window.CodeMirror.fromTextArea(document.getElementById("footerHtml"),{mode:"xml",tabMode:"indent",theme:"flatly",lineNumbers:!0,htmlMode:!0,fixedGutter:!1});e.setValue(e.getValue())}if($("#googleAnalytics").length&&window.CodeMirror.fromTextArea(document.getElementById("googleAnalytics"),{mode:"xml",tabMode:"indent",theme:"flatly",lineNumbers:!0,htmlMode:!0,fixedGutter:!1}),$("#customCss").length){var t=window.CodeMirror.fromTextArea(document.getElementById("customCss"),{mode:"text/css",tabMode:"indent",theme:"flatly",lineNumbers:!0}),a=window.cssbeautify(t.getValue(),{indent:" ",autosemicolon:!0});t.setValue(a)}$(document).on("click","#btnPageUpdate",function(e){e.preventDefault(),$.ajax({method:"POST",url:"/admin/settings/page",data:{pageId:$("#pageId").val(),pageName:$("#pageName").val(),pageSlug:$("#pageSlug").val(),pageEnabled:$("#pageEnabled").is(":checked"),pageContent:$("#pageContent").val()}}).done(function(e){showNotification(e.message,"success",!0)}).fail(function(e){showNotification(e.responseJSON.message,"danger")})}),$(document).on("click","#btnPageDelete",function(e){e.preventDefault(),confirm("Are you sure?")&&$.ajax({method:"POST",url:"/admin/settings/page/delete",data:{pageId:$(this).attr("data-id")}}).done(function(e){showNotification(e.message,"success",!0)}).fail(function(e){showNotification(e.message,"danger",!0)})}),$("#discountNewForm").validator().on("submit",function(e){e.isDefaultPrevented()||(e.preventDefault(),$.ajax({method:"POST",url:"/admin/settings/discount/create",data:{code:$("#discountCode").val(),type:$("#discountType").val(),value:$("#discountValue").val(),start:$("#discountStart").val(),end:$("#discountEnd").val()}}).done(function(e){showNotification(e.message,"success",!1,"/admin/settings/discount/edit/"+e.discountId)}).fail(function(e){showNotification(e.responseJSON.message,"danger")}))}),$("#discountEditForm").validator().on("submit",function(e){e.isDefaultPrevented()||(e.preventDefault(),$.ajax({method:"POST",url:"/admin/settings/discount/update",data:{discountId:$("#discountId").val(),code:$("#discountCode").val(),type:$("#discountType").val(),value:$("#discountValue").val(),start:$("#discountStart").val(),end:$("#discountEnd").val()}}).done(function(e){showNotification(e.message,"success")}).fail(function(e){showNotification(e.responseJSON.message,"danger")}))}),$("#discountStart").datetimepicker({uiLibrary:"bootstrap4",footer:!0,modal:!0,format:"dd/mm/yyyy HH:MM",showOtherMonths:!0}),$("#discountEnd").datetimepicker({uiLibrary:"bootstrap4",footer:!0,modal:!0,format:"dd/mm/yyyy HH:MM"}),$(document).on("click","#btnDiscountDelete",function(e){e.preventDefault(),confirm("Are you sure?")&&$.ajax({method:"DELETE",url:"/admin/settings/discount/delete",data:{discountId:$(this).attr("data-id")}}).done(function(e){showNotification(e.message,"success",!0)}).fail(function(e){showNotification(e.message,"danger",!0)})}),$(document).on("click","#settings-menu-new",function(e){e.preventDefault(),$.ajax({method:"POST",url:"/admin/settings/menu/new",data:{navMenu:$("#newNavMenu").val(),navLink:$("#newNavLink").val()}}).done(function(e){showNotification(e.message,"success",!0)}).fail(function(e){showNotification(e.message,"danger",!0)})}),$(document).on("click","#settings-menu-update",function(e){e.preventDefault();var t=$(this).attr("data-id"),a=$("#menuId-"+t);$.ajax({method:"POST",url:"/admin/settings/menu/update",data:{navId:a.find(".navId").val(),navMenu:a.find(".navMenu").val(),navLink:a.find(".navLink").val()}}).done(function(e){showNotification(e.message,"success",!0)}).fail(function(e){showNotification(e.message,"danger",!0)})}),$(document).on("click",".settings-menu-delete",function(e){e.preventDefault(),confirm("Are you sure?")&&$.ajax({method:"POST",url:"/admin/settings/menu/delete",data:{menuId:$(this).attr("data-id")}}).done(function(e){showNotification(e.message,"success",!0)}).fail(function(e){showNotification(e.message,"danger",!0)})}),$("#draggable_list").length&&$("#draggable_list").sortable({update:function(){var e=[];$(".navId").each(function(t){e.push($($(".navId")[t]).val())}),$.ajax({data:{order:e},type:"POST",url:"/admin/settings/menu/saveOrder"}).done(function(){showNotification("Menu order saved","success",!0)}).fail(function(e){showNotification(e.responseJSON.message,"danger",!0)})}}),$(document).on("click","#uploadButton",function(e){e.preventDefault();var t=new FormData($("#uploadForm")[0]);t.append("productId",$("#productId").val()),$.ajax({method:"POST",url:"/admin/file/upload",processData:!1,contentType:!1,cache:!1,data:t}).done(function(e){showNotification(e.message,"success",!0)}).fail(function(e){showNotification(e.responseJSON.message,"danger")})}),$("#global-search-value").on("keyup",e=>{""===$("#global-search-value").val()&&($("#global-search-results").empty(),$("#global-search-results").addClass("invisible"));let t=3;/^\d*\.?\d*$/.test($("#global-search-value").val())&&(t=1),$("#global-search-value").val().length>t&&($("#global-search").html(''),globalSearch())}),$("#globalSearchModal").on("shown.bs.modal",function(){$("#global-search-value").focus()}),$("body").on("click",".gr-click",e=>{$("#global-search-value").val();const t=$(e.currentTarget).closest(".global-result").attr("data-url");t&&(window.location=t)})}); \ No newline at end of file diff --git a/public/javascripts/expressCart.js b/public/javascripts/expressCart.js index 7acaaf9..9314b0f 100644 --- a/public/javascripts/expressCart.js +++ b/public/javascripts/expressCart.js @@ -237,6 +237,27 @@ $(document).ready(function (){ e.preventDefault(); }); + $('#customerloginForm').on('click', function(e){ + if(!e.isDefaultPrevented()){ + e.preventDefault(); + $.ajax({ + method: 'POST', + url: '/customer/login_action', + data: { + loginEmail: $('#email').val(), + loginPassword: $('#password').val() + } + }) + .done(function(msg){ + window.location = '/customer/account'; + }) + .fail(function(msg){ + showNotification(msg.responseJSON.message, 'danger'); + }); + } + e.preventDefault(); + }); + // call update settings API $('#customerLogin').on('click', function(e){ if(!e.isDefaultPrevented()){ @@ -270,6 +291,37 @@ $(document).ready(function (){ e.preventDefault(); }); + // Customer saving own details + $('#customerSave').validator().on('click', function(e){ + e.preventDefault(); + if($('#customer-form').validator('validate').has('.has-error').length === 0){ + $.ajax({ + method: 'POST', + url: '/customer/update', + data: { + email: $('#shipEmail').val(), + company: $('#shipCompany').val(), + firstName: $('#shipFirstname').val(), + lastName: $('#shipLastname').val(), + address1: $('#shipAddr1').val(), + address2: $('#shipAddr2').val(), + country: $('#shipCountry').val(), + state: $('#shipState').val(), + postcode: $('#shipPostcode').val(), + phone: $('#shipPhoneNumber').val(), + password: $('#newCustomerPassword').val(), + orderComment: $('#orderComment').val() + } + }) + .done(function(){ + showNotification('Customer saved', 'success'); + }) + .fail(function(msg){ + showNotification(msg.responseJSON.message, 'danger'); + }); + } + }); + $(document).on('click', '.image-next', function(e){ var thumbnails = $('.thumbnail-image'); var index = 0; diff --git a/public/javascripts/expressCart.min.js b/public/javascripts/expressCart.min.js index 9ff0b33..4708f81 100644 --- a/public/javascripts/expressCart.min.js +++ b/public/javascripts/expressCart.min.js @@ -1 +1 @@ -function checkMaxQuantity(t,a){if($("#maxQuantity").length){if(46===t.keyCode||8===t.keyCode)return;if(parseInt($(t.target).val())>parseInt($("#maxQuantity").val())){const e=a.val();t.preventDefault(),a.val(e.slice(0,-1)),showNotification(`Exceeds maximum quantity: ${$("#maxQuantity").val()}`,"warning",!1)}}}function deleteFromCart(t){$.ajax({method:"POST",url:"/product/removefromcart",data:{cartId:t.attr("data-cartid")}}).done(function(t){showNotification(t.message,"success"),updateCartDiv()}).fail(function(t){showNotification(t.responseJSON.message,"danger")})}function cartUpdate(t){$(t).val()>0?""!==$(t).val()&&updateCart(t):$(t).val(1)}function updateCart(t){$.ajax({method:"POST",url:"/product/updatecart",data:{cartId:t.attr("data-cartid"),productId:t.attr("data-id"),quantity:t.val()}}).done(function(t){updateCartDiv()}).fail(function(t){showNotification(t.responseJSON.message,"danger",!0)})}function getSelectedOptions(){var t={};return $(".product-opt").each(function(){var a=$(this).val().trim(),e=$(this).attr("data-label"),n=$(this).attr("name"),o=$(this).attr("type");o||(t[n]={label:e,name:n,value:a}),"radio"===o&&(t[n]={label:e,name:n,value:$('input[name="'+n+'"]:checked').val()}),"checkbox"===o&&(t[n]={label:e,name:n,value:$('input[name="'+$(this).attr("name")+'"]').is(":checked")})}),t}function updateCartDiv(){$.ajax({method:"GET",url:"/checkout/cartdata"}).done(function(t){var a=t.cart,e=t.session,n="",o=numeral(e.totalCartAmount).format("0.00"),i=numeral(e.totalCartShipping).format("0.00"),c=`${e.shippingMessage} :${t.currencySymbol}${i}`;0===e.totalCartShipping&&(c=`${e.shippingMessage}`);var r=numeral(e.totalCartDiscount).format("0.00"),s="";e.totalCartDiscount>0&&(s=`\n
    \n Discount: ${t.currencySymbol}${r}\n
    `),a?($("#cart-empty").empty(),Object.keys(a).forEach(function(e){var o=a[e],i=numeral(o.totalItemPrice).format("0.00"),c="",r=1;Object.keys(o.options).forEach(function(t){var a=o.options[t];r===Object.keys(o.options).length?c+=`${upperFirst(a.name)}: ${a.value}`:c+=`${upperFirst(a.name)}: ${a.value} / `,r++});var s=`${o.title} product image`;o.productImage&&(s=`${o.title} product image`),n+=`\n
    \n
    \n
    \n
    \n ${s}\n
    \n
    \n
    \n
    \n
    ${o.title}
    \n ${c}\n
    \n
    \n
    \n
    \n \n
    \n \n
    \n \n
    \n
    \n
    \n
    \n \n
    \n
    \n ${t.currencySymbol}${i}\n
    \n
    \n
    \n
    \n
    \n
    `}),$(".cartBodyWrapper").html(n)):$(".cartBodyWrapper").html(""),$("#cart-count").text(e.totalCartItems);var d=`\n
    \n
    \n
    \n ${c}\n
    \n ${s}\n
    \n Total:\n ${t.currencySymbol}${o}\n
    \n
    \n
    `;a?($(".cartTotalsWrapper").html(d),$(".cart-buttons").removeClass("d-none")):($(".cartTotalsWrapper").html('\n
    \n
    t.toUpperCase())}function emptyCart(){$.ajax({method:"POST",url:"/product/emptycart"}).done(function(t){showNotification(t.message,"success",!0),updateCartDiv()})}$(document).ready(function(){if($(window).width()<768&&($(".menu-side").on("click",function(t){t.preventDefault(),$('.menu-side li:not(".active")').slideToggle()}),$('.menu-side li:not(".active")').hide(),$(".menu-side>.active").html(''),$(".menu-side>.active").addClass("menu-side-mobile"),0===$("#navbar ul li").length&&$("#navbar").hide(),$("#offcanvasClose").hide()),$("#userSetupForm").validator().on("submit",function(t){t.isDefaultPrevented()||(t.preventDefault(),$.ajax({method:"POST",url:"/admin/setup_action",data:{usersName:$("#usersName").val(),userEmail:$("#userEmail").val(),userPassword:$("#userPassword").val()}}).done(function(t){showNotification(t.message,"success",!1,"/admin/login")}).fail(function(t){showNotification(t.responseJSON.message,"danger")}))}),$(document).on("click",".menu-btn",function(t){t.preventDefault(),$("body").addClass("pushy-open-right")}),$("table").each(function(){$(this).addClass("table table-hover")}),$("#productTags").length&&$("#productTags").tokenfield(),$(document).on("click",".dashboard_list",function(t){window.document.location=$(this).attr("href")}).hover(function(){$(this).toggleClass("hover")}),$(document).on("click",".btn-qty-minus",function(t){t.preventDefault();var a=$(t.target).parent().parent().find(".cart-product-quantity");$(a).val(parseInt(a.val())-1),cartUpdate(a)}),$(document).on("click",".btn-qty-add",function(t){t.preventDefault();var a=$(t.target).parent().parent().find(".cart-product-quantity");$(a).val(parseInt(a.val())+1),cartUpdate(a)}),$(document).on("click",".btn-delete-from-cart",function(t){deleteFromCart($(t.target))}),$("#pager").length){var t=$("#pageNum").val(),a=$("#productsPerPage").val(),e=$("#totalProductCount").val(),n=$("#paginateUrl").val(),o=$("#searchTerm").val();""!==o&&(o+="/");var i="/"+n+"/"+o+"{{number}}",c=Math.ceil(e/a);parseInt(e)>parseInt(a)&&($("#pager").bootpag({total:c,page:t,maxVisible:5,href:i,wrapClass:"pagination",prevClass:"page-item previous",nextClass:"page-item next",activeClass:"page-item active"}),$("#pager a").each(function(){$(this).addClass("page-link")}))}if($("#customerLogout").on("click",function(t){$.ajax({method:"POST",url:"/customer/logout",data:{}}).done(function(t){location.reload()})}),$("#customerForgotten").validator().on("submit",function(t){t.isDefaultPrevented()||(t.preventDefault(),$.ajax({method:"POST",url:"/customer/forgotten_action",data:{email:$("#email").val()}}).done(function(t){showNotification(t.message,"success")}).fail(function(t){t.message?showNotification(t.responseJSON.message,"danger"):showNotification(t.responseText,"danger")}))}),$(document).on("click","#createAccountCheckbox",function(t){$("#newCustomerPassword").prop("required",$("#createAccountCheckbox").prop("checked"))}),$("#checkoutInformation").validator().on("click",function(t){if(t.preventDefault(),0===$("#shipping-form").validator("validate").has(".has-error").length){var a="/customer/save";$("#createAccountCheckbox").prop("checked")&&(a="/customer/create"),$.ajax({method:"POST",url:a,data:{email:$("#shipEmail").val(),firstName:$("#shipFirstname").val(),lastName:$("#shipLastname").val(),address1:$("#shipAddr1").val(),address2:$("#shipAddr2").val(),country:$("#shipCountry").val(),state:$("#shipState").val(),postcode:$("#shipPostcode").val(),phone:$("#shipPhoneNumber").val(),password:$("#newCustomerPassword").val(),orderComment:$("#orderComment").val()}}).done(function(){window.location="/checkout/shipping"}).fail(function(t){showNotification(t.responseJSON.message,"danger")})}}),$("#addDiscountCode").on("click",function(t){t.preventDefault(),$.ajax({method:"POST",url:"/checkout/adddiscountcode",data:{discountCode:$("#discountCode").val()}}).done(function(t){showNotification(t.message,"success",!0)}).fail(function(t){showNotification(t.responseJSON.message,"danger")})}),$("#removeDiscountCode").on("click",function(t){t.preventDefault(),$.ajax({method:"POST",url:"/checkout/removediscountcode",data:{}}).done(function(t){showNotification(t.message,"success",!0)}).fail(function(t){showNotification(t.responseJSON.message,"danger")})}),$("#loginForm").on("click",function(t){t.isDefaultPrevented()||(t.preventDefault(),$.ajax({method:"POST",url:"/admin/login_action",data:{email:$("#email").val(),password:$("#password").val()}}).done(function(t){window.location="/admin"}).fail(function(t){showNotification(t.responseJSON.message,"danger")})),t.preventDefault()}),$("#customerLogin").on("click",function(t){t.isDefaultPrevented()||(t.preventDefault(),$.ajax({method:"POST",url:"/customer/login_action",data:{loginEmail:$("#customerLoginEmail").val(),loginPassword:$("#customerLoginPassword").val()}}).done(function(t){var a=t.customer;$("#shipEmail").val(a.email),$("#shipFirstname").val(a.firstName),$("#shipLastname").val(a.lastName),$("#shipAddr1").val(a.address1),$("#shipAddr2").val(a.address2),$("#shipCountry").val(a.country),$("#shipState").val(a.state),$("#shipPostcode").val(a.postcode),$("#shipPhoneNumber").val(a.phone),location.reload()}).fail(function(t){showNotification(t.responseJSON.message,"danger")})),t.preventDefault()}),$(document).on("click",".image-next",function(t){var a=$(".thumbnail-image"),e=0,n=0;$(".thumbnail-image").each(function(){$("#product-title-image").attr("src")===$(this).attr("src")&&(n=e+1===a.length||e+1<0?0:e+1),e++}),$("#product-title-image").attr("src",$(a).eq(n).attr("src"))}),$(document).on("click",".image-prev",function(t){var a=$(".thumbnail-image"),e=0,n=0;$(".thumbnail-image").each(function(){$("#product-title-image").attr("src")===$(this).attr("src")&&(n=e-1===a.length||e-1<0?a.length-1:e-1),e++}),$("#product-title-image").attr("src",$(a).eq(n).attr("src"))}),$(document).on("click",".product-add-to-cart",function(t){var a=getSelectedOptions();parseInt($("#product_quantity").val())<1&&$("#product_quantity").val(1),$.ajax({method:"POST",url:"/product/addtocart",data:{productId:$("#productId").val(),productQuantity:$("#product_quantity").val(),productOptions:JSON.stringify(a),productComment:$("#product_comment").val()}}).done(function(t){showNotification(t.message,"success"),updateCartDiv()}).fail(function(t){showNotification(t.responseJSON.message,"danger")})}),$("#product_quantity").on("keyup",function(t){checkMaxQuantity(t,$("#product_quantity"))}),$(".cart-product-quantity").on("keyup",function(t){checkMaxQuantity(t,$(".cart-product-quantity"))}),$(".cart-product-quantity").on("focusout",function(t){cartUpdate($(t.target))}),$(document).on("click",".pushy-link",function(t){$("body").removeClass("pushy-open-right")}),$(document).on("click",".add-to-cart",function(t){var a="/product/"+$(this).attr("data-id");$(this).attr("data-link")&&(a="/product/"+$(this).attr("data-link")),"true"===$(this).attr("data-has-options")?window.location=a:$.ajax({method:"POST",url:"/product/addtocart",data:{productId:$(this).attr("data-id")}}).done(function(t){showNotification(t.message,"success"),updateCartDiv()}).fail(function(t){showNotification(t.responseJSON.message,"danger")})}),$(document).on("click","#empty-cart",function(t){$("#confirmModal").modal("show"),$("#buttonConfirm").attr("data-func","emptyCart")}),$(document).on("click","#buttonConfirm",function(t){var a=$(t.target).attr("data-func");window[a](),$("#confirmModal").modal("hide")}),$(".qty-btn-minus").on("click",function(){var t=parseInt($("#product_quantity").val())-1;$("#product_quantity").val(t>0?t:1)}),$(".qty-btn-plus").on("click",function(){$("#product_quantity").val(parseInt($("#product_quantity").val())+1)}),$(".thumbnail-image").on("click",function(){$("#product-title-image").attr("src",$(this).attr("src"))}),$(document).on("click","#btn_search_reset",function(t){window.location.replace("/")}),$(document).on("click","#btn_search",function(t){t.preventDefault(),""===$("#frm_search").val().trim()?showNotification("Please enter a search value","danger"):window.location.href="/search/"+$("#frm_search").val()}),""!==$("#input_notify_message").val()){var r=$("#input_notify_message").val(),s=$("#input_notify_messageType").val();$("#input_notify_message").val(""),$("#input_notify_messageType").val(""),showNotification(r,s||"danger",!1)}if($("#blockonomics_div").length>0){var d=$("#blockonomics_div").data("orderid")||"",l=$("#blockonomics_div").data("timestamp")||-1,u=$("#blockonomics_div").data("address")||"",m=new WebSocket("wss://www.blockonomics.co/payment/"+u+"?timestamp="+l);m.onopen=function(t){};setTimeout(function(){$("#blockonomics_waiting").html("Payment expired

    Click here to try again.

    If you already paid, your order will be processed automatically."),showNotification("Payment expired","danger"),m.close()},6e5);var p=$("#blockonomics_timeout"),f=new Date((new Date).getTime()+6e5),v=setInterval(function(){var t=(new Date).getTime(),a=f-t;if(a<0)clearInterval(v);else{var e=Math.floor(a%36e5/6e4),n=Math.floor(a%6e4/1e3);p.html(e+"m "+n+"s")}},1e3);m.onmessage=function(t){var a=JSON.parse(t.data);if(0===a.status||1===a.status||2===a.status){var e='
    View Order';$("#blockonomics_waiting").html("Payment detected ("+a.value/1e8+" BTC)."+e),showNotification("Payment detected","success"),$("#cart-count").html("0"),m.close(),$.ajax({method:"POST",url:"/product/emptycart"}).done(function(){window.location.replace("/payment/"+d)})}}}}); \ No newline at end of file +function checkMaxQuantity(t,a){if($("#maxQuantity").length){if(46===t.keyCode||8===t.keyCode)return;if(parseInt($(t.target).val())>parseInt($("#maxQuantity").val())){const e=a.val();t.preventDefault(),a.val(e.slice(0,-1)),showNotification(`Exceeds maximum quantity: ${$("#maxQuantity").val()}`,"warning",!1)}}}function deleteFromCart(t){$.ajax({method:"POST",url:"/product/removefromcart",data:{cartId:t.attr("data-cartid")}}).done(function(t){showNotification(t.message,"success"),updateCartDiv()}).fail(function(t){showNotification(t.responseJSON.message,"danger")})}function cartUpdate(t){$(t).val()>0?""!==$(t).val()&&updateCart(t):$(t).val(1)}function updateCart(t){$.ajax({method:"POST",url:"/product/updatecart",data:{cartId:t.attr("data-cartid"),productId:t.attr("data-id"),quantity:t.val()}}).done(function(t){updateCartDiv()}).fail(function(t){showNotification(t.responseJSON.message,"danger",!0)})}function getSelectedOptions(){var t={};return $(".product-opt").each(function(){var a=$(this).val().trim(),e=$(this).attr("data-label"),n=$(this).attr("name"),o=$(this).attr("type");o||(t[n]={label:e,name:n,value:a}),"radio"===o&&(t[n]={label:e,name:n,value:$('input[name="'+n+'"]:checked').val()}),"checkbox"===o&&(t[n]={label:e,name:n,value:$('input[name="'+$(this).attr("name")+'"]').is(":checked")})}),t}function updateCartDiv(){$.ajax({method:"GET",url:"/checkout/cartdata"}).done(function(t){var a=t.cart,e=t.session,n="",o=numeral(e.totalCartAmount).format("0.00"),i=numeral(e.totalCartShipping).format("0.00"),r=`${e.shippingMessage} :${t.currencySymbol}${i}`;0===e.totalCartShipping&&(r=`${e.shippingMessage}`);var s=numeral(e.totalCartDiscount).format("0.00"),c="";e.totalCartDiscount>0&&(c=`\n
    \n Discount: ${t.currencySymbol}${s}\n
    `),a?($("#cart-empty").empty(),Object.keys(a).forEach(function(e){var o=a[e],i=numeral(o.totalItemPrice).format("0.00"),r="",s=1;Object.keys(o.options).forEach(function(t){var a=o.options[t];s===Object.keys(o.options).length?r+=`${upperFirst(a.name)}: ${a.value}`:r+=`${upperFirst(a.name)}: ${a.value} / `,s++});var c=`${o.title} product image`;o.productImage&&(c=`${o.title} product image`),n+=`\n
    \n
    \n
    \n
    \n ${c}\n
    \n
    \n
    \n
    \n
    ${o.title}
    \n ${r}\n
    \n
    \n
    \n
    \n \n
    \n \n
    \n \n
    \n
    \n
    \n
    \n \n
    \n
    \n ${t.currencySymbol}${i}\n
    \n
    \n
    \n
    \n
    \n
    `}),$(".cartBodyWrapper").html(n)):$(".cartBodyWrapper").html(""),$("#cart-count").text(e.totalCartItems);var d=`\n
    \n
    \n
    \n ${r}\n
    \n ${c}\n
    \n Total:\n ${t.currencySymbol}${o}\n
    \n
    \n
    `;a?($(".cartTotalsWrapper").html(d),$(".cart-buttons").removeClass("d-none")):($(".cartTotalsWrapper").html('\n
    \n
    t.toUpperCase())}function emptyCart(){$.ajax({method:"POST",url:"/product/emptycart"}).done(function(t){showNotification(t.message,"success",!0),updateCartDiv()})}$(document).ready(function(){if($(window).width()<768&&($(".menu-side").on("click",function(t){t.preventDefault(),$('.menu-side li:not(".active")').slideToggle()}),$('.menu-side li:not(".active")').hide(),$(".menu-side>.active").html(''),$(".menu-side>.active").addClass("menu-side-mobile"),0===$("#navbar ul li").length&&$("#navbar").hide(),$("#offcanvasClose").hide()),$("#userSetupForm").validator().on("submit",function(t){t.isDefaultPrevented()||(t.preventDefault(),$.ajax({method:"POST",url:"/admin/setup_action",data:{usersName:$("#usersName").val(),userEmail:$("#userEmail").val(),userPassword:$("#userPassword").val()}}).done(function(t){showNotification(t.message,"success",!1,"/admin/login")}).fail(function(t){showNotification(t.responseJSON.message,"danger")}))}),$(document).on("click",".menu-btn",function(t){t.preventDefault(),$("body").addClass("pushy-open-right")}),$("table").each(function(){$(this).addClass("table table-hover")}),$("#productTags").length&&$("#productTags").tokenfield(),$(document).on("click",".dashboard_list",function(t){window.document.location=$(this).attr("href")}).hover(function(){$(this).toggleClass("hover")}),$(document).on("click",".btn-qty-minus",function(t){t.preventDefault();var a=$(t.target).parent().parent().find(".cart-product-quantity");$(a).val(parseInt(a.val())-1),cartUpdate(a)}),$(document).on("click",".btn-qty-add",function(t){t.preventDefault();var a=$(t.target).parent().parent().find(".cart-product-quantity");$(a).val(parseInt(a.val())+1),cartUpdate(a)}),$(document).on("click",".btn-delete-from-cart",function(t){deleteFromCart($(t.target))}),$("#pager").length){var t=$("#pageNum").val(),a=$("#productsPerPage").val(),e=$("#totalProductCount").val(),n=$("#paginateUrl").val(),o=$("#searchTerm").val();""!==o&&(o+="/");var i="/"+n+"/"+o+"{{number}}",r=Math.ceil(e/a);parseInt(e)>parseInt(a)&&($("#pager").bootpag({total:r,page:t,maxVisible:5,href:i,wrapClass:"pagination",prevClass:"page-item previous",nextClass:"page-item next",activeClass:"page-item active"}),$("#pager a").each(function(){$(this).addClass("page-link")}))}if($("#customerLogout").on("click",function(t){$.ajax({method:"POST",url:"/customer/logout",data:{}}).done(function(t){location.reload()})}),$("#customerForgotten").validator().on("submit",function(t){t.isDefaultPrevented()||(t.preventDefault(),$.ajax({method:"POST",url:"/customer/forgotten_action",data:{email:$("#email").val()}}).done(function(t){showNotification(t.message,"success")}).fail(function(t){t.message?showNotification(t.responseJSON.message,"danger"):showNotification(t.responseText,"danger")}))}),$(document).on("click","#createAccountCheckbox",function(t){$("#newCustomerPassword").prop("required",$("#createAccountCheckbox").prop("checked"))}),$("#checkoutInformation").validator().on("click",function(t){if(t.preventDefault(),0===$("#shipping-form").validator("validate").has(".has-error").length){var a="/customer/save";$("#createAccountCheckbox").prop("checked")&&(a="/customer/create"),$.ajax({method:"POST",url:a,data:{email:$("#shipEmail").val(),company:$("#shipCompany").val(),firstName:$("#shipFirstname").val(),lastName:$("#shipLastname").val(),address1:$("#shipAddr1").val(),address2:$("#shipAddr2").val(),country:$("#shipCountry").val(),state:$("#shipState").val(),postcode:$("#shipPostcode").val(),phone:$("#shipPhoneNumber").val(),password:$("#newCustomerPassword").val(),orderComment:$("#orderComment").val()}}).done(function(){window.location="/checkout/shipping"}).fail(function(t){showNotification(t.responseJSON.message,"danger")})}}),$("#addDiscountCode").on("click",function(t){t.preventDefault(),$.ajax({method:"POST",url:"/checkout/adddiscountcode",data:{discountCode:$("#discountCode").val()}}).done(function(t){showNotification(t.message,"success",!0)}).fail(function(t){showNotification(t.responseJSON.message,"danger")})}),$("#removeDiscountCode").on("click",function(t){t.preventDefault(),$.ajax({method:"POST",url:"/checkout/removediscountcode",data:{}}).done(function(t){showNotification(t.message,"success",!0)}).fail(function(t){showNotification(t.responseJSON.message,"danger")})}),$("#loginForm").on("click",function(t){t.isDefaultPrevented()||(t.preventDefault(),$.ajax({method:"POST",url:"/admin/login_action",data:{email:$("#email").val(),password:$("#password").val()}}).done(function(t){window.location="/admin"}).fail(function(t){showNotification(t.responseJSON.message,"danger")})),t.preventDefault()}),$("#customerloginForm").on("click",function(t){t.isDefaultPrevented()||(t.preventDefault(),$.ajax({method:"POST",url:"/customer/login_action",data:{loginEmail:$("#email").val(),loginPassword:$("#password").val()}}).done(function(t){window.location="/customer/account"}).fail(function(t){showNotification(t.responseJSON.message,"danger")})),t.preventDefault()}),$("#customerLogin").on("click",function(t){t.isDefaultPrevented()||(t.preventDefault(),$.ajax({method:"POST",url:"/customer/login_action",data:{loginEmail:$("#customerLoginEmail").val(),loginPassword:$("#customerLoginPassword").val()}}).done(function(t){var a=t.customer;$("#shipEmail").val(a.email),$("#shipFirstname").val(a.firstName),$("#shipLastname").val(a.lastName),$("#shipAddr1").val(a.address1),$("#shipAddr2").val(a.address2),$("#shipCountry").val(a.country),$("#shipState").val(a.state),$("#shipPostcode").val(a.postcode),$("#shipPhoneNumber").val(a.phone),location.reload()}).fail(function(t){showNotification(t.responseJSON.message,"danger")})),t.preventDefault()}),$("#customerSave").validator().on("click",function(t){t.preventDefault(),0===$("#customer-form").validator("validate").has(".has-error").length&&$.ajax({method:"POST",url:"/customer/save",data:{email:$("#shipEmail").val(),company:$("#shipCompany").val(),firstName:$("#shipFirstname").val(),lastName:$("#shipLastname").val(),address1:$("#shipAddr1").val(),address2:$("#shipAddr2").val(),country:$("#shipCountry").val(),state:$("#shipState").val(),postcode:$("#shipPostcode").val(),phone:$("#shipPhoneNumber").val(),password:$("#newCustomerPassword").val(),orderComment:$("#orderComment").val()}}).done(function(){showNotification("Customer saved","success")}).fail(function(t){showNotification(t.responseJSON.message,"danger")})}),$(document).on("click",".image-next",function(t){var a=$(".thumbnail-image"),e=0,n=0;$(".thumbnail-image").each(function(){$("#product-title-image").attr("src")===$(this).attr("src")&&(n=e+1===a.length||e+1<0?0:e+1),e++}),$("#product-title-image").attr("src",$(a).eq(n).attr("src"))}),$(document).on("click",".image-prev",function(t){var a=$(".thumbnail-image"),e=0,n=0;$(".thumbnail-image").each(function(){$("#product-title-image").attr("src")===$(this).attr("src")&&(n=e-1===a.length||e-1<0?a.length-1:e-1),e++}),$("#product-title-image").attr("src",$(a).eq(n).attr("src"))}),$(document).on("click",".product-add-to-cart",function(t){var a=getSelectedOptions();parseInt($("#product_quantity").val())<1&&$("#product_quantity").val(1),$.ajax({method:"POST",url:"/product/addtocart",data:{productId:$("#productId").val(),productQuantity:$("#product_quantity").val(),productOptions:JSON.stringify(a),productComment:$("#product_comment").val()}}).done(function(t){showNotification(t.message,"success"),updateCartDiv()}).fail(function(t){showNotification(t.responseJSON.message,"danger")})}),$("#product_quantity").on("keyup",function(t){checkMaxQuantity(t,$("#product_quantity"))}),$(".cart-product-quantity").on("keyup",function(t){checkMaxQuantity(t,$(".cart-product-quantity"))}),$(".cart-product-quantity").on("focusout",function(t){cartUpdate($(t.target))}),$(document).on("click",".pushy-link",function(t){$("body").removeClass("pushy-open-right")}),$(document).on("click",".add-to-cart",function(t){var a="/product/"+$(this).attr("data-id");$(this).attr("data-link")&&(a="/product/"+$(this).attr("data-link")),"true"===$(this).attr("data-has-options")?window.location=a:$.ajax({method:"POST",url:"/product/addtocart",data:{productId:$(this).attr("data-id")}}).done(function(t){showNotification(t.message,"success"),updateCartDiv()}).fail(function(t){showNotification(t.responseJSON.message,"danger")})}),$(document).on("click","#empty-cart",function(t){$("#confirmModal").modal("show"),$("#buttonConfirm").attr("data-func","emptyCart")}),$(document).on("click","#buttonConfirm",function(t){var a=$(t.target).attr("data-func");window[a](),$("#confirmModal").modal("hide")}),$(".qty-btn-minus").on("click",function(){var t=parseInt($("#product_quantity").val())-1;$("#product_quantity").val(t>0?t:1)}),$(".qty-btn-plus").on("click",function(){$("#product_quantity").val(parseInt($("#product_quantity").val())+1)}),$(".thumbnail-image").on("click",function(){$("#product-title-image").attr("src",$(this).attr("src"))}),$(document).on("click","#btn_search_reset",function(t){window.location.replace("/")}),$(document).on("click","#btn_search",function(t){t.preventDefault(),""===$("#frm_search").val().trim()?showNotification("Please enter a search value","danger"):window.location.href="/search/"+$("#frm_search").val()}),""!==$("#input_notify_message").val()){var s=$("#input_notify_message").val(),c=$("#input_notify_messageType").val();$("#input_notify_message").val(""),$("#input_notify_messageType").val(""),showNotification(s,c||"danger",!1)}if($("#blockonomics_div").length>0){var d=$("#blockonomics_div").data("orderid")||"",l=$("#blockonomics_div").data("timestamp")||-1,u=$("#blockonomics_div").data("address")||"",m=new WebSocket("wss://www.blockonomics.co/payment/"+u+"?timestamp="+l);m.onopen=function(t){};setTimeout(function(){$("#blockonomics_waiting").html("Payment expired

    Click here to try again.

    If you already paid, your order will be processed automatically."),showNotification("Payment expired","danger"),m.close()},6e5);var p=$("#blockonomics_timeout"),f=new Date((new Date).getTime()+6e5),v=setInterval(function(){var t=(new Date).getTime(),a=f-t;if(a<0)clearInterval(v);else{var e=Math.floor(a%36e5/6e4),n=Math.floor(a%6e4/1e3);p.html(e+"m "+n+"s")}},1e3);m.onmessage=function(t){var a=JSON.parse(t.data);if(0===a.status||1===a.status||2===a.status){var e='
    View Order';$("#blockonomics_waiting").html("Payment detected ("+a.value/1e8+" BTC)."+e),showNotification("Payment detected","success"),$("#cart-count").html("0"),m.close(),$.ajax({method:"POST",url:"/product/emptycart"}).done(function(){window.location.replace("/payment/"+d)})}}}}); \ No newline at end of file diff --git a/public/stylesheets/admin.css b/public/stylesheets/admin.css index d17f633..981decd 100644 --- a/public/stylesheets/admin.css +++ b/public/stylesheets/admin.css @@ -244,8 +244,6 @@ body .popover { [role="main"] { padding-top: 20px; margin-bottom: 20px; - min-height: 100%; - height: 100%; } @media (min-width: 768px) { [role="main"] { diff --git a/public/stylesheets/admin.min.css b/public/stylesheets/admin.min.css index 54496ca..71dac10 100644 --- a/public/stylesheets/admin.min.css +++ b/public/stylesheets/admin.min.css @@ -1 +1 @@ -body,html{height:100%;background-color:#f8f9fa!important}.content-body{margin-bottom:0}.feather{width:16px;height:16px}.btn-outline-danger,.btn-outline-info,.btn-outline-primary,.btn-outline-success,.btn-outline-warning{background-color:#fff}.btn-outline-primary{color:#fff!important;background-color:#000;border-color:#000}.btn-outline-danger{color:#dc3545!important}.btn-outline-danger:hover{color:#fff!important}.has-error div,.has-error input,.has-error textarea{border-color:#cc4135}#frm_search,.search-bar-input,.search-bar-input .btn{padding-top:10px;height:45px}.footer{padding-top:20px}.admin-menu{padding-left:0}.admin-menu .list-group-item{border-bottom:none}.navbarMenuWrapper{background-color:#f5f5f5}.navbarMenu>ul>li>a:hover{color:#cc4135!important}.navbarMenu{padding-right:0;padding-left:0}.product-wrapper>a:hover{color:#cc4135!important}#navbar,#navbar>.navbar-nav,#navbar>.navbar-nav>li>a,.navbar-header,.navbar-static-top{margin-bottom:0;height:100px!important}#navbar>.navbar-nav>li>a{padding-top:35px}.pagination>li>a{background-color:#cc4135!important}.admin-card{background-color:#fff!important;border-radius:5px;padding:15px;margin:10px;box-shadow:0 0 1px rgba(0,0,0,.12),0 1px 6px rgba(0,0,0,.03),0 6px 10px -8px rgba(0,0,0,.1)}.admin-card-body{padding:5px}body .popover{display:none!important}.navbar-brand{color:#cc4135!important;letter-spacing:4px;padding-left:20px!important;padding-top:0!important;height:80px!important;font-size:55px!important}.navbar-brand,.navbar-brand-image{height:80px;padding-left:10px;padding-top:10px}.navbar-default .badge{background-color:#cc4135}#empty-cart:active,#empty-cart:active:hover,#empty-cart:focus,#empty-cart:hover,.pushy-link:active,.pushy-link:active:hover,.pushy-link:focus,.pushy-link:hover{border-color:#cc4135;background-color:#cc4135}.navActive>a{margin-bottom:0;padding-top:15px;border-bottom:5px solid #cc4135}#navbar,#navbar>.navbar-nav,#navbar>.navbar-nav>li>a,.navbar-header,.navbar-static-top{background-color:#fff}.navbar-default .navbar-nav>li>a{color:#838b8f;font-size:20px}.global-result-type{color:#8d8d8d}.global-result:hover{background-color:#007bff}.global-result:hover .global-result-detail,.global-result:hover .global-result-type,.global-result:hover .global-result-type .fal{color:#fff!important}.global-result a{text-decoration:none!important}.global-result:hover{cursor:pointer}.global-result:first-child{border-top-left-radius:0;border-top-right-radius:0}.global-result{border-left:0;border-right:0}.global-search-modal-content,.global-search-modal-header{background-color:transparent;border:none}#global-search-results{padding-right:0;border-bottom-left-radius:.3rem;border-bottom-right-radius:.3rem}.global-search-form{margin-bottom:0}#global-search-value{border-bottom-right-radius:0}.search-input-addon{border-bottom-left-radius:0}.sidebar{position:fixed;top:0;bottom:0;left:0;z-index:100;padding:0;background-color:#fff;box-shadow:inset -1px 0 0 rgba(0,0,0,.1)}.sidebar-sticky{position:relative;top:0;height:100vh;padding-top:15px;overflow-x:hidden;overflow-y:auto}@supports ((position:-webkit-sticky) or (position:sticky)){.sidebar-sticky{position:-webkit-sticky;position:sticky}}.sidebar .nav-link{font-weight:400;color:#333}.sidebar .nav-link .feather{margin-right:4px;color:#999}.sidebar .nav-link.active .feather,.sidebar .nav-link:hover .feather{color:inherit}.sidebar-heading{font-size:.75rem;text-transform:uppercase}.sidebar-brand{width:80%}.sidebar-search{text-align:center;width:20%}.sidebar-addon{height:40px}.sidebar-link{display:inline-block;width:80%}.sidebar-link-addon{display:inline-block;width:10%}[role=main]{padding-top:20px;margin-bottom:20px;min-height:100%;height:100%}@media (min-width:768px){[role=main]{padding-top:20px;padding-bottom:20px}}@media only screen and (max-width:768px){.navbar-default .navbar-brand{padding-top:10px}.navbar-default .navbar-nav>li>a{font-size:16px}.searchBarWrapper{padding-top:10px}.navbarMenuWrapper{padding-left:0;padding-right:0}.navbarMenuOuter{padding-left:0;padding-right:0}.navActive>a{color:#fff!important}.navbarMenu{padding-right:7.5px;padding-left:7.5px}.navActive>a{color:#fff!important;background-color:#cc4135;border-bottom:none}.footer{padding-top:10px}} \ No newline at end of file +body,html{height:100%;background-color:#f8f9fa!important}.content-body{margin-bottom:0}.feather{width:16px;height:16px}.btn-outline-danger,.btn-outline-info,.btn-outline-primary,.btn-outline-success,.btn-outline-warning{background-color:#fff}.btn-outline-primary{color:#fff!important;background-color:#000;border-color:#000}.btn-outline-danger{color:#dc3545!important}.btn-outline-danger:hover{color:#fff!important}.has-error div,.has-error input,.has-error textarea{border-color:#cc4135}#frm_search,.search-bar-input,.search-bar-input .btn{padding-top:10px;height:45px}.footer{padding-top:20px}.admin-menu{padding-left:0}.admin-menu .list-group-item{border-bottom:none}.navbarMenuWrapper{background-color:#f5f5f5}.navbarMenu>ul>li>a:hover{color:#cc4135!important}.navbarMenu{padding-right:0;padding-left:0}.product-wrapper>a:hover{color:#cc4135!important}#navbar,#navbar>.navbar-nav,#navbar>.navbar-nav>li>a,.navbar-header,.navbar-static-top{margin-bottom:0;height:100px!important}#navbar>.navbar-nav>li>a{padding-top:35px}.pagination>li>a{background-color:#cc4135!important}.admin-card{background-color:#fff!important;border-radius:5px;padding:15px;margin:10px;box-shadow:0 0 1px rgba(0,0,0,.12),0 1px 6px rgba(0,0,0,.03),0 6px 10px -8px rgba(0,0,0,.1)}.admin-card-body{padding:5px}body .popover{display:none!important}.navbar-brand{color:#cc4135!important;letter-spacing:4px;padding-left:20px!important;padding-top:0!important;height:80px!important;font-size:55px!important}.navbar-brand,.navbar-brand-image{height:80px;padding-left:10px;padding-top:10px}.navbar-default .badge{background-color:#cc4135}#empty-cart:active,#empty-cart:active:hover,#empty-cart:focus,#empty-cart:hover,.pushy-link:active,.pushy-link:active:hover,.pushy-link:focus,.pushy-link:hover{border-color:#cc4135;background-color:#cc4135}.navActive>a{margin-bottom:0;padding-top:15px;border-bottom:5px solid #cc4135}#navbar,#navbar>.navbar-nav,#navbar>.navbar-nav>li>a,.navbar-header,.navbar-static-top{background-color:#fff}.navbar-default .navbar-nav>li>a{color:#838b8f;font-size:20px}.global-result-type{color:#8d8d8d}.global-result:hover{background-color:#007bff}.global-result:hover .global-result-detail,.global-result:hover .global-result-type,.global-result:hover .global-result-type .fal{color:#fff!important}.global-result a{text-decoration:none!important}.global-result:hover{cursor:pointer}.global-result:first-child{border-top-left-radius:0;border-top-right-radius:0}.global-result{border-left:0;border-right:0}.global-search-modal-content,.global-search-modal-header{background-color:transparent;border:none}#global-search-results{padding-right:0;border-bottom-left-radius:.3rem;border-bottom-right-radius:.3rem}.global-search-form{margin-bottom:0}#global-search-value{border-bottom-right-radius:0}.search-input-addon{border-bottom-left-radius:0}.sidebar{position:fixed;top:0;bottom:0;left:0;z-index:100;padding:0;background-color:#fff;box-shadow:inset -1px 0 0 rgba(0,0,0,.1)}.sidebar-sticky{position:relative;top:0;height:100vh;padding-top:15px;overflow-x:hidden;overflow-y:auto}@supports ((position:-webkit-sticky) or (position:sticky)){.sidebar-sticky{position:-webkit-sticky;position:sticky}}.sidebar .nav-link{font-weight:400;color:#333}.sidebar .nav-link .feather{margin-right:4px;color:#999}.sidebar .nav-link.active .feather,.sidebar .nav-link:hover .feather{color:inherit}.sidebar-heading{font-size:.75rem;text-transform:uppercase}.sidebar-brand{width:80%}.sidebar-search{text-align:center;width:20%}.sidebar-addon{height:40px}.sidebar-link{display:inline-block;width:80%}.sidebar-link-addon{display:inline-block;width:10%}[role=main]{padding-top:20px;margin-bottom:20px}@media (min-width:768px){[role=main]{padding-top:20px;padding-bottom:20px}}@media only screen and (max-width:768px){.navbar-default .navbar-brand{padding-top:10px}.navbar-default .navbar-nav>li>a{font-size:16px}.searchBarWrapper{padding-top:10px}.navbarMenuWrapper{padding-left:0;padding-right:0}.navbarMenuOuter{padding-left:0;padding-right:0}.navActive>a{color:#fff!important}.navbarMenu{padding-right:7.5px;padding-left:7.5px}.navActive>a{color:#fff!important;background-color:#cc4135;border-bottom:none}.footer{padding-top:10px}} \ No newline at end of file diff --git a/public/stylesheets/less/admin.less b/public/stylesheets/less/admin.less index 247dcc2..0a985ae 100644 --- a/public/stylesheets/less/admin.less +++ b/public/stylesheets/less/admin.less @@ -283,8 +283,6 @@ body .popover{display:none !important; } [role="main"] { padding-top: 20px; margin-bottom: 20px; - min-height: 100%; - height: 100%; } @media (min-width: 768px) { diff --git a/routes/customer.js b/routes/customer.js index cdb420f..131da13 100644 --- a/routes/customer.js +++ b/routes/customer.js @@ -3,7 +3,14 @@ const router = express.Router(); const colors = require('colors'); const randtoken = require('rand-token'); const bcrypt = require('bcryptjs'); -const common = require('../lib/common'); +const { + getId, + clearSessionValue, + getCountryList, + mongoSanitize, + sendEmail, + clearCustomer +} = require('../lib/common'); const rateLimit = require('express-rate-limit'); const { indexCustomers } = require('../lib/indexing'); const { validateJson } = require('../lib/schema'); @@ -58,6 +65,7 @@ router.post('/customer/create', async (req, res) => { // Set the customer into the session req.session.customerPresent = true; + req.session.customerId = customerReturn._id; req.session.customerEmail = customerReturn.email; req.session.customerCompany = customerReturn.company; req.session.customerFirstname = customerReturn.firstName; @@ -118,11 +126,107 @@ router.post('/customer/save', async (req, res) => { res.status(200).json(customerObj); }); +// Get customer orders +router.get('/customer/account', async (req, res) => { + const db = req.app.db; + const config = req.app.config; + + if(!req.session.customerPresent){ + res.redirect('/customer/login'); + return; + } + + const orders = await db.orders.find({ + orderCustomer: getId(req.session.customerId) + }) + .sort({ orderDate: -1 }) + .toArray(); + res.render(`${config.themeViews}customer-account`, { + title: 'Orders', + session: req.session, + orders, + message: clearSessionValue(req.session, 'message'), + messageType: clearSessionValue(req.session, 'messageType'), + countryList: getCountryList(), + config: req.app.config, + helpers: req.handlebars.helpers + }); +}); + +// Update a customer +router.post('/customer/update', async (req, res) => { + const db = req.app.db; + + if(!req.session.customerPresent){ + res.redirect('/customer/login'); + return; + } + + const customerObj = { + company: req.body.company, + email: req.body.email, + firstName: req.body.firstName, + lastName: req.body.lastName, + address1: req.body.address1, + address2: req.body.address2, + country: req.body.country, + state: req.body.state, + postcode: req.body.postcode, + phone: req.body.phone + }; + + const schemaResult = validateJson('editCustomer', customerObj); + if(!schemaResult.result){ + console.log('errors', schemaResult.errors); + res.status(400).json(schemaResult.errors); + return; + } + + // check for existing customer + const customer = await db.customers.findOne({ _id: getId(req.session.customerId) }); + if(!customer){ + res.status(400).json({ + message: 'Customer not found' + }); + return; + } + // Update customer + try{ + const updatedCustomer = await db.customers.findOneAndUpdate( + { _id: getId(req.session.customerId) }, + { + $set: customerObj + }, { multi: false, returnOriginal: false } + ); + indexCustomers(req.app) + .then(() => { + // Set the customer into the session + req.session.customerEmail = customerObj.email; + req.session.customerCompany = customerObj.company; + req.session.customerFirstname = customerObj.firstName; + req.session.customerLastname = customerObj.lastName; + req.session.customerAddress1 = customerObj.address1; + req.session.customerAddress2 = customerObj.address2; + req.session.customerCountry = customerObj.country; + req.session.customerState = customerObj.state; + req.session.customerPostcode = customerObj.postcode; + req.session.customerPhone = customerObj.phone; + req.session.orderComment = req.body.orderComment; + + res.status(200).json({ message: 'Customer updated', customer: updatedCustomer.value }); + }); + }catch(ex){ + console.error(colors.red('Failed updating customer: ' + ex)); + res.status(400).json({ message: 'Failed to update customer' }); + } +}); + // Update a customer router.post('/admin/customer/update', restrict, async (req, res) => { const db = req.app.db; const customerObj = { + company: req.body.company, email: req.body.email, firstName: req.body.firstName, lastName: req.body.lastName, @@ -145,7 +249,7 @@ router.post('/admin/customer/update', restrict, async (req, res) => { } // check for existing customer - const customer = await db.customers.findOne({ _id: common.getId(req.body.customerId) }); + const customer = await db.customers.findOne({ _id: getId(req.body.customerId) }); if(!customer){ res.status(400).json({ message: 'Customer not found' @@ -155,7 +259,7 @@ router.post('/admin/customer/update', restrict, async (req, res) => { // Update customer try{ const updatedCustomer = await db.customers.findOneAndUpdate( - { _id: common.getId(req.body.customerId) }, + { _id: getId(req.body.customerId) }, { $set: customerObj }, { multi: false, returnOriginal: false } @@ -177,7 +281,7 @@ router.delete('/admin/customer', restrict, async (req, res) => { const db = req.app.db; // check for existing customer - const customer = await db.customers.findOne({ _id: common.getId(req.body.customerId) }); + const customer = await db.customers.findOne({ _id: getId(req.body.customerId) }); if(!customer){ res.status(400).json({ message: 'Failed to delete customer. Customer not found' @@ -186,7 +290,7 @@ router.delete('/admin/customer', restrict, async (req, res) => { } // Update customer try{ - await db.customers.deleteOne({ _id: common.getId(req.body.customerId) }); + await db.customers.deleteOne({ _id: getId(req.body.customerId) }); indexCustomers(req.app) .then(() => { res.status(200).json({ message: 'Customer deleted' }); @@ -201,7 +305,7 @@ router.delete('/admin/customer', restrict, async (req, res) => { router.get('/admin/customer/view/:id?', restrict, async (req, res) => { const db = req.app.db; - const customer = await db.customers.findOne({ _id: common.getId(req.params.id) }); + const customer = await db.customers.findOne({ _id: getId(req.params.id) }); if(!customer){ // If API request, return json @@ -223,9 +327,9 @@ router.get('/admin/customer/view/:id?', restrict, async (req, res) => { result: customer, admin: true, session: req.session, - message: common.clearSessionValue(req.session, 'message'), - messageType: common.clearSessionValue(req.session, 'messageType'), - countryList: common.getCountryList(), + message: clearSessionValue(req.session, 'message'), + messageType: clearSessionValue(req.session, 'messageType'), + countryList: getCountryList(), config: req.app.config, editor: true, helpers: req.handlebars.helpers @@ -249,8 +353,8 @@ router.get('/admin/customers', restrict, async (req, res) => { customers: customers, session: req.session, helpers: req.handlebars.helpers, - message: common.clearSessionValue(req.session, 'message'), - messageType: common.clearSessionValue(req.session, 'messageType'), + message: clearSessionValue(req.session, 'message'), + messageType: clearSessionValue(req.session, 'messageType'), config: req.app.config }); }); @@ -263,7 +367,7 @@ router.get('/admin/customers/filter/:search', restrict, async (req, res, next) = const lunrIdArray = []; customersIndex.search(searchTerm).forEach((id) => { - lunrIdArray.push(common.getId(id.ref)); + lunrIdArray.push(getId(id.ref)); }); // we search on the lunr indexes @@ -283,8 +387,8 @@ router.get('/admin/customers/filter/:search', restrict, async (req, res, next) = config: req.app.config, session: req.session, searchTerm: searchTerm, - message: common.clearSessionValue(req.session, 'message'), - messageType: common.clearSessionValue(req.session, 'messageType'), + message: clearSessionValue(req.session, 'message'), + messageType: clearSessionValue(req.session, 'messageType'), helpers: req.handlebars.helpers }); }); @@ -298,6 +402,7 @@ router.post('/admin/customer/lookup', restrict, async (req, res, next) => { if(customer){ req.session.customerPresent = true; + req.session.customerId = customer._id; req.session.customerEmail = customer.email; req.session.customerCompany = customer.company; req.session.customerFirstname = customer.firstName; @@ -319,11 +424,24 @@ router.post('/admin/customer/lookup', restrict, async (req, res, next) => { }); }); +router.get('/customer/login', async (req, res, next) => { + const config = req.app.config; + + res.render(`${config.themeViews}customer-login`, { + title: 'Customer login', + config: req.app.config, + session: req.session, + message: clearSessionValue(req.session, 'message'), + messageType: clearSessionValue(req.session, 'messageType'), + helpers: req.handlebars.helpers + }); +}); + // login the customer and check the password router.post('/customer/login_action', async (req, res) => { const db = req.app.db; - const customer = await db.customers.findOne({ email: common.mongoSanitize(req.body.loginEmail) }); + const customer = await db.customers.findOne({ email: mongoSanitize(req.body.loginEmail) }); // check if customer exists with that email if(customer === undefined || customer === null){ res.status(400).json({ @@ -344,6 +462,7 @@ router.post('/customer/login_action', async (req, res) => { // Customer login successful req.session.customerPresent = true; + req.session.customerId = customer._id; req.session.customerEmail = customer.email; req.session.customerCompany = customer.company; req.session.customerFirstname = customer.firstName; @@ -375,8 +494,8 @@ router.get('/customer/forgotten', (req, res) => { forgotType: 'customer', config: req.app.config, helpers: req.handlebars.helpers, - message: common.clearSessionValue(req.session, 'message'), - messageType: common.clearSessionValue(req.session, 'messageType'), + message: clearSessionValue(req.session, 'message'), + messageType: clearSessionValue(req.session, 'messageType'), showFooter: 'showFooter' }); }); @@ -411,7 +530,7 @@ router.post('/customer/forgotten_action', apiLimiter, async (req, res) => { // send the email with token to the user // TODO: Should fix this to properly handle result - common.sendEmail(mailOpts.to, mailOpts.subject, mailOpts.body); + sendEmail(mailOpts.to, mailOpts.subject, mailOpts.body); res.status(200).json({ message: 'If your account exists, a password reset has been sent to your email' }); @@ -441,8 +560,8 @@ router.get('/customer/reset/:token', async (req, res) => { token: req.params.token, route: 'customer', config: req.app.config, - message: common.clearSessionValue(req.session, 'message'), - message_type: common.clearSessionValue(req.session, 'message_type'), + message: clearSessionValue(req.session, 'message'), + message_type: clearSessionValue(req.session, 'message_type'), show_footer: 'show_footer', helpers: req.handlebars.helpers }); @@ -471,7 +590,7 @@ router.post('/customer/reset/:token', async (req, res) => { }; // TODO: Should fix this to properly handle result - common.sendEmail(mailOpts.to, mailOpts.subject, mailOpts.body); + sendEmail(mailOpts.to, mailOpts.subject, mailOpts.body); req.session.message = 'Password successfully updated'; req.session.message_type = 'success'; return res.redirect('/checkout/payment'); @@ -486,8 +605,15 @@ router.post('/customer/reset/:token', async (req, res) => { // logout the customer router.post('/customer/logout', (req, res) => { // Clear our session - common.clearCustomer(req); + clearCustomer(req); res.status(200).json({}); }); +// logout the customer +router.get('/customer/logout', (req, res) => { + // Clear our session + clearCustomer(req); + res.redirect('/customer/login'); +}); + module.exports = router; diff --git a/routes/payments/adyen.js b/routes/payments/adyen.js index a4e6b34..4b385fd 100644 --- a/routes/payments/adyen.js +++ b/routes/payments/adyen.js @@ -80,6 +80,7 @@ router.post('/checkout_action', async (req, res, next) => { orderShipping: req.session.totalCartShipping, orderItemCount: req.session.totalCartItems, orderProductCount: req.session.totalCartProducts, + orderCustomer: common.getId(req.session.customerId), orderEmail: req.session.customerEmail, orderCompany: req.session.customerCompany, orderFirstname: req.session.customerFirstname, diff --git a/routes/payments/authorizenet.js b/routes/payments/authorizenet.js index ef39907..9c150ee 100644 --- a/routes/payments/authorizenet.js +++ b/routes/payments/authorizenet.js @@ -63,6 +63,7 @@ router.post('/checkout_action', (req, res, next) => { orderShipping: req.session.totalCartShipping, orderItemCount: req.session.totalCartItems, orderProductCount: req.session.totalCartProducts, + orderCustomer: common.getId(req.session.customerId), orderEmail: req.session.customerEmail, orderCompany: req.session.customerCompany, orderFirstname: req.session.customerFirstname, diff --git a/routes/payments/blockonomics.js b/routes/payments/blockonomics.js index c889479..59b0633 100644 --- a/routes/payments/blockonomics.js +++ b/routes/payments/blockonomics.js @@ -94,6 +94,7 @@ router.post('/checkout_action', (req, res, next) => { orderShipping: req.session.totalCartShipping, orderItemCount: req.session.totalCartItems, orderProductCount: req.session.totalCartProducts, + orderCustomer: common.getId(req.session.customerId), orderEmail: req.session.customerEmail, orderCompany: req.session.customerCompany, orderFirstname: req.session.customerFirstname, diff --git a/routes/payments/instore.js b/routes/payments/instore.js index 2d767ea..b29feae 100644 --- a/routes/payments/instore.js +++ b/routes/payments/instore.js @@ -17,6 +17,7 @@ router.post('/checkout_action', async (req, res, next) => { orderShipping: 0, orderItemCount: req.session.totalCartItems, orderProductCount: req.session.totalCartProducts, + orderCustomer: common.getId(req.session.customerId), orderEmail: req.session.customerEmail, orderCompany: req.session.customerCompany, orderFirstname: req.session.customerFirstname, diff --git a/routes/payments/paypal.js b/routes/payments/paypal.js index f812cac..7f7d99c 100644 --- a/routes/payments/paypal.js +++ b/routes/payments/paypal.js @@ -166,6 +166,7 @@ router.post('/checkout_action', (req, res, next) => { orderShipping: req.session.totalCartShipping, orderItemCount: req.session.totalCartItems, orderProductCount: req.session.totalCartProducts, + orderCustomer: common.getId(req.session.customerId), orderEmail: req.session.customerEmail, orderCompany: req.session.customerCompany, orderFirstname: req.session.customerFirstname, diff --git a/routes/payments/stripe.js b/routes/payments/stripe.js index 8eb05b8..c47d16d 100644 --- a/routes/payments/stripe.js +++ b/routes/payments/stripe.js @@ -56,6 +56,7 @@ router.post('/checkout_action', (req, res, next) => { orderShipping: req.session.totalCartShipping, orderItemCount: req.session.totalCartItems, orderProductCount: req.session.totalCartProducts, + orderCustomer: common.getId(req.session.customerId), orderEmail: req.session.customerEmail, orderCompany: req.session.customerCompany, orderFirstname: req.session.customerFirstname, diff --git a/test/specs/customers.js b/test/specs/customers.js index 7763ade..8154896 100644 --- a/test/specs/customers.js +++ b/test/specs/customers.js @@ -78,9 +78,10 @@ test('[Fail] Create with invalid email address', async t => { t.deepEqual(res.body[0].message, 'should match format "emailAddress"'); }); -test('[Success] Update existing customer', async t => { +test('[Success] Update existing customer from dashboard', async t => { const customer = { customerId: g.customers[1]._id, + company: 'Acme Co', email: 'sarah.jones@test.com', firstName: 'Sarah', lastName: 'Jones', @@ -99,6 +100,47 @@ test('[Success] Update existing customer', async t => { .expect(200); t.deepEqual(res.body.message, 'Customer updated'); + t.deepEqual(res.body.customer.company, customer.company); + t.deepEqual(res.body.customer.email, customer.email); + t.deepEqual(res.body.customer.firstName, customer.firstName); + t.deepEqual(res.body.customer.lastName, customer.lastName); + t.deepEqual(res.body.customer.address1, customer.address1); + t.deepEqual(res.body.customer.country, customer.country); + t.deepEqual(res.body.customer.state, customer.state); + t.deepEqual(res.body.customer.postcode, customer.postcode); + t.deepEqual(res.body.customer.phone, customer.phone); +}); + +test('[Success] Update existing customer from customer page', async t => { + const customer = { + customerId: g.customers[1]._id, + company: 'Acme Company', + email: 'sarah.jones@test.com', + firstName: 'Tina', + lastName: 'Smith', + address1: '2 Sydney Street', + address2: '', + country: 'Australia', + state: 'NSW', + postcode: '2000', + phone: '0444444444' + }; + + await g.request + .post('/customer/login_action') + .send({ + loginEmail: 'sarah.jones@test.com', + loginPassword: 'test' + }) + .expect(200); + + const res = await g.request + .post('/customer/update') + .send(customer) + .expect(200); + + t.deepEqual(res.body.message, 'Customer updated'); + t.deepEqual(res.body.customer.company, customer.company); t.deepEqual(res.body.customer.email, customer.email); t.deepEqual(res.body.customer.firstName, customer.firstName); t.deepEqual(res.body.customer.lastName, customer.lastName); diff --git a/views/layouts/layout.hbs b/views/layouts/layout.hbs index cd80b03..7592b5b 100644 --- a/views/layouts/layout.hbs +++ b/views/layouts/layout.hbs @@ -185,6 +185,19 @@
    {{/ifCond}} + {{#if @root.session.customerPresent}} + + {{else}} + + {{/if}} {{#if @root.session.cart}} {{else}} diff --git a/views/settings-menu.hbs b/views/settings-menu.hbs index c3e1f56..80bd8f9 100644 --- a/views/settings-menu.hbs +++ b/views/settings-menu.hbs @@ -9,7 +9,7 @@
    {{#each menu.items}} - diff --git a/views/themes/Cloth/customer-account.hbs b/views/themes/Cloth/customer-account.hbs new file mode 100644 index 0000000..3c743f1 --- /dev/null +++ b/views/themes/Cloth/customer-account.hbs @@ -0,0 +1,129 @@ +
    + +
    +
    +
    + +
    +
    +
    +
    +
    +
    +
    {{ @root.__ "Orders" }}
    +
    + {{#each orders}} +
    +
    +

    + OrderId: {{this._id}} - + Date: {{formatDate this.orderDate "DD/MM/YYYY hh:mmA"}} + +

    +
    +
    +
    +
      +
    • + Order status: {{this.orderStatus}} +
    • +
    • {{ @root.__ "Order date" }}: {{formatDate result.orderDate "DD/MM/YYYY hh:mmA"}}
    • +
    • {{ @root.__ "Order ID" }}: {{this._id}}
    • + {{#if result.orderExpectedBtc }} +
    • {{ @root.__ "Order Expected BTC" }}: {{this.orderExpectedBtc}}
    • + {{/if}} + {{#if this.orderReceivedBtc }} +
    • {{ @root.__ "Order Received BTC" }}: {{this.orderReceivedBtc}}
    • + {{/if}} + {{#if this.orderBlockonomicsTxid }} +
    • {{ @root.__ "Order Blockonomics Txid" }}: {{this.orderBlockonomicsTxid}}
    • + {{/if}} +
    • {{ @root.__ "Order net amount" }}: {{currencySymbol config.currencySymbol}}{{formatAmount (math this.orderTotal '-' this.orderShipping)}}
    • +
    • {{ @root.__ "Order shipping amount" }}: {{currencySymbol config.currencySymbol}}{{formatAmount this.orderShipping}}
    • +
    • {{ @root.__ "Order total amount" }}: {{currencySymbol config.currencySymbol}}{{formatAmount this.orderTotal}}
    • +
    • {{ @root.__ "Email address" }}: {{this.orderEmail}}
    • +
    • {{ @root.__ "Company" }}: {{this.orderCompany}}
    • +
    • {{ @root.__ "First name" }}: {{this.orderFirstname}}
    • +
    • {{ @root.__ "Last name" }}: {{this.orderLastname}}
    • +
    • {{ @root.__ "Address 1" }}: {{this.orderAddr1}}
    • +
    • {{ @root.__ "Address 2" }}: {{this.orderAddr2}}
    • +
    • {{ @root.__ "Country" }}: {{this.orderCountry}}
    • +
    • {{ @root.__ "State" }}: {{this.orderState}}
    • +
    • {{ @root.__ "Postcode" }}: {{this.orderPostcode}}
    • +
    • {{ @root.__ "Phone number" }}: {{this.orderPhoneNumber}}
    • +
    •  
    • +
    • {{ @root.__ "Products ordered" }}
    • + {{#each this.orderProducts}} +
    • + {{this.quantity}} x {{this.title}} + {{#if this.options}} +   >   + {{ @root.__ "Options" }}: + ( + {{#each this.options}} + {{#if @last}} + {{#upperFirst this.name}}{{/upperFirst}}: {{this.value}} + {{else}} + {{#upperFirst this.name}}{{/upperFirst}}: {{this.value}} / + {{/if}} + {{/each}} + ) + {{/if}} +
      {{currencySymbol @root.config.currencySymbol}}{{formatAmount this.totalItemPrice}}
      + {{#if productComment}} +

      Comment: {{this.productComment}}

      + {{/if}} +
    • + {{/each}} +
    +
    +
    +
    + {{/each}} +
    +
    +
    +
    +
    +
    +
    \ No newline at end of file diff --git a/views/themes/Cloth/customer-login.hbs b/views/themes/Cloth/customer-login.hbs new file mode 100644 index 0000000..8af84ec --- /dev/null +++ b/views/themes/Cloth/customer-login.hbs @@ -0,0 +1,12 @@ +
    + +