Votes.tsx 2.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114
  1. import React from "react";
  2. import { Button } from "react-bootstrap";
  3. import { Vote } from "../types";
  4. export const voteKeys: { [key: string]: string } = {
  5. abstensions: "Abstain",
  6. approvals: "Approve",
  7. rejections: "Reject",
  8. slashes: "Slash",
  9. };
  10. export const voteStyles: { [key: string]: string } = {
  11. Abstain: "secondary",
  12. Approve: "success",
  13. Reject: "danger",
  14. Slash: "warning",
  15. "": "body",
  16. };
  17. export const VoteButton = (props: { handle: string; vote: string }) => {
  18. const { handle, vote } = props;
  19. return (
  20. <Button title={vote} className="btn-sm p-1" variant={voteStyles[vote]}>
  21. {handle}
  22. </Button>
  23. );
  24. };
  25. // Vote!
  26. export const VoteNowButton = (props: { show: boolean; url: string }) => {
  27. const { show, url } = props;
  28. if (!show) return <div />;
  29. return (
  30. <Button variant="success">
  31. <a href={url}>Vote</a>
  32. </Button>
  33. );
  34. };
  35. // Bubbles
  36. const VoteBubble = (props: {
  37. detailed?: boolean;
  38. vote: Vote;
  39. count: number;
  40. }) => {
  41. const { detailed, vote } = props;
  42. if (!vote.member) return <div />;
  43. const handle = vote.member.handle;
  44. return (
  45. <Button className="btn-sm p-1" variant={voteStyles[vote.vote]}>
  46. <a href={`/members/${handle}`}>
  47. {handle} {detailed && vote.vote}
  48. </a>
  49. </Button>
  50. );
  51. };
  52. export const VotesBubbles = (props: { detailed?: boolean; votes: Vote[] }) => {
  53. const votes = props.votes.reduce(
  54. (uniq, vote) =>
  55. uniq.find((v) => v.member.handle === vote.member.handle)
  56. ? uniq
  57. : uniq.concat(vote),
  58. []
  59. );
  60. return (
  61. <>
  62. {votes.map((vote: Vote) => (
  63. <VoteBubble
  64. key={vote.id}
  65. detailed={props.detailed}
  66. vote={vote}
  67. count={votes.length}
  68. />
  69. ))}
  70. </>
  71. );
  72. };
  73. // Tooltip
  74. //interface IProps {
  75. // votes: VotingResults;
  76. // votesByAccount?: Vote[];
  77. //}
  78. // TODO Property 'votes' does not exist on type 'IntrinsicAttributes & IProps'
  79. // https://stackoverflow.com/questions/59969756/not-assignable-to-type-intrinsicattributes-intrinsicclassattributes-react-js
  80. export const VotesTooltip = (props: any) => {
  81. const { votes } = props;
  82. if (!votes)
  83. return (
  84. <div>
  85. <VotesBubbles detailed={true} votes={votes} />
  86. </div>
  87. );
  88. if (!votes.length) return <div>No votes were cast.</div>;
  89. return (
  90. <div className="text-left text-light">
  91. {votes.map((vote: Vote) => (
  92. <VoteButton
  93. key={vote.member.handle}
  94. handle={vote.member.handle}
  95. vote={vote.vote}
  96. />
  97. ))}
  98. </div>
  99. );
  100. };