summaryrefslogtreecommitdiffstats
path: root/components
diff options
context:
space:
mode:
authorWes Bos <wesbos@gmail.com>2017-08-08 22:09:05 -0400
committerWes Bos <wesbos@gmail.com>2017-08-08 22:09:05 -0400
commit222ab374d53a206332b1ab51c7c43f6d5dc7a31e (patch)
tree2b446d96bfc6c7efab07f3d0fbb84d96ecb1253b /components
yep
Diffstat (limited to 'components')
-rw-r--r--components/Count.js37
-rw-r--r--components/CreateItem.js100
-rw-r--r--components/Items.js83
-rw-r--r--components/UpdateItem.js82
4 files changed, 302 insertions, 0 deletions
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 <div>Loading</div>
+ }
+
+ // 2
+ if (this.props.allLinksQuery && this.props.allLinksQuery.error) {
+ return <div>Error</div>
+ }
+
+ // 3
+ const itemsToRender = this.props.allLinksQuery.allItems
+
+ return (
+ <div>
+ <h1>There are {itemsToRender.length} items for sale</h1>
+ </div>
+ )
+ }
+
+}
+
+// 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 (
+ <div>
+ { this.state.loading ? 'LOADING...' : 'Ready!' }
+ <form onSubmit={this._createLink}>
+ <p>Image: {this.state.image}</p>
+ <input
+ value={this.state.title}
+ onChange={(e) => this.setState({ title: e.target.value })}
+ type='text'
+ placeholder='A description for the link'
+ />
+ <input
+ onChange={this.uploadFile}
+ type='file'
+ />
+ <textarea
+ value={this.state.description}
+ onChange={(e) => this.setState({ description: e.target.value })}
+ type='text'
+ placeholder='The desc for this item'
+ ></textarea>
+ <button type="submit">Submit</button>
+ </form>
+ </div>
+ )
+ }
+
+ _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 <div>Loading</div>
+ }
+
+ // 2
+ if (this.props.allLinksQuery && this.props.allLinksQuery.error) {
+ console.log(this.props.allLinksQuery.error)
+ return <div>Error</div>
+ }
+
+ // 3
+ const itemsToRender = this.props.allLinksQuery.allItems
+
+ return (
+ <div>
+ <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 }
+ <h3>{item.title}</h3>
+ <p>{item.description}</p>
+ <Link href={{
+ pathname: '/admin/update',
+ query: { id: item.id }
+ }}>
+ <a>Edit {item.id}</a>
+ </Link>
+
+ <UpdateItem id={item.id} />
+
+ <button onClick={() => this.props.removeItemMutation({ variables: { id: item.id }})}>&times; Delete item</button>
+
+ </div>
+ ))}
+ </div>
+ )
+ }
+
+}
+
+// 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 (
+ <div>
+
+ <h2>Edit {this.props.id}</h2>
+ { this.state.loading ? 'LOADING...' : 'Ready!' }
+ <form onSubmit={this._createLink}>
+
+ <label htmlFor="title">Title</label>
+ <input value={this.state.title} name="title" onChange={this.saveToState} type='text'/>
+
+ <label htmlFor="description">Description</label>
+ <textarea value={this.state.description} name="description" onChange={this.saveToState}></textarea>
+
+ <label htmlFor="price">Price</label>
+ <input type="number" name="price" onChange={this.saveToState} value={this.state.price} />
+
+ <label htmlFor="fullPrice">Full Price</label>
+ <input type="number" name="fullPrice" onChange={this.saveToState} value={this.state.fullPrice} />
+
+ <button type="submit">Save...</button>
+ </form>
+ </div>
+ )
+ }
+
+ _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;