From 222ab374d53a206332b1ab51c7c43f6d5dc7a31e Mon Sep 17 00:00:00 2001 From: Wes Bos Date: Tue, 8 Aug 2017 22:09:05 -0400 Subject: yep --- components/Count.js | 37 ++++++++++++++++++ components/CreateItem.js | 100 +++++++++++++++++++++++++++++++++++++++++++++++ components/Items.js | 83 +++++++++++++++++++++++++++++++++++++++ components/UpdateItem.js | 82 ++++++++++++++++++++++++++++++++++++++ 4 files changed, 302 insertions(+) create mode 100644 components/Count.js create mode 100644 components/CreateItem.js create mode 100644 components/Items.js create mode 100644 components/UpdateItem.js (limited to 'components') diff --git a/components/Count.js b/components/Count.js new file mode 100644 index 0000000..800a902 --- /dev/null +++ b/components/Count.js @@ -0,0 +1,37 @@ +import React, { Component } from 'react' +import { graphql, gql } from 'react-apollo' + +import { ALL_ITEMS_QUERY } from '../queries'; + +class Count extends Component { + + render() { + + // 1 + if (this.props.allLinksQuery && this.props.allLinksQuery.loading) { + return
Loading
+ } + + // 2 + if (this.props.allLinksQuery && this.props.allLinksQuery.error) { + return
Error
+ } + + // 3 + const itemsToRender = this.props.allLinksQuery.allItems + + return ( +
+

There are {itemsToRender.length} items for sale

+
+ ) + } + +} + +// 1 + +// We export the graphQL HOC - this will fetch the data and inject it into the Count compeont via props + +export { ALL_ITEMS_QUERY } +export default graphql(ALL_ITEMS_QUERY, { name: 'allLinksQuery' }) (Count) diff --git a/components/CreateItem.js b/components/CreateItem.js new file mode 100644 index 0000000..843263c --- /dev/null +++ b/components/CreateItem.js @@ -0,0 +1,100 @@ +import React, { Component } from 'react' +import { graphql, gql } from 'react-apollo' +import { ALL_ITEMS_QUERY, CREATE_LINK_MUTATION } from '../queries'; + +class CreateLink extends Component { + + state = { + description: '', + title: '', + image: '', + loading: false + } + + componentWillReceiveProps(nextProps) { + console.log(nextProps); + } + + uploadFile = async (e) => { + const files = e.currentTarget.files; + + let data = new FormData(); + data.append('data', files[0]); + + // use the file endpoint + const res = await fetch('https://api.graph.cool/file/v1/cj5xz8szs28930145gct82bdj', { + method: 'POST', + body: data + }); + const file = await res.json(); + console.log(file); + this.setState({ image: file.id }); + } + + render() { + return ( +
+ { this.state.loading ? 'LOADING...' : 'Ready!' } +
+

Image: {this.state.image}

+ this.setState({ title: e.target.value })} + type='text' + placeholder='A description for the link' + /> + + + +
+
+ ) + } + + _createLink = async (e) => { + e.preventDefault(); + // pull the values from state + const { description, title, image } = this.state + // create a mutation + // TODO: handle any errors + // turn loading on + this.setState({ loading: true }); + const res = await this.props.createLinkMutation({ + // pass in those variables from state + variables: { + description, + title, + imageId: image + } + }); + 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_LINK_MUTATION, { name: 'createLinkMutation', 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! + update: (proxy, { data: { createItem } }) => { + console.log({createItem, ALL_ITEMS_QUERY}); + const data = proxy.readQuery({ query: ALL_ITEMS_QUERY }); + // data is our store, allItems is our sub-"state", it's just an array. We can just add it to + data.allItems.unshift(createItem); + // and then "set state", so it will update on the page. This will update the cache for us! + proxy.writeQuery({ query: ALL_ITEMS_QUERY, data }); + }, + } })(CreateLink) diff --git a/components/Items.js b/components/Items.js new file mode 100644 index 0000000..1e6b3bf --- /dev/null +++ b/components/Items.js @@ -0,0 +1,83 @@ +import React, { Component } from 'react' +import { graphql, compose } from 'react-apollo' +import UpdateItem from './UpdateItem'; +import Link from 'next/link'; +import styled from 'styled-components'; + +import { ALL_ITEMS_QUERY, DELETE_ITEM_MUTATION } from '../queries'; + +const Title = styled.h1` + font-size: 50px; +`; + +class ItemList extends Component { + + render() { + + // 1 + if (this.props.allLinksQuery && this.props.allLinksQuery.loading) { + return
Loading
+ } + + // 2 + if (this.props.allLinksQuery && this.props.allLinksQuery.error) { + console.log(this.props.allLinksQuery.error) + return
Error
+ } + + // 3 + const itemsToRender = this.props.allLinksQuery.allItems + + return ( +
+ Items For Sale + {itemsToRender.map((item,i) => ( +
+
+ { item.image ? : null } +

{item.title}

+

{item.description}

+ + Edit {item.id} + + + + + + +
+ ))} +
+ ) + } + +} + +// 1 + +// We export the graphQL HOC - this will fetch the data and inject it into the ItemList compeont via props + +// Create some Enhancers +const itemsEnahncer = graphql(ALL_ITEMS_QUERY, { name: 'allLinksQuery' }); +const deleteItemEnhancer = graphql(DELETE_ITEM_MUTATION, { + name: 'removeItemMutation', + options: { + update: (proxy, { data: { deleteItem } }) => { + + // grab the data from our cache + const data = proxy.readQuery({ query: ALL_ITEMS_QUERY }); + + // filter out the delted item + data.allItems = data.allItems.filter(item => item.id !== deleteItem.id); + + // and then "set state" (update cache), so it will update whereever we have used this data on the page + proxy.writeQuery({ query: ALL_ITEMS_QUERY, data }); + + }, + } +}); + +export default compose(itemsEnahncer, deleteItemEnhancer)(ItemList) diff --git a/components/UpdateItem.js b/components/UpdateItem.js new file mode 100644 index 0000000..8ca8b73 --- /dev/null +++ b/components/UpdateItem.js @@ -0,0 +1,82 @@ +import React, { Component } from 'react' +import { graphql, gql, compose } from 'react-apollo' +import { SINGLE_LINK_QUERY, UPDATE_LINK_MUTATION } from '../queries'; + +class UpdateLink extends Component { + + state = { + ...this.props.findItem.Item, + price: 0, + fullPrice: 0 + } + + saveToState = (e) => { + let { name, value, type } = e.target; + if (type === 'number') { + value = parseInt(value); + } + + this.setState({ [name]: value }); + } + + render() { + return ( +
+ +

Edit {this.props.id}

+ { this.state.loading ? 'LOADING...' : 'Ready!' } +
+ + + + + + + + + + + + + + +
+
+ ) + } + + _createLink = async (e) => { + e.preventDefault(); + // pull the values from state + const { description, title } = this.state + const { id } = this.props; + // create a mutation + // TODO: handle any errors + // turn loading on + this.setState({ loading: true }); + console.log(this.state); + const res = await this.props.updateItem({ + // pass in those variables from state + variables: { + ...this.state + } + }); + this.setState({ loading: false }); + } + +} + +const ComponentWithMutations = compose( + // First, query for getting the link + graphql(SINGLE_LINK_QUERY, { + name: 'findItem', + options: ({ id }) => ({ + variables: { id } + }) + }), + // Second, the mutation for updating the link + graphql(UPDATE_LINK_MUTATION, { name: 'updateItem' }) +)(UpdateLink); + + +export default ComponentWithMutations; -- cgit v1.3