Skip to content
This repository was archived by the owner on May 4, 2023. It is now read-only.

Commit 78dd08c

Browse files
chore: pulled Votes into its own folder
1 parent 77e71f8 commit 78dd08c

File tree

2 files changed

+147
-0
lines changed

2 files changed

+147
-0
lines changed
Lines changed: 146 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,146 @@
1+
import { useRef } from 'react';
2+
import { useInView } from 'framer-motion';
3+
import { useMutation, useQuery } from '@apollo/client';
4+
import { Flex, FlexProps, IconButton, Text, Tooltip } from '@chakra-ui/react';
5+
import { DownVoteIcon, UpVoteIcon, useToast } from '@codiga/components';
6+
7+
import { useUser } from '../UserContext';
8+
import {
9+
AddVoteMutationVariables,
10+
ADD_VOTE,
11+
DeleteVoteMutationVariables,
12+
DELETE_VOTE,
13+
} from '../../graphql/mutations';
14+
import { GET_RECIPE_VOTES_QUERY } from '../../graphql/queries';
15+
import { formatNumber } from '../../utils/formatUtils';
16+
17+
type VotesProps = FlexProps & {
18+
entityId: number;
19+
entityType: 'Recipe';
20+
upvotes: number;
21+
downvotes: number;
22+
};
23+
24+
export default function Votes({
25+
upvotes,
26+
downvotes,
27+
entityId,
28+
entityType = 'Recipe',
29+
...props
30+
}: VotesProps) {
31+
const toast = useToast();
32+
const { id: userId } = useUser();
33+
34+
const ref = useRef(null);
35+
const isInView = useInView(ref);
36+
37+
const { data, refetch } = useQuery(GET_RECIPE_VOTES_QUERY, {
38+
skip: !userId || !isInView,
39+
variables: {
40+
recipeId: entityId,
41+
},
42+
});
43+
44+
const isUpVoted = Boolean(data?.votesData?.isUpVoted);
45+
const isDownVoted = Boolean(data?.votesData?.isDownVoted);
46+
const upVoteCount = Number(data?.votesData?.upvotes || upvotes);
47+
const downVoteCount = Number(data?.votesData?.downvotes || downvotes);
48+
const voteText = data ? upVoteCount - downVoteCount : upvotes - downvotes;
49+
50+
const [addVote] = useMutation<void, AddVoteMutationVariables>(ADD_VOTE);
51+
const [deleteVote] = useMutation<void, DeleteVoteMutationVariables>(
52+
DELETE_VOTE
53+
);
54+
55+
const handleUpVote = async () => {
56+
try {
57+
if (isUpVoted) {
58+
await deleteVote({ variables: { entityId, entityType } });
59+
} else {
60+
await addVote({ variables: { entityId, entityType, isUpvote: true } });
61+
}
62+
refetch();
63+
toast({
64+
status: 'success',
65+
description: 'Snippet upvoted',
66+
});
67+
} catch (err) {
68+
toast({
69+
status: 'error',
70+
description: 'An error occured while upvoting. Please refresh.',
71+
});
72+
}
73+
};
74+
75+
const handleDownVote = async () => {
76+
try {
77+
if (isDownVoted) {
78+
await deleteVote({ variables: { entityId, entityType } });
79+
} else {
80+
await addVote({ variables: { entityId, entityType, isUpvote: false } });
81+
}
82+
refetch();
83+
toast({
84+
status: 'success',
85+
description: 'Snippet downvoted.',
86+
});
87+
} catch (err) {
88+
toast({
89+
status: 'error',
90+
description: 'An error occured while downvoting. Please refresh.',
91+
});
92+
}
93+
};
94+
95+
const countColor = isUpVoted || isDownVoted ? 'rose.50' : undefined;
96+
97+
return (
98+
<Flex ref={ref} gridGap="space_4" alignItems="center" {...props}>
99+
<Tooltip
100+
label="Please log in to upvote"
101+
shouldWrapChildren
102+
isDisabled={!!userId}
103+
>
104+
<IconButton
105+
isDisabled={!userId}
106+
minW="auto"
107+
boxSize="20px"
108+
variant="ghost"
109+
aria-label={`Upvote ${entityType.toLowerCase()}`}
110+
icon={
111+
<UpVoteIcon
112+
boxSize="16px"
113+
color={isUpVoted ? 'base.rose' : 'inherit'}
114+
fillRule={isUpVoted ? 'nonzero' : 'evenodd'}
115+
/>
116+
}
117+
onClick={handleUpVote}
118+
/>
119+
</Tooltip>
120+
<Text lineHeight="20px" color={countColor} _dark={{ color: countColor }}>
121+
{formatNumber(voteText)}
122+
</Text>
123+
<Tooltip
124+
label="Please log in to downvote"
125+
shouldWrapChildren
126+
isDisabled={!!userId}
127+
>
128+
<IconButton
129+
isDisabled={!userId}
130+
minW="auto"
131+
boxSize="20px"
132+
variant="ghost"
133+
aria-label={`Downvote ${entityType.toLowerCase()}`}
134+
icon={
135+
<DownVoteIcon
136+
boxSize="16px"
137+
color={isDownVoted ? 'base.rose' : 'inherit'}
138+
fillRule={isDownVoted ? 'nonzero' : 'evenodd'}
139+
/>
140+
}
141+
onClick={handleDownVote}
142+
/>
143+
</Tooltip>
144+
</Flex>
145+
);
146+
}
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
export { default } from './Votes';

0 commit comments

Comments
 (0)