import { useQuery } from '@apollo/react-hooks' import Grid from '@material-ui/core/Grid' import { makeStyles } from '@material-ui/core/styles' import BigNumber from 'bignumber.js' import classnames from 'classnames' import { isAfter, sub } from 'date-fns/fp' import gql from 'graphql-tag' import * as R from 'ramda' import React, { useState } from 'react' import { EmptyTable } from 'src/components/table' import { Label1, Label2, P } from 'src/components/typography/index' import { ReactComponent as PercentDownIcon } from 'src/styling/icons/dashboard/down.svg' import { ReactComponent as PercentNeutralIcon } from 'src/styling/icons/dashboard/equal.svg' import { ReactComponent as PercentUpIcon } from 'src/styling/icons/dashboard/up.svg' import { java, neon } from 'src/styling/variables' import { fromNamespace } from 'src/utils/config' import { timezones } from 'src/utils/timezone-list' import { toTimezone } from 'src/utils/timezones' import PercentageChart from './Graphs/PercentageChart' import LineChart from './Graphs/RefLineChart' import Scatterplot from './Graphs/RefScatterplot' import InfoWithLabel from './InfoWithLabel' import Nav from './Nav' import styles from './SystemPerformance.styles' BigNumber.config({ ROUNDING_MODE: BigNumber.ROUND_HALF_UP }) const getFiats = R.map(R.prop('fiat')) const useStyles = makeStyles(styles) const getDateSecondsAgo = (seconds = 0, startDate = null) => { const date = startDate ? new Date(startDate) : new Date() return sub({ seconds: seconds }, date) } const ranges = { Day: { left: getDateSecondsAgo(2 * 24 * 3600, new Date()), right: getDateSecondsAgo(24 * 3600, new Date()) }, Week: { left: getDateSecondsAgo(14 * 24 * 3600, new Date()), right: getDateSecondsAgo(7 * 24 * 3600, new Date()) }, Month: { left: getDateSecondsAgo(60 * 24 * 3600, new Date()), right: getDateSecondsAgo(30 * 24 * 3600, new Date()) } } const GET_DATA = gql` query getData($excludeTestingCustomers: Boolean) { transactions(excludeTestingCustomers: $excludeTestingCustomers) { fiatCode fiat cashInFee commissionPercentage created txClass error profit } fiatRates { code name rate } config } ` const SystemPerformance = () => { const classes = useStyles() const [selectedRange, setSelectedRange] = useState('Day') const { data, loading } = useQuery(GET_DATA, { variables: { excludeTestingCustomers: true } }) const fiatLocale = fromNamespace('locale')(data?.config).fiatCurrency const timezone = fromNamespace('locale')(data?.config).timezone const isInRangeAndNoError = getLastTimePeriod => t => { if (t.error !== null) return false if (!getLastTimePeriod) { return ( t.error === null && isAfter(ranges[selectedRange].right, toTimezone(t.created, timezone)) && isAfter(toTimezone(t.created, timezone), new Date()) ) } return ( t.error === null && isAfter(ranges[selectedRange].left, toTimezone(t.created, timezone)) && isAfter(toTimezone(t.created, timezone), ranges[selectedRange].right) ) } const convertFiatToLocale = item => { if (item.fiatCode === fiatLocale) return item const itemRate = R.find(R.propEq('code', item.fiatCode))(data.fiatRates) const localeRate = R.find(R.propEq('code', fiatLocale))(data.fiatRates) const multiplier = localeRate.rate / itemRate.rate return { ...item, fiat: parseFloat(item.fiat) * multiplier } } const transactionsToShow = R.map(convertFiatToLocale)( R.filter(isInRangeAndNoError(false), data?.transactions ?? []) ) const transactionsLastTimePeriod = R.map(convertFiatToLocale)( R.filter(isInRangeAndNoError(true), data?.transactions ?? []) ) const getNumTransactions = () => { return R.length(transactionsToShow) } const getFiatVolume = () => new BigNumber(R.sum(getFiats(transactionsToShow))).toFormat(2) const getProfit = transactions => { return R.reduce( (acc, value) => acc.plus(value.profit), new BigNumber(0), transactions ) } const getPercentChange = () => { const thisTimePeriodProfit = getProfit(transactionsToShow) const previousTimePeriodProfit = getProfit(transactionsLastTimePeriod) if (thisTimePeriodProfit.eq(previousTimePeriodProfit)) return 0 if (previousTimePeriodProfit.eq(0)) return 100 return thisTimePeriodProfit .minus(previousTimePeriodProfit) .times(100) .div(previousTimePeriodProfit) .toNumber() } const getDirectionPercent = () => { const [cashIn, cashOut] = R.partition(R.propEq('txClass', 'cashIn'))( transactionsToShow ) const totalLength = cashIn.length + cashOut.length if (totalLength === 0) { return { cashIn: 0, cashOut: 0 } } return { cashIn: Math.round((cashIn.length / totalLength) * 100), cashOut: Math.round((cashOut.length / totalLength) * 100) } } const percentChange = getPercentChange() const percentageClasses = { [classes.percentDown]: percentChange < 0, [classes.percentUp]: percentChange > 0, [classes.percentNeutral]: percentChange === 0 } const getPercentageIcon = () => { if (percentChange === 0) return if (percentChange > 0) return return } return ( <> {!loading && R.isEmpty(data.transactions) && ( )} {!loading && !R.isEmpty(data.transactions) && ( <> {/* todo new customers */} Transactions {timezones[timezone]?.short ?? timezones[timezone]?.long}{' '} timezone In Out Profit from commissions {`${getProfit(transactionsToShow).toFormat(2)} ${ data?.config.locale_fiatCurrency }`} {getPercentageIcon()} {`${new BigNumber(percentChange).toFormat(2)}%`} Direction In Out > )} > ) } export default SystemPerformance
{timezones[timezone]?.short ?? timezones[timezone]?.long}{' '} timezone