1 import { showScores } from "@utils/app";
2 import { numToSI } from "@utils/helpers";
3 import classNames from "classnames";
4 import { Component, linkEvent } from "inferno";
5 import { CommentAggregates, PostAggregates } from "lemmy-js-client";
6 import { I18NextService } from "../../services";
7 import { Icon, Spinner } from "../common/icon";
8 import { PostListing } from "../post/post-listing";
10 interface VoteButtonsProps {
11 postListing: PostListing;
12 enableDownvotes?: boolean;
13 upvoteLoading?: boolean;
14 downvoteLoading?: boolean;
15 handleUpvote: (i: PostListing) => void;
16 handleDownvote: (i: PostListing) => void;
17 counts: CommentAggregates | PostAggregates;
21 interface VoteButtonsState {
22 upvoteLoading: boolean;
23 downvoteLoading: boolean;
26 export class VoteButtonsCompact extends Component<
30 state: VoteButtonsState = {
32 downvoteLoading: false,
35 constructor(props: any, context: any) {
36 super(props, context);
39 get pointsTippy(): string {
40 const points = I18NextService.i18n.t("number_of_points", {
41 count: Number(this.props.counts.score),
42 formattedCount: Number(this.props.counts.score),
45 const upvotes = I18NextService.i18n.t("number_of_upvotes", {
46 count: Number(this.props.counts.upvotes),
47 formattedCount: Number(this.props.counts.upvotes),
50 const downvotes = I18NextService.i18n.t("number_of_downvotes", {
51 count: Number(this.props.counts.downvotes),
52 formattedCount: Number(this.props.counts.downvotes),
55 return `${points} • ${upvotes} • ${downvotes}`;
59 return showScores() ? { "data-tippy-content": this.pointsTippy } : {};
66 className={`btn-animate btn py-0 px-1 ${
67 this.props.my_vote === 1 ? "text-info" : "text-muted"
70 onClick={linkEvent(this.props.postListing, this.props.handleUpvote)}
71 aria-label={I18NextService.i18n.t("upvote")}
72 aria-pressed={this.props.my_vote === 1}
74 {this.state.upvoteLoading ? (
78 <Icon icon="arrow-up1" classes="icon-inline small" />
80 <span className="ms-2">
81 {numToSI(this.props.counts.upvotes)}
87 {this.props.enableDownvotes && (
89 className={`ms-2 btn-animate btn py-0 px-1 ${
90 this.props.my_vote === -1 ? "text-danger" : "text-muted"
93 this.props.postListing,
94 this.props.handleDownvote
97 aria-label={I18NextService.i18n.t("downvote")}
98 aria-pressed={this.props.my_vote === -1}
100 {this.state.downvoteLoading ? (
104 <Icon icon="arrow-down1" classes="icon-inline small" />
107 className={classNames("ms-2", {
108 invisible: this.props.counts.downvotes === 0,
111 {numToSI(this.props.counts.downvotes)}
123 export class VoteButtons extends Component<VoteButtonsProps, VoteButtonsState> {
124 state: VoteButtonsState = {
125 upvoteLoading: false,
126 downvoteLoading: false,
129 constructor(props: any, context: any) {
130 super(props, context);
133 get pointsTippy(): string {
134 const points = I18NextService.i18n.t("number_of_points", {
135 count: Number(this.props.counts.score),
136 formattedCount: Number(this.props.counts.score),
139 const upvotes = I18NextService.i18n.t("number_of_upvotes", {
140 count: Number(this.props.counts.upvotes),
141 formattedCount: Number(this.props.counts.upvotes),
144 const downvotes = I18NextService.i18n.t("number_of_downvotes", {
145 count: Number(this.props.counts.downvotes),
146 formattedCount: Number(this.props.counts.downvotes),
149 return `${points} • ${upvotes} • ${downvotes}`;
153 return showScores() ? { "data-tippy-content": this.pointsTippy } : {};
158 <div className={`vote-bar col-1 pe-0 small text-center`}>
160 className={`btn-animate btn btn-link p-0 ${
161 this.props.my_vote == 1 ? "text-info" : "text-muted"
163 onClick={linkEvent(this.props.postListing, this.props.handleUpvote)}
164 data-tippy-content={I18NextService.i18n.t("upvote")}
165 aria-label={I18NextService.i18n.t("upvote")}
166 aria-pressed={this.props.my_vote === 1}
168 {this.state.upvoteLoading ? (
171 <Icon icon="arrow-up1" classes="upvote" />
176 className={`unselectable pointer text-muted px-1 post-score`}
177 data-tippy-content={this.pointsTippy}
179 {numToSI(this.props.counts.score)}
182 <div className="p-1"></div>
184 {this.props.enableDownvotes && (
186 className={`btn-animate btn btn-link p-0 ${
187 this.props.my_vote == -1 ? "text-danger" : "text-muted"
190 this.props.postListing,
191 this.props.handleDownvote
193 data-tippy-content={I18NextService.i18n.t("downvote")}
194 aria-label={I18NextService.i18n.t("downvote")}
195 aria-pressed={this.props.my_vote === -1}
197 {this.state.downvoteLoading ? (
200 <Icon icon="arrow-down1" classes="downvote" />