75 lines
2.2 KiB
TypeScript
Executable File
75 lines
2.2 KiB
TypeScript
Executable File
import {ThumbUpIcon} from '@common/icons/material/ThumbUp';
|
|
import {ThumbDownIcon} from '@common/icons/material/ThumbDown';
|
|
import {VotableModel} from '@common/votes/votable-model';
|
|
import {Button} from '@common/ui/buttons/button';
|
|
import {useStoreVote} from '@common/votes/requests/use-store-vote';
|
|
import {useState} from 'react';
|
|
import {FormattedNumber} from '@common/i18n/formatted-number';
|
|
import clsx from 'clsx';
|
|
|
|
interface Props {
|
|
model: VotableModel;
|
|
className?: string;
|
|
showUpvotesOnly?: boolean;
|
|
}
|
|
export function ThumbButtons({model, className, showUpvotesOnly}: Props) {
|
|
const changeVote = useStoreVote(model);
|
|
|
|
const [upvotes, setUpvotes] = useState(model.upvotes || 0);
|
|
const [downvotes, setDownvotes] = useState(model.downvotes || 0);
|
|
const [currentVote, setCurrentVote] = useState(model.current_vote);
|
|
|
|
const syncLocalState = (model: VotableModel) => {
|
|
setUpvotes(model.upvotes);
|
|
setDownvotes(model.downvotes);
|
|
setCurrentVote(model.current_vote);
|
|
};
|
|
|
|
return (
|
|
<div className={clsx(className, 'whitespace-nowrap')}>
|
|
<Button
|
|
className="gap-6"
|
|
sizeClassName="px-8 py-4"
|
|
color={currentVote === 'upvote' ? 'primary' : undefined}
|
|
disabled={changeVote.isPending}
|
|
aria-label="Upvote"
|
|
onClick={() => {
|
|
changeVote.mutate(
|
|
{voteType: 'upvote'},
|
|
{
|
|
onSuccess: response => syncLocalState(response.model),
|
|
},
|
|
);
|
|
}}
|
|
>
|
|
<ThumbUpIcon />
|
|
<div>
|
|
<FormattedNumber value={upvotes} />
|
|
</div>
|
|
</Button>
|
|
{!showUpvotesOnly && (
|
|
<Button
|
|
className="gap-6"
|
|
sizeClassName="px-8 py-4"
|
|
color={currentVote === 'downvote' ? 'primary' : undefined}
|
|
disabled={changeVote.isPending}
|
|
aria-label="Downvote"
|
|
onClick={() => {
|
|
changeVote.mutate(
|
|
{voteType: 'downvote'},
|
|
{
|
|
onSuccess: response => syncLocalState(response.model),
|
|
},
|
|
);
|
|
}}
|
|
>
|
|
<ThumbDownIcon />
|
|
<div>
|
|
<FormattedNumber value={downvotes} />
|
|
</div>
|
|
</Button>
|
|
)}
|
|
</div>
|
|
);
|
|
}
|