diff --git a/app/components/NavBar.jsx b/app/components/NavBar.jsx index 803a2f4..9c2f552 100644 --- a/app/components/NavBar.jsx +++ b/app/components/NavBar.jsx @@ -1,9 +1,16 @@ import React from 'react'; import Login from './Login'; import { Link } from 'react-router'; - +import axios from 'axios' const NavBar = (props) =>{ + + const loginWithGmail = function(){ + + axios.post('/api/auth/google/login') + + } + return(
diff --git a/app/components/ShoppingCart.jsx b/app/components/ShoppingCart.jsx index d582158..2f7a53e 100644 --- a/app/components/ShoppingCart.jsx +++ b/app/components/ShoppingCart.jsx @@ -4,6 +4,8 @@ import { connect } from 'react-redux'; import store from '../store.jsx' import Promise from 'bluebird'; import axios from 'axios'; +import { Link } from 'react-router'; +import Checkout from './proceedToCheckout.jsx' // this is the component // const ShoppingCart = (props) => { @@ -13,6 +15,7 @@ class ShoppingCart extends Component { super(); this.state = { shoppingCart: [], + // currentUser: {}, productToCheckForQuanity: {productId: 0, newQuantity: 0}, quantityAvailable: true, unitsRemaining: 0 @@ -21,12 +24,13 @@ class ShoppingCart extends Component { this.deleteFromCart = this.deleteFromCart.bind(this); this.handleQuantity = this.handleQuantity.bind(this); this.handleQuantityUpdate = this.handleQuantityUpdate.bind(this); - this.proceedToOrder = this.proceedToOrder.bind(this); } componentDidMount(){ this.setState({shoppingCart: this.props.shoppingCart.shoppingCart}) + // axios.get('/api/auth/whoami') + // .then(res => this.setState({currentUser: res.auth})) } componentWillReceiveProps(nextProps) { @@ -37,7 +41,6 @@ class ShoppingCart extends Component { } deleteFromCart(idToRemove){ - console.log(idToRemove) if(this.state.shoppingCart.length){ const currentCart = this.state.shoppingCart; const newCart = currentCart.filter(elem => {return elem.id != idToRemove}) @@ -68,17 +71,11 @@ class ShoppingCart extends Component { } - proceedToOrder(){ - //create and submit to orders table - //update quantity on products - //move to the checkout page (maybe just create a div below?) - } - render(){ - console.log(this.props) return( -
+
+
Shopping Cart
@@ -122,12 +119,10 @@ class ShoppingCart extends Component {
} -
-
Address
-
- - - + + + +
) diff --git a/app/components/confirmation.jsx b/app/components/confirmation.jsx new file mode 100644 index 0000000..4d0ec9f --- /dev/null +++ b/app/components/confirmation.jsx @@ -0,0 +1,52 @@ +import React, { Component } from 'react'; +import { connect } from 'react-redux'; +import store from '../store.jsx' +import Promise from 'bluebird'; +import axios from 'axios'; +// this is the component + +class Confirmation extends Component { +// const Confirmation = (props) => { + constructor(){ + super(); + } + + + render(){ + const order = this.props.orderFromPreviousPage.shoppingCart.order; + const user = this.props.orderFromPreviousPage.auth; + console.log(this.props.orderFromPreviousPage) + + return( + +
+

Dear {user ? user.name : 'Anonymous'},

+

Thank you for your purchase. Your confirmation number is:

+

{order.orderNumber}

+

A copy of your order has been sent to {order.email}

+ +
+ + ) +} + +} + +export default Confirmation; + + +// this is the container +// const mapStateToProps = (state) => { +// return { +// shoppingCart: state.shoppingCart, +// auth: state.auth, +// order: state.order +// }; +// }; + + + +// export default connect( +// mapStateToProps, +// )(Confirmation); + diff --git a/app/components/proceedToCheckout.jsx b/app/components/proceedToCheckout.jsx new file mode 100644 index 0000000..bc10960 --- /dev/null +++ b/app/components/proceedToCheckout.jsx @@ -0,0 +1,173 @@ +import React, { Component } from 'react'; +import { connect } from 'react-redux'; +import store from '../store.jsx' +import Promise from 'bluebird'; +import axios from 'axios'; +import { Link } from 'react-router'; +import { purchase } from '../reducers/ShoppingCart_reducer'; +import crypto from 'crypto'; +import Confirmation from './confirmation' + +// this is the component + +class Checkout extends Component { + constructor(){ + super(); + this.state = { + currentuser:{}, + order:{}, + emailValid: false, + goToConfirmation: false, + error: false + } + + + this.updateAddress = this.updateAddress.bind(this); + this.sendToPurchase = this.sendToPurchase.bind(this); + this.emailValidation = this.emailValidation.bind(this); + + } + + componentDidMount(){ + const id = this.props.auth ? this.props.auth.id : 'anonymous' + const order = {user_id: id, quantity: [], products: this.props.shoppingCart.shoppingCart} + this.setState({currentuser: this.props.auth, order: order}) + } + + + updateAddress(event){ + const order = this.state.order; + order.deliveryAddress = event.target.value; + this.setState({order: order}) + } + + sendToPurchase(event){ + event.preventDefault(); + const emailToPass = event.target.email.value; + const order = this.state.order; + order.email = emailToPass; + + if(!this.state.currentuser){ + order.orderNumber = crypto.randomBytes(5).toString('hex').toUpperCase(); + this.setState({order: order}) + axios.post('/api/sendmail', this.state.order) + + } else{ + // console.log(this.state.order) + axios.post('/api/orders', this.state.order) + .then((res) => { + if(res === 'error'){this.setState({error: true})} + else{ + order.orderNumber = res.data.orderNumber; + this.setState({order:order}) + this.setState({goToConfirmation: true}) + this.props.purchase_func(this.state.order) + + } + }) + + } + + } + + emailValidation(event){ + event.preventDefault(); + var validEmail = false; + const email = event.target.value; + const atpos = email.indexOf("@"); + const dotpos = email.lastIndexOf("."); + if (atpos<1 || dotpos=email.length) { + this.setState({emailValid: false}) + } else this.setState({emailValid: true}) + + } + + render(){ + // console.log(this.state) + return( +
+ {!this.state.goToConfirmation + ? +
+ Welcome {this.props.auth ? this.props.auth.name : 'Unknown user'} +
this.sendToPurchase(event)}> +
+ + this.updateAddress(event)}type="text" className="form-control" id="formGroupExampleInput" placeholder="Example input"/> +
+ {this.props.auth + ? +
+ + this.emailValidation(event)}name="email" type="text" className="form-control" id="formGroupExampleInput2" value={this.props.auth.email}/> + + + { + !this.state.emailValid + ?
+ Please enter a valid email! +
+ : + } +
+ + + :
+ + this.emailValidation(event)}name="email" type="text" className="form-control" id="formGroupExampleInput2" /> + { + !this.state.emailValid + ?
+ Please enter a valid email! +
+ : + } +
+ } +
+ +
+ :
+ {!this.state.error + ? + :
+ Sorry, one of your items is no longer available +
+ } + +
+ + } +
+ + ) + +} +} + + +// this is the container +const mapStateToProps = (state) => { + // console.log(state) + return { + shoppingCart: state.shoppingCart, + auth: state.auth, + order: state.order + +}; +}; + +const mapDispatchToProps = (dispatch) => { + return ({ + purchase_func: function(ord) { + dispatch(purchase(ord)); + } + + }); +}; + +export default connect( + mapStateToProps, + mapDispatchToProps +)(Checkout); + diff --git a/app/constants.js b/app/constants.js index 671f77f..68f3e87 100644 --- a/app/constants.js +++ b/app/constants.js @@ -1,3 +1,3 @@ -export const PURCHASE = 'PROCEED_TO_CHECKOUT'; +export const PURCHASE = 'PURCHASE'; export const UPDATE_CART = 'UPDATE_CART'; export const ADD_TO_CART = 'ADD_TO_CART'; \ No newline at end of file diff --git a/app/main.jsx b/app/main.jsx index 9df9ff6..3b44564 100644 --- a/app/main.jsx +++ b/app/main.jsx @@ -12,7 +12,8 @@ import ShoppingCart from './components/ShoppingCart' import ProductDetailContainer from './containers/ProductDetailContainer.jsx'; import ProductsHomeContainer from './containers/ProductsHomeContainer.jsx'; - +import Checkout from './components/proceedToCheckout' +import Confirmation from './components/confirmation' render ( @@ -23,6 +24,10 @@ render ( + + + + , diff --git a/app/reducers/ShoppingCart_reducer.jsx b/app/reducers/ShoppingCart_reducer.jsx index 01d9cf4..a63a519 100644 --- a/app/reducers/ShoppingCart_reducer.jsx +++ b/app/reducers/ShoppingCart_reducer.jsx @@ -14,6 +14,11 @@ const addToCart_action = (obj) => ({ payload: obj }) +const purchasedItems = (ord) => ({ + type: PURCHASE, + payload: ord +}) + //defining dispatch action to define value of action-creator (also to be called by component) export const deleteFromCart = (arr) => { return (dispatch) => { @@ -22,9 +27,9 @@ export const deleteFromCart = (arr) => { } -export const purchase = (arr) => { +export const purchase = (ord) => { return (dispatch) => { - dispatch(purchasedItems(arr)) + dispatch(purchasedItems(ord)) } } @@ -39,42 +44,8 @@ export const addToCart = (obj) => { //initializing state const initialState= { - shoppingCart: [] - -// shoppingCart: [ -// {giveImage: "/dj-default.png", -// id: 1, -// artistName: "Big Boi", -// description: "Fat jams all day", -// price: 104, -// image: null, -// genre: "RAP", -// location: "NYC", -// email: "bigboi@money.com", -// audioSample: null, -// rating: null, -// quantity: 1 - -// }, - -// {giveImage: "/dj-default.png", -// id: 2, -// artistName: "yo", -// description: "Fat jams all day", -// price: 104, -// image: null, -// genre: "RAP", -// location: "NYC", -// email: "bigboi@money.com", -// audioSample: null, -// rating: null, -// quantity: 1 - -// } - - -// ] - + shoppingCart: [], + order: {} }; @@ -90,7 +61,7 @@ export default function (state = initialState, action) { break; case PURCHASE: - newState.shoppingCart = action.payload; + newState.order = action.payload; break; case ADD_TO_CART: diff --git a/package.json b/package.json index 837e7c6..06edbbc 100644 --- a/package.json +++ b/package.json @@ -42,6 +42,7 @@ "enzyme": "^2.5.1", "epilogue": "^0.7.0", "express": "^4.14.0", + "nodemailer": "^2.7.0", "passport": "^0.3.2", "passport-facebook": "^2.1.1", "passport-github2": "^0.1.10", diff --git a/public/index.html b/public/index.html index 4d39568..25fac9a 100644 --- a/public/index.html +++ b/public/index.html @@ -21,5 +21,6 @@
+ diff --git a/public/style.css b/public/style.css index dd8b866..a6c6fee 100644 --- a/public/style.css +++ b/public/style.css @@ -4,6 +4,7 @@ .ShoppingCart_div{ margin: 2%; + margin-top: 10%; } .glyphicon-remove{ @@ -31,3 +32,8 @@ background-color: green; border:none; }; + +.checkout{ + margin-top:5%; + background-color: yellow; +} diff --git a/server/api.js b/server/api.js index 3d04bf2..0e0c962 100644 --- a/server/api.js +++ b/server/api.js @@ -10,6 +10,7 @@ api .use('/products', require('./products')) .use('/orders', require('./orders')) .use('/reviews', require('./reviews')) + .use('/sendmail', require('./sendmail')) // Send along any errors api.use((err, req, res, next) => { diff --git a/server/auth.js b/server/auth.js index 9250969..2618032 100644 --- a/server/auth.js +++ b/server/auth.js @@ -52,8 +52,10 @@ OAuth.setupStrategy({ provider: 'google', strategy: require('passport-google-oauth').Strategy, config: { - consumerKey: env.GOOGLE_CONSUMER_KEY, - consumerSecret: env.GOOGLE_CONSUMER_SECRET, + // consumerKey: env.GOOGLE_CONSUMER_KEY, + // consumerSecret: env.GOOGLE_CONSUMER_SECRET, + consumerKey: '444169114220-18uoi6t7bukvh0pk3e4ojck4s4cjhuq7.apps.googleusercontent.com', + consumerSecret: 'G06vM16MeGHZnvwAVflx9-UZ', callbackURL: `${app.rootUrl}/api/auth/login/google`, }, passport @@ -96,6 +98,7 @@ passport.deserializeUser( ) passport.use(new (require('passport-local').Strategy) ( + // passport.use(new (require('passport-google-oauth').Strategy) ( (email, password, done) => { debug('will authenticate user(email: "%s")', email) User.findOne({where: {email}}) diff --git a/server/orders.js b/server/orders.js index 40d7fa0..16a012a 100644 --- a/server/orders.js +++ b/server/orders.js @@ -115,11 +115,16 @@ customOrderRoutes.get('/:orderNumber/products', function (request, response, nex customOrderRoutes.post('/', function (request, response, next) { + console.log(request.body) + + // const temp = request.body; + // if temp const cartProducts = request.body.products; const cartProductIds = []; cartProducts.forEach((product) => { - cartProductIds.push(product.pId); + // cartProductIds.push(product.pId); changing from pid to id + cartProductIds.push(product.id); }); let grandTotal = 0; @@ -148,7 +153,8 @@ customOrderRoutes.post('/', function (request, response, next) { .then((productsArray) => { productsArray.forEach((prod) => { cartProducts.forEach((cartPr) => { - if(prod.id.toString()===cartPr.pId.toString()) { + // if(prod.id.toString()===cartPr.pId.toString()) { changing from pid + if(prod.id.toString()===cartPr.id.toString()) { grandTotal += cartPr.quantity*cartPr.price; order.addProduct(prod, { quantity: cartPr.quantity, @@ -167,7 +173,18 @@ customOrderRoutes.post('/', function (request, response, next) { return order.save(); }) .then((order) => { - response.sendStatus(200); + // response.sendStatus(200); + + cartProducts.forEach((product) => { + + Product.findOne({ + where: {id: product.id} + }) + .then(data => data.updateQuantity(product.id)) + + }); + + response.json(order) }) .catch(next); }); diff --git a/server/sendmail.js b/server/sendmail.js new file mode 100644 index 0000000..0a62253 --- /dev/null +++ b/server/sendmail.js @@ -0,0 +1,62 @@ + 'use strict' + +const Router = require('express').Router() + +const nodemailer = require('nodemailer') + +// const transport = { +// name: 'localhost:1337' // must be the same that can be reverse resolved by DNS for your IP +// }; + +const transport = { + host: 'smtp.gmail.com', + port: 465, + secure: true, // use SSL + auth: { + user: 'djkm.team@gmail.com', + pass: 'Fullst@ck' + } +}; + +const transporter = nodemailer.createTransport(transport); + +Router.post('/', function(req,res,next){ +console.log(req.body.products[0].artistName) + const mailOptions = { + from: 'djkm.team@gmail.com', + to: req.body.email, + subject: 'DJ KM Order ' + req.body.orderNumber, + // text: 'haye', + html: `

Thank you for your purchase!

+

You have the following purchases:

+ ` + }; + +transporter.sendMail(mailOptions, function(error, info){ + if(error){ + return console.log(error); + } + console.log('Message sent: ' + info.response); +}); + + +}) + + + +// var mailOptions = { +// from: '"Fred Foo 👥" ', // sender address +// to: 'bar@blurdybloop.com, baz@blurdybloop.com', // list of receivers +// subject: 'Hello ✔', // Subject line +// text: 'Hello world 🐴', // plaintext body +// html: 'Hello world 🐴' // html body +// }; + + +module.exports = Router; \ No newline at end of file