Added support for returning customers
							parent
							
								
									3730f84796
								
							
						
					
					
						commit
						6076455d06
					
				
							
								
								
									
										1
									
								
								app.js
								
								
								
								
							
							
						
						
									
										1
									
								
								app.js
								
								
								
								
							|  | @ -288,6 +288,7 @@ MongoClient.connect(config.databaseConnectionString, {}, (err, client) => { | |||
|     db.orders = db.collection('orders'); | ||||
|     db.pages = db.collection('pages'); | ||||
|     db.menu = db.collection('menu'); | ||||
|     db.customers = db.collection('customers'); | ||||
| 
 | ||||
|     // add db to app for routes
 | ||||
|     app.db = db; | ||||
|  |  | |||
|  | @ -32,6 +32,7 @@ | |||
|     "nodemailer": "^4.4.1", | ||||
|     "numeral": "^2.0.6", | ||||
|     "paypal-rest-sdk": "^1.6.9", | ||||
|     "rand-token": "^0.4.0", | ||||
|     "rimraf": "^2.6.2", | ||||
|     "sitemap": "^1.6.0", | ||||
|     "stripe": "^5.4.0", | ||||
|  |  | |||
|  | @ -294,6 +294,79 @@ $(document).ready(function (){ | |||
|         } | ||||
|     }); | ||||
| 
 | ||||
|     $('#customerLogout').on('click', function(e){ | ||||
|         $.ajax({ | ||||
|             method: 'POST', | ||||
|             url: '/customer/logout', | ||||
|             data: {} | ||||
|         }) | ||||
|         .done(function(msg){ | ||||
|             location.reload(); | ||||
|         }); | ||||
|     }); | ||||
| 
 | ||||
|     $('#createCustomerAccount').validator().on('click', function(e){ | ||||
|         e.preventDefault(); | ||||
|         if($('#shipping-form').validator('validate').has('.has-error').length === 0){ | ||||
|             $.ajax({ | ||||
|                 method: 'POST', | ||||
|                 url: '/customer/create', | ||||
|                 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() | ||||
|                 } | ||||
|             }) | ||||
|             .done(function(msg){ | ||||
|                 // Just reload to fill in the form from session
 | ||||
|                 location.reload(); | ||||
|             }) | ||||
|             .fail(function(msg){ | ||||
|                 showNotification(msg.responseJSON.err, 'danger'); | ||||
|             }); | ||||
|         } | ||||
|     }); | ||||
| 
 | ||||
|     // call update settings API
 | ||||
|     $('#customerLogin').on('click', function(e){ | ||||
|         if(!e.isDefaultPrevented()){ | ||||
|             e.preventDefault(); | ||||
|             $.ajax({ | ||||
|                 method: 'POST', | ||||
|                 url: '/customer/login_action', | ||||
|                 data: { | ||||
|                     loginEmail: $('#customerLoginEmail').val(), | ||||
|                     loginPassword: $('#customerLoginPassword').val() | ||||
|                 } | ||||
|             }) | ||||
|             .done(function(msg){ | ||||
|                 var customer = msg.customer; | ||||
|                 // Fill in customer form
 | ||||
|                 $('#shipEmail').val(customer.email); | ||||
|                 $('#shipFirstname').val(customer.firstName); | ||||
|                 $('#shipLastname').val(customer.lastName); | ||||
|                 $('#shipAddr1').val(customer.address1); | ||||
|                 $('#shipAddr2').val(customer.address2); | ||||
|                 $('#shipCountry').val(customer.country); | ||||
|                 $('#shipState').val(customer.state); | ||||
|                 $('#shipPostcode').val(customer.postcode); | ||||
|                 $('#shipPhoneNumber').val(customer.phone); | ||||
|                 location.reload(); | ||||
|             }) | ||||
|             .fail(function(msg){ | ||||
|                 showNotification(msg.responseJSON.err, 'danger'); | ||||
|             }); | ||||
|         } | ||||
|         e.preventDefault(); | ||||
|     }); | ||||
| 
 | ||||
|     $(document).on('click', '.image-next', function(e){ | ||||
|         var thumbnails = $('.thumbnail-image'); | ||||
|         var index = 0; | ||||
|  | @ -491,21 +564,20 @@ $(document).ready(function (){ | |||
|         } | ||||
|     }); | ||||
| 
 | ||||
|     // applies an product filter
 | ||||
|     $(document).on('click', '#btn_customer_filter', function(e){ | ||||
|         if($('#customer_filter').val() !== ''){ | ||||
|             window.location.href = '/admin/customers/filter/' + $('#customer_filter').val(); | ||||
|         }else{ | ||||
|             showNotification('Please enter a keyword to filter', 'danger'); | ||||
|         } | ||||
|     }); | ||||
| 
 | ||||
|     // resets the order filter
 | ||||
|     $(document).on('click', '#btn_search_reset', function(e){ | ||||
|         window.location.replace('/'); | ||||
|     }); | ||||
| 
 | ||||
|     // resets the product filter
 | ||||
|     $(document).on('click', '#btn_product_reset', function(e){ | ||||
|         window.location.href = '/admin/products'; | ||||
|     }); | ||||
| 
 | ||||
| 	// resets the order filter
 | ||||
|     $(document).on('click', '#btn_order_reset', function(e){ | ||||
|         window.location.href = '/admin/orders'; | ||||
|     }); | ||||
| 
 | ||||
|     // search button click event
 | ||||
|     $(document).on('click', '#btn_search', function(e){ | ||||
|         e.preventDefault(); | ||||
|  |  | |||
										
											
												File diff suppressed because one or more lines are too long
											
										
									
								
							|  | @ -6,59 +6,93 @@ | |||
|         <div class="col-md-5"> | ||||
|             <div class="panel panel-default" style="margin-top: 30px;"> | ||||
|                 <div class="panel-heading">Customer details</div> | ||||
|                 {{#unless session.customer}} | ||||
|                 <div class="panel-body customer-details-login"> | ||||
|                     <p>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-default pull-left">Forgotten</a> | ||||
|                     </div> | ||||
|                     <div class="form-group"> | ||||
|                         <button id="customerLogin" class="btn btn-success pull-right" type="submit">Login</button> | ||||
|                     </div> | ||||
|                 </div> | ||||
|                 {{/unless}} | ||||
|                 <div class="panel-body customer-details"> | ||||
|                     {{#if session.customer}} | ||||
|                     <div class="col-xs-12 col-md-12"> | ||||
|                         <button id="customerLogout" class="btn btn-sm btn-success pull-right">Change customer</button> | ||||
|                     </div> | ||||
|                     {{/if}} | ||||
|                     <form id="shipping-form" class="shipping-form" action="/{{config.paymentGateway}}/checkout_action" method="post" role="form" data-toggle="validator" novalidate="false"> | ||||
|                         <div class="col-xs-12 col-md-12"> | ||||
|                             <div class="form-group"> | ||||
|                                 <input type="email" class="form-control customerDetails" id="shipEmail" name="shipEmail" minlength="5" placeholder="Email address" required> | ||||
|                                 <input type="email" class="form-control customerDetails" id="shipEmail" name="shipEmail" minlength="5" placeholder="Email address" value="{{session.customer.email}}" required> | ||||
|                             </div> | ||||
|                         </div> | ||||
|                         <div class="col-xs-12 col-md-6"> | ||||
|                             <div class="form-group"> | ||||
|                                 <input type="text" class="form-control customerDetails" id="shipFirstname" name="shipFirstname" placeholder="First name" required> | ||||
|                                 <input type="text" class="form-control customerDetails" id="shipFirstname" name="shipFirstname" placeholder="First name" value="{{session.customer.firstName}}" required> | ||||
|                             </div> | ||||
|                         </div> | ||||
|                         <div class="col-xs-12 col-md-6"> | ||||
|                             <div class="form-group"> | ||||
|                                 <input type="text" class="form-control customerDetails" id="shipLastname" name="shipLastname" placeholder="Last name" required> | ||||
|                                 <input type="text" class="form-control customerDetails" id="shipLastname" name="shipLastname" placeholder="Last name" value="{{session.customer.lastName}}" required> | ||||
|                             </div> | ||||
|                         </div> | ||||
|                         <div class="col-xs-12 col-md-12"> | ||||
|                             <div class="form-group"> | ||||
|                                 <input type="text" class="form-control customerDetails" id="shipAddr1" name="shipAddr1" placeholder="Address 1" required> | ||||
|                                 <input type="text" class="form-control customerDetails" id="shipAddr1" name="shipAddr1" placeholder="Address 1" value="{{session.customer.address1}}" required> | ||||
|                             </div> | ||||
|                         </div> | ||||
|                         <div class="col-xs-12 col-md-12"> | ||||
|                             <div class="form-group"> | ||||
|                                 <input type="text" class="form-control customerDetails" id="shipAddr2" name="shipAddr2" placeholder="Address 2 (optional)"> | ||||
|                                 <input type="text" class="form-control customerDetails" id="shipAddr2" name="shipAddr2" placeholder="Address 2 (optional)" value="{{session.customer.address1}}"> | ||||
|                             </div> | ||||
|                         </div> | ||||
|                         <div class="col-xs-12 col-md-4"> | ||||
|                             <div class="form-group"> | ||||
|                                 <input type="text" class="form-control customerDetails" id="shipCountry" name="shipCountry" placeholder="Country" required> | ||||
|                                 <input type="text" class="form-control customerDetails" id="shipCountry" name="shipCountry" placeholder="Country" value="{{session.customer.country}}" required> | ||||
|                             </div> | ||||
|                         </div> | ||||
|                         <div class="col-xs-12 col-md-4"> | ||||
|                             <div class="form-group"> | ||||
|                                 <input type="text" class="form-control customerDetails" id="shipState" name="shipState" placeholder="State" required> | ||||
|                                 <input type="text" class="form-control customerDetails" id="shipState" name="shipState" placeholder="State" value="{{session.customer.state}}" required> | ||||
|                             </div> | ||||
|                         </div> | ||||
|                         <div class="col-xs-12 col-md-4"> | ||||
|                             <div class="form-group"> | ||||
|                                 <input type="number" class="form-control customerDetails" id="shipPostcode" name="shipPostcode" placeholder="Post code" required> | ||||
|                                 <input type="text" class="form-control customerDetails" id="shipPostcode" name="shipPostcode" placeholder="Post code" value="{{session.customer.postcode}}" required> | ||||
|                             </div> | ||||
|                         </div> | ||||
|                         <div class="col-xs-12 col-md-12"> | ||||
|                             <div class="form-group"> | ||||
|                                 <input type="number" class="form-control customerDetails" id="shipPhoneNumber" name="shipPhoneNumber" placeholder="Phone number (optional)"> | ||||
|                                 <input type="number" class="form-control customerDetails" id="shipPhoneNumber" name="shipPhoneNumber" placeholder="Phone number" value="{{session.customer.phone}}" required> | ||||
|                             </div> | ||||
|                         </div> | ||||
|                         {{#if session.customer}} | ||||
|                         {{#ifCond config.paymentGateway '==' 'paypal'}} | ||||
|                         <div class="paypal_button col-xs-12 col-md-12 text-center"> | ||||
|                             <button id="checkout_paypal" class="btn btn-success" type="submit"><i class="fa fa-cc-paypal fa-lg" aria-hidden="true"></i> Pay with PayPal <i class="fa fa-cc-paypal fa-lg" aria-hidden="true"></i></button> | ||||
|                         </div> | ||||
|                         {{/ifCond}} | ||||
|                         {{/if}} | ||||
|                         {{#unless session.customer}} | ||||
|                         <div class="col-xs-12 col-md-12"> | ||||
|                             <p class="text-muted">Enter a password to create an account for next time</p> | ||||
|                             <div class="form-group"> | ||||
|                                 <input type="password" class="form-control customerDetails" id="newCustomerPassword" name="newCustomerPassword" placeholder="Password" required> | ||||
|                             </div> | ||||
|                             <a id="createCustomerAccount" class="btn btn-success pull-right">Create account</a> | ||||
|                         </div> | ||||
|                         {{/unless}} | ||||
|                     </form> | ||||
|                     {{#if session.customer}} | ||||
|                     {{#ifCond config.paymentGateway '==' 'stripe'}} | ||||
|                     <div class="col-xs-12 col-md-12 text-center"> | ||||
|                         <form method="POST" id="payment-form"> | ||||
|  | @ -82,6 +116,8 @@ | |||
|                         </form> | ||||
|                     </div> | ||||
|                     {{/ifCond}} | ||||
|                     {{/if}} | ||||
| 
 | ||||
|                 </div> | ||||
|             </div> | ||||
|         </div> | ||||
|  |  | |||
							
								
								
									
										138
									
								
								routes/admin.js
								
								
								
								
							
							
						
						
									
										138
									
								
								routes/admin.js
								
								
								
								
							|  | @ -13,7 +13,7 @@ router.get('/', common.restrict, (req, res, next) => { | |||
| 
 | ||||
| // Admin section
 | ||||
| router.get('/orders', common.restrict, (req, res, next) => { | ||||
|     let db = req.app.db; | ||||
|     const db = req.app.db; | ||||
| 
 | ||||
|     // Top 10 products
 | ||||
|     common.dbQuery(db.orders, {}, {'orderDate': -1}, 10, (err, orders) => { | ||||
|  | @ -35,7 +35,7 @@ router.get('/orders', common.restrict, (req, res, next) => { | |||
| 
 | ||||
| // Admin section
 | ||||
| router.get('/orders/bystatus/:orderstatus', common.restrict, (req, res, next) => { | ||||
|     let db = req.app.db; | ||||
|     const db = req.app.db; | ||||
| 
 | ||||
|     if(typeof req.params.orderstatus === 'undefined'){ | ||||
|         res.redirect('/admin/orders'); | ||||
|  | @ -65,7 +65,7 @@ router.get('/orders/bystatus/:orderstatus', common.restrict, (req, res, next) => | |||
| 
 | ||||
| // render the editor
 | ||||
| router.get('/order/view/:id', common.restrict, (req, res) => { | ||||
|     let db = req.app.db; | ||||
|     const db = req.app.db; | ||||
|     db.orders.findOne({_id: common.getId(req.params.id)}, (err, result) => { | ||||
|         if(err){ | ||||
|             console.info(err.stack); | ||||
|  | @ -91,7 +91,7 @@ router.get('/order/view/:id', common.restrict, (req, res) => { | |||
| 
 | ||||
| // Admin section
 | ||||
| router.get('/orders/filter/:search', common.restrict, (req, res, next) => { | ||||
|     let db = req.app.db; | ||||
|     const db = req.app.db; | ||||
|     let searchTerm = req.params.search; | ||||
|     let ordersIndex = req.app.ordersIndex; | ||||
| 
 | ||||
|  | @ -121,7 +121,7 @@ router.get('/orders/filter/:search', common.restrict, (req, res, next) => { | |||
| 
 | ||||
| // order product
 | ||||
| router.get('/order/delete/:id', common.restrict, (req, res) => { | ||||
|     let db = req.app.db; | ||||
|     const db = req.app.db; | ||||
| 
 | ||||
|     // remove the article
 | ||||
|     db.orders.remove({_id: common.getId(req.params.id)}, {}, (err, numRemoved) => { | ||||
|  | @ -141,7 +141,7 @@ router.get('/order/delete/:id', common.restrict, (req, res) => { | |||
| 
 | ||||
| // update order status
 | ||||
| router.post('/order/statusupdate', common.restrict, (req, res) => { | ||||
|     let db = req.app.db; | ||||
|     const db = req.app.db; | ||||
|     db.orders.update({_id: common.getId(req.body.order_id)}, {$set: {orderStatus: req.body.status}}, {multi: false}, (err, numReplaced) => { | ||||
|         if(err){ | ||||
|             console.info(err.stack); | ||||
|  | @ -152,7 +152,7 @@ router.post('/order/statusupdate', common.restrict, (req, res) => { | |||
| 
 | ||||
| // Admin section
 | ||||
| router.get('/products', common.restrict, (req, res, next) => { | ||||
|     let db = req.app.db; | ||||
|     const db = req.app.db; | ||||
|     // get the top results
 | ||||
|     common.dbQuery(db.products, {}, {'productAddedDate': -1}, 10, (err, topResults) => { | ||||
|         if(err){ | ||||
|  | @ -173,7 +173,7 @@ router.get('/products', common.restrict, (req, res, next) => { | |||
| 
 | ||||
| // Admin section
 | ||||
| router.post('/product/addtocart', (req, res, next) => { | ||||
|     let db = req.app.db; | ||||
|     const db = req.app.db; | ||||
|     let productQuantity = req.body.productQuantity ? parseInt(req.body.productQuantity) : 1; | ||||
| 
 | ||||
|     // setup cart object if it doesn't exist
 | ||||
|  | @ -240,7 +240,7 @@ router.post('/product/addtocart', (req, res, next) => { | |||
| 
 | ||||
| // Updates a single product quantity
 | ||||
| router.post('/product/updatecart', (req, res, next) => { | ||||
|     let db = req.app.db; | ||||
|     const db = req.app.db; | ||||
|     let cartItems = JSON.parse(req.body.items); | ||||
|     let hasError = false; | ||||
| 
 | ||||
|  | @ -310,7 +310,7 @@ router.post('/product/emptycart', (req, res, next) => { | |||
| 
 | ||||
| // Admin section
 | ||||
| router.get('/products/filter/:search', common.restrict, (req, res, next) => { | ||||
|     let db = req.app.db; | ||||
|     const db = req.app.db; | ||||
|     let searchTerm = req.params.search; | ||||
|     let productsIndex = req.app.productsIndex; | ||||
| 
 | ||||
|  | @ -358,7 +358,7 @@ router.get('/product/new', common.restrict, (req, res) => { | |||
| 
 | ||||
| // insert new product form action
 | ||||
| router.post('/product/insert', common.restrict, (req, res) => { | ||||
|     let db = req.app.db; | ||||
|     const db = req.app.db; | ||||
| 
 | ||||
|     let doc = { | ||||
|         productPermalink: req.body.frmProductPermalink, | ||||
|  | @ -429,7 +429,7 @@ router.post('/product/insert', common.restrict, (req, res) => { | |||
| 
 | ||||
| // render the editor
 | ||||
| router.get('/product/edit/:id', common.restrict, (req, res) => { | ||||
|     let db = req.app.db; | ||||
|     const db = req.app.db; | ||||
| 
 | ||||
|     common.getImages(req.params.id, req, res, (images) => { | ||||
|         db.products.findOne({_id: common.getId(req.params.id)}, (err, result) => { | ||||
|  | @ -460,7 +460,7 @@ router.get('/product/edit/:id', common.restrict, (req, res) => { | |||
| 
 | ||||
| // Update an existing product form action
 | ||||
| router.post('/product/update', common.restrict, (req, res) => { | ||||
|     let db = req.app.db; | ||||
|     const db = req.app.db; | ||||
| 
 | ||||
|     db.products.findOne({_id: common.getId(req.body.frmProductId)}, (err, product) => { | ||||
|         if(err){ | ||||
|  | @ -540,7 +540,7 @@ router.post('/product/update', common.restrict, (req, res) => { | |||
| 
 | ||||
| // delete product
 | ||||
| router.get('/product/delete/:id', common.restrict, (req, res) => { | ||||
|     let db = req.app.db; | ||||
|     const db = req.app.db; | ||||
|     let rimraf = require('rimraf'); | ||||
| 
 | ||||
|     // remove the article
 | ||||
|  | @ -568,7 +568,7 @@ router.get('/product/delete/:id', common.restrict, (req, res) => { | |||
| 
 | ||||
| // users
 | ||||
| router.get('/users', common.restrict, (req, res) => { | ||||
|     let db = req.app.db; | ||||
|     const db = req.app.db; | ||||
|     db.users.find({}).toArray((err, users) => { | ||||
|         if(err){ | ||||
|             console.info(err.stack); | ||||
|  | @ -589,7 +589,7 @@ router.get('/users', common.restrict, (req, res) => { | |||
| 
 | ||||
| // edit user
 | ||||
| router.get('/user/edit/:id', common.restrict, (req, res) => { | ||||
|     let db = req.app.db; | ||||
|     const db = req.app.db; | ||||
|     db.users.findOne({_id: common.getId(req.params.id)}, (err, user) => { | ||||
|         if(err){ | ||||
|             console.info(err.stack); | ||||
|  | @ -618,7 +618,7 @@ router.get('/user/edit/:id', common.restrict, (req, res) => { | |||
| 
 | ||||
| // update a user
 | ||||
| router.post('/user/update', common.restrict, (req, res) => { | ||||
|     let db = req.app.db; | ||||
|     const db = req.app.db; | ||||
|     let bcrypt = req.bcrypt; | ||||
| 
 | ||||
|     let isAdmin = req.body.user_admin === 'on' ? 'true' : 'false'; | ||||
|  | @ -666,7 +666,7 @@ router.post('/user/update', common.restrict, (req, res) => { | |||
| 
 | ||||
| // insert a user
 | ||||
| router.post('/setup_action', (req, res) => { | ||||
|     let db = req.app.db; | ||||
|     const db = req.app.db; | ||||
|     let bcrypt = req.bcrypt; | ||||
| 
 | ||||
|     let doc = { | ||||
|  | @ -704,7 +704,7 @@ router.post('/setup_action', (req, res) => { | |||
| 
 | ||||
| // insert a user
 | ||||
| router.post('/user/insert', common.restrict, (req, res) => { | ||||
|     let db = req.app.db; | ||||
|     const db = req.app.db; | ||||
|     let bcrypt = req.bcrypt; | ||||
|     let url = require('url'); | ||||
| 
 | ||||
|  | @ -765,6 +765,79 @@ router.post('/user/insert', common.restrict, (req, res) => { | |||
|     }); | ||||
| }); | ||||
| 
 | ||||
| // render the customer view
 | ||||
| router.get('/customer/view/:id?', common.restrict, (req, res) => { | ||||
|     const db = req.app.db; | ||||
| 
 | ||||
|     console.log('here'); | ||||
| 
 | ||||
|     db.customers.findOne({_id: common.getId(req.params.id)}, (err, result) => { | ||||
|         if(err){ | ||||
|             console.info(err.stack); | ||||
|         } | ||||
| 
 | ||||
|         res.render('customer', { | ||||
|             title: 'View customer', | ||||
|             result: result, | ||||
|             admin: true, | ||||
|             session: req.session, | ||||
|             message: common.clearSessionValue(req.session, 'message'), | ||||
|             messageType: common.clearSessionValue(req.session, 'messageType'), | ||||
|             config: common.getConfig(), | ||||
|             editor: true, | ||||
|             helpers: req.handlebars.helpers | ||||
|         }); | ||||
|     }); | ||||
| }); | ||||
| 
 | ||||
| // customers list
 | ||||
| router.get('/customers', common.restrict, (req, res) => { | ||||
|     const db = req.app.db; | ||||
| 
 | ||||
|     db.customers.find({}).limit(20).sort({created: -1}).toArray((err, customers) => { | ||||
|         res.render('customers', { | ||||
|             title: 'Customers - List', | ||||
|             admin: true, | ||||
|             customers: customers, | ||||
|             session: req.session, | ||||
|             helpers: req.handlebars.helpers, | ||||
|             message: common.clearSessionValue(req.session, 'message'), | ||||
|             messageType: common.clearSessionValue(req.session, 'messageType'), | ||||
|             config: common.getConfig() | ||||
|         }); | ||||
|     }); | ||||
| }); | ||||
| 
 | ||||
| // Filtered customers list
 | ||||
| router.get('/customers/filter/:search', common.restrict, (req, res, next) => { | ||||
|     const db = req.app.db; | ||||
|     let searchTerm = req.params.search; | ||||
|     let customersIndex = req.app.customersIndex; | ||||
| 
 | ||||
|     let lunrIdArray = []; | ||||
|     customersIndex.search(searchTerm).forEach((id) => { | ||||
|         lunrIdArray.push(common.getId(id.ref)); | ||||
|     }); | ||||
| 
 | ||||
|     // we search on the lunr indexes
 | ||||
|     db.customers.find({_id: {$in: lunrIdArray}}).sort({created: -1}).toArray((err, customers) => { | ||||
|         if(err){ | ||||
|             console.error(colors.red('Error searching', err)); | ||||
|         } | ||||
|         res.render('customers', { | ||||
|             title: 'Customer results', | ||||
|             customers: customers, | ||||
|             admin: true, | ||||
|             config: common.getConfig(), | ||||
|             session: req.session, | ||||
|             searchTerm: searchTerm, | ||||
|             message: common.clearSessionValue(req.session, 'message'), | ||||
|             messageType: common.clearSessionValue(req.session, 'messageType'), | ||||
|             helpers: req.handlebars.helpers | ||||
|         }); | ||||
|     }); | ||||
| }); | ||||
| 
 | ||||
| // users new
 | ||||
| router.get('/user/new', common.restrict, (req, res) => { | ||||
|     res.render('user_new', { | ||||
|  | @ -780,7 +853,7 @@ router.get('/user/new', common.restrict, (req, res) => { | |||
| 
 | ||||
| // delete user
 | ||||
| router.get('/user/delete/:id', common.restrict, (req, res) => { | ||||
|     let db = req.app.db; | ||||
|     const db = req.app.db; | ||||
|     if(req.session.isAdmin === 'true'){ | ||||
|         db.users.remove({_id: common.getId(req.params.id)}, {}, (err, numRemoved) => { | ||||
|             if(err){ | ||||
|  | @ -825,7 +898,7 @@ router.post('/settings/update', common.restrict, (req, res) => { | |||
| 
 | ||||
| // settings update
 | ||||
| router.post('/settings/option/remove', common.restrict, (req, res) => { | ||||
|     let db = req.app.db; | ||||
|     const db = req.app.db; | ||||
|     db.products.findOne({_id: common.getId(req.body.productId)}, (err, product) => { | ||||
|         if(err){ | ||||
|             console.info(err.stack); | ||||
|  | @ -852,7 +925,7 @@ router.post('/settings/option/remove', common.restrict, (req, res) => { | |||
| 
 | ||||
| // settings update
 | ||||
| router.get('/settings/menu', common.restrict, async (req, res) => { | ||||
|     let db = req.app.db; | ||||
|     const db = req.app.db; | ||||
|     res.render('settings_menu', { | ||||
|         title: 'Cart menu', | ||||
|         session: req.session, | ||||
|  | @ -867,7 +940,7 @@ router.get('/settings/menu', common.restrict, async (req, res) => { | |||
| 
 | ||||
| // settings page list
 | ||||
| router.get('/settings/pages', common.restrict, (req, res) => { | ||||
|     let db = req.app.db; | ||||
|     const db = req.app.db; | ||||
|     common.dbQuery(db.pages, {}, null, null, async (err, pages) => { | ||||
|         if(err){ | ||||
|             console.info(err.stack); | ||||
|  | @ -889,7 +962,7 @@ router.get('/settings/pages', common.restrict, (req, res) => { | |||
| 
 | ||||
| // settings pages new
 | ||||
| router.get('/settings/pages/new', common.restrict, async (req, res) => { | ||||
|     let db = req.app.db; | ||||
|     const db = req.app.db; | ||||
| 
 | ||||
|     res.render('settings_page_edit', { | ||||
|         title: 'Static pages', | ||||
|  | @ -906,7 +979,7 @@ router.get('/settings/pages/new', common.restrict, async (req, res) => { | |||
| 
 | ||||
| // settings pages editor
 | ||||
| router.get('/settings/pages/edit/:page', common.restrict, (req, res) => { | ||||
|     let db = req.app.db; | ||||
|     const db = req.app.db; | ||||
|     db.pages.findOne({_id: common.getId(req.params.page)}, async (err, page) => { | ||||
|         if(err){ | ||||
|             console.info(err.stack); | ||||
|  | @ -942,7 +1015,7 @@ router.get('/settings/pages/edit/:page', common.restrict, (req, res) => { | |||
| 
 | ||||
| // settings update page
 | ||||
| router.post('/settings/pages/update', common.restrict, (req, res) => { | ||||
|     let db = req.app.db; | ||||
|     const db = req.app.db; | ||||
| 
 | ||||
|     let doc = { | ||||
|         pageName: req.body.pageName, | ||||
|  | @ -982,7 +1055,7 @@ router.post('/settings/pages/update', common.restrict, (req, res) => { | |||
| 
 | ||||
| // settings delete page
 | ||||
| router.get('/settings/pages/delete/:page', common.restrict, (req, res) => { | ||||
|     let db = req.app.db; | ||||
|     const db = req.app.db; | ||||
|     db.pages.remove({_id: common.getId(req.params.page)}, {}, (err, numRemoved) => { | ||||
|         if(err){ | ||||
|             req.session.message = 'Error deleting page. Please try again.'; | ||||
|  | @ -1040,7 +1113,7 @@ router.post('/settings/menu/save_order', common.restrict, (req, res) => { | |||
| router.post('/api/validate_permalink', (req, res) => { | ||||
|     // if doc id is provided it checks for permalink in any products other that one provided,
 | ||||
|     // else it just checks for any products with that permalink
 | ||||
|     let db = req.app.db; | ||||
|     const db = req.app.db; | ||||
| 
 | ||||
|     let query = {}; | ||||
|     if(typeof req.body.docId === 'undefined' || req.body.docId === ''){ | ||||
|  | @ -1065,7 +1138,7 @@ router.post('/api/validate_permalink', (req, res) => { | |||
| 
 | ||||
| // update the published state based on an ajax call from the frontend
 | ||||
| router.post('/product/published_state', common.restrict, (req, res) => { | ||||
|     let db = req.app.db; | ||||
|     const db = req.app.db; | ||||
| 
 | ||||
|     db.products.update({_id: common.getId(req.body.id)}, {$set: {productPublished: req.body.state}}, {multi: false}, (err, numReplaced) => { | ||||
|         if(err){ | ||||
|  | @ -1081,7 +1154,7 @@ router.post('/product/published_state', common.restrict, (req, res) => { | |||
| 
 | ||||
| // set as main product image
 | ||||
| router.post('/product/setasmainimage', common.restrict, (req, res) => { | ||||
|     let db = req.app.db; | ||||
|     const db = req.app.db; | ||||
| 
 | ||||
|     // update the productImage to the db
 | ||||
|     db.products.update({_id: common.getId(req.body.product_id)}, {$set: {productImage: req.body.productImage}}, {multi: false}, (err, numReplaced) => { | ||||
|  | @ -1095,7 +1168,7 @@ router.post('/product/setasmainimage', common.restrict, (req, res) => { | |||
| 
 | ||||
| // deletes a product image
 | ||||
| router.post('/product/deleteimage', common.restrict, (req, res) => { | ||||
|     let db = req.app.db; | ||||
|     const db = req.app.db; | ||||
|     let fs = require('fs'); | ||||
|     let path = require('path'); | ||||
| 
 | ||||
|  | @ -1136,7 +1209,7 @@ router.post('/product/deleteimage', common.restrict, (req, res) => { | |||
| let multer = require('multer'); | ||||
| let upload = multer({dest: 'public/uploads/'}); | ||||
| router.post('/file/upload', common.restrict, upload.single('upload_file'), (req, res, next) => { | ||||
|     let db = req.app.db; | ||||
|     const db = req.app.db; | ||||
|     let fs = require('fs'); | ||||
|     let path = require('path'); | ||||
| 
 | ||||
|  | @ -1195,6 +1268,7 @@ router.post('/file/upload', common.restrict, upload.single('upload_file'), (req, | |||
| // delete a file via ajax request
 | ||||
| router.post('/testEmail', common.restrict, (req, res) => { | ||||
|     let config = common.getConfig(); | ||||
|     // TODO: Should fix this to properly handle result
 | ||||
|     common.sendEmail(config.emailAddress, 'expressCart test email', 'Your email settings are working'); | ||||
|     res.status(200).json('Test email sent'); | ||||
| }); | ||||
|  |  | |||
							
								
								
									
										206
									
								
								routes/index.js
								
								
								
								
							
							
						
						
									
										206
									
								
								routes/index.js
								
								
								
								
							|  | @ -2,6 +2,7 @@ const express = require('express'); | |||
| const router = express.Router(); | ||||
| const colors = require('colors'); | ||||
| const _ = require('lodash'); | ||||
| const randtoken = require('rand-token'); | ||||
| const common = require('./common'); | ||||
| 
 | ||||
| router.get('/payment/:orderId', async (req, res, next) => { | ||||
|  | @ -236,6 +237,211 @@ router.post('/login_action', (req, res) => { | |||
|     }); | ||||
| }); | ||||
| 
 | ||||
| // insert a customer
 | ||||
| router.post('/customer/create', (req, res) => { | ||||
|     const db = req.app.db; | ||||
|     const bcrypt = req.bcrypt; | ||||
| 
 | ||||
|     let doc = { | ||||
|         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, | ||||
|         password: bcrypt.hashSync(req.body.password), | ||||
|         created: new Date() | ||||
|     }; | ||||
| 
 | ||||
|     // check for existing customer
 | ||||
|     db.customers.findOne({email: req.body.email}, (err, customer) => { | ||||
|         if(customer){ | ||||
|             res.status(404).json({ | ||||
|                 err: 'A customer already exists with that email address' | ||||
|             }); | ||||
|             return; | ||||
|         } | ||||
|         // email is ok to be used.
 | ||||
|         db.customers.insertOne(doc, (err, newCustomer) => { | ||||
|             if(err){ | ||||
|                 if(newCustomer){ | ||||
|                     console.error(colors.red('Failed to insert customer: ' + err)); | ||||
|                     res.status(400).json({ | ||||
|                         err: 'A customer already exists with that email address' | ||||
|                     }); | ||||
|                     return; | ||||
|                 } | ||||
|                 console.error(colors.red('Failed to insert customer: ' + err)); | ||||
|                 res.status(400).json({ | ||||
|                     err: 'Customer creation failed.' | ||||
|                 }); | ||||
|                 return; | ||||
|             } | ||||
| 
 | ||||
|             // Customer creation successful
 | ||||
|             req.session.customer = newCustomer.ops[0]; | ||||
|             res.status(200).json({ | ||||
|                 message: 'Successfully logged in', | ||||
|                 customer: newCustomer | ||||
|             }); | ||||
|         }); | ||||
|     }); | ||||
| }); | ||||
| 
 | ||||
| // login the customer and check the password
 | ||||
| router.post('/customer/login_action', (req, res) => { | ||||
|     let db = req.app.db; | ||||
|     let bcrypt = req.bcrypt; | ||||
| 
 | ||||
|     db.customers.findOne({email: req.body.loginEmail}, (err, customer) => { | ||||
|         if(err){ | ||||
|             // An error accurred
 | ||||
|             return res.status(400).json({ | ||||
|                 err: 'Access denied. Check password and try again.' | ||||
|             }); | ||||
|         } | ||||
| 
 | ||||
|         // check if customer exists with that email
 | ||||
|         if(customer === undefined || customer === null){ | ||||
|             return res.status(400).json({ | ||||
|                 err: 'A customer with that email does not exist.' | ||||
|             }); | ||||
|         } | ||||
|         // we have a customer under that email so we compare the password
 | ||||
|         if(bcrypt.compareSync(req.body.loginPassword, customer.password) === false){ | ||||
|             // password is not correct
 | ||||
|             return res.status(400).json({ | ||||
|                 err: 'Access denied. Check password and try again.' | ||||
|             }); | ||||
|         } | ||||
| 
 | ||||
|         // Customer login successful
 | ||||
|         req.session.customer = customer; | ||||
|         return res.status(200).json({ | ||||
|             message: 'Successfully logged in', | ||||
|             customer: customer | ||||
|         }); | ||||
|     }); | ||||
| }); | ||||
| 
 | ||||
| // customer forgotten password
 | ||||
| router.get('/customer/forgotten', (req, res) => { | ||||
|     res.render('forgotten', { | ||||
|         title: 'Forgotten', | ||||
|         route: 'customer', | ||||
|         forgotType: 'customer', | ||||
|         config: common.getConfig(), | ||||
|         helpers: req.handlebars.helpers, | ||||
|         message: common.clearSessionValue(req.session, 'message'), | ||||
|         messageType: common.clearSessionValue(req.session, 'messageType'), | ||||
|         showFooter: 'showFooter' | ||||
|     }); | ||||
| }); | ||||
| 
 | ||||
| // forgotten password
 | ||||
| router.post('/customer/forgotten_action', (req, res) => { | ||||
|     const db = req.app.db; | ||||
|     const config = common.getConfig(); | ||||
|     let passwordToken = randtoken.generate(30); | ||||
| 
 | ||||
|     // find the user
 | ||||
|     db.customers.findOne({email: req.body.email}, (err, customer) => { | ||||
|         // if we have a customer, set a token, expiry and email it
 | ||||
|         if(customer){ | ||||
|             let tokenExpiry = Date.now() + 3600000; | ||||
|             db.customers.update({email: req.body.email}, {$set: {resetToken: passwordToken, resetTokenExpiry: tokenExpiry}}, {multi: false}, (err, numReplaced) => { | ||||
|                 // send forgotten password email
 | ||||
|                 let mailOpts = { | ||||
|                     to: req.body.email, | ||||
|                     subject: 'Forgotten password request', | ||||
|                     body: `You are receiving this because you (or someone else) have requested the reset of the password for your user account.\n\n | ||||
|                         Please click on the following link, or paste this into your browser to complete the process:\n\n | ||||
|                         ${config.baseUrl}/customer/reset/${passwordToken}\n\n | ||||
|                         If you did not request this, please ignore this email and your password will remain unchanged.\n` | ||||
|                 }; | ||||
| 
 | ||||
|                 // send the email with token to the user
 | ||||
|                 // TODO: Should fix this to properly handle result
 | ||||
|                 common.sendEmail(mailOpts.to, mailOpts.subject, mailOpts.body); | ||||
|                 req.session.message = 'An email has been sent to ' + req.body.email + ' with further instructions'; | ||||
|                 req.session.message_type = 'success'; | ||||
|                 return res.redirect('/customer/forgotten'); | ||||
|             }); | ||||
|         }else{ | ||||
|             req.session.message = 'Account does not exist'; | ||||
|             res.redirect('/customer/forgotten'); | ||||
|         } | ||||
|     }); | ||||
| }); | ||||
| 
 | ||||
| // reset password form
 | ||||
| router.get('/customer/reset/:token', (req, res) => { | ||||
|     const db = req.app.db; | ||||
| 
 | ||||
|     // Find the customer using the token
 | ||||
|     db.customers.findOne({resetToken: req.params.token, resetTokenExpiry: {$gt: Date.now()}}, (err, customer) => { | ||||
|         if(!customer){ | ||||
|             req.session.message = 'Password reset token is invalid or has expired'; | ||||
|             req.session.message_type = 'danger'; | ||||
|             res.redirect('/forgot'); | ||||
|             return; | ||||
|         } | ||||
| 
 | ||||
|         // show the password reset form
 | ||||
|         res.render('reset', { | ||||
|             title: 'Reset password', | ||||
|             token: req.params.token, | ||||
|             route: 'customer', | ||||
|             config: common.getConfig(), | ||||
|             message: common.clearSessionValue(req.session, 'message'), | ||||
|             message_type: common.clearSessionValue(req.session, 'message_type'), | ||||
|             show_footer: 'show_footer', | ||||
|             helpers: req.handlebars.helpers | ||||
|         }); | ||||
|     }); | ||||
| }); | ||||
| 
 | ||||
| // reset password action
 | ||||
| router.post('/customer/reset/:token', (req, res) => { | ||||
|     const db = req.app.db; | ||||
|     let bcrypt = req.bcrypt; | ||||
| 
 | ||||
|     // get the customer
 | ||||
|     db.customers.findOne({resetToken: req.params.token, resetTokenExpiry: {$gt: Date.now()}}, (err, customer) => { | ||||
|         if(!customer){ | ||||
|             req.session.message = 'Password reset token is invalid or has expired'; | ||||
|             req.session.message_type = 'danger'; | ||||
|             return res.redirect('/forgot'); | ||||
|         } | ||||
| 
 | ||||
|         // update the password and remove the token
 | ||||
|         let newPassword = bcrypt.hashSync(req.body.password); | ||||
|         db.customers.update({email: customer.email}, {$set: {password: newPassword, resetToken: undefined, resetTokenExpiry: undefined}}, {multi: false}, (err, numReplaced) => { | ||||
|             let mailOpts = { | ||||
|                 to: customer.email, | ||||
|                 subject: 'Password successfully reset', | ||||
|                 body: 'This is a confirmation that the password for your account ' + customer.email + ' has just been changed successfully.\n' | ||||
|             }; | ||||
| 
 | ||||
|             // TODO: Should fix this to properly handle result
 | ||||
|             common.sendEmail(mailOpts.to, mailOpts.subject, mailOpts.body); | ||||
|             req.session.message = 'Password successfully updated'; | ||||
|             req.session.message_type = 'success'; | ||||
|             return res.redirect('/pay'); | ||||
|         }); | ||||
|         return''; | ||||
|     }); | ||||
| }); | ||||
| 
 | ||||
| // logout the customer
 | ||||
| router.post('/customer/logout', (req, res) => { | ||||
|     req.session.customer = null; | ||||
|     res.status(200).json({}); | ||||
| }); | ||||
| 
 | ||||
| // search products
 | ||||
| router.get('/search/:searchTerm/:pageNum?', (req, res) => { | ||||
|     let db = req.app.db; | ||||
|  |  | |||
|  | @ -0,0 +1,49 @@ | |||
| {{> menu}} | ||||
| <div class="col-lg-9"> | ||||
|     <div class="row"> | ||||
|         <div class="col-lg-12"> | ||||
|             <h2>Customer</h2> | ||||
|         </div> | ||||
|         <div class="col-xs-12 col-md-12"> | ||||
|             <table class="table-bordered"> | ||||
|                 <tr> | ||||
|                     <td><span class="text-info">Email:</span></td> | ||||
|                     <td>{{result.email}}</td> | ||||
|                 </tr> | ||||
|                 <tr> | ||||
|                     <td><span class="text-info">Name:</span></td> | ||||
|                     <td>{{result.firstName}} {{result.lastName}}</td> | ||||
|                 </tr> | ||||
|                 <tr> | ||||
|                     <td><span class="text-info">Address 1:</span></td> | ||||
|                     <td>{{result.address1}}</td> | ||||
|                 </tr> | ||||
|                 <tr> | ||||
|                     <td><span class="text-info">Address 2:</span></td> | ||||
|                     <td>{{result.address2}}</td> | ||||
|                 </tr> | ||||
|                 <tr> | ||||
|                     <td><span class="text-info">Country:</span></td> | ||||
|                     <td>{{result.country}}</td> | ||||
|                 </tr> | ||||
|                 <tr> | ||||
|                     <td><span class="text-info">State:</span></td> | ||||
|                     <td>{{result.state}}</td> | ||||
|                 </tr> | ||||
|                 <tr> | ||||
|                     <td><span class="text-info">Postcode:</span></td> | ||||
|                     <td>{{result.postcode}}</td> | ||||
|                 </tr> | ||||
|                 <tr> | ||||
|                     <td><span class="text-info">Phone number:</span></td> | ||||
|                     <td>{{result.phone}}</td> | ||||
|                 </tr> | ||||
|                 <tr> | ||||
|                     <td><span class="text-info">Creation date:</span></td> | ||||
|                     <td>{{formatDate result.created "DD/MM/YYYY hh:mmA"}}</td> | ||||
|                 </tr> | ||||
|             </table> | ||||
|         </div> | ||||
|     </div> | ||||
|     <input type="hidden" id="productId" value="{{result._id}}"> | ||||
| </div> | ||||
|  | @ -0,0 +1,64 @@ | |||
| {{> menu}} | ||||
| <div class="col-lg-9"> | ||||
|     <div class="col-lg-12"> | ||||
|         <h2>Customers</h2> | ||||
|     </div> | ||||
|     <div class="col-lg-12 search_bar"> | ||||
|         <div class="input-group"> | ||||
|             <input type="text" name="customer_filter" id="customer_filter" class="form-control input-lg" placeholder="Filter customers"> | ||||
|             <span class="input-group-btn"> | ||||
|                 <button class="btn btn-success btn-lg" id="btn_customer_filter">Filter</button> | ||||
|                 <a href="/admin/customers" class="hidden-xs btn btn-warning btn-lg"><i class="fa fa-times" aria-hidden="true"></i></a> | ||||
|             </span> | ||||
|         </div> | ||||
|         <p class="text-warning top-pad-10">Customers can be filtered by: email, name or phone numnber</p> | ||||
|     </div> | ||||
|     {{#if customers}} | ||||
|         <div class="col-lg-12"> | ||||
|             <ul class="list-group"> | ||||
|                 <li class="list-group-item"> | ||||
|                     <strong> | ||||
|                         Customers | ||||
|                         {{#if searchTerm}} | ||||
|                             - <span class="text-danger">Filtered term: {{searchTerm}} </span> | ||||
|                         {{/if}} | ||||
|                     </strong> | ||||
|                 </li> | ||||
|                 <li class="list-group-item"> | ||||
|                     <div class="row"> | ||||
|                         <div class="col-md-4"> | ||||
|                             <h5 class="text-info"><strong>Email address</strong></h5> | ||||
|                         </div> | ||||
|                         <div class="col-md-4"> | ||||
|                             <h5 class="text-info"><strong>Name</strong></h5> | ||||
|                         </div> | ||||
|                         <div class="col-md-4"> | ||||
|                             <h5 class="text-info"><strong>Phone number</strong></h5> | ||||
|                         </div> | ||||
|                     </div> | ||||
|                 </li> | ||||
|                 {{#each customers}} | ||||
|                     <li class="list-group-item"> | ||||
|                         <div class="row"> | ||||
|                             <a href="/admin/customer/view/{{this._id}}"> | ||||
|                                 <div class="col-md-4"> | ||||
|                                     <h5 class="">{{this.email}}</h5> | ||||
|                                 </div> | ||||
|                                 <div class="col-md-4"> | ||||
|                                     <h5 class="">{{this.firstName}} {{this.lastName}}</h5> | ||||
|                                 </div> | ||||
|                                 <div class="col-md-4"> | ||||
|                                     <h5 class="">{{this.phone}}</h5> | ||||
|                                 </div> | ||||
|                             </a> | ||||
|                         </div> | ||||
|                     </li> | ||||
|                 {{/each}} | ||||
|             </ul> | ||||
|         </div> | ||||
|     {{else}} | ||||
|     <h4 class="text-center"> | ||||
|         No orders found | ||||
|     </h4> | ||||
|     {{/if}} | ||||
| </div> | ||||
|  | @ -0,0 +1,9 @@ | |||
| <div class="col-md-offset-4 col-md-4 col-lg-offset-4 col-lg-4" style="padding-top: 100px" > | ||||
| 	<form class="form-signin" action="/{{route}}/forgotten_action" method="post" role="form" data-toggle="validator"> | ||||
| 		<h2 class="form-signin-heading">Please enter your email address</h2> | ||||
| 		<div class="form-group"> | ||||
| 			<input type="email" name="email" class="form-control" placeholder="email address" required autofocus> | ||||
| 		</div> | ||||
| 		<button class="btn btn-lg btn-primary btn-block" type="submit">Reset</button> | ||||
| 	</form> | ||||
| </div> | ||||
|  | @ -6,6 +6,8 @@ | |||
|         <li class="list-group-item"><i class="fa fa-list fa-icon" aria-hidden="true"></i>   <a href="/admin/products">List</a></li> | ||||
|         <li class="list-group-item"><strong>Orders</strong></li> | ||||
|         <li class="list-group-item"><i class="fa fa-cube fa-icon" aria-hidden="true"></i>   <a href="/admin/orders">List</a></li> | ||||
|         <li class="list-group-item"><strong>Customers</strong></li> | ||||
|         <li class="list-group-item"><i class="fa fa-users fa-icon" aria-hidden="true"></i>   <a href="/admin/customers">List</a></li> | ||||
|         <li class="list-group-item"><strong>Users</strong></li> | ||||
|         <li class="list-group-item"><i class="fa fa-user-plus fa-icon" aria-hidden="true"></i>   <a href="/admin/user/new">New</a></li> | ||||
|         <li class="list-group-item"><i class="fa fa-user fa-icon" aria-hidden="true"></i>   <a href="/admin/users">Edit</a></li> | ||||
|  |  | |||
|  | @ -6,64 +6,93 @@ | |||
|         <div class="col-md-5"> | ||||
|             <div class="panel panel-default" style="margin-top: 30px;"> | ||||
|                 <div class="panel-heading">Customer details</div> | ||||
|                 {{#unless session.customer}} | ||||
|                 <div class="panel-body customer-details-login"> | ||||
|                     <p>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-default pull-left">Forgotten</a> | ||||
|                     </div> | ||||
|                     <div class="form-group"> | ||||
|                         <button id="customerLogin" class="btn btn-success pull-right" type="submit">Login</button> | ||||
|                     </div> | ||||
|                 </div> | ||||
|                 {{/unless}} | ||||
|                 <div class="panel-body customer-details"> | ||||
|                     {{#if session.customer}} | ||||
|                     <div class="col-xs-12 col-md-12"> | ||||
|                         <button id="customerLogout" class="btn btn-sm btn-success pull-right">Change customer</button> | ||||
|                     </div> | ||||
|                     {{/if}} | ||||
|                     <form id="shipping-form" class="shipping-form" action="/{{config.paymentGateway}}/checkout_action" method="post" role="form" data-toggle="validator" novalidate="false"> | ||||
|                         <div class="col-xs-12 col-md-12"> | ||||
|                             <div class="form-group"> | ||||
|                                 <input type="email" class="form-control customerDetails" id="shipEmail" name="shipEmail" minlength="5" placeholder="Email address" required> | ||||
|                                 <input type="email" class="form-control customerDetails" id="shipEmail" name="shipEmail" minlength="5" placeholder="Email address" value="{{session.customer.email}}" required> | ||||
|                             </div> | ||||
|                         </div> | ||||
|                         <div class="col-xs-12 col-md-6"> | ||||
|                             <div class="form-group"> | ||||
|                                 <input type="text" class="form-control customerDetails" id="shipFirstname" name="shipFirstname" placeholder="First name" required> | ||||
|                                 <input type="text" class="form-control customerDetails" id="shipFirstname" name="shipFirstname" placeholder="First name" value="{{session.customer.firstName}}" required> | ||||
|                             </div> | ||||
|                         </div> | ||||
|                         <div class="col-xs-12 col-md-6"> | ||||
|                             <div class="form-group"> | ||||
|                                 <input type="text" class="form-control customerDetails" id="shipLastname" name="shipLastname" placeholder="Last name" required> | ||||
|                                 <input type="text" class="form-control customerDetails" id="shipLastname" name="shipLastname" placeholder="Last name" value="{{session.customer.lastName}}" required> | ||||
|                             </div> | ||||
|                         </div> | ||||
|                         <div class="col-xs-12 col-md-12"> | ||||
|                             <div class="form-group"> | ||||
|                                 <input type="text" class="form-control customerDetails" id="shipAddr1" name="shipAddr1" placeholder="Address 1" required> | ||||
|                                 <input type="text" class="form-control customerDetails" id="shipAddr1" name="shipAddr1" placeholder="Address 1" value="{{session.customer.address1}}" required> | ||||
|                             </div> | ||||
|                         </div> | ||||
|                         <div class="col-xs-12 col-md-12"> | ||||
|                             <div class="form-group"> | ||||
|                                 <input type="text" class="form-control customerDetails" id="shipAddr2" name="shipAddr2" placeholder="Address 2 (optional)"> | ||||
|                                 <input type="text" class="form-control customerDetails" id="shipAddr2" name="shipAddr2" placeholder="Address 2 (optional)" value="{{session.customer.address1}}"> | ||||
|                             </div> | ||||
|                         </div> | ||||
|                         <div class="col-xs-12 col-md-4"> | ||||
|                             <div class="form-group"> | ||||
|                                 <input type="text" class="form-control customerDetails" id="shipCountry" name="shipCountry" placeholder="Country" required> | ||||
|                                 <input type="text" class="form-control customerDetails" id="shipCountry" name="shipCountry" placeholder="Country" value="{{session.customer.country}}" required> | ||||
|                             </div> | ||||
|                         </div> | ||||
|                         <div class="col-xs-12 col-md-4"> | ||||
|                             <div class="form-group"> | ||||
|                                 <input type="text" class="form-control customerDetails" id="shipState" name="shipState" placeholder="State" required> | ||||
|                                 <input type="text" class="form-control customerDetails" id="shipState" name="shipState" placeholder="State" value="{{session.customer.state}}" required> | ||||
|                             </div> | ||||
|                         </div> | ||||
|                         <div class="col-xs-12 col-md-4"> | ||||
|                             <div class="form-group"> | ||||
|                                 <input type="number" class="form-control customerDetails" id="shipPostcode" name="shipPostcode" placeholder="Post code" required> | ||||
|                                 <input type="text" class="form-control customerDetails" id="shipPostcode" name="shipPostcode" placeholder="Post code" value="{{session.customer.postcode}}" required> | ||||
|                             </div> | ||||
|                         </div> | ||||
|                         <div class="col-xs-12 col-md-12"> | ||||
|                             <div class="form-group"> | ||||
|                                 <input type="number" class="form-control customerDetails" id="shipPostcode" name="shipPostcode" placeholder="Post code" required> | ||||
|                             </div> | ||||
|                         </div> | ||||
|                         <div class="col-xs-12 col-md-12"> | ||||
|                             <div class="form-group"> | ||||
|                                 <input type="number" class="form-control customerDetails" id="shipPhoneNumber" name="shipPhoneNumber" placeholder="Phone number (optional)"> | ||||
|                                 <input type="number" class="form-control customerDetails" id="shipPhoneNumber" name="shipPhoneNumber" placeholder="Phone number" value="{{session.customer.phone}}" required> | ||||
|                             </div> | ||||
|                         </div> | ||||
|                         {{#if session.customer}} | ||||
|                         {{#ifCond config.paymentGateway '==' 'paypal'}} | ||||
|                         <div class="paypal_button col-xs-12 col-md-12 text-center"> | ||||
|                             <button id="checkout_paypal" class="btn btn-success" type="submit"><i class="fa fa-cc-paypal fa-lg" aria-hidden="true"></i> Pay with PayPal <i class="fa fa-cc-paypal fa-lg" aria-hidden="true"></i></button> | ||||
|                         </div> | ||||
|                         {{/ifCond}} | ||||
|                         {{/if}} | ||||
|                         {{#unless session.customer}} | ||||
|                         <div class="col-xs-12 col-md-12"> | ||||
|                             <p class="text-muted">Enter a password to create an account for next time</p> | ||||
|                             <div class="form-group"> | ||||
|                                 <input type="password" class="form-control customerDetails" id="newCustomerPassword" name="newCustomerPassword" placeholder="Password" required> | ||||
|                             </div> | ||||
|                             <a id="createCustomerAccount" class="btn btn-success pull-right">Create account</a> | ||||
|                         </div> | ||||
|                         {{/unless}} | ||||
|                     </form> | ||||
|                     {{#if session.customer}} | ||||
|                     {{#ifCond config.paymentGateway '==' 'stripe'}} | ||||
|                     <div class="col-xs-12 col-md-12 text-center"> | ||||
|                         <form method="POST" id="payment-form"> | ||||
|  | @ -87,6 +116,7 @@ | |||
|                         </form> | ||||
|                     </div> | ||||
|                     {{/ifCond}} | ||||
|                     {{/if}} | ||||
|                 </div> | ||||
|             </div> | ||||
|         </div> | ||||
|  |  | |||
|  | @ -0,0 +1,15 @@ | |||
| <div class="col-md-offset-4 col-md-4 col-lg-offset-4 col-lg-4"> | ||||
| 	<form class="form-signin" action="/{{route}}/reset/{{token}}" method="post" role="form" data-toggle="validator"> | ||||
| 		<h2 class="form-signin-heading">Password reset</h2> | ||||
| 		<div class="form-group"> | ||||
|             <label for="user_password">Password *</label> | ||||
|             <input type="password" class="form-control" id="user_password" name="password" placeholder="Password" required> | ||||
|         </div> | ||||
|         <div class="form-group"> | ||||
|             <label for="frm_user_password_confirm">Confirm password *</label> | ||||
|             <input type="password" data-match="#user_password" placeholder="Confirm password" class="form-control" name="frm_user_password_confirm" required> | ||||
|         </div> | ||||
| 		<button class="btn btn-lg btn-success btn-block" type="submit">Update password</button> | ||||
|         </br> | ||||
| 	</form> | ||||
| </div> | ||||
		Loading…
	
		Reference in New Issue