123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226 |
- import React from 'react';
- import { Table, Popup, Icon } from 'semantic-ui-react';
- import styled from 'styled-components';
- import { useWindowDimensions } from '../../../joy-utils/src/react/hooks';
- import { TokenomicsData, StatusServerData } from '@polkadot/joy-utils/src/types/tokenomics';
- const round = (num: number): number => Math.round((num + Number.EPSILON) * 100) / 100;
- const applyCss = (columns: number[]): string => {
- let columnString = '';
- columns.forEach((column, index) => {
- if (index === 0) {
- columnString += `td:nth-of-type(${column}), th:nth-of-type(${column})`;
- } else {
- columnString += ` ,td:nth-of-type(${column}), th:nth-of-type(${column})`;
- }
- });
- return columnString;
- };
- const StyledTable = styled(({ divideColumnsAt, ...rest }) => <Table {...rest} />)`
- border: none !important;
- width: 70% !important;
- margin-bottom:1.5rem;
- @media (max-width: 1400px){
- width:100% !important;
- }
- & tr {
- td:nth-of-type(1),
- th:nth-of-type(1),
- ${(props: { divideColumnsAt: number[]}): string => applyCss(props.divideColumnsAt)} {
- border-left: 0.12rem solid rgba(20,20,20,0.3) !important;
- }
- td:nth-of-type(1){
- position: relative !important;
- }
- td:last-child, th:last-child{
- border-right: 0.12rem solid rgba(20,20,20,0.3) !important;
- }
- }
- & tr:last-child > td{
- border-bottom: 0.12rem solid rgba(20,20,20,0.3) !important;
- }
- & tr:last-child > td:nth-of-type(1){
- border-bottom-left-radius: 0.2rem !important;
- }
- & tr:last-child > td:last-child{
- border-bottom-right-radius: 0.2rem !important;
- }
- th{
- border-top: 0.12rem solid rgba(20,20,20,0.3) !important;
- }
- & .tableColorBlock{
- height: 1rem;
- width:1rem;
- margin: 0 auto;
- @media (max-width: 768px){
- margin: 0;
- }
- }
- `;
- const StyledTableRow = styled(Table.Row)`
- .help-icon{
- position: absolute !important;
- right: 0.5rem !important;
- top: 0.8rem !important;
- @media (max-width: 767px){
- top:0.8rem !important;
- }
- }
- `;
- const SpendingAndStakeTableRow: React.FC<{
- role: string;
- numberOfActors?: string;
- groupEarning?: string;
- groupEarningDollar?: string;
- earningShare?: string;
- groupStake?: string;
- groupStakeDollar?: string;
- stakeShare?: string;
- color?: string;
- active?: boolean;
- helpContent?: string;
- }> = ({ role, numberOfActors, groupEarning, groupEarningDollar, earningShare, groupStake, groupStakeDollar, stakeShare, color, active, helpContent }) => {
- const parseData = (data: string | undefined): string | JSX.Element => {
- if (data && active) {
- return <em>{data}</em>;
- } else if (data) {
- return data;
- } else {
- return 'Loading..';
- }
- };
- return (
- <StyledTableRow color={active && 'rgb(150, 150, 150)'}>
- <Table.Cell>
- {active ? <strong>{role}</strong> : role}
- {helpContent && <Popup
- trigger={<Icon className='help-icon' name='help circle' color='grey'/>}
- content={helpContent}
- position='right center'
- />}
- </Table.Cell>
- <Table.Cell>{parseData(numberOfActors)}</Table.Cell>
- <Table.Cell>{parseData(groupEarning)}</Table.Cell>
- <Table.Cell>{parseData(groupEarningDollar)}</Table.Cell>
- <Table.Cell>{parseData(earningShare)}</Table.Cell>
- <Table.Cell>{parseData(groupStake)}</Table.Cell>
- <Table.Cell>{parseData(groupStakeDollar)}</Table.Cell>
- <Table.Cell>{parseData(stakeShare)}</Table.Cell>
- <Table.Cell><div className='tableColorBlock' style={{ backgroundColor: color }}></div></Table.Cell>
- </StyledTableRow>
- );
- };
- const SpendingAndStakeDistributionTable: React.FC<{data?: TokenomicsData; statusData?: StatusServerData | null}> = ({ data, statusData }) => {
- const { width } = useWindowDimensions();
- const displayStatusData = (group: 'validators' | 'council' | 'storageProviders' | 'storageProviderLead' | 'contentCurators', action: 'rewardsPerWeek' | 'totalStake'): string | undefined => {
- if (group === 'storageProviderLead') {
- return statusData === null ? 'Data currently unavailable...' : (data && statusData) && `${(data.storageProviders.lead[action] * Number(statusData.price)).toFixed(2)}`;
- } else {
- return statusData === null ? 'Data currently unavailable...' : (data && statusData) && `${(data[group][action] * Number(statusData.price)).toFixed(2)}`;
- }
- };
- return (
- <StyledTable divideColumnsAt={[3, 6, 9]} celled>
- <Table.Header>
- <Table.Row>
- <Table.HeaderCell width={4}>Group/Role</Table.HeaderCell>
- <Table.HeaderCell><div>Actors</div>[Number]</Table.HeaderCell>
- <Table.HeaderCell><div>Group earning</div> [JOY/Week]</Table.HeaderCell>
- <Table.HeaderCell><div>Group earning</div> [USD/Week]</Table.HeaderCell>
- <Table.HeaderCell><div>Share</div> [%]</Table.HeaderCell>
- <Table.HeaderCell><div>Group Stake</div> [JOY]</Table.HeaderCell>
- <Table.HeaderCell><div>Group Stake</div> [USD]</Table.HeaderCell>
- <Table.HeaderCell><div>Share</div> [%]</Table.HeaderCell>
- <Table.HeaderCell width={1}>Color</Table.HeaderCell>
- </Table.Row>
- </Table.Header>
- <Table.Body>
- <SpendingAndStakeTableRow
- role={width <= 1050 ? 'Validators' : 'Validators (Nominators)'}
- helpContent='The current set of active Validators (and Nominators), and the sum of the sets projected rewards and total stakes (including Nominators).'
- numberOfActors={data && `${data.validators.number} (${data.validators.nominators.number})`}
- groupEarning={data && `${Math.round(data.validators.rewardsPerWeek)}`}
- groupEarningDollar={displayStatusData('validators', 'rewardsPerWeek')}
- earningShare={data && `${round(data.validators.rewardsShare * 100)}`}
- groupStake={data && `${data.validators.totalStake}`}
- groupStakeDollar={displayStatusData('validators', 'totalStake')}
- stakeShare={data && `${round(data.validators.stakeShare * 100)}`}
- color='rgb(246, 109, 68)'
- />
- <SpendingAndStakeTableRow
- role={width <= 1015 ? 'Council' : 'Council Members'}
- helpContent='The current Council Members, and the sum of their projected rewards and total stakes (including voters/backers).'
- numberOfActors={data && `${data.council.number}`}
- groupEarning={data && `${Math.round(data.council.rewardsPerWeek)}`}
- groupEarningDollar={displayStatusData('council', 'rewardsPerWeek')}
- earningShare={data && `${round(data.council.rewardsShare * 100)}`}
- groupStake={data && `${data.council.totalStake}`}
- groupStakeDollar={displayStatusData('council', 'totalStake')}
- stakeShare={data && `${round(data.council.stakeShare * 100)}`}
- color='rgb(254, 174, 101)'
- />
- <SpendingAndStakeTableRow
- role={width <= 1015 ? 'Storage' : 'Storage Providers'}
- helpContent='The current Storage Providers, and the sum of their projected rewards and stakes.'
- numberOfActors={data && `${data.storageProviders.number}`}
- groupEarning={data && `${Math.round(data.storageProviders.rewardsPerWeek)}`}
- groupEarningDollar={displayStatusData('storageProviders', 'rewardsPerWeek')}
- earningShare={data && `${round(data.storageProviders.rewardsShare * 100)}`}
- groupStake={data && `${data.storageProviders.totalStake}`}
- groupStakeDollar={displayStatusData('storageProviders', 'totalStake')}
- stakeShare={data && `${round(data.storageProviders.stakeShare * 100)}`}
- color='rgb(230, 246, 157)'
- />
- <SpendingAndStakeTableRow
- role={width <= 1015 ? 'S. Lead' : width <= 1050 ? 'Storage Lead' : 'Storage Provider Lead'}
- helpContent='Current Storage Provider Lead, and their projected reward and stake.'
- numberOfActors={data && `${data.storageProviders.lead.number}`}
- groupEarning={data && `${Math.round(data.storageProviders.lead.rewardsPerWeek)}`}
- groupEarningDollar={displayStatusData('storageProviderLead', 'rewardsPerWeek')}
- earningShare={data && `${round(data.storageProviders.lead.rewardsShare * 100)}`}
- groupStake={data && `${data.storageProviders.lead.totalStake}`}
- groupStakeDollar={displayStatusData('storageProviderLead', 'totalStake')}
- stakeShare={data && `${round(data.storageProviders.lead.stakeShare * 100)}`}
- color='rgb(170, 222, 167)'
- />
- <SpendingAndStakeTableRow
- role={width <= 1015 ? 'Content' : 'Content Curators'}
- helpContent='The current Content Curators (and their Lead), and the sum of their projected rewards and stakes.'
- numberOfActors={data && `${data.contentCurators.number} (${data.contentCurators.contentCuratorLead})`}
- groupEarning={data && `${Math.round(data.contentCurators.rewardsPerWeek)}`}
- groupEarningDollar={displayStatusData('contentCurators', 'rewardsPerWeek')}
- earningShare={data && `${round(data.contentCurators.rewardsShare * 100)}`}
- groupStake={data && `${data.contentCurators.totalStake}`}
- groupStakeDollar={displayStatusData('contentCurators', 'totalStake')}
- stakeShare={data && `${round(data.contentCurators.stakeShare * 100)}`}
- color='rgb(100, 194, 166)'
- />
- <SpendingAndStakeTableRow
- role='TOTAL'
- active={true}
- numberOfActors={data && `${data.totalNumberOfActors}`}
- groupEarning={data && `${Math.round(data.totalWeeklySpending)}`}
- groupEarningDollar={statusData === null ? 'Data currently unavailable..' : (data && statusData) && `${round(data.totalWeeklySpending * Number(statusData.price))}`}
- earningShare={data && '100'}
- groupStake={data && `${data.currentlyStakedTokens}`}
- groupStakeDollar={statusData === null ? 'Data currently unavailable..' : (data && statusData) && `${round(data.currentlyStakedTokens * Number(statusData.price))}`}
- stakeShare={data && '100'}
- />
- </Table.Body>
- </StyledTable>
- );
- };
- export default SpendingAndStakeDistributionTable;
|