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 <mark@Marks-MacBook-Pro-2.local>master
parent
6b9f4b2e6b
commit
78e06e511b
|
@ -2,6 +2,9 @@
|
||||||
"$id": "editCustomer",
|
"$id": "editCustomer",
|
||||||
"type": "object",
|
"type": "object",
|
||||||
"properties": {
|
"properties": {
|
||||||
|
"company": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
"email": {
|
"email": {
|
||||||
"type": "string",
|
"type": "string",
|
||||||
"format": "emailAddress"
|
"format": "emailAddress"
|
||||||
|
|
File diff suppressed because one or more lines are too long
|
@ -237,6 +237,27 @@ $(document).ready(function (){
|
||||||
e.preventDefault();
|
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
|
// call update settings API
|
||||||
$('#customerLogin').on('click', function(e){
|
$('#customerLogin').on('click', function(e){
|
||||||
if(!e.isDefaultPrevented()){
|
if(!e.isDefaultPrevented()){
|
||||||
|
@ -270,6 +291,37 @@ $(document).ready(function (){
|
||||||
e.preventDefault();
|
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){
|
$(document).on('click', '.image-next', function(e){
|
||||||
var thumbnails = $('.thumbnail-image');
|
var thumbnails = $('.thumbnail-image');
|
||||||
var index = 0;
|
var index = 0;
|
||||||
|
|
File diff suppressed because one or more lines are too long
|
@ -244,8 +244,6 @@ body .popover {
|
||||||
[role="main"] {
|
[role="main"] {
|
||||||
padding-top: 20px;
|
padding-top: 20px;
|
||||||
margin-bottom: 20px;
|
margin-bottom: 20px;
|
||||||
min-height: 100%;
|
|
||||||
height: 100%;
|
|
||||||
}
|
}
|
||||||
@media (min-width: 768px) {
|
@media (min-width: 768px) {
|
||||||
[role="main"] {
|
[role="main"] {
|
||||||
|
|
|
@ -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}}
|
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}}
|
|
@ -283,8 +283,6 @@ body .popover{display:none !important; }
|
||||||
[role="main"] {
|
[role="main"] {
|
||||||
padding-top: 20px;
|
padding-top: 20px;
|
||||||
margin-bottom: 20px;
|
margin-bottom: 20px;
|
||||||
min-height: 100%;
|
|
||||||
height: 100%;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@media (min-width: 768px) {
|
@media (min-width: 768px) {
|
||||||
|
|
|
@ -3,7 +3,14 @@ const router = express.Router();
|
||||||
const colors = require('colors');
|
const colors = require('colors');
|
||||||
const randtoken = require('rand-token');
|
const randtoken = require('rand-token');
|
||||||
const bcrypt = require('bcryptjs');
|
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 rateLimit = require('express-rate-limit');
|
||||||
const { indexCustomers } = require('../lib/indexing');
|
const { indexCustomers } = require('../lib/indexing');
|
||||||
const { validateJson } = require('../lib/schema');
|
const { validateJson } = require('../lib/schema');
|
||||||
|
@ -58,6 +65,7 @@ router.post('/customer/create', async (req, res) => {
|
||||||
|
|
||||||
// Set the customer into the session
|
// Set the customer into the session
|
||||||
req.session.customerPresent = true;
|
req.session.customerPresent = true;
|
||||||
|
req.session.customerId = customerReturn._id;
|
||||||
req.session.customerEmail = customerReturn.email;
|
req.session.customerEmail = customerReturn.email;
|
||||||
req.session.customerCompany = customerReturn.company;
|
req.session.customerCompany = customerReturn.company;
|
||||||
req.session.customerFirstname = customerReturn.firstName;
|
req.session.customerFirstname = customerReturn.firstName;
|
||||||
|
@ -118,11 +126,107 @@ router.post('/customer/save', async (req, res) => {
|
||||||
res.status(200).json(customerObj);
|
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
|
// Update a customer
|
||||||
router.post('/admin/customer/update', restrict, async (req, res) => {
|
router.post('/admin/customer/update', restrict, async (req, res) => {
|
||||||
const db = req.app.db;
|
const db = req.app.db;
|
||||||
|
|
||||||
const customerObj = {
|
const customerObj = {
|
||||||
|
company: req.body.company,
|
||||||
email: req.body.email,
|
email: req.body.email,
|
||||||
firstName: req.body.firstName,
|
firstName: req.body.firstName,
|
||||||
lastName: req.body.lastName,
|
lastName: req.body.lastName,
|
||||||
|
@ -145,7 +249,7 @@ router.post('/admin/customer/update', restrict, async (req, res) => {
|
||||||
}
|
}
|
||||||
|
|
||||||
// check for existing customer
|
// 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){
|
if(!customer){
|
||||||
res.status(400).json({
|
res.status(400).json({
|
||||||
message: 'Customer not found'
|
message: 'Customer not found'
|
||||||
|
@ -155,7 +259,7 @@ router.post('/admin/customer/update', restrict, async (req, res) => {
|
||||||
// Update customer
|
// Update customer
|
||||||
try{
|
try{
|
||||||
const updatedCustomer = await db.customers.findOneAndUpdate(
|
const updatedCustomer = await db.customers.findOneAndUpdate(
|
||||||
{ _id: common.getId(req.body.customerId) },
|
{ _id: getId(req.body.customerId) },
|
||||||
{
|
{
|
||||||
$set: customerObj
|
$set: customerObj
|
||||||
}, { multi: false, returnOriginal: false }
|
}, { multi: false, returnOriginal: false }
|
||||||
|
@ -177,7 +281,7 @@ router.delete('/admin/customer', restrict, async (req, res) => {
|
||||||
const db = req.app.db;
|
const db = req.app.db;
|
||||||
|
|
||||||
// check for existing customer
|
// 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){
|
if(!customer){
|
||||||
res.status(400).json({
|
res.status(400).json({
|
||||||
message: 'Failed to delete customer. Customer not found'
|
message: 'Failed to delete customer. Customer not found'
|
||||||
|
@ -186,7 +290,7 @@ router.delete('/admin/customer', restrict, async (req, res) => {
|
||||||
}
|
}
|
||||||
// Update customer
|
// Update customer
|
||||||
try{
|
try{
|
||||||
await db.customers.deleteOne({ _id: common.getId(req.body.customerId) });
|
await db.customers.deleteOne({ _id: getId(req.body.customerId) });
|
||||||
indexCustomers(req.app)
|
indexCustomers(req.app)
|
||||||
.then(() => {
|
.then(() => {
|
||||||
res.status(200).json({ message: 'Customer deleted' });
|
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) => {
|
router.get('/admin/customer/view/:id?', restrict, async (req, res) => {
|
||||||
const db = req.app.db;
|
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(!customer){
|
||||||
// If API request, return json
|
// If API request, return json
|
||||||
|
@ -223,9 +327,9 @@ router.get('/admin/customer/view/:id?', restrict, async (req, res) => {
|
||||||
result: customer,
|
result: customer,
|
||||||
admin: true,
|
admin: true,
|
||||||
session: req.session,
|
session: req.session,
|
||||||
message: common.clearSessionValue(req.session, 'message'),
|
message: clearSessionValue(req.session, 'message'),
|
||||||
messageType: common.clearSessionValue(req.session, 'messageType'),
|
messageType: clearSessionValue(req.session, 'messageType'),
|
||||||
countryList: common.getCountryList(),
|
countryList: getCountryList(),
|
||||||
config: req.app.config,
|
config: req.app.config,
|
||||||
editor: true,
|
editor: true,
|
||||||
helpers: req.handlebars.helpers
|
helpers: req.handlebars.helpers
|
||||||
|
@ -249,8 +353,8 @@ router.get('/admin/customers', restrict, async (req, res) => {
|
||||||
customers: customers,
|
customers: customers,
|
||||||
session: req.session,
|
session: req.session,
|
||||||
helpers: req.handlebars.helpers,
|
helpers: req.handlebars.helpers,
|
||||||
message: common.clearSessionValue(req.session, 'message'),
|
message: clearSessionValue(req.session, 'message'),
|
||||||
messageType: common.clearSessionValue(req.session, 'messageType'),
|
messageType: clearSessionValue(req.session, 'messageType'),
|
||||||
config: req.app.config
|
config: req.app.config
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -263,7 +367,7 @@ router.get('/admin/customers/filter/:search', restrict, async (req, res, next) =
|
||||||
|
|
||||||
const lunrIdArray = [];
|
const lunrIdArray = [];
|
||||||
customersIndex.search(searchTerm).forEach((id) => {
|
customersIndex.search(searchTerm).forEach((id) => {
|
||||||
lunrIdArray.push(common.getId(id.ref));
|
lunrIdArray.push(getId(id.ref));
|
||||||
});
|
});
|
||||||
|
|
||||||
// we search on the lunr indexes
|
// 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,
|
config: req.app.config,
|
||||||
session: req.session,
|
session: req.session,
|
||||||
searchTerm: searchTerm,
|
searchTerm: searchTerm,
|
||||||
message: common.clearSessionValue(req.session, 'message'),
|
message: clearSessionValue(req.session, 'message'),
|
||||||
messageType: common.clearSessionValue(req.session, 'messageType'),
|
messageType: clearSessionValue(req.session, 'messageType'),
|
||||||
helpers: req.handlebars.helpers
|
helpers: req.handlebars.helpers
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -298,6 +402,7 @@ router.post('/admin/customer/lookup', restrict, async (req, res, next) => {
|
||||||
|
|
||||||
if(customer){
|
if(customer){
|
||||||
req.session.customerPresent = true;
|
req.session.customerPresent = true;
|
||||||
|
req.session.customerId = customer._id;
|
||||||
req.session.customerEmail = customer.email;
|
req.session.customerEmail = customer.email;
|
||||||
req.session.customerCompany = customer.company;
|
req.session.customerCompany = customer.company;
|
||||||
req.session.customerFirstname = customer.firstName;
|
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
|
// login the customer and check the password
|
||||||
router.post('/customer/login_action', async (req, res) => {
|
router.post('/customer/login_action', async (req, res) => {
|
||||||
const db = req.app.db;
|
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
|
// check if customer exists with that email
|
||||||
if(customer === undefined || customer === null){
|
if(customer === undefined || customer === null){
|
||||||
res.status(400).json({
|
res.status(400).json({
|
||||||
|
@ -344,6 +462,7 @@ router.post('/customer/login_action', async (req, res) => {
|
||||||
|
|
||||||
// Customer login successful
|
// Customer login successful
|
||||||
req.session.customerPresent = true;
|
req.session.customerPresent = true;
|
||||||
|
req.session.customerId = customer._id;
|
||||||
req.session.customerEmail = customer.email;
|
req.session.customerEmail = customer.email;
|
||||||
req.session.customerCompany = customer.company;
|
req.session.customerCompany = customer.company;
|
||||||
req.session.customerFirstname = customer.firstName;
|
req.session.customerFirstname = customer.firstName;
|
||||||
|
@ -375,8 +494,8 @@ router.get('/customer/forgotten', (req, res) => {
|
||||||
forgotType: 'customer',
|
forgotType: 'customer',
|
||||||
config: req.app.config,
|
config: req.app.config,
|
||||||
helpers: req.handlebars.helpers,
|
helpers: req.handlebars.helpers,
|
||||||
message: common.clearSessionValue(req.session, 'message'),
|
message: clearSessionValue(req.session, 'message'),
|
||||||
messageType: common.clearSessionValue(req.session, 'messageType'),
|
messageType: clearSessionValue(req.session, 'messageType'),
|
||||||
showFooter: 'showFooter'
|
showFooter: 'showFooter'
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -411,7 +530,7 @@ router.post('/customer/forgotten_action', apiLimiter, async (req, res) => {
|
||||||
|
|
||||||
// send the email with token to the user
|
// send the email with token to the user
|
||||||
// TODO: Should fix this to properly handle result
|
// 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({
|
res.status(200).json({
|
||||||
message: 'If your account exists, a password reset has been sent to your email'
|
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,
|
token: req.params.token,
|
||||||
route: 'customer',
|
route: 'customer',
|
||||||
config: req.app.config,
|
config: req.app.config,
|
||||||
message: common.clearSessionValue(req.session, 'message'),
|
message: clearSessionValue(req.session, 'message'),
|
||||||
message_type: common.clearSessionValue(req.session, 'message_type'),
|
message_type: clearSessionValue(req.session, 'message_type'),
|
||||||
show_footer: 'show_footer',
|
show_footer: 'show_footer',
|
||||||
helpers: req.handlebars.helpers
|
helpers: req.handlebars.helpers
|
||||||
});
|
});
|
||||||
|
@ -471,7 +590,7 @@ router.post('/customer/reset/:token', async (req, res) => {
|
||||||
};
|
};
|
||||||
|
|
||||||
// TODO: Should fix this to properly handle result
|
// 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 = 'Password successfully updated';
|
||||||
req.session.message_type = 'success';
|
req.session.message_type = 'success';
|
||||||
return res.redirect('/checkout/payment');
|
return res.redirect('/checkout/payment');
|
||||||
|
@ -486,8 +605,15 @@ router.post('/customer/reset/:token', async (req, res) => {
|
||||||
// logout the customer
|
// logout the customer
|
||||||
router.post('/customer/logout', (req, res) => {
|
router.post('/customer/logout', (req, res) => {
|
||||||
// Clear our session
|
// Clear our session
|
||||||
common.clearCustomer(req);
|
clearCustomer(req);
|
||||||
res.status(200).json({});
|
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;
|
module.exports = router;
|
||||||
|
|
|
@ -80,6 +80,7 @@ router.post('/checkout_action', async (req, res, next) => {
|
||||||
orderShipping: req.session.totalCartShipping,
|
orderShipping: req.session.totalCartShipping,
|
||||||
orderItemCount: req.session.totalCartItems,
|
orderItemCount: req.session.totalCartItems,
|
||||||
orderProductCount: req.session.totalCartProducts,
|
orderProductCount: req.session.totalCartProducts,
|
||||||
|
orderCustomer: common.getId(req.session.customerId),
|
||||||
orderEmail: req.session.customerEmail,
|
orderEmail: req.session.customerEmail,
|
||||||
orderCompany: req.session.customerCompany,
|
orderCompany: req.session.customerCompany,
|
||||||
orderFirstname: req.session.customerFirstname,
|
orderFirstname: req.session.customerFirstname,
|
||||||
|
|
|
@ -63,6 +63,7 @@ router.post('/checkout_action', (req, res, next) => {
|
||||||
orderShipping: req.session.totalCartShipping,
|
orderShipping: req.session.totalCartShipping,
|
||||||
orderItemCount: req.session.totalCartItems,
|
orderItemCount: req.session.totalCartItems,
|
||||||
orderProductCount: req.session.totalCartProducts,
|
orderProductCount: req.session.totalCartProducts,
|
||||||
|
orderCustomer: common.getId(req.session.customerId),
|
||||||
orderEmail: req.session.customerEmail,
|
orderEmail: req.session.customerEmail,
|
||||||
orderCompany: req.session.customerCompany,
|
orderCompany: req.session.customerCompany,
|
||||||
orderFirstname: req.session.customerFirstname,
|
orderFirstname: req.session.customerFirstname,
|
||||||
|
|
|
@ -94,6 +94,7 @@ router.post('/checkout_action', (req, res, next) => {
|
||||||
orderShipping: req.session.totalCartShipping,
|
orderShipping: req.session.totalCartShipping,
|
||||||
orderItemCount: req.session.totalCartItems,
|
orderItemCount: req.session.totalCartItems,
|
||||||
orderProductCount: req.session.totalCartProducts,
|
orderProductCount: req.session.totalCartProducts,
|
||||||
|
orderCustomer: common.getId(req.session.customerId),
|
||||||
orderEmail: req.session.customerEmail,
|
orderEmail: req.session.customerEmail,
|
||||||
orderCompany: req.session.customerCompany,
|
orderCompany: req.session.customerCompany,
|
||||||
orderFirstname: req.session.customerFirstname,
|
orderFirstname: req.session.customerFirstname,
|
||||||
|
|
|
@ -17,6 +17,7 @@ router.post('/checkout_action', async (req, res, next) => {
|
||||||
orderShipping: 0,
|
orderShipping: 0,
|
||||||
orderItemCount: req.session.totalCartItems,
|
orderItemCount: req.session.totalCartItems,
|
||||||
orderProductCount: req.session.totalCartProducts,
|
orderProductCount: req.session.totalCartProducts,
|
||||||
|
orderCustomer: common.getId(req.session.customerId),
|
||||||
orderEmail: req.session.customerEmail,
|
orderEmail: req.session.customerEmail,
|
||||||
orderCompany: req.session.customerCompany,
|
orderCompany: req.session.customerCompany,
|
||||||
orderFirstname: req.session.customerFirstname,
|
orderFirstname: req.session.customerFirstname,
|
||||||
|
|
|
@ -166,6 +166,7 @@ router.post('/checkout_action', (req, res, next) => {
|
||||||
orderShipping: req.session.totalCartShipping,
|
orderShipping: req.session.totalCartShipping,
|
||||||
orderItemCount: req.session.totalCartItems,
|
orderItemCount: req.session.totalCartItems,
|
||||||
orderProductCount: req.session.totalCartProducts,
|
orderProductCount: req.session.totalCartProducts,
|
||||||
|
orderCustomer: common.getId(req.session.customerId),
|
||||||
orderEmail: req.session.customerEmail,
|
orderEmail: req.session.customerEmail,
|
||||||
orderCompany: req.session.customerCompany,
|
orderCompany: req.session.customerCompany,
|
||||||
orderFirstname: req.session.customerFirstname,
|
orderFirstname: req.session.customerFirstname,
|
||||||
|
|
|
@ -56,6 +56,7 @@ router.post('/checkout_action', (req, res, next) => {
|
||||||
orderShipping: req.session.totalCartShipping,
|
orderShipping: req.session.totalCartShipping,
|
||||||
orderItemCount: req.session.totalCartItems,
|
orderItemCount: req.session.totalCartItems,
|
||||||
orderProductCount: req.session.totalCartProducts,
|
orderProductCount: req.session.totalCartProducts,
|
||||||
|
orderCustomer: common.getId(req.session.customerId),
|
||||||
orderEmail: req.session.customerEmail,
|
orderEmail: req.session.customerEmail,
|
||||||
orderCompany: req.session.customerCompany,
|
orderCompany: req.session.customerCompany,
|
||||||
orderFirstname: req.session.customerFirstname,
|
orderFirstname: req.session.customerFirstname,
|
||||||
|
|
|
@ -78,9 +78,10 @@ test('[Fail] Create with invalid email address', async t => {
|
||||||
t.deepEqual(res.body[0].message, 'should match format "emailAddress"');
|
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 = {
|
const customer = {
|
||||||
customerId: g.customers[1]._id,
|
customerId: g.customers[1]._id,
|
||||||
|
company: 'Acme Co',
|
||||||
email: 'sarah.jones@test.com',
|
email: 'sarah.jones@test.com',
|
||||||
firstName: 'Sarah',
|
firstName: 'Sarah',
|
||||||
lastName: 'Jones',
|
lastName: 'Jones',
|
||||||
|
@ -99,6 +100,47 @@ test('[Success] Update existing customer', async t => {
|
||||||
.expect(200);
|
.expect(200);
|
||||||
|
|
||||||
t.deepEqual(res.body.message, 'Customer updated');
|
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.email, customer.email);
|
||||||
t.deepEqual(res.body.customer.firstName, customer.firstName);
|
t.deepEqual(res.body.customer.firstName, customer.firstName);
|
||||||
t.deepEqual(res.body.customer.lastName, customer.lastName);
|
t.deepEqual(res.body.customer.lastName, customer.lastName);
|
||||||
|
|
|
@ -185,6 +185,19 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{{/ifCond}}
|
{{/ifCond}}
|
||||||
|
{{#if @root.session.customerPresent}}
|
||||||
|
<div class="dropdown d-none d-sm-block">
|
||||||
|
<button class="btn dropdown-toggle" type="button" id="dropdownMenuButton" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
|
||||||
|
{{{feather 'user'}}}
|
||||||
|
</button>
|
||||||
|
<div class="dropdown-menu" aria-labelledby="dropdownMenuButton">
|
||||||
|
<li><a class="dropdown-item" href="/customer/account">Account</a></li>
|
||||||
|
<li><a class="dropdown-item" href="/customer/logout">Logout</a></li>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{{else}}
|
||||||
|
<li class="nav-item ml-3"><a href="/customer/account" class="btn">{{{feather 'user'}}}</a></li>
|
||||||
|
{{/if}}
|
||||||
{{#if @root.session.cart}}
|
{{#if @root.session.cart}}
|
||||||
<li class="nav-item"><a href="/checkout/cart" class="btn menu-btn">{{{feather 'shopping-cart'}}} {{ @root.__ "Cart" }} <span class="badge badge-danger" id="cart-count">{{@root.session.totalCartItems}}</span></a></li>
|
<li class="nav-item"><a href="/checkout/cart" class="btn menu-btn">{{{feather 'shopping-cart'}}} {{ @root.__ "Cart" }} <span class="badge badge-danger" id="cart-count">{{@root.session.totalCartItems}}</span></a></li>
|
||||||
{{else}}
|
{{else}}
|
||||||
|
|
|
@ -9,7 +9,7 @@
|
||||||
</div>
|
</div>
|
||||||
<div id="draggable_list">
|
<div id="draggable_list">
|
||||||
{{#each menu.items}}
|
{{#each menu.items}}
|
||||||
<div class="row drag-row" id="menuId-{{@key}}">
|
<div class="row drag-row mb-2" id="menuId-{{@key}}">
|
||||||
<input type="hidden" class="navId" value="{{title}}">
|
<input type="hidden" class="navId" value="{{title}}">
|
||||||
<div class="col-sm-1 dragable_item">{{{feather 'move'}}}</div>
|
<div class="col-sm-1 dragable_item">{{{feather 'move'}}}</div>
|
||||||
<div class="col-sm-2 dragable_item">
|
<div class="col-sm-2 dragable_item">
|
||||||
|
@ -42,7 +42,7 @@
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<p class="text-muted">
|
<p class="text-muted mt-4">
|
||||||
{{ @root.__ "Setting_menu_explain" }}
|
{{ @root.__ "Setting_menu_explain" }}
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -0,0 +1,129 @@
|
||||||
|
<div class="col-md-10 offset-md-1 col-sm-12">
|
||||||
|
<nav aria-label="breadcrumb">
|
||||||
|
<ol class="breadcrumb">
|
||||||
|
<li class="breadcrumb-item"><a href="/">Home</a></li>
|
||||||
|
<li class="breadcrumb-item active" aria-current="page"><a href="/customer/account">Orders</a></li>
|
||||||
|
</ol>
|
||||||
|
</nav>
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-12 col-md-5 bottom-pad-15">
|
||||||
|
<div class="card top-marg-15">
|
||||||
|
<div class="card-body customer-details-login">
|
||||||
|
<h5 class="card-heading">{{ @root.__ "Customer details" }}</h5>
|
||||||
|
{{#unless @root.session.customerPresent}}
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-sm-12 bottom-marg-15">
|
||||||
|
<p>{{ @root.__ "Existing customer" }}</p>
|
||||||
|
<div class="form-group">
|
||||||
|
<input type="email" class="form-control" id="customerLoginEmail" name="loginEmail"
|
||||||
|
minlength="5" placeholder="Email address" required>
|
||||||
|
</div>
|
||||||
|
<div class="form-group">
|
||||||
|
<input type="password" class="form-control" id="customerLoginPassword"
|
||||||
|
name="loginPassword" minlength="5" placeholder="Password" required>
|
||||||
|
</div>
|
||||||
|
<div class="form-group">
|
||||||
|
<a href="/customer/forgotten"
|
||||||
|
class="btn btn-primary float-left">{{ @root.__ "Forgotten" }}</a>
|
||||||
|
</div>
|
||||||
|
<div class="form-group">
|
||||||
|
<button id="customerLogin" class="btn btn-primary float-right"
|
||||||
|
type="submit">Login</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{{/unless}}
|
||||||
|
<form id="customer-form" role="form" data-toggle="validator" novalidate="false">
|
||||||
|
{{> themes/Cloth/shipping-form}}
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-sm-12">
|
||||||
|
<a href="/checkout/cart" id="customerSave" class="btn btn-primary float-left">Save details</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="col-md-7">
|
||||||
|
<div class="col-12 bottom-pad-15 no-pad-right">
|
||||||
|
<div class="card top-marg-15">
|
||||||
|
<div class="card-body">
|
||||||
|
<h5 class="card-heading">{{ @root.__ "Orders" }}</h5>
|
||||||
|
<div id="accordion">
|
||||||
|
{{#each orders}}
|
||||||
|
<div class="card mb-3">
|
||||||
|
<div class="card-header" id="headingOne">
|
||||||
|
<p class="mb-0">
|
||||||
|
OrderId: {{this._id}} -
|
||||||
|
Date: {{formatDate this.orderDate "DD/MM/YYYY hh:mmA"}}
|
||||||
|
<button class="btn btn-sm btn-outline-success float-right" data-toggle="collapse" data-target="#collapse{{this._id}}" aria-expanded="true" aria-controls="collapse{{this._id}}">
|
||||||
|
View
|
||||||
|
</button>
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
<div id="collapse{{this._id}}" class="collapse" aria-labelledby="headingOne" data-parent="#accordion">
|
||||||
|
<div class="card-body">
|
||||||
|
<ul class="list-group">
|
||||||
|
<li class="list-group-item list-group-input-pad">
|
||||||
|
<strong> Order status: </strong><span class="text-{{getStatusColor this.orderStatus}} float-right">{{this.orderStatus}}</span>
|
||||||
|
</li>
|
||||||
|
<li class="list-group-item"><strong> {{ @root.__ "Order date" }}: </strong><span class="float-right">{{formatDate result.orderDate "DD/MM/YYYY hh:mmA"}}</span></li>
|
||||||
|
<li class="list-group-item"><strong> {{ @root.__ "Order ID" }}: </strong><span class="float-right">{{this._id}}</span></li>
|
||||||
|
{{#if result.orderExpectedBtc }}
|
||||||
|
<li class="list-group-item"><strong> {{ @root.__ "Order Expected BTC" }}: </strong><span class="float-right">{{this.orderExpectedBtc}}</span></li>
|
||||||
|
{{/if}}
|
||||||
|
{{#if this.orderReceivedBtc }}
|
||||||
|
<li class="list-group-item"><strong> {{ @root.__ "Order Received BTC" }}: </strong><span class="float-right">{{this.orderReceivedBtc}}</span></li>
|
||||||
|
{{/if}}
|
||||||
|
{{#if this.orderBlockonomicsTxid }}
|
||||||
|
<li class="list-group-item"><strong> {{ @root.__ "Order Blockonomics Txid" }}: </strong><span class="float-right">{{this.orderBlockonomicsTxid}}</span></li>
|
||||||
|
{{/if}}
|
||||||
|
<li class="list-group-item"><strong> {{ @root.__ "Order net amount" }}: </strong><span class="float-right">{{currencySymbol config.currencySymbol}}{{formatAmount (math this.orderTotal '-' this.orderShipping)}}</span></li>
|
||||||
|
<li class="list-group-item"><strong> {{ @root.__ "Order shipping amount" }}: </strong><span class="float-right">{{currencySymbol config.currencySymbol}}{{formatAmount this.orderShipping}}</span></li>
|
||||||
|
<li class="list-group-item"><strong> {{ @root.__ "Order total amount" }}: </strong><span class="float-right">{{currencySymbol config.currencySymbol}}{{formatAmount this.orderTotal}}</span></li>
|
||||||
|
<li class="list-group-item"><strong> {{ @root.__ "Email address" }}: </strong><span class="float-right">{{this.orderEmail}}</span></li>
|
||||||
|
<li class="list-group-item"><strong> {{ @root.__ "Company" }}: </strong><span class="float-right">{{this.orderCompany}}</span></li>
|
||||||
|
<li class="list-group-item"><strong> {{ @root.__ "First name" }}: </strong><span class="float-right">{{this.orderFirstname}}</span></li>
|
||||||
|
<li class="list-group-item"><strong> {{ @root.__ "Last name" }}: </strong><span class="float-right">{{this.orderLastname}}</span></li>
|
||||||
|
<li class="list-group-item"><strong> {{ @root.__ "Address 1" }}: </strong><span class="float-right">{{this.orderAddr1}}</span></li>
|
||||||
|
<li class="list-group-item"><strong> {{ @root.__ "Address 2" }}: </strong><span class="float-right">{{this.orderAddr2}}</span></li>
|
||||||
|
<li class="list-group-item"><strong> {{ @root.__ "Country" }}: </strong><span class="float-right">{{this.orderCountry}}</span></li>
|
||||||
|
<li class="list-group-item"><strong> {{ @root.__ "State" }}: </strong><span class="float-right">{{this.orderState}}</span></li>
|
||||||
|
<li class="list-group-item"><strong> {{ @root.__ "Postcode" }}: </strong><span class="float-right">{{this.orderPostcode}}</span></li>
|
||||||
|
<li class="list-group-item"><strong> {{ @root.__ "Phone number" }}: </strong><span class="float-right">{{this.orderPhoneNumber}}</span></li>
|
||||||
|
<li class="list-group-item"> </li>
|
||||||
|
<li class="list-group-item"><strong class="text-info">{{ @root.__ "Products ordered" }}</strong></li>
|
||||||
|
{{#each this.orderProducts}}
|
||||||
|
<li class="list-group-item">
|
||||||
|
{{this.quantity}} x {{this.title}}
|
||||||
|
{{#if this.options}}
|
||||||
|
>
|
||||||
|
<span class="text-warning"> {{ @root.__ "Options" }}: </span>
|
||||||
|
(
|
||||||
|
{{#each this.options}}
|
||||||
|
{{#if @last}}
|
||||||
|
<strong>{{#upperFirst this.name}}{{/upperFirst}}</strong>: {{this.value}}
|
||||||
|
{{else}}
|
||||||
|
<strong>{{#upperFirst this.name}}{{/upperFirst}}:</strong> {{this.value}} /
|
||||||
|
{{/if}}
|
||||||
|
{{/each}}
|
||||||
|
)
|
||||||
|
{{/if}}
|
||||||
|
<div class="float-right">{{currencySymbol @root.config.currencySymbol}}{{formatAmount this.totalItemPrice}}</div>
|
||||||
|
{{#if productComment}}
|
||||||
|
<h4><span class="text-danger">Comment:</span> {{this.productComment}}</h4>
|
||||||
|
{{/if}}
|
||||||
|
</li>
|
||||||
|
{{/each}}
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{{/each}}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
|
@ -0,0 +1,12 @@
|
||||||
|
<div class="col-md-4 offset-md-4 top-pad-100">
|
||||||
|
<form class="form-signin" method="post" role="form" data-toggle="validator">
|
||||||
|
<h2 class="form-signin-heading">{{ @root.__ "Please sign in" }}</h2>
|
||||||
|
<div class="form-group">
|
||||||
|
<input type="email" id="email" name="email" class="form-control" placeholder="email address" required autofocus>
|
||||||
|
</div>
|
||||||
|
<div class="form-group">
|
||||||
|
<input type="password" id="password" name="password" class="form-control" placeholder="Password" required>
|
||||||
|
</div>
|
||||||
|
<button class="btn btn-outline-primary btn-block" id="customerloginForm" type="submit">{{ @root.__ "Sign in" }}</button>
|
||||||
|
</form>
|
||||||
|
</div>
|
Loading…
Reference in New Issue