Joystream Stats před 2 roky
rodič
revize
7e503d4919

+ 3 - 1
src/components/Validators/Content.tsx

@@ -1,6 +1,7 @@
+import Leaderboard from "./Leaderboard";
+import Stakes from "./Stakes";
 import Stats from "./MinMax";
 import ValidatorList from "./ValidatorList";
-import Leaderboard from "./Leaderboard";
 import { Spinner } from "..";
 
 const Content = (props: IState) => {
@@ -26,6 +27,7 @@ const Content = (props: IState) => {
         reward={status.lastReward}
       />
       <Leaderboard members={props.members} points={props.rewardPoints} />
+      <Stakes stakes={props.stakes} members={props.members} />
       <ValidatorList
         toggleStar={props.toggleStar}
         waiting={waiting}

+ 109 - 0
src/components/Validators/Stakes.tsx

@@ -0,0 +1,109 @@
+import { Link } from "react-router-dom";
+import { Member, Stake } from "../types";
+
+import {
+  Accordion,
+  AccordionDetails,
+  AccordionSummary,
+  createStyles,
+  makeStyles,
+  Theme,
+  Typography,
+} from "@material-ui/core";
+import ExpandMoreIcon from "@material-ui/icons/ExpandMore";
+
+const useStyles = makeStyles((theme: Theme) =>
+  createStyles({
+    root: {
+      textAlign: "center",
+      backgroundColor: "#000",
+      color: "#fff",
+    },
+    acc: {
+      color: "#fff",
+      backgroundColor: "#4138ff",
+    },
+  })
+);
+
+const mJoy = (mJoy: number) => (mJoy / 1000000).toFixed(1) + ` M`;
+const getSum = (stakes) => stakes.reduce((sum, { value }) => sum + value, 0);
+
+const getNominators = (stakes: Stake[], members: Member[]) => {
+  let nominators = {};
+  Object.keys(stakes).forEach((validator) =>
+    stakes[validator].others.forEach(({ who, value }) => {
+      if (!nominators[who]) nominators[who] = [];
+      const member = members.find((m) => m.rootKey === validator);
+      nominators[who].push({ validator, handle: member?.handle, value });
+    })
+  );
+  return Object.keys(nominators)
+    .map((nominator) => {
+      const stakes = nominators[nominator];
+      const sum = getSum(stakes);
+      const member = members.find((m) => m.rootKey === nominator);
+      return { key: nominator, handle: member?.handle, sum, stakes };
+    })
+    .sort((a, b) => b.sum - a.sum);
+};
+
+const Nominators = (props: { members: Member[]; stakes: Stake[] }) => {
+  const { showAll = false, stakes, members } = props;
+  const nominators = getNominators(stakes, members);
+  return (
+    <div className="mt-3 overflow-hidden">
+      <h2 className="text-center">Nominators</h2>
+      <div className="d-flex flex-column" style={{ overFlowY: true }}>
+        {nominators.slice(0, showAll ? null : 10).map((nominator) => (
+          <Nominator key={nominator.key} nominator={nominator} />
+        ))}
+      </div>
+    </div>
+  );
+};
+
+export default Nominators;
+
+const Nominator = (props: {
+  nominator: {
+    who: string;
+    sum: number;
+    stakes: { validator: string; value: number }[];
+  };
+}) => {
+  const classes = useStyles();
+  const { key, handle, sum, stakes } = props.nominator;
+  return (
+    <Accordion className={classes.acc} key={key}>
+      <AccordionSummary
+        expandIcon={<ExpandMoreIcon style={{ color: "#fff" }} />}
+        aria-controls={`${key}-content`}
+        id={`${key}-header`}
+      >
+        <div className="d-flex flex-row justify-content-start w-100">
+          <div className="col-2 text-right">{mJoy(sum)}</div>
+          <div className="col-10">{handle || key}</div>
+        </div>
+      </AccordionSummary>
+      <AccordionDetails>
+        <div className="d-flex flex-column w-100">
+          {stakes
+            .sort((a, b) => b.value - a.value)
+            .map((stake) => (
+              <div
+                key={stake.validator}
+                className="d-flex flex-row justify-content-end text-left"
+              >
+                <div className="col-2 text-right">{mJoy(stake.value)}</div>
+
+                <a className="col-10 text-left" href={`#${stake.validator}`}>
+                  {stake.handle || stake.validator}
+                </a>
+              </div>
+            ))}
+        </div>
+      </AccordionDetails>
+    </Accordion>
+  );
+};