diff options
| author | Wes Bos <wesbos@gmail.com> | 2018-03-22 21:11:15 -0400 |
|---|---|---|
| committer | Wes Bos <wesbos@gmail.com> | 2018-03-22 21:11:15 -0400 |
| commit | 169b0953ad91f22bb3b2bf2d80d87ebfbe30d45d (patch) | |
| tree | e66454fb1055440996ae01cb980394d84715bf59 /frontend | |
| parent | a6af043686e4375d7944e91cae3d5b63c59edab0 (diff) | |
yay
Diffstat (limited to 'frontend')
| -rw-r--r-- | frontend/components/Dump.js | 19 | ||||
| -rw-r--r-- | frontend/components/ErrorMessage.js | 10 | ||||
| -rw-r--r-- | frontend/components/Items.js | 16 | ||||
| -rw-r--r-- | frontend/components/Pagination.js | 3 | ||||
| -rw-r--r-- | frontend/components/Signup.js | 7 | ||||
| -rw-r--r-- | frontend/components/SingleItem.js | 40 | ||||
| -rw-r--r-- | frontend/components/TakeMyMoney.js | 50 | ||||
| -rw-r--r-- | frontend/components/UpdateItem.js | 96 | ||||
| -rw-r--r-- | frontend/lib/catchError.js | 8 | ||||
| -rw-r--r-- | frontend/lib/initApollo-OLD.js | 92 | ||||
| -rw-r--r-- | frontend/pages/admin/update.js | 1 | ||||
| -rw-r--r-- | frontend/queries/index.js | 10 |
12 files changed, 129 insertions, 223 deletions
diff --git a/frontend/components/Dump.js b/frontend/components/Dump.js new file mode 100644 index 0000000..f281281 --- /dev/null +++ b/frontend/components/Dump.js @@ -0,0 +1,19 @@ +const Dump = props => ( + <div + style={{ + fontSize: 20, + border: '1px solid #efefef', + padding: 10, + background: 'white', + }} + > + {Object.keys(props).map(prop => ( + <pre key={prop}> + <strong style={{ color: 'white', background: 'red' }}>{prop} 💩</strong> + {JSON.stringify(props[prop], '', ' ')} + </pre> + ))} + </div> +); + +export default Dump; diff --git a/frontend/components/ErrorMessage.js b/frontend/components/ErrorMessage.js index ed5d031..c473731 100644 --- a/frontend/components/ErrorMessage.js +++ b/frontend/components/ErrorMessage.js @@ -20,6 +20,16 @@ const StyledError = styled.div` const DisplayError = ({ error }) => { if (!error || !error.message) return null; + if (error.networkError && error.networkError.result && error.networkError.result.errors.length) { + return error.networkError.result.errors.map(error => ( + <StyledError> + <p> + <strong>Shoot!</strong> + {error.message} + </p> + </StyledError> + )); + } return ( <StyledError> <p> diff --git a/frontend/components/Items.js b/frontend/components/Items.js index 1f4918f..36491e6 100644 --- a/frontend/components/Items.js +++ b/frontend/components/Items.js @@ -7,15 +7,6 @@ import Item from './Item'; import { perPage } from '../config'; import { ALL_ITEMS_QUERY } from '../queries/index'; -// export const itemEnhancer = graphql(ALL_ITEMS_QUERY, { -// name: 'itemsQuery', -// options({ page }) { -// return { -// variables: , -// }; -// }, -// }); - const Items = styled.div` display: grid; grid-template-columns: repeat(auto-fit, minmax(300px, 1fr)); @@ -48,12 +39,10 @@ class ItemList extends React.Component { first: perPage, }} > - {({ data, error, loading, variables }) => { + {({ data, error, loading }) => { if (loading) return <div>Loading</div>; if (error) return <div>Error</div>; - return ( - <Items key={this.props.page}>{data.items.map((item, i) => <Item key={item.id} item={item} />)}</Items> - ); + return <Items key={this.props.page}>{data.items.map(item => <Item key={item.id} item={item} />)}</Items>; }} </Query> <Pagination page={this.props.page} /> @@ -62,5 +51,4 @@ class ItemList extends React.Component { } } -// export default compose(itemEnhancer)(ItemList); export default ItemList; diff --git a/frontend/components/Pagination.js b/frontend/components/Pagination.js index 138e1b2..d42c807 100644 --- a/frontend/components/Pagination.js +++ b/frontend/components/Pagination.js @@ -1,9 +1,8 @@ import React from 'react'; -import { compose, Query } from 'react-apollo'; +import { Query } from 'react-apollo'; import styled from 'styled-components'; import Link from 'next/link'; import PropTypes from 'prop-types'; -import { itemEnhancer } from '../enhancers/enhancers'; import { perPage } from '../config'; import { ALL_ITEMS_QUERY } from '../queries/index'; diff --git a/frontend/components/Signup.js b/frontend/components/Signup.js index 314d0ab..4adc1ad 100644 --- a/frontend/components/Signup.js +++ b/frontend/components/Signup.js @@ -1,8 +1,7 @@ import React, { Component } from 'react'; -import { graphql, compose, Mutation } from 'react-apollo'; -import { SIGNUP_MUTATION, CURRENT_USER_QUERY } from '../queries'; +import { Mutation } from 'react-apollo'; +import { SIGNUP_MUTATION } from '../queries'; import Form from './styles/Form'; -import catchError from '../lib/catchError'; import Error from './ErrorMessage'; class Signup extends Component { @@ -20,7 +19,7 @@ class Signup extends Component { render() { return ( <Mutation mutation={SIGNUP_MUTATION} variables={this.state}> - {(signup, { data, loading, error }) => ( + {(signup, { loading, error }) => ( <Form onSubmit={e => { e.preventDefault(); diff --git a/frontend/components/SingleItem.js b/frontend/components/SingleItem.js index 5a6373f..d4bec4f 100644 --- a/frontend/components/SingleItem.js +++ b/frontend/components/SingleItem.js @@ -1,23 +1,25 @@ -import { compose } from 'react-apollo'; -import { singleItemEnhancer } from '../enhancers/enhancers'; +import { Query } from 'react-apollo'; +import PropTypes from 'prop-types'; +import { SINGLE_ITEM_QUERY } from '../queries/index'; -const SingleItem = ({ findItem: { error, loading, items } }) => { - if (loading) return <p>Loading...</p>; - if (error) return <p>Error...</p>; - const item = items[0]; +const SingleItem = props => ( + <Query query={SINGLE_ITEM_QUERY} variables={{ id: props.id }}> + {({ data: { items }, loading, error }) => { + if (loading || error) return null; + const [item] = items; + return ( + <div> + <img src={item.largeImage || item.image} alt={item.title} /> + <h2>Viewing {item.title}</h2> + <p>{item.description}</p> + </div> + ); + }} + </Query> +); - if (!item) { - return <p>No Item Found</p>; - } - - return ( - <div> - <img src={item.largeImage || item.image} alt={item.title} /> - <h2>Viewing {item.title}</h2> - <p>{item.description}</p> - </div> - ); +SingleItem.propTypes = { + id: PropTypes.string.isRequired, }; -export default compose(singleItemEnhancer)(SingleItem); -export { SingleItem }; +export default SingleItem; diff --git a/frontend/components/TakeMyMoney.js b/frontend/components/TakeMyMoney.js index 20fc334..e52b08c 100644 --- a/frontend/components/TakeMyMoney.js +++ b/frontend/components/TakeMyMoney.js @@ -1,9 +1,8 @@ import { Component } from 'react'; import StripeCheckout from 'react-stripe-checkout'; -import { compose, Mutation, Query } from 'react-apollo'; +import { Mutation, Query } from 'react-apollo'; import Router from 'next/router'; import NProgress from 'nprogress'; -import PropTypes from 'prop-types'; import { CREATE_ORDER_MUTATION, CURRENT_USER_QUERY } from '../queries'; function totalItems(cart) { @@ -33,35 +32,30 @@ class TakeMyMoney extends Component { render() { return ( <Query query={CURRENT_USER_QUERY}> - {({ data: { me } }) => ( - <Mutation mutation={CREATE_ORDER_MUTATION}> - {createOrder => ( - <StripeCheckout - amount={total(me.cart)} - name="Sick Fits Haul" - description={`Order of ${totalItems(me.cart)} Items From Sick Fits`} - image={me.cart[0].item.image} - token={res => this.onToken(res, createOrder)} - stripeKey="pk_lclTtThFp8CnO3QtEZSd8HA9mFUps" - currency="USD" - email={me.email} - > - {this.props.children} - </StripeCheckout> - )} - </Mutation> - )} + {({ data: { me } }) => { + if (!me || !me.cart.length) return null; + return ( + <Mutation mutation={CREATE_ORDER_MUTATION}> + {createOrder => ( + <StripeCheckout + amount={total(me.cart)} + name="Sick Fits Haul" + description={`Order of ${totalItems(me.cart)} Items From Sick Fits`} + image={me.cart[0].item.image} + token={res => this.onToken(res, createOrder)} + stripeKey="pk_lclTtThFp8CnO3QtEZSd8HA9mFUps" + currency="USD" + email={me.email} + > + {this.props.children} + </StripeCheckout> + )} + </Mutation> + ); + }} </Query> ); } } -TakeMyMoney.propTypes = { - currentUser: PropTypes.object.isRequired, - createOrder: PropTypes.func.isRequired, -}; - -// export default compose(userEnhancer, createOrderEnhancer)(TakeMyMoney); -// export { TakeMyMoney }; - export default TakeMyMoney; diff --git a/frontend/components/UpdateItem.js b/frontend/components/UpdateItem.js index 4841006..4292d41 100644 --- a/frontend/components/UpdateItem.js +++ b/frontend/components/UpdateItem.js @@ -1,16 +1,15 @@ import React, { Component } from 'react'; -import { graphql, gql, compose } from 'react-apollo'; -import { SINGLE_ITEM_QUERY, UPDATE_LINK_MUTATION } from '../queries'; +import { Query, Mutation } from 'react-apollo'; +import { SINGLE_ITEM_QUERY, UPDATE_ITEM_MUTATION } from '../queries'; import Form from './styles/Form'; - -import { singleItemEnhancer } from '../enhancers/enhancers'; +import Error from './ErrorMessage'; +import Dump from './Dump'; class UpdateItem extends Component { state = { item: {}, }; - saveToState = e => { let { name, value, type } = e.target; if (type === 'number') { @@ -22,64 +21,63 @@ class UpdateItem extends Component { this.setState({ item }); }; - updateItem = async e => { + updateItem = async (e, updateItemMutation) => { + console.log('Updating Item'); e.preventDefault(); - // pull the values from state - const { description, title } = this.state; - const { id } = this.props; - // create a mutation - // TODO: handle any errors. If you send an extra field it should break -how do we display those errors if they are currently only visible via the network tab? - // turn loading on - this.setState({ loading: true }); - const res = await this.props.updateItem({ + + const res = await updateItemMutation({ // pass in those variables from state variables: { - ...this.props.findItem.items[0], + id: this.props.id, ...this.state.item, }, }); console.log(res); - this.setState({ loading: false }); }; render() { - if (this.props.findItem.loading) { - return <p>Loading...</p>; - } - - const item = this.props.findItem.items[0]; return ( - <div> - <Form onSubmit={this.updateItem}> - <h2>Edit {item.title}</h2> - {this.state.loading ? 'LOADING...' : 'Ready!'} - <fieldset disabled={this.state.loading}> - <label htmlFor="title"> - Title - <input id="title" defaultValue={item.title} name="title" onChange={this.saveToState} type="text" /> - </label> + <Query query={SINGLE_ITEM_QUERY} variables={{ id: this.props.id }}> + {({ data: { items } }) => { + if (!items || !items.length) return <p>Item Not Found</p>; + const [item] = items; + return ( + <Mutation mutation={UPDATE_ITEM_MUTATION}> + {(updateItemMutation, { error, loading }) => ( + <Form onSubmit={e => this.updateItem(e, updateItemMutation)}> + <Error error={error} /> + <h2>Edit {item.title}</h2> + <fieldset disabled={loading} aria-busy={loading}> + <label htmlFor="title"> + Title + <input + id="title" + defaultValue={item.title} + name="title" + onChange={this.saveToState} + type="text" + /> + </label> - <label htmlFor="description"> - Description - <textarea defaultValue={item.description} name="description" onChange={this.saveToState} /> - </label> + <label htmlFor="description"> + Description + <textarea defaultValue={item.description} name="description" onChange={this.saveToState} /> + </label> - <label htmlFor="price"> - Price - <input type="number" name="price" onChange={this.saveToState} defaultValue={item.price} /> - </label> - <button type="submit">Save...</button> - </fieldset> - </Form> - </div> + <label htmlFor="price"> + Price + <input type="number" name="price" onChange={this.saveToState} defaultValue={item.price} /> + </label> + <button type="submit">Save...</button> + </fieldset> + </Form> + )} + </Mutation> + ); + }} + </Query> ); } } -const ComponentWithMutations = compose( - singleItemEnhancer, - // Second, the mutation for updating the link - graphql(UPDATE_LINK_MUTATION, { name: 'updateItem' }) -)(UpdateItem); - -export default ComponentWithMutations; +export default UpdateItem; diff --git a/frontend/lib/catchError.js b/frontend/lib/catchError.js deleted file mode 100644 index 581d2f3..0000000 --- a/frontend/lib/catchError.js +++ /dev/null @@ -1,8 +0,0 @@ -const catchError = function(fn) { - return (...args) => - fn(...args).catch(error => { - this.setState({ error }); - }); -}; - -export default catchError; diff --git a/frontend/lib/initApollo-OLD.js b/frontend/lib/initApollo-OLD.js deleted file mode 100644 index e86c7e1..0000000 --- a/frontend/lib/initApollo-OLD.js +++ /dev/null @@ -1,92 +0,0 @@ -import { ApolloClient } from 'apollo-client'; -import { ApolloLink, from } from 'apollo-link'; -import { HttpLink } from 'apollo-link-http'; -import { InMemoryCache } from 'apollo-cache-inmemory'; -import fetch from 'isomorphic-fetch'; -import { withClientState } from 'apollo-link-state'; -import { endpoint } from '../config'; - -let apolloClient = null; - -// Polyfill fetch() on the server (used by apollo-client) -if (!process.browser) { - global.fetch = fetch; -} - -function create(initialState) { - // Create a new Cache - const cache = new InMemoryCache().restore(initialState || {}); - // First we create three peices of middleware - const stateLink = withClientState({ - cache, - defaults: { - uiData: { - __typename: 'UIData', - isConnected: true, - isCartOpen: false, - }, - }, - resolvers: { - Mutation: { - setLocalData: (_, values, { cache }) => { - const data = { - uiData: { - __typename: 'UIData', - ...values, - }, - }; - cache.writeData({ data }); - return null; - }, - }, - }, - }); - - // 1. Create a link for local state to be managed in Apollo - - // 2. connect to our GraphQL API - const httpLink = new HttpLink({ - uri: endpoint, // Server URL (must be absolute) - opts: { - credentials: 'same-origin', - }, - }); - - // 3. One to tack on our auth token on each request - const authMiddleware = new ApolloLink((operation, forward) => { - const headers = {}; - - if (typeof localStorage !== 'undefined' && localStorage.getItem('token')) { - headers.authorization = `Bearer ${localStorage.getItem('token')}`; - } - - operation.setContext({ headers }); - return forward(operation); - }); - - return new ApolloClient({ - connectToDevTools: process.browser, - ssrMode: !process.browser, // Disables forceFetch on the server (so queries are only run once) - link: from([stateLink, authMiddleware, httpLink]), - cache, - defaultOptions: { - query: { errorPolicy: 'all' }, - mutate: { errorPolicy: 'all' }, - }, - }); -} - -export default function initApollo(initialState) { - // Make sure to create a new client for every server-side request so that data - // isn't shared between connections (which would be bad) - if (!process.browser) { - return create(initialState); - } - - // Reuse client on the client-side - if (!apolloClient) { - apolloClient = create(initialState); - } - - return apolloClient; -} diff --git a/frontend/pages/admin/update.js b/frontend/pages/admin/update.js index e9cd745..2731f05 100644 --- a/frontend/pages/admin/update.js +++ b/frontend/pages/admin/update.js @@ -7,7 +7,6 @@ class Home extends Component { render() { return ( <Page> - <p>Update You Item!</p> <UpdateItem id={this.props.url.query.id} /> </Page> ); diff --git a/frontend/queries/index.js b/frontend/queries/index.js index 94070e8..bf3b9b1 100644 --- a/frontend/queries/index.js +++ b/frontend/queries/index.js @@ -140,21 +140,19 @@ export const REMOVE_ITEM_MUTATION = gql` } `; -export const UPDATE_LINK_MUTATION = gql` +export const UPDATE_ITEM_MUTATION = gql` ${itemDetails} mutation UpdateItem( $id: ID! - $title: String! - $description: String! - $price: Int! - # $fullPrice: Int! + $title: String + $description: String + $price: Int ) { updateItem( id: $id description: $description title: $title price: $price - # fullPrice: $fullPrice ) { ...itemDetails } |
