Hook up reactions data

This commit is contained in:
Kurt Hutten
2020-11-08 15:41:59 +11:00
parent db06a3852a
commit 9ff1d5043d
13 changed files with 103 additions and 36 deletions

View File

@@ -13,7 +13,7 @@ const noEmotes =[{
const textShadow = {textShadow: '0 4px 6px rgba(0, 0, 0, 0.3)'}
const EmojiReaction = ({ emotes, onEmote = () => {}, className }) => {
const EmojiReaction = ({ emotes, userEmotes, onEmote = () => {}, className }) => {
const [isOpen, setIsOpen] = useState(false)
const [anchorEl, setAnchorEl] = useState(null)
const [popoverId, setPopoverId] = useState(undefined)
@@ -59,7 +59,10 @@ const EmojiReaction = ({ emotes, onEmote = () => {}, className }) => {
<div className="whitespace-no-wrap absolute right-0 inset-y-0 flex items-center flex-row-reverse">
{(emotes.length ? emotes : noEmotes).map((emote, i) => (
<span
className="rounded-full tracking-wide hover:bg-indigo-100 p-1 mx-px transform hover:-translate-y-px transition-all duration-150"
className={getActiveClasses(
"rounded-full tracking-wide hover:bg-indigo-100 p-1 mx-px transform hover:-translate-y-px transition-all duration-150 border-indigo-400",
{'border': userEmotes.includes(emote.emoji)}
)}
style={textShadow}
key={`${emote.emoji}--${i}`}
onClick={() => handleEmojiClick(emote.emoji)}

View File

@@ -3,8 +3,8 @@ import { navigate, routes } from '@redwoodjs/router'
import PartReactionForm from 'src/components/PartReactionForm'
const CREATE_PART_REACTION_MUTATION = gql`
mutation CreatePartReactionMutation($input: CreatePartReactionInput!) {
createPartReaction(input: $input) {
mutation TogglePartReactionMutation($input: TogglePartReactionInput!) {
togglePartReaction(input: $input) {
id
}
}
@@ -12,7 +12,7 @@ const CREATE_PART_REACTION_MUTATION = gql`
const NewPartReaction = () => {
const { addMessage } = useFlash()
const [createPartReaction, { loading, error }] = useMutation(
const [togglePartReaction, { loading, error }] = useMutation(
CREATE_PART_REACTION_MUTATION,
{
onCompleted: () => {
@@ -23,7 +23,7 @@ const NewPartReaction = () => {
)
const onSave = (input) => {
createPartReaction({ variables: { input } })
togglePartReaction({ variables: { input } })
}
return (

View File

@@ -1,10 +1,11 @@
import { useMutation, useFlash } from '@redwoodjs/web'
import { navigate, routes } from '@redwoodjs/router'
import { useAuth } from '@redwoodjs/auth'
import PartProfile from 'src/components/PartProfile'
export const QUERY = gql`
query FIND_PART_BY_USERNAME_TITLE($userName: String!, $partTitle: String!) {
query FIND_PART_BY_USERNAME_TITLE($userName: String!, $partTitle: String!, $currentUserId: String!) {
userPart: userName(userName: $userName) {
id
name
@@ -20,6 +21,12 @@ export const QUERY = gql`
createdAt
updatedAt
userId
Reaction {
emote
}
userReactions: Reaction(userId: $currentUserId) {
emote
}
}
}
}
@@ -37,6 +44,14 @@ const UPDATE_PART_MUTATION = gql`
}
}
`
const TOGGLE_REACTION_MUTATION = gql`
mutation ToggleReactionMutation($input: TogglePartReactionInput!) {
togglePartReaction(input: $input){
id
emote
}
}
`
export const Loading = () => <div>Loading...</div>
@@ -44,7 +59,8 @@ export const Empty = () => <div>Empty</div>
export const Failure = ({ error }) => <div>Error: {error.message}</div>
export const Success = ({ userPart, variables: {isEditable} }) => {
export const Success = ({ userPart, variables: {isEditable}, refetch}) => {
const { currentUser } = useAuth()
const { addMessage } = useFlash()
const [updateUser, { loading, error }] = useMutation(UPDATE_PART_MUTATION, {
onCompleted: ({updatePart}) => {
@@ -52,16 +68,25 @@ export const Success = ({ userPart, variables: {isEditable} }) => {
addMessage('Part updated.', { classes: 'rw-flash-success' })
},
})
const onSave = (id, input) => {
updateUser({ variables: { id, input } })
}
const [toggleReaction] = useMutation(TOGGLE_REACTION_MUTATION, {
onCompleted: (hey) => refetch()
})
const onReaction = (emote) => toggleReaction({variables: {input: {
emote,
userId: currentUser.sub,
partId: userPart?.Part?.id,
}}})
return <PartProfile
userPart={userPart}
onSave={onSave}
loading={loading}
error={error}
isEditable={isEditable}
onReaction={onReaction}
/>
}

View File

@@ -7,11 +7,14 @@ import ImageUploader from 'src/components/ImageUploader'
import Breadcrumb from 'src/components/Breadcrumb'
import EmojiReaction from 'src/components/EmojiReaction'
import Button from 'src/components/Button'
import { countEmotes } from 'src/helpers/emote'
const PartProfile = ({userPart, isEditable, onSave, loading, error}) => {
const PartProfile = ({userPart, isEditable, onSave, loading, error, onReaction}) => {
const { currentUser } = useAuth()
const canEdit = currentUser?.sub === userPart.id
const part = userPart?.Part
const emotes = countEmotes(part?.Reaction)
const userEmotes = part?.userReactions.map(({emote}) => emote)
useEffect(() => {isEditable &&
!canEdit &&
navigate(routes.part2({userName: userPart.userName, partTitle: part.title}))},
@@ -50,12 +53,10 @@ const PartProfile = ({userPart, isEditable, onSave, loading, error}) => {
/>
<h4 className="text-indigo-800 text-xl underline text-right py-4">{userPart?.name}</h4>
<div className="h-px bg-indigo-200 mb-4" />
{/* TODO hook up to emoji data properly */}
<EmojiReaction
// emotes={[{emoji: '❤️',count: 3},{emoji: '😁',count: 2},{emoji: '😜',count: 2},{emoji: '🤩',count: 2},{emoji: '🤣',count: 2},{emoji: '🙌',count: 2},{emoji: '🚀',count: 2}]}
emotes={[{emoji: '❤️',count: 3},{emoji: '😁',count: 2}]}
// emotes={[]}
onEmote={() => {}}
emotes={emotes}
userEmotes={userEmotes}
onEmote={onReaction}
/>
<Button
className="mt-6 ml-auto hover:shadow-lg bg-gradient-to-r from-transparent to-indigo-100"

View File

@@ -1,17 +1,10 @@
import { useMemo } from 'react'
import { Link, routes } from '@redwoodjs/router'
import { countEmotes } from 'src/helpers/emote'
import ImageUploader from 'src/components/ImageUploader'
const PartsList = ({ parts }) => {
const countEmotes = (reactions) => {
// would be good to do this sever side
// counting unique emojis, and limiting to the 5 largest
const emoteCounts = {}
reactions.forEach(({emote}) => {
emoteCounts[emote] = emoteCounts[emote] ? emoteCounts[emote] + 1 : 1
})
return Object.entries(emoteCounts).map(([emoji, count]) => ({emoji, count})).sort((a,b) => a.count-b.count).slice(-5)
}
return (
<section className="max-w-6xl mx-auto mt-20">
<ul className="grid gap-x-8 gap-y-12 items-center mx-4 relative" style={{gridTemplateColumns: 'repeat(auto-fit, minmax(16rem, 1fr))'}}>