import clsx from 'clsx'; import { h } from 'preact'; import { useState } from 'preact/hooks'; import { defineMessages, useIntl } from 'react-intl'; import { useDispatch } from 'react-redux'; import { patchComment } from 'store/comments/actions'; import { putCommentVote } from 'common/api'; import { StaticStore } from 'common/static-store'; import { ArrowIcon } from 'components/icons/arrow'; import styles from './comment-votes.module.css'; import { Tooltip } from 'components/tooltip'; import { extractErrorMessageFromResponse } from 'utils/errorUtils'; type Props = { id: string; vote: 0 | -1 | 1; votes: number; controversy: number | undefined; disabled?: boolean; }; export function CommentVotes({ id, votes, vote, disabled, controversy = 0 }: Props) { const intl = useIntl(); const dispatch = useDispatch(); const [loadingState, setLoadingState] = useState<{ vote: number; votes: number } | null>(null); const [errorMessage, setErrorMessage] = useState(undefined); async function handleClick(evt: preact.JSX.TargetedEvent) { const { value } = evt.currentTarget.dataset; const increment = Number(value) as -1 | 1; setLoadingState({ vote: vote + increment, votes: votes + increment }); try { const p = await putCommentVote({ id, vote: increment }); dispatch(patchComment({ ...p, vote: (vote + increment) as -1 | 0 | 1 })); setErrorMessage(undefined); setTimeout(() => setLoadingState(null), 200); } catch (err) { // @ts-ignore setErrorMessage(extractErrorMessageFromResponse(err, intl)); setLoadingState(null); } } const isUpvoted = vote === 1; const isDownvoted = vote === -1; const value = loadingState?.votes ?? votes; const isPositiveScore = StaticStore.config.positive_score && value > -1; return ( {Boolean(!disabled) && ( )} {errorMessage} : undefined} position="top-left" hideBehavior="mouseleave" hideTimeout={10000} permanent onHide={() => { setErrorMessage(undefined); }} >
0, })} > {value}
{!disabled && ( )}
); } export const messages = defineMessages({ score: { id: 'vote.score', defaultMessage: 'Votes score', }, upvote: { id: 'vote.upvote', defaultMessage: 'Vote up', }, downvote: { id: 'vote.downvote', defaultMessage: 'Vote down', }, controversy: { id: 'vote.controversy', defaultMessage: 'Controversy: {value}', }, });