1 import { showScores } from "@utils/app";
2 import { numToSI } from "@utils/helpers";
3 import { Component, linkEvent } from "inferno";
4 import { CommentAggregates, PostAggregates } from "lemmy-js-client";
5 import { I18NextService } from "../../services";
6 import { Icon, Spinner } from "../common/icon";
7 import { PostListing } from "../post/post-listing";
9 interface VoteButtonsProps {
10 postListing: PostListing;
11 enableDownvotes?: boolean;
12 upvoteLoading?: boolean;
13 downvoteLoading?: boolean;
14 handleUpvote: (i: PostListing) => void;
15 handleDownvote: (i: PostListing) => void;
16 counts: CommentAggregates | PostAggregates;
20 interface VoteButtonsState {
21 upvoteLoading: boolean;
22 downvoteLoading: boolean;
25 export class VoteButtonsCompact extends Component<
29 state: VoteButtonsState = {
31 downvoteLoading: false,
34 constructor(props: any, context: any) {
35 super(props, context);
38 get pointsTippy(): string {
39 const points = I18NextService.i18n.t("number_of_points", {
40 count: Number(this.props.counts.score),
41 formattedCount: Number(this.props.counts.score),
44 const upvotes = I18NextService.i18n.t("number_of_upvotes", {
45 count: Number(this.props.counts.upvotes),
46 formattedCount: Number(this.props.counts.upvotes),
49 const downvotes = I18NextService.i18n.t("number_of_downvotes", {
50 count: Number(this.props.counts.downvotes),
51 formattedCount: Number(this.props.counts.downvotes),
54 return `${points} • ${upvotes} • ${downvotes}`;
58 return showScores() ? { "data-tippy-content": this.pointsTippy } : {};
64 <div className="input-group input-group-sm w-auto">
66 className={`btn btn-sm btn-animate btn-outline-primary rounded-start py-0 ${
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 <span className="input-group-text small py-0">
88 {numToSI(this.props.counts.score)}
90 {this.props.enableDownvotes && (
92 className={`btn btn-sm btn-animate btn-outline-primary rounded-end py-0 ${
93 this.props.my_vote === -1 ? "text-danger" : "text-muted"
96 this.props.postListing,
97 this.props.handleDownvote
100 aria-label={I18NextService.i18n.t("downvote")}
101 aria-pressed={this.props.my_vote === -1}
103 {this.state.downvoteLoading ? (
107 <Icon icon="arrow-down1" classes="icon-inline small" />
109 <span className="ms-2">
110 {numToSI(this.props.counts.downvotes)}
123 export class VoteButtons extends Component<VotesProps, VotesState> {
124 state: VotesState = {
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" />