feat: flow report

This commit is contained in:
AP 2019-12-03 21:33:45 +01:00
parent 86e30be98d
commit 34a335870b
6 changed files with 280 additions and 151 deletions

View file

@ -132,10 +132,15 @@ export const SimpleButton = styled.button`
white-space: nowrap;
`;
interface DarkProps {
fontSize?: string;
bottom?: string;
}
export const DarkSubTitle = styled.div`
font-size: 14px;
font-size: ${({ fontSize }: DarkProps) => (fontSize ? fontSize : '14px')};
color: ${unSelectedNavButton};
margin-bottom: 10px;
margin-bottom: ${({ bottom }: DarkProps) => (bottom ? bottom : '10px')};
`;
export const ColorButton = styled(SimpleButton)`

View file

@ -0,0 +1,55 @@
import React, { useContext } from 'react';
import { DarkSubTitle } from '../../generic/Styled';
import { SettingsContext } from '../../../context/SettingsContext';
import { getValue } from '../../../helpers/Helpers';
import { VictoryPie } from 'victory';
import { chartAxisColor } from '../../../styles/Themes';
import { Row, Col, PieRow } from '.';
interface Props {
flowPie: { x: string; y: number }[];
isType: string;
}
export const FlowPie = ({ flowPie, isType }: Props) => {
const { theme, price, symbol, currency } = useContext(SettingsContext);
const priceProps = { price, symbol, currency };
const getFormat = (amount: number) =>
getValue({
amount,
...priceProps,
});
return (
<Row>
<Col>
<PieRow>
<DarkSubTitle bottom={'0px'}>{flowPie[0].x}</DarkSubTitle>
{isType === 'tokens'
? getFormat(flowPie[0].y)
: flowPie[0].y}
</PieRow>
<PieRow>
<DarkSubTitle bottom={'0px'}>{flowPie[1].x}</DarkSubTitle>
{isType === 'tokens'
? getFormat(flowPie[1].y)
: flowPie[1].y}
</PieRow>
</Col>
<VictoryPie
padding={0}
height={150}
colorScale={['#FD5F00', '#ffd300']}
labels={() => ''}
padAngle={3}
innerRadius={50}
labelRadius={55}
data={flowPie}
style={{
labels: { fontSize: 24, fill: chartAxisColor[theme] },
}}
/>
</Row>
);
};

View file

@ -1,19 +1,13 @@
import React, { useContext } from 'react';
import { DarkSubTitle } from '../../generic/Styled';
import { useQuery } from '@apollo/react-hooks';
import { GET_IN_OUT } from '../../../graphql/query';
import numeral from 'numeral';
import { SettingsContext } from '../../../context/SettingsContext';
import { getValue } from '../../../helpers/Helpers';
import { AccountContext } from '../../../context/AccountContext';
import { getAuthString } from '../../../utils/auth';
import {
VictoryBar,
VictoryChart,
VictoryAxis,
VictoryVoronoiContainer,
VictoryGroup,
VictoryPie,
} from 'victory';
import {
chartAxisColor,
@ -21,11 +15,12 @@ import {
flowBarColor,
flowBarColor2,
} from '../../../styles/Themes';
import { ChannelRow, CardContent, Row } from '.';
interface Props {
isTime: string;
isType: string;
parsedData: {}[];
parsedData2: {}[];
}
const getValueString = (amount: number): string => {
@ -37,16 +32,14 @@ const getValueString = (amount: number): string => {
return `${amount}`;
};
export const FlowReport = ({ isTime, isType }: Props) => {
export const FlowReport = ({
isTime,
isType,
parsedData,
parsedData2,
}: Props) => {
const { theme, price, symbol, currency } = useContext(SettingsContext);
const { host, read, cert } = useContext(AccountContext);
const auth = getAuthString(host, read, cert);
const { data, loading, error } = useQuery(GET_IN_OUT, {
variables: { time: isTime, auth },
});
const priceProps = { price, symbol, currency };
const getFormat = (amount: number) =>
getValue({
@ -54,12 +47,8 @@ export const FlowReport = ({ isTime, isType }: Props) => {
...priceProps,
});
if (!data || loading) {
return <div>Loading</div>;
}
let domain = 24;
let barWidth = 10;
let barWidth = 3;
if (isTime === 'week') {
domain = 7;
barWidth = 15;
@ -68,13 +57,6 @@ export const FlowReport = ({ isTime, isType }: Props) => {
barWidth = 3;
}
const parsedData: {}[] = JSON.parse(data.getInOut.invoices);
const parsedData2: {}[] = JSON.parse(data.getInOut.payments);
const invoicePie = [
{ x: 'Confirmed', y: data.getInOut.confirmedInvoices },
{ x: 'Unconfirmed', y: data.getInOut.unConfirmedInvoices },
];
const getLabelString = (value: number) => {
if (isType === 'amount') {
return numeral(value).format('0,0');
@ -82,106 +64,67 @@ export const FlowReport = ({ isTime, isType }: Props) => {
return getFormat(value);
};
const total = getLabelString(
parsedData
.map((x: any) => x[isType])
.reduce((a: number, c: number) => a + c, 0),
);
if (parsedData.length <= 0) {
return <p>Your node has not forwarded any payments.</p>;
}
return (
<Row>
<CardContent>
<div>
<VictoryChart
domainPadding={50}
padding={{ top: 10, left: 50, right: 50, bottom: 20 }}
containerComponent={
<VictoryVoronoiContainer
voronoiDimension="x"
labels={({ datum }) =>
getLabelString(datum[isType])
}
/>
}
>
<VictoryAxis
domain={[0, domain]}
tickFormat={() => ''}
style={{
axis: { stroke: chartGridColor[theme] },
}}
/>
<VictoryAxis
dependentAxis
style={{
tickLabels: {
fill: chartAxisColor[theme],
fontSize: 18,
},
grid: { stroke: chartGridColor[theme] },
axis: { stroke: 'transparent' },
}}
tickFormat={a =>
isType === 'tokens' ? getValueString(a) : a
}
/>
<VictoryGroup offset={barWidth}>
<VictoryBar
animate={{
duration: 100,
}}
cornerRadius={barWidth / 2}
data={parsedData}
x="period"
y={isType}
style={{
data: {
fill: flowBarColor[theme],
width: barWidth,
},
}}
/>
<VictoryBar
animate={{
duration: 100,
}}
cornerRadius={barWidth / 2}
data={parsedData2}
x="period"
y={isType}
style={{
data: {
fill: flowBarColor2[theme],
width: barWidth,
},
}}
/>
</VictoryGroup>
</VictoryChart>
</div>
<ChannelRow>
<DarkSubTitle>Total:</DarkSubTitle>
{total}
</ChannelRow>
</CardContent>
<CardContent>
<VictoryPie
height={300}
colorScale={['tomato', 'orange', 'gold', 'cyan', 'navy']}
labels={({ datum }: any) => `${datum.y}`}
padAngle={3}
innerRadius={50}
labelRadius={55}
data={invoicePie}
<VictoryChart
height={100}
domainPadding={50}
padding={{ top: 10, left: 50, right: 50, bottom: 10 }}
containerComponent={
<VictoryVoronoiContainer
voronoiDimension="x"
labels={({ datum }) => getLabelString(datum[isType])}
/>
}
>
<VictoryAxis
domain={[0, domain]}
tickFormat={() => ''}
style={{
axis: { stroke: chartGridColor[theme] },
}}
/>
<VictoryAxis
dependentAxis
style={{
tickLabels: {
fill: chartAxisColor[theme],
fontSize: 8,
},
grid: { stroke: chartGridColor[theme] },
axis: { stroke: 'transparent' },
}}
tickFormat={a => (isType === 'tokens' ? getFormat(a) : a)}
/>
<VictoryGroup offset={barWidth}>
<VictoryBar
data={parsedData}
x="period"
y={isType}
style={{
labels: { fontSize: 24, fill: chartAxisColor[theme] },
data: {
fill: flowBarColor[theme],
width: barWidth,
},
labels: {
fontSize: '12px',
},
}}
/>
</CardContent>
</Row>
<VictoryBar
data={parsedData2}
x="period"
y={isType}
style={{
data: {
fill: flowBarColor2[theme],
width: barWidth,
},
labels: {
fontSize: '12px',
},
}}
/>
</VictoryGroup>
</VictoryChart>
);
};

View file

@ -0,0 +1,42 @@
import React, { useContext } from 'react';
import { DarkSubTitle } from '../../generic/Styled';
import { SettingsContext } from '../../../context/SettingsContext';
import { VictoryPie } from 'victory';
import { chartAxisColor } from '../../../styles/Themes';
import { Row, Col, PieRow } from '.';
interface Props {
invoicePie: { x: string; y: string }[];
}
export const InvoicePie = ({ invoicePie }: Props) => {
const { theme } = useContext(SettingsContext);
return (
<Row>
<Col>
<PieRow>
<DarkSubTitle bottom={'0px'}>Confirmed:</DarkSubTitle>
{invoicePie[0].y}
</PieRow>
<PieRow>
<DarkSubTitle bottom={'0px'}>Unconfirmed:</DarkSubTitle>
{invoicePie[1].y}
</PieRow>
</Col>
<VictoryPie
padding={0}
height={150}
colorScale={['#FD5F00', '#ffd300']}
labels={() => ''}
padAngle={3}
innerRadius={50}
labelRadius={55}
data={invoicePie}
style={{
labels: { fontSize: 24, fill: chartAxisColor[theme] },
}}
/>
</Row>
);
};

View file

@ -1,16 +1,20 @@
import React, { useState } from 'react';
import React, { useState, useContext } from 'react';
import styled from 'styled-components';
import { CardWithTitle, SubTitle, Card, CardTitle } from '../../generic/Styled';
import {
CardWithTitle,
SubTitle,
Card,
CardTitle,
Sub4Title,
} from '../../generic/Styled';
import { ButtonRow } from '../forwardReport/Buttons';
import { FlowReport } from './FlowReport';
export const CardContent = styled.div`
height: 100%;
display: flex;
flex-flow: column;
width: 50%;
padding: 0 20px;
`;
import { getAuthString } from '../../../utils/auth';
import { AccountContext } from '../../../context/AccountContext';
import { GET_IN_OUT } from '../../../graphql/query';
import { useQuery } from '@apollo/react-hooks';
import { FlowPie } from './FlowPie';
import { InvoicePie } from './InvoicePie';
export const ChannelRow = styled.div`
font-size: 14px;
@ -23,6 +27,27 @@ export const Row = styled.div`
display: flex;
`;
export const PieRow = styled(Row)`
justify-content: space-between;
`;
export const Col = styled.div`
display: flex;
flex-direction: column;
justify-content: space-around;
min-width: 200px;
`;
const HalfCardWithTitle = styled(CardWithTitle)`
width: 50%;
`;
interface PeriodProps {
period: number;
amount: number;
tokens: number;
}
const availableTimes = ['day', 'week', 'month'];
const mappedTimes = ['Day', 'Week', 'Month'];
const availableTypes = ['amount', 'tokens'];
@ -30,10 +55,15 @@ const mappedTypes = ['Amount', 'Value'];
const buttonBorder = `#FD5F00`;
export const FlowBox = () => {
const [isTime, setIsTime] = useState<string>('week');
const [isTime, setIsTime] = useState<string>('month');
const [isType, setIsType] = useState<string>('amount');
const props = { isTime, isType };
const { host, read, cert } = useContext(AccountContext);
const auth = getAuthString(host, read, cert);
const { data, loading, error } = useQuery(GET_IN_OUT, {
variables: { time: isTime, auth },
});
const buttonProps = {
isTime,
isType,
@ -46,15 +76,73 @@ export const FlowBox = () => {
buttonBorder,
};
if (!data || loading) {
return <div>Loading</div>;
}
const parsedData: PeriodProps[] = JSON.parse(data.getInOut.invoices);
const parsedData2: PeriodProps[] = JSON.parse(data.getInOut.payments);
if (parsedData.length <= 0) {
return <p>Your node has not forwarded any payments.</p>;
}
const reduce = (array: PeriodProps[]) =>
array.reduce((p, c) => {
return {
tokens: p.tokens + c.tokens,
period: 0,
amount: p.amount + c.amount,
};
});
const totalInvoices: any = reduce(parsedData);
const totalPayments: any = reduce(parsedData2);
const flowPie = [
{ x: 'Invoice', y: totalInvoices[isType] },
{ x: 'Payments', y: totalPayments[isType] },
];
const invoicePie = [
{ x: 'Confirmed', y: data.getInOut.confirmedInvoices },
{ x: 'Unconfirmed', y: data.getInOut.unConfirmedInvoices },
];
const props = { isTime, isType, parsedData, parsedData2 };
const pieProps = { invoicePie };
const flowProps = { flowPie, isType };
return (
<CardWithTitle>
<CardTitle>
<SubTitle>Invoices and Payments Report</SubTitle>
<ButtonRow {...buttonProps} />
</CardTitle>
<Card>
<FlowReport {...props} />
</Card>
</CardWithTitle>
<>
<CardWithTitle>
<CardTitle>
<SubTitle>Invoices and Payments Report</SubTitle>
<ButtonRow {...buttonProps} />
</CardTitle>
<Card bottom={'10px'}>
<FlowReport {...props} />
</Card>
</CardWithTitle>
<Row>
<HalfCardWithTitle>
<CardTitle>
<Sub4Title>Total</Sub4Title>
</CardTitle>
<Card>
<FlowPie {...flowProps} />
</Card>
</HalfCardWithTitle>
<div style={{ width: '20px' }} />
<HalfCardWithTitle>
<CardTitle>
<Sub4Title>Invoices</Sub4Title>
</CardTitle>
<Card>
<InvoicePie {...pieProps} />
</Card>
</HalfCardWithTitle>
</Row>
</>
);
};

View file

@ -124,10 +124,6 @@ export const ForwardReport = ({ isTime, isType }: Props) => {
}
/>
<VictoryBar
animate={{
duration: 100,
}}
cornerRadius={barWidth / 2}
data={parsedData}
x="period"
y={isType}