Skip to content

Commit a030764

Browse files
author
Carlos Rufo Jimenez
committed
6.4-end-store-v2.1
1 parent 26ccb45 commit a030764

File tree

4 files changed

+128
-20
lines changed

4 files changed

+128
-20
lines changed

src/components/CreateLink.js

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import React, { Component } from 'react'
22
import { Mutation } from 'react-apollo'
33
import gql from 'graphql-tag'
4+
import { FEED_QUERY } from './LinkList'
45

56
const POST_MUTATION = gql`
67
mutation PostMutation($description: String!, $url: String!) {
@@ -43,6 +44,14 @@ class CreateLink extends Component {
4344
mutation={POST_MUTATION}
4445
variables={{ description, url }}
4546
onCompleted={() => this.props.history.push('/')}
47+
update={(cache, { data: { post } }) => {
48+
const data = cache.readQuery({ query: FEED_QUERY })
49+
data.feed.links.splice(0, 0, post)
50+
cache.writeQuery({
51+
query: FEED_QUERY,
52+
data
53+
})
54+
}}
4655
>
4756
{postMutation => <button onClick={postMutation}>Submit</button>}
4857
</Mutation>

src/components/Link.js

Lines changed: 58 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,60 @@
11
import React from 'react'
2+
import { AUTH_TOKEN } from '../constants'
3+
import { timeDifferenceForDate } from '../utils'
4+
import { Mutation } from 'react-apollo'
5+
import gql from 'graphql-tag'
26

3-
export default ({ link }) => (
4-
<div>
5-
{link.description} ({link.url})
6-
</div>
7-
)
7+
const VOTE_MUTATION = gql`
8+
mutation VoteMutation($linkId: ID!) {
9+
vote(linkId: $linkId) {
10+
id
11+
link {
12+
votes {
13+
id
14+
user {
15+
id
16+
}
17+
}
18+
}
19+
user {
20+
id
21+
}
22+
}
23+
}
24+
`
25+
26+
export default ({ link, index, updateStoreAfterVote }) => {
27+
const authToken = localStorage.getItem(AUTH_TOKEN)
28+
return (
29+
<div className="flex mt2 items-start">
30+
<div className="flex items-center">
31+
<span className="gray">{index + 1}.</span>
32+
{authToken && (
33+
<Mutation
34+
mutation={VOTE_MUTATION}
35+
variables={{ linkId: link.id }}
36+
update={(cache, { data: { vote } }) =>
37+
updateStoreAfterVote(cache, vote, link.id)
38+
}
39+
>
40+
{voteMutation => (
41+
<div className="ml1 gray f11" onClick={voteMutation}>
42+
43+
</div>
44+
)}
45+
</Mutation>
46+
)}
47+
</div>
48+
<div className="ml1">
49+
<div>
50+
{link.description} ({link.url})
51+
</div>
52+
<div className="f6 lh-copy gray">
53+
{`${link.votes.length} votes | by
54+
${link.postedBy ? link.postedBy.name : 'Unknown'}
55+
${timeDifferenceForDate(link.createdAt)}`}
56+
</div>
57+
</div>
58+
</div>
59+
)
60+
}

src/components/LinkList.js

Lines changed: 28 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -3,33 +3,39 @@ import Link from './Link'
33
import { Query } from 'react-apollo'
44
import gql from 'graphql-tag'
55

6-
const FEED_QUERY = gql`
6+
export const FEED_QUERY = gql`
77
{
88
feed {
99
links {
1010
id
1111
createdAt
1212
url
1313
description
14+
postedBy {
15+
id
16+
name
17+
}
18+
votes {
19+
id
20+
user {
21+
id
22+
}
23+
}
1424
}
1525
}
1626
}
1727
`
1828

19-
export default () => {
20-
const linksToRender = [
21-
{
22-
id: '1',
23-
description: 'Prisma turns your database into a GraphQL API 😎',
24-
url: 'https://www.prismagraphql.com'
25-
},
26-
{
27-
id: '2',
28-
description: 'The best GraphQL client',
29-
url: 'https://www.apollographql.com/docs/react/'
30-
}
31-
]
29+
const updateCacheAfterVote = (store, createVote, linkId) => {
30+
const data = store.readQuery({ query: FEED_QUERY })
31+
32+
const votedLink = data.feed.links.find(link => link.id === linkId)
33+
votedLink.votes = createVote.link.votes
3234

35+
store.writeQuery({ query: FEED_QUERY, data })
36+
}
37+
38+
export default () => {
3339
return (
3440
<Query query={FEED_QUERY}>
3541
{({ loading, error, data }) => {
@@ -40,7 +46,14 @@ export default () => {
4046

4147
return (
4248
<div>
43-
{linksToRender.map(link => <Link key={link.id} link={link} />)}
49+
{linksToRender.map((link, index) => (
50+
<Link
51+
key={link.id}
52+
link={link}
53+
index={index}
54+
updateStoreAfterVote={updateCacheAfterVote}
55+
/>
56+
))}
4457
</div>
4558
)
4659
}}

src/utils.js

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
function timeDifference(current, previous) {
2+
const milliSecondsPerMinute = 60 * 1000
3+
const milliSecondsPerHour = milliSecondsPerMinute * 60
4+
const milliSecondsPerDay = milliSecondsPerHour * 24
5+
const milliSecondsPerMonth = milliSecondsPerDay * 30
6+
const milliSecondsPerYear = milliSecondsPerDay * 365
7+
8+
const elapsed = current - previous
9+
10+
if (elapsed < milliSecondsPerMinute / 3) {
11+
return 'just now'
12+
}
13+
14+
if (elapsed < milliSecondsPerMinute) {
15+
return 'less than 1 min ago'
16+
} else if (elapsed < milliSecondsPerHour) {
17+
return Math.round(elapsed / milliSecondsPerMinute) + ' min ago'
18+
} else if (elapsed < milliSecondsPerDay) {
19+
return Math.round(elapsed / milliSecondsPerHour) + ' h ago'
20+
} else if (elapsed < milliSecondsPerMonth) {
21+
return Math.round(elapsed / milliSecondsPerDay) + ' days ago'
22+
} else if (elapsed < milliSecondsPerYear) {
23+
return Math.round(elapsed / milliSecondsPerMonth) + ' mo ago'
24+
} else {
25+
return Math.round(elapsed / milliSecondsPerYear) + ' years ago'
26+
}
27+
}
28+
29+
export function timeDifferenceForDate(date) {
30+
const now = new Date().getTime()
31+
const updated = new Date(date).getTime()
32+
return timeDifference(now, updated)
33+
}

0 commit comments

Comments
 (0)