diff options
| author | Wes Bos <wesbos@gmail.com> | 2017-08-25 09:33:53 -0400 |
|---|---|---|
| committer | Wes Bos <wesbos@gmail.com> | 2017-08-25 09:33:53 -0400 |
| commit | 7af74ff8988961c988f03c95961b70c2918521ae (patch) | |
| tree | d73cd0dd94751b76595b7febcae4162811c2040b /components | |
| parent | 416c2cbae0e69b724876d232bf813eefd7550174 (diff) | |
yay
Diffstat (limited to 'components')
| -rw-r--r-- | components/CreateItem.js | 7 | ||||
| -rw-r--r-- | components/Header.js | 28 | ||||
| -rw-r--r-- | components/Items.js | 36 | ||||
| -rw-r--r-- | components/LoginAuth0.js | 58 | ||||
| -rw-r--r-- | components/Meta.js | 16 | ||||
| -rw-r--r-- | components/Nav.js | 9 | ||||
| -rw-r--r-- | components/OrderList.js | 52 | ||||
| -rw-r--r-- | components/Page.js | 25 | ||||
| -rw-r--r-- | components/Signup.js | 76 | ||||
| -rw-r--r-- | components/TakeMyMoney.js | 38 |
10 files changed, 320 insertions, 25 deletions
diff --git a/components/CreateItem.js b/components/CreateItem.js index b29b210..3b86f2c 100644 --- a/components/CreateItem.js +++ b/components/CreateItem.js @@ -8,6 +8,8 @@ class CreateLink extends Component { description: '', title: '', image: '', + price: 0, + fullPrice: 0, loading: false } @@ -43,6 +45,7 @@ class CreateLink extends Component { <p>Title <input value={this.state.title} onChange={(e) => this.setState({ title: e.target.value })} type='text' placeholder='A description for the link'/> </p> + <label>Price<input type="number" min="0" value={this.state.price} onChange={(e) => this.setState({ price: e.target.value })} /></label> <textarea value={this.state.description} onChange={(e) => this.setState({ description: e.target.value })} @@ -58,7 +61,7 @@ class CreateLink extends Component { _createLink = async (e) => { e.preventDefault(); // pull the values from state - const { description, title, image } = this.state + const { description, title, image, price, fullPrice } = this.state; // create a mutation // TODO: handle any errors // turn loading on @@ -68,6 +71,8 @@ class CreateLink extends Component { variables: { description, title, + price: parseInt(price), + fullPrice, imageId: image } }); diff --git a/components/Header.js b/components/Header.js new file mode 100644 index 0000000..52aeef9 --- /dev/null +++ b/components/Header.js @@ -0,0 +1,28 @@ +import { Component } from 'react' +import { graphql, compose } from 'react-apollo' +import { CURRENT_USER_QUERY } from '../queries'; + +class Header extends Component { + + componentDidMount() { + // This fetches the new data, but doesn't populate the user via props + // this.props.currentUserQuery.refetch(); + // This fetches the new data, and populates the user via props + setTimeout(this.props.currentUserQuery.refetch, 1); + } + + render() { + console.log(this.props.currentUserQuery.user); + const user = this.props.currentUserQuery.user || {}; + const { email = '' } = user; + + return ( + <div> + <p>{email} I'm the header!</p> + </div> + ) + } +} + +const userEnhancer = graphql(CURRENT_USER_QUERY, { name: 'currentUserQuery' }); +export default compose(userEnhancer)(Header) diff --git a/components/Items.js b/components/Items.js index 35db906..7d07643 100644 --- a/components/Items.js +++ b/components/Items.js @@ -1,10 +1,11 @@ -import React, { Component } from 'react' +import { Component } from 'react' import { graphql, compose } from 'react-apollo' import UpdateItem from './UpdateItem'; import Link from 'next/link'; import styled from 'styled-components'; import TakeMyMoney from './TakeMyMoney'; import formatMoney from '../lib/formatMoney'; +import makeImage from '../lib/image'; import { ALL_ITEMS_QUERY, DELETE_ITEM_MUTATION } from '../queries'; @@ -12,6 +13,22 @@ const Title = styled.h1` font-size: 50px; `; + + +const Items = styled.div` + display: grid; + grid-template-columns: repeat(4, calc(25% - 20px)); + grid-gap: 20px; +`; + +const Item = styled.div` + background: #f3f3f3; + padding: 20px; + img { + width: 100%; + } +`; + class ItemList extends Component { render() { @@ -31,12 +48,11 @@ class ItemList extends Component { const itemsToRender = this.props.allLinksQuery.allItems return ( - <div> + <Items> <Title>Items For Sale</Title> {itemsToRender.map((item,i) => ( - <div className="item" key={i}> - <hr/> - { item.image ? <img src={`https://images.graph.cool/v1/cj5xz8szs28930145gct82bdj/${item.image.secret}/300x300`} /> : null } + <Item className="item" key={i}> + { item.image ? <img src={makeImage(item.image)} /> : null } <h3>{item.title}</h3> <p>{item.description}</p> <Link href={{ @@ -47,21 +63,19 @@ class ItemList extends Component { </Link> <TakeMyMoney + id={item.id} amount={item.price} name={item.title} // the pop-in header title description={item.description} // the pop-in header subtitle - image={`https://images.graph.cool/v1/cj5xz8szs28930145gct82bdj/${item.image.secret}/300x300`} + image={makeImage(item.image)} > <button>Buy for {formatMoney(item.price)}</button> </TakeMyMoney> - - <UpdateItem id={item.id} /> - <button onClick={() => this.props.removeItemMutation({ variables: { id: item.id }})}>× Delete item</button> - </div> + </Item> ))} - </div> + </Items> ) } diff --git a/components/LoginAuth0.js b/components/LoginAuth0.js new file mode 100644 index 0000000..d5293b5 --- /dev/null +++ b/components/LoginAuth0.js @@ -0,0 +1,58 @@ +import { Component, PropTypes } from 'react' +import Auth0Lock from 'auth0-lock' + +class LoginAuth0 extends Component { + + constructor (props) { + super(props) + if(typeof window === 'undefined') return; + const redirectUrl = `http://localhost:3000/signup`; + console.log(redirectUrl); + this._lock = new Auth0Lock('l851ev2q8X48wf56eGLjIWFbMwwbvWPE', 'wesbos.auth0.com', { + auth: { + redirect: false, + } + }); + } + + createUser = () => { + const variables = { + idToken: window.localStorage.getItem("auth0IdToken"), + emailAddress: 'wesbos@gmail.com', + name: 'Hardcoded Wes' + }; + // TODO - make a createUser function + this.props + .createUser({ variables }) + .then(response => { + this.props.history.replace("/"); + }) + .catch(e => { + console.error(e); + this.props.history.replace("/"); + }); + }; + + componentDidMount() { + console.log('MOUNT'); + this._lock.on('authenticated', (authResult) => { + console.log('HIIIIIIII') + window.localStorage.setItem('auth0IdToken', authResult.idToken) + console.log('Done!', authResult); + }) + } + + _showLogin = () => { + this._lock.show() + } + + render() { + return ( + <div> + <button onClick={this._showLogin}>Log in with Auth0 </button> + </div> + ) + } +} + +export default LoginAuth0; diff --git a/components/Meta.js b/components/Meta.js new file mode 100644 index 0000000..d851946 --- /dev/null +++ b/components/Meta.js @@ -0,0 +1,16 @@ +import Head from 'next/head' +import Router from 'next/router' +import Nav from './Nav'; + +export default () => ( + <div> + <Head> + <meta name="viewport" content="width=device-width, initial-scale=1" /> + <meta charSet="utf-8" /> + <Nav/> + <link rel="shortcut icon" href="https://wesbos.com/wp-content/themes/wb2014/i/crown-yellow-small.png" /> + <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/font-awesome/4.7.0/css/font-awesome.min.css"/> + <title>Sick Fits</title> + </Head> + </div> +) diff --git a/components/Nav.js b/components/Nav.js new file mode 100644 index 0000000..2e32a1c --- /dev/null +++ b/components/Nav.js @@ -0,0 +1,9 @@ +import Link from 'next/link' + +export default () => ( + <ul> + <Link href="/"><a>Home</a></Link> + <Link href="/signup/"><a>Signup</a></Link> + <Link href="/orders/"><a>Orders</a></Link> + </ul> +) diff --git a/components/OrderList.js b/components/OrderList.js new file mode 100644 index 0000000..c33f0b9 --- /dev/null +++ b/components/OrderList.js @@ -0,0 +1,52 @@ +import { Component } from 'react'; +import withData from '../lib/withData'; +import Items from '../components/Items'; +import CreateItem from '../components/CreateItem'; +import Signup from '../components/Signup'; +import LoginAuth0 from '../components/LoginAuth0'; +import Page from '../components/Page'; +import { USER_ORDERS_QUERY } from '../queries'; +import { graphql, compose } from 'react-apollo' +import has from 'lodash.has'; +import get from 'lodash.get'; +import formatMoney from '../lib/formatMoney'; +import makeImage from '../lib/image'; + +class OrderList extends Component { + componentDidMount() { + console.log('Mounting!'); + } + render() { + + if(this.props.loading) { + return <p>Loading...</p> + } + + if(this.props.error) { + return <p>Error...</p> + } + + if(!has(this.props, 'userOrdersQuery.user.orders')) { + return <p>Don't have it yet!</p> + } + + const orders = this.props.userOrdersQuery.user.orders; + + console.log(orders); + return ( + <div> + <h2>You have {orders.length} Orders</h2> + <ul> + {orders.map(order => <li key={order.id}> + <img src={makeImage(order.item.image)} alt=""/> + <h3>{order.item.title} ({formatMoney(order.amount)}) </h3> + <p>{order.item.description}</p> + </li>)} + </ul> + </div> + ) + } +} + +const ordersEnhancer = graphql(USER_ORDERS_QUERY, { name: 'userOrdersQuery' }); +export default compose(ordersEnhancer)(OrderList) diff --git a/components/Page.js b/components/Page.js new file mode 100644 index 0000000..1b07fe6 --- /dev/null +++ b/components/Page.js @@ -0,0 +1,25 @@ +import Header from './Header' +import Meta from './Meta' +import withData from '../lib/withData'; +import Nav from './Nav'; +import styled from 'styled-components'; + +const StyledPage = styled.div` + font-family: sans-serif; + color: #303030; + background: #efc600; + padding: 100px; +`; + +const Page = ({ children }) => ( + <StyledPage className="main"> + <Meta /> + <Header /> + <Nav></Nav> + <div> + { children } + </div> + </StyledPage> +) + +export default withData(Page); diff --git a/components/Signup.js b/components/Signup.js new file mode 100644 index 0000000..ab0a498 --- /dev/null +++ b/components/Signup.js @@ -0,0 +1,76 @@ +import React, { Component } from 'react' +import { graphql, gql } from 'react-apollo' +import { CREATE_USER_MUTATION } from '../queries'; + +class Signup extends Component { + + constructor() { + super(); + const idToken = typeof window !== 'undefined' ? localStorage.getItem('auth0IdToken') || '' : ''; + this.state = { + email: '', + name: '', + idToken, + error: undefined + } + + } + + + render() { + return ( + <div> + { this.state.loading ? 'LOADING...' : 'Ready!' } + + { this.state.error ? <p>{this.state.error.message}</p> : '' } + + <form onSubmit={this._createUser}> + <p>Email + <input value={this.state.email} onChange={(e) => this.setState({ email: e.target.value })} type='text' placeholder='email'/> + </p> + + <p>Name + <input value={this.state.name} onChange={(e) => this.setState({ name: e.target.value })} type='text' placeholder='name'/> + </p> + + <p>idToken + <input disabled value={this.state.idToken} onChange={(e) => this.setState({ idToken: e.target.value })} type='text' placeholder='name'/> + </p> + + <button type="submit">Submit</button> + </form> + </div> + ) + } + + _createUser = async (e) => { + e.preventDefault(); + // pull the values from state + const { email, name, idToken } = this.state + // create a mutation + // TODO: handle any errors + // turn loading on + this.setState({ loading: true }); + console.log(name, email, idToken); + try { + const res = await this.props.createUserMutation({ + // pass in those variables from state + variables: { name, email, idToken } + }); + } catch(error) { + this.setState({ error }); + console.dir(error); + } + this.setState({ loading: false }); + } +} +// When we submit this mutation, we need to update our store - we have a few ways to do that: +// One - we can go nucular and run refetchQueries() which will just go get everything - this is easy, but at the cost of efficiency. + + +export default graphql(CREATE_USER_MUTATION, { name: 'createUserMutation', options: { + // Easy, but slow + // refetchQueries: ['AllLinksQuery'] + // This is much Better / efficient + // Notice how the variable is called createItem - that is because createItem is the name of the query! + } })(Signup) diff --git a/components/TakeMyMoney.js b/components/TakeMyMoney.js index 143f990..d68cca1 100644 --- a/components/TakeMyMoney.js +++ b/components/TakeMyMoney.js @@ -1,31 +1,43 @@ import { Component } from 'react'; import StripeCheckout from 'react-stripe-checkout'; -import { CREATE_ORDER_MUTATION } from '../queries'; -import { graphql } from 'react-apollo'; +import { CREATE_ORDER_MUTATION, CURRENT_USER_QUERY } from '../queries'; +import { graphql, compose } from 'react-apollo'; class TakeMyMoney extends Component { onToken = async (res) => { const token = res.id; + const userId = this.props.currentUserQuery.user.id; + const itemId = this.props.id; console.log(`Going to make a purchase with ${token}`); - const charge = await this.props.createOrder({ variables: { token }}); + console.log(`THe person that bought this was ${userId}`) + console.log(`The item id is ${itemId}`) + const charge = await this.props.createOrder({ variables: { token, userId, itemId }}); alert(`Back from the charge! ${charge.id}`); console.log(charge); } render() { + const user = this.props.currentUserQuery.user || {}; + const email = user.email || ''; return ( - // ... - <StripeCheckout - {...this.props} - token={this.onToken} - stripeKey="pk_lclTtThFp8CnO3QtEZSd8HA9mFUps" - currency="USD" - > - {this.props.children} - </StripeCheckout> + <div> + <StripeCheckout + amount={this.props.amount} + name={this.props.name} + description={this.props.description} + token={this.onToken} + stripeKey="pk_lclTtThFp8CnO3QtEZSd8HA9mFUps" + currency="USD" + email={email} + > + {this.props.children} + </StripeCheckout> + </div> ) } } -export default graphql(CREATE_ORDER_MUTATION, { name: 'createOrder' })(TakeMyMoney); +const userEnhancer = graphql(CURRENT_USER_QUERY, { name: 'currentUserQuery' }); +const createOrderEnhancer = graphql(CREATE_ORDER_MUTATION, { name: 'createOrder' }); +export default compose(userEnhancer, createOrderEnhancer)(TakeMyMoney); |
